Skip to content

Develop#125

Merged
docodocod merged 3 commits into
mainfrom
develop
Jun 2, 2026
Merged

Develop#125
docodocod merged 3 commits into
mainfrom
develop

Conversation

@docodocod

Copy link
Copy Markdown
Contributor

📢 기능 설명

필요시 실행결과 스크린샷 첨부

연결된 issue

연결된 issue를 자동을 닫기 위해 아래 {이슈넘버}를 입력해주세요.

close #{이슈넘버}

✅ 체크리스트

  • PR 제목 규칙 잘 지켰는가?
  • 추가/수정사항을 설명하였는가?
  • 이슈넘버를 적었는가?

docodocod and others added 3 commits June 2, 2026 22:18
- Store 엔티티에 idx_store_popularity 복합 인덱스 추가 (is_deleted, average_star, review_count, bookmark_count, id)
- findInBounds 쿼리를 ST_DistanceSphere 전수계산에서 GIST && + KNN <-> 정렬로 교체
- getStores() 에 @Cacheable(storeList, TTL 10분) 적용
- createStore/updateStore/updateStoreStatus 에 @CacheEvict(storeList) 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- idx_store_popularity 인덱스 컬럼 방향 명시 (average_star DESC, review_count DESC, bookmark_count DESC, id ASC)
- COALESCE 제거, findInBounds GIST 캐스팅 수정 (::geography)
- applyReviewCreated/Deleted/Updated 에 @CacheEvict(popularStores + storeList) 추가
- evictPopularStoresCache 도 storeList 함께 evict 하도록 수정

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
perf: store 목록/nearby/in-bounds 성능 개선

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces database query optimizations and caching mechanisms for store listings. Specifically, it adds a composite index for popularity-based sorting, removes COALESCE from order-by clauses to leverage this index, and refactors spatial queries to use PostGIS operators (&& and <->). Additionally, it implements caching for store lists using Spring's @Cacheable and @CacheEvict. The review feedback recommends ensuring cache consistency by also evicting the popularStores cache when updating a store or its status, and suggests simplifying the SpEL key expression while expanding the cache condition to handle blank or empty search names.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

}

// 매장 정보 수정
@CacheEvict(value = "storeList", allEntries = true)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

매장 정보가 수정되면 인기 매장 목록(popularStores) 캐시에도 영향이 있을 수 있습니다. 예를 들어, 인기 매장에 포함된 매장의 이름이나 이미지가 변경되었을 때 캐시가 즉시 비워지지 않으면 사용자는 최대 5분 동안 이전 정보를 보게 됩니다.\n\n따라서 storeList뿐만 아니라 popularStores 캐시도 함께 비워주어야 캐시 일관성을 유지할 수 있습니다.

Suggested change
@CacheEvict(value = "storeList", allEntries = true)
@CacheEvict(value = {"storeList", "popularStores"}, allEntries = true)

}

// 매장 상태 변경
@CacheEvict(value = "storeList", allEntries = true)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

매장의 상태가 변경되어 비활성화(INACTIVE, 즉 soft delete)되는 경우, 해당 매장은 인기 매장 목록(popularStores)에서도 즉시 제외되어야 합니다. 그렇지 않으면 캐시가 만료될 때까지 사용자가 삭제된 매장을 인기 매장 목록에서 보게 되고, 클릭 시 404 에러를 마주하게 됩니다.\n\n따라서 storeList뿐만 아니라 popularStores 캐시도 함께 비워주어야 합니다.

Suggested change
@CacheEvict(value = "storeList", allEntries = true)
@CacheEvict(value = {"storeList", "popularStores"}, allEntries = true)

* 매장 목록 통합 조회 (이름·카테고리·지역 옵셔널 필터 + DB 페이지네이션 + 인기 정렬)
* Specification 사용으로 PostgreSQL+enum 조합에서 :param IS NULL 회피.
*/
@Cacheable(value = "storeList", key = "T(String).valueOf(#category) + ':' + T(String).valueOf(#district) + ':' + #page + ':' + #size", condition = "#name == null")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

SpEL(Spring Expression Language)에서 null 객체를 문자열과 연결(+)할 때 자동으로 "null" 문자열로 변환되므로, T(String).valueOf(...)를 생략하여 코드를 더 간결하게 작성할 수 있습니다.\n\n또한, 현재 condition = "#name == null" 조건은 검색어(name)가 빈 문자열("")이나 공백(" ")으로 들어오는 경우 캐시를 타지 않고 항상 DB를 조회하게 만듭니다. 메서드 내부에서는 name.isBlank()일 때 trimmedNamenull로 처리하여 전체 목록을 조회하므로, 결과적으로 동일한 전체 목록 조회 쿼리가 캐시 없이 반복 실행될 수 있습니다. 빈 문자열이나 공백인 경우에도 캐시가 적용되도록 조건을 개선하는 것을 추천합니다.

Suggested change
@Cacheable(value = "storeList", key = "T(String).valueOf(#category) + ':' + T(String).valueOf(#district) + ':' + #page + ':' + #size", condition = "#name == null")
@Cacheable(value = "storeList", key = "#category + ':' + #district + ':' + #page + ':' + #size", condition = "#name == null || #name.trim().isEmpty()")

@johe00123 johe00123 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@docodocod docodocod merged commit 2e71c85 into main Jun 2, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants