-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat] '최근 응원한 가게 조회 API'에 검색 조건 추가 #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Caution Review failedThe pull request is closed. Walkthrough검색 필터 구조를 개편하여 /api/shops 조회에 카테고리(StoreCategory), 태그(List), 지역(List)를 추가했고, StoreSearchParameters로 집계 전달하도록 컨트롤러·서비스 시그니처를 변경했다. 리포지토리는 JPA Specification 기반 동적 필터링으로 전환했고, 관련 테스트·문서·픽스처를 업데이트했다. Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant Controller as StoreController
participant Service as StoreService
participant Repo as StoreRepository
Client->>Controller: GET /api/shops?page&size&category&tag&location
Controller->>Service: getStores(StoreSearchParameters)
Service->>Repo: findAllByConditions(category, tags, districts, pageable)
Repo-->>Service: List<Store>
Service-->>Controller: StoresResponse
Controller-->>Client: 200 OK (StoresResponse)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: .coderabbit.yaml 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (8)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (14)
src/test/java/eatda/fixture/StoreGenerator.java (2)
52-55: 오버로드 확장에 따른 중복 최소화 제안generate 오버로드가 계속 늘어나는 추세라, 빌더/옵션 객체 기반(예: GenerateOptions.withCreatedAt(...).withDistrict(...).withCategory(...))으로 중복을 줄이는 것을 고려해볼 만합니다. 테스트 픽스처 유지보수에 유리합니다.
57-57: create 메서드 public 전환 — 용도 명시 주석 권장create는 “비영속 엔티티 생성”, generate는 “저장까지 포함”이라는 의미가 분명하지만, public 노출로 혼용 가능성이 있습니다. 간단한 Javadoc을 추가해 오용을 방지하는 것을 권장합니다.
추가(파일 외) 예시:
/** * 테스트용 비영속 Store 인스턴스를 생성합니다. * - 저장이 필요하면 generate(...)를 사용하세요. */ public Store create(String kakaoId, String lotNumberAddress, District district, StoreCategory category) { ... }src/main/java/eatda/domain/store/Store.java (1)
58-60: 연관관계 기본 fetch 명시 권장 및 도메인 의도 점검
- 일대다 컬렉션의 기본 fetch는 LAZY이지만, 명시적으로 적어 의도를 드러내는 것을 권장합니다.
- cascade/orphanRemoval 설정은 도메인 의도(가게 삭제 시 응원 일괄 삭제 여부 등)에 따라 결정되어야 합니다. 현재 기본값(비캐스케이드) 유지도 합리적이지만, 의도 확정 후 주석으로 남기면 좋습니다.
다음 변경 제안:
- @OneToMany(mappedBy = "store") + @OneToMany(mappedBy = "store", fetch = FetchType.LAZY) private List<Cheer> cheers = new ArrayList<>();추가(파일 외) import:
import jakarta.persistence.FetchType;src/test/java/eatda/service/store/StoreServiceTest.java (1)
96-99: 태그/지역 필터 케이스도 서비스 레벨에서 커버 제안리포지토리/컨트롤러 테스트가 존재하더라도, 서비스 계층 통합 관점에서
- 태그가 N개일 때 OR 매칭
- 지역이 N개일 때 OR 매칭(SearchDistrict → District 확장 포함)
- 태그/지역 혼합 지정 시 조합 동작
을 검증하는 테스트를 추가하면 회귀에 강해집니다. 필요시 테스트 케이스 초안 드리겠습니다.src/test/java/eatda/fixture/CheerTagGenerator.java (1)
19-23: saveAll 사용으로 DB 라운드트립 최소화 + null/빈 리스트 방어 로직 추가 제안현재 map 내부에서 save를 호출하는 방식은 부작용(side-effect) 사용이며 INSERT 호출이 tag 개수만큼 발생합니다. 테스트라 하더라도 saveAll로 한 번에 저장하고, null/빈 입력을 안전하게 처리하면 가독성과 성능이 좋아집니다.
아래처럼 변경을 제안드립니다:
- public List<CheerTag> generate(Cheer cheer, List<CheerTagName> tagNames) { - return tagNames.stream() - .map(name -> cheerTagRepository.save(new CheerTag(cheer, name))) - .toList(); - } + public List<CheerTag> generate(Cheer cheer, List<CheerTagName> tagNames) { + if (tagNames == null || tagNames.isEmpty()) { + return List.of(); + } + List<CheerTag> entities = tagNames.stream() + .map(name -> new CheerTag(cheer, name)) + .toList(); + return cheerTagRepository.saveAll(entities); + }src/main/java/eatda/controller/store/StoreSearchParameters.java (2)
31-32: 내부 리스트의 불변성 보장(List.copyOf)으로 방어적 복사 권장현재는 외부에서 전달된 컬렉션 레퍼런스를 그대로 보관하고 있어, 호출 측이 이후에 리스트를 변경하면 내부 상태가 변할 수 있습니다. 불변 리스트로 복사해 두면 안전합니다.
- this.tag = tag != null ? tag : Collections.emptyList(); - this.location = location != null ? location : Collections.emptyList(); + this.tag = tag != null ? List.copyOf(tag) : List.of(); + this.location = location != null ? List.copyOf(location) : List.of();
23-33: page/size 유효성 검증 위치 확인 필요이 VO에서는 음수 page/size, size 상한 등에 대한 검증이 없습니다. 컨트롤러 바인딩 레벨(@min, @max 등)에서 보장되는지 확인 부탁드립니다. 만약 서비스/레포지토리까지 흘러들 가능성이 있다면, 방어적 검증을 추가하는 것이 안전합니다.
원하시면 컨트롤러 파라미터에 Bean Validation 애노테이션을 추가하고, 테스트 케이스(잘못된 page/size에 대한 400 응답)도 함께 드리겠습니다.
src/test/java/eatda/repository/store/StoreRepositoryTest.java (1)
150-171: 무조건 전체 조회 케이스 OK + 추가 커버리지 제안전체 조회 검증은 적절합니다. 추가로 다음 케이스가 있으면 신뢰도가 더 올라갑니다:
- 다중 지역 OR 검증: 예) [GANGNAM, SEONGBUK] 입력 시 두 지역의 결과가 모두 포함되는지
- 존재하지 않는 조합 시 빈 페이지 반환
원하시면 위 두 케이스에 대한 테스트 메서드를 초안으로 제공하겠습니다.
src/test/java/eatda/controller/store/StoreControllerTest.java (1)
78-111: 다중 값 바인딩 검증 보강 및 빈 location 파라미터 전달 방식 조정 제안
- 현재 tag는 단일 값만 검증합니다. 이번 PR 목표(태그/지역 N개 OR 매칭)를 반영해 tag/location에 다중 값을 전달하는 컨트롤러 레벨 바인딩 테스트를 추가하는 것을 권장합니다.
- location에 빈 문자열("")을 넘기는 방식은 스프링 타입 컨버터에서 Enum 변환 오류를 유발할 수 있습니다. 단순히 파라미터를 생략하거나, 값이 없을 때는 아예 쿼리 파라미터를 넣지 않는 편이 안전합니다.
예: 다중 값 전달(추가 테스트 제안)
given() .queryParam("page", 0) .queryParam("size", 10) .queryParam("category", StoreCategory.CAFE) .queryParam("tag", CheerTagName.INSTAGRAMMABLE, CheerTagName.CLEAN_RESTROOM) // varargs // .queryParam("location", SearchDistrict.GANGNAM, SearchDistrict.SEONGBUK) // 필요 시 .when().get("/api/shops") .then().statusCode(200);src/main/java/eatda/domain/store/SearchDistrict.java (2)
26-33: enum 필드를 final로 선언해 불변성 강화enum 특성상 변경될 일이 없으므로 final로 명시하는 것이 안전합니다.
- private String displayName; - private List<District> districts; + private final String displayName; + private final List<District> districts;
14-24: 지역 매핑 정확성 재확인 요청(MYEONGDONG, DAECHI 등)도메인 지식에 의존하는 매핑이라 확정 코멘트는 어렵지만, 아래 항목은 재검토를 권장합니다:
- MYEONGDONG이 DONGDAEMUN/SEONGBUK로 매핑되어 있음
- DAECHI("대치/논현/서초")가 SEOCHO만 포함(대치/논현은 일반적으로 강남구)
사내 정책/기획 분류 기준과 일치하는지 확인 부탁드립니다. 필요 시 테스트로 고정(매핑 변경 시 깨지는 회귀 테스트)하는 것도 추천합니다.
정책 표를 기준으로 enum 상수/매핑을 자동 검증하는 단위 테스트 템플릿을 제공할 수 있습니다. 원하시면 알려주세요.
src/main/java/eatda/service/store/StoreService.java (1)
46-49: getStoreImageUrl 호출로 인한 N+1 + 외부 호출 폭증 가능성stores 개수만큼 cheerRepository.findRecentImageKey + imageStorage.getPreSignedUrl 이 반복되어 DB 쿼리와 스토리지 서명이 N배 발생할 수 있습니다. 데이터·트래픽 규모에 따라 응답 지연이 커질 수 있어 개선을 권장합니다.
다음 중 하나를 고려해 주세요:
- 리포지토리에 배치 쿼리 도입: findRecentImageKeyByStores(List) → Map<StoreId, ImageKey> 형태로 일괄 조회 후 매핑
- 최근 이미지 키를 가게 목록과 함께 join/fetch 해오는 전용 쿼리(서브쿼리/윈도우 함수 활용)
- preSignedUrl 역시 배치 생성(가능 시) 또는 캐시 도입
필요하시면 리포지토리 스펙/JPQL 스케치와 서비스 매핑 코드까지 제안 드릴게요.
src/test/java/eatda/document/store/StoreDocumentTest.java (1)
111-116: 요청 파라미터 문서 보강 제안: Enum 허용값 명시category/tag/location 이 Enum 바인딩이므로, 문서에 허용 가능한 값 목록을 함께 노출하면 API 사용성이 좋아집니다. Spring REST Docs의 attributes 또는 커스텀 설명을 통해 Enum 값들을 나열하는 방식을 권장합니다.
예: "카테고리 ... (허용값: KOREAN, CAFE, ...)" / "태그 ... (허용값: INSTAGRAMMABLE, ENERGETIC, ...)" / "지역 ... (허용값: GANGNAM, KONDAE, ...)"
src/main/java/eatda/controller/store/StoreController.java (1)
39-41: 리스트 파라미터 바인딩 UX 개선 여지tag/location은 다중 값 파라미터로 바인딩됩니다. 대부분의 Spring 설정에서 "tag=A,B"와 "tag=A&tag=B" 모두 수용되지만, "tag="처럼 빈 문자열이 전달되면 400이 날 수 있습니다. 필요 시 기본값/빈 값 무시 로직 문서화 또는 빈 값 필터링을 고려해 주세요.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (14)
src/main/java/eatda/controller/store/StoreController.java(2 hunks)src/main/java/eatda/controller/store/StoreSearchParameters.java(1 hunks)src/main/java/eatda/domain/store/SearchDistrict.java(1 hunks)src/main/java/eatda/domain/store/Store.java(3 hunks)src/main/java/eatda/repository/store/StoreRepository.java(2 hunks)src/main/java/eatda/service/store/StoreService.java(2 hunks)src/test/java/eatda/controller/BaseControllerTest.java(2 hunks)src/test/java/eatda/controller/store/StoreControllerTest.java(2 hunks)src/test/java/eatda/document/store/StoreDocumentTest.java(6 hunks)src/test/java/eatda/fixture/CheerTagGenerator.java(1 hunks)src/test/java/eatda/fixture/StoreGenerator.java(1 hunks)src/test/java/eatda/repository/BaseRepositoryTest.java(3 hunks)src/test/java/eatda/repository/store/StoreRepositoryTest.java(2 hunks)src/test/java/eatda/service/store/StoreServiceTest.java(5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/test/java/eatda/fixture/CheerTagGenerator.java (1)
src/test/java/eatda/fixture/StoreGenerator.java (1)
Component(11-71)
src/test/java/eatda/service/store/StoreServiceTest.java (1)
src/main/java/eatda/controller/store/StoreSearchParameters.java (1)
StoreSearchParameters(12-50)
src/main/java/eatda/service/store/StoreService.java (1)
src/main/java/eatda/controller/store/StoreSearchParameters.java (1)
StoreSearchParameters(12-50)
🔇 Additional comments (22)
src/test/java/eatda/fixture/StoreGenerator.java (1)
52-55: 새 오버로드(generate with District, StoreCategory) 추가 적절테스트 픽스처 사용성이 좋아졌습니다. 동일한 패턴으로 create → save 흐름을 유지한 점도 일관성 있어요.
src/test/java/eatda/controller/BaseControllerTest.java (2)
17-17: CheerTagGenerator 주입 반영 OK컨트롤러 통합 테스트에서 태그 관련 데이터 셋업을 쉽게 할 수 있어 보입니다.
Also applies to: 64-66
64-66: 테스트 빈 스캔 범위 확인 요청CheerTagGenerator가 @component 등으로 스캔 대상이라면 현재 @SpringBootTest 구성에서 문제 없겠지만, 스캔 대상이 아닐 경우 NoSuchBeanDefinitionException이 발생할 수 있습니다. 필요시 @import(CheerTagGenerator.class) 추가를 고려해 주세요.
src/main/java/eatda/domain/store/Store.java (1)
4-4: mappedBy 대상 필드명 일치 확인 완료Cheer 엔티티에
private Store store필드가 존재(41번 라인)하며,mappedBy="store"와 정확히 일치합니다. 추가 수정이나 검증은 필요하지 않습니다.src/test/java/eatda/repository/BaseRepositoryTest.java (1)
16-16: CheerTag 관련 테스트 스캐폴딩 연동 LGTM
- @import에 CheerTagGenerator 추가
- cheerTagGenerator, cheerTagRepository 주입
리포지토리 테스트에서 태그 필터링 케이스를 셋업/검증하기에 적절합니다.
Also applies to: 29-31, 41-43
src/test/java/eatda/service/store/StoreServiceTest.java (2)
9-9: StoreSearchParameters import 추가 적절서비스 시그니처 변경에 맞춘 테스트 정리 좋습니다.
73-76: 파라미터 객체 도입에 따른 호출부 정리 LGTM
- page/size/category를 객체로 묶어 가독성과 확장성이 향상되었습니다.
- 최신순 정렬 및 페이징 기대값도 일관성 있게 유지됩니다.
Also applies to: 98-99, 119-122, 141-144
src/test/java/eatda/fixture/CheerTagGenerator.java (1)
10-17: 테스트 픽스처 DI 구성은 적절합니다생성자 주입과 @component 등록으로 테스트에서 재사용하기 좋은 형태입니다.
src/main/java/eatda/controller/store/StoreSearchParameters.java (1)
44-49: 장소 필터의 중복 제거 로직은 명확하고 적절합니다SearchDistrict -> District 플래튼 후 distinct 처리로 기대 동작(중복 제외)을 잘 만족합니다.
src/test/java/eatda/repository/store/StoreRepositoryTest.java (4)
58-71: 카테고리 단일 조건 필터링 테스트 구성 적절카테고리 EQ 필터 동작과 반환 집합만 검증해 깔끔합니다.
73-98: 태그 다중(OR) 조건 테스트 훌륭함 + 중복 제거(distinct) 보장 확인 권장두 태그 중 하나라도 매칭되는 스토어를 기대하는 검증으로 OR semantics가 잘 드러납니다. 다만 Cheer/Tag 조인 시 동일 스토어가 중복 조회될 수 있어 Specification에서 criteriaQuery.distinct(true) 처리가 필수입니다. 레포지토리 구현에 distinct 설정이 있는지 확인 부탁드립니다.
참고 예시(레포지토리 구현 쪽):
return (root, query, cb) -> { query.distinct(true); // ... joins and predicates };
100-113: 지역 필터(OR) 테스트도 간결하고 타당합니다District IN 조건 검증이 잘 되어 있습니다.
115-148: 복합 조건 테스트 케이스 구성 매우 좋음카테고리 AND 지역 AND 태그(OR) 조합을 현실적으로 구성했습니다. 이 조합은 본 PR 요구사항을 잘 커버합니다.
src/test/java/eatda/controller/store/StoreControllerTest.java (1)
62-73: 페이지/사이즈 쿼리 파라미터 명시 좋습니다page/size를 명시해 페이징 동작이 테스트에 명확히 드러납니다.
src/main/java/eatda/domain/store/SearchDistrict.java (1)
6-24: 구조 전반은 명확하고 확장 용이합니다표시명과 District 리스트를 보유하는 단순 enum 설계가 컨트롤러 파라미터 및 검색 파이프라인과 잘 맞습니다. List.of로 불변 컬렉션을 사용하는 점도 좋습니다.
src/main/java/eatda/service/store/StoreService.java (2)
37-44: 동적 검색 + 정렬 적용은 적절합니다JpaSpecificationExecutor로의 위임과 PageRequest.of(..., Sort.by(Direction.DESC, "createdAt"))로 최신순 보장이 명확해졌습니다. 컨트롤러의 파라미터 객체화와도 일관됩니다.
43-43: 정렬 키 ‘createdAt’ 검증 완료Store 엔티티가 AuditingEntity를 상속하며,
AuditingEntity( src/main/java/eatda/domain/AuditingEntity.java )에private LocalDateTime createdAt필드가 정의되어 있어
Sort.by(Direction.DESC, "createdAt")사용 시 런타임 오류가 발생하지 않습니다.src/test/java/eatda/document/store/StoreDocumentTest.java (2)
135-149: 목킹/요청 파라미터 변경이 서비스 시그니처 개편과 정합적입니다storeService.getStores(any())로 변경, Enum 기반 queryParam 사용, 새 파라미터(tag/location) 추가 모두 컨트롤러/서비스 개편과 일치합니다. 문서 샘플 쿼리 또한 최신 인터페이스를 반영합니다.
156-169: 에러 경로도 동일하게 업데이트된 점 👍실패 케이스에서 getStores(any())로 목킹/요청 파라미터를 일관되게 유지해 회귀 리스크를 줄였습니다.
src/main/java/eatda/repository/store/StoreRepository.java (2)
37-44: findAllByConditions 기본 동작은 적절합니다빈 리스트/널 입력 시 조건을 생략하고, Pageable을 통해 정렬/페이징을 일관 적용하는 접근이 깔끔합니다. createSpecification 분리도 가독성에 이점이 있습니다.
49-49: Specification.allOf() 사용 가능 확인됨현재 프로젝트의 Spring Boot 플러그인 버전이 3.5.0이므로 Spring Data JPA의
Specification.allOf()가 지원됩니다. 별도 대체안 없이 그대로 사용하셔도 무방합니다.src/main/java/eatda/controller/store/StoreController.java (1)
37-45: 타입 세이프 파라미터 + 파라미터 객체 도입 적절Enum 기반 바인딩(StoreCategory/CheerTagName/SearchDistrict)과 StoreSearchParameters 집계 후 서비스 호출은 API 표면을 명확히 하고 확장성도 좋습니다. StoreSearchParameters가 null 리스트를 빈 리스트로 정규화하므로 컨트롤러 단에서의 보일러플레이트도 줄었습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/main/java/eatda/repository/store/StoreRepository.java (1)
53-56: 태그 조인 경로가 잘못되었고 중복 행 반환 위험 — 명시적 조인 + distinct 필요
- 현재 경로
root.join("cheers").get("cheerTags").get("values").get("name")는 컬렉션 경로를get()으로 접근하고 있어 Criteria 오류가 납니다.cheerTags는 조인해야 합니다.- 태그 조건이 있는 경우 cheers/cheerTags 조인으로 인해 동일 Store가 중복 행으로 확장됩니다.
query.distinct(true)가 필요합니다.수정(diff) 제안:
- if (!cheerTagNames.isEmpty()) { - spec = spec.and(((root, query, cb) -> - root.join("cheers").get("cheerTags").get("values").get("name").in(cheerTagNames))); - } + if (!cheerTagNames.isEmpty()) { + spec = spec.and((root, query, cb) -> { + // 다대다/일대다 조인 시 중복 제거 + query.distinct(true); + // cheers -> cheerTags 명시적 조인 후 태그 이름으로 필터 + return root.join("cheers") + .join("cheerTags") + .get("name") + .in(cheerTagNames); + }); + }
🧹 Nitpick comments (2)
src/main/java/eatda/repository/store/StoreRepository.java (1)
57-59: District 조건은 OK — 성능/가독성 보완은 선택 사항
root.get("district").in(districts)는 요구사항(선택된 지역 중 하나라도 포함)에 부합합니다.- 선택:
districts가 매우 클 경우 별도 인덱스 확인 또는 쿼리 힌트/배치 전략 검토를 제안합니다.src/main/java/eatda/service/store/StoreService.java (1)
46-49: 스트림 매핑은 간결하고 명확합니다
- 프리뷰 응답 매핑과 이미지 URL resolve는 의도대로 동작합니다. N+1 관련 TODO는 별도 과제로 유지해도 충분합니다.
선택: 이미지 URL을 배치로 로딩하는 전용 리포지토리 쿼리로 N+1을 제거할 수 있습니다(후속 PR 권장).
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
src/main/java/eatda/domain/store/SearchDistrict.java(1 hunks)src/main/java/eatda/repository/store/StoreRepository.java(2 hunks)src/main/java/eatda/service/store/StoreService.java(2 hunks)src/test/java/eatda/repository/store/StoreRepositoryTest.java(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/test/java/eatda/repository/store/StoreRepositoryTest.java
- src/main/java/eatda/domain/store/SearchDistrict.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/eatda/service/store/StoreService.java (1)
src/main/java/eatda/controller/store/StoreSearchParameters.java (1)
StoreSearchParameters(12-50)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (1)
src/main/java/eatda/service/store/StoreService.java (1)
39-44: 정렬 기준 확인 필요 — ‘최근 응원’ 의미라면 Cheer.createdAt 기준 정렬이 맞는지 검토
- 현재는
Store.createdAt DESC로 정렬하고 있습니다.- PR/이슈 요건이 “최근 응원한 가게”의 최근성을 뜻한다면,
Cheer.createdAt DESC가 더 자연스러울 수 있습니다. 이 경우 조인 정렬이 필요하며, 스펙/정렬 구성 또는 별도 쿼리 경로가 요구됩니다.원하는 정렬 기준이 무엇인지 확인 부탁드립니다. 필요 시 정렬을
Sort.by(Direction.DESC, "cheers.createdAt")로 변경하거나, 스펙 내에서query.orderBy(cb.desc(cheers.get("createdAt")))를 설정하는 방향으로 조정 가능합니다(중복 방지를 위해 distinct 유지).
lvalentine6
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이번 PR도 고생하셨습니다! 📟
동적 쿼리 관련해서 질문 하나 남겼습니다!
|
|
||
| List<Store> findAll(Specification<Store> spec, Pageable pageable); | ||
|
|
||
| private Specification<Store> createSpecification(@Nullable StoreCategory category, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 동적 쿼리가 등장했군요. 👍🏻
- [질문] 사용자가 만약 한 가게에 INSTAGRAMMABLE 태그와 ENERGETIC 태그가 모두 달려있고, 사용자가 이 두 태그를 모두 선택하여 검색하면, 해당 가게는 결과 목록에 두 번 포함되는 경우는 없나요??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Test
void 응원_태그를_필터링하여_조회할_수_있다() {
Member member1 = memberGenerator.generateRegisteredMember("커찬", "[email protected]", "123", "01012341235");
Member member2 = memberGenerator.generateRegisteredMember("지민", "[email protected]", "124", "01012341236");
LocalDateTime startAt = LocalDateTime.of(2023, 10, 1, 12, 0);
Store store1 = storeGenerator.generate("1235", "서울시 강남구 역삼동 123-45", StoreCategory.KOREAN, startAt);
Store store2 = storeGenerator.generate("1236", "서울시 강남구 역삼동 123-45", StoreCategory.KOREAN, startAt);
Store store3 = storeGenerator.generate("1237", "서울시 강남구 역삼동 123-45", StoreCategory.KOREAN, startAt);
Store store4 = storeGenerator.generate("1238", "서울시 강남구 역삼동 123-45", StoreCategory.KOREAN, startAt);
Cheer cheer1_1 = cheerGenerator.generate(member1, store1, startAt);
Cheer cheer2_1 = cheerGenerator.generate(member1, store2, startAt);
Cheer cheer2_2 = cheerGenerator.generate(member2, store2, startAt);
Cheer cheer3_1 = cheerGenerator.generate(member1, store3, startAt);
Cheer cheer4_2 = cheerGenerator.generate(member2, store4, startAt);
cheerTagGenerator.generate(cheer1_1, List.of(CheerTagName.INSTAGRAMMABLE, CheerTagName.ENERGETIC));
cheerTagGenerator.generate(cheer2_1, List.of(CheerTagName.CLEAN_RESTROOM));
cheerTagGenerator.generate(cheer2_2, List.of(CheerTagName.CLEAN_RESTROOM));
cheerTagGenerator.generate(cheer3_1, List.of(CheerTagName.ENERGETIC, CheerTagName.QUIET));
List<Store> actual = storeRepository.findAllByConditions(null,
List.of(CheerTagName.INSTAGRAMMABLE, CheerTagName.CLEAN_RESTROOM), List.of(), Pageable.unpaged());
assertThat(actual).map(Store::getId)
.containsExactlyInAnyOrder(store1.getId(), store2.getId());
}해당 테스트의 containsExactlyInAnyOrder() 를 통해 검증 완료했습니다~
# Conflicts: # src/main/java/eatda/repository/store/StoreRepository.java # src/main/java/eatda/service/store/StoreService.java # src/test/java/eatda/controller/BaseControllerTest.java # src/test/java/eatda/controller/store/StoreControllerTest.java # src/test/java/eatda/service/store/StoreServiceTest.java
|
🎉 This PR is included in version 1.4.0-develop.93 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
|
|
🎉 This PR is included in version 1.8.0-develop.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.8.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |



✨ 개요
🧾 관련 이슈
closed #176
🔍 참고 사항 (선택)
JpaSpecificationExecutor를 이용한 동적 쿼리를 추가하였습니다.StoreRepositoryTest를 통해 여러 케이스를 테스트하였습니다.Summary by CodeRabbit
1개), 태그(0N개), 지역군(0~N개) 파라미터 설명과 예시 추가.