-
Notifications
You must be signed in to change notification settings - Fork 0
✨️ feat/ZIP-29 : 대시보드 기능 구현 #64
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
- 서비스 및 유즈케이스 정의
|
""" Walkthrough대시보드에서 사용자별 즐겨찾기와 소유 부동산 정보를 조회하는 기능이 추가되었습니다. 이를 위해 여러 포트, 어댑터, 서비스, 레포지토리 인터페이스에 관련 메서드가 신설되었으며, 새로운 서비스 클래스 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant DashBoardService
participant UserPort
participant FavoritePort
participant RegionPort
participant EstatePort
participant EstateOwnerShipPort
User->>DashBoardService: getFavoriteRegion(userId)
DashBoardService->>UserPort: checkExistingById(userId)
UserPort-->>DashBoardService: OK/Exception
DashBoardService->>FavoritePort: loadUserFavoriteByType(userId, REGION)
FavoritePort-->>DashBoardService: List<Favorite>
DashBoardService->>RegionPort: loadRegionsByCodes(regionCodes)
RegionPort-->>DashBoardService: List<Region>
DashBoardService-->>User: List<Region>
sequenceDiagram
participant User
participant DashBoardService
participant UserPort
participant FavoritePort
participant EstatePort
User->>DashBoardService: getFavoriteEstates(userId)
DashBoardService->>UserPort: checkExistingById(userId)
UserPort-->>DashBoardService: OK/Exception
DashBoardService->>FavoritePort: loadUserFavoriteByType(userId, APARTMENT)
FavoritePort-->>DashBoardService: List<Favorite>
DashBoardService->>EstatePort: loadEstatesByCodes(kaptCodes)
EstatePort-->>DashBoardService: List<Estate>
DashBoardService-->>User: List<Estate>
sequenceDiagram
participant User
participant DashBoardService
participant UserPort
participant EstateOwnerShipPort
participant EstatePricePort
User->>DashBoardService: getMyEstatePrices(userId)
DashBoardService->>UserPort: checkExistingById(userId)
UserPort-->>DashBoardService: OK/Exception
DashBoardService->>EstateOwnerShipPort: loadMyOwnerships(userId)
EstateOwnerShipPort-->>DashBoardService: List<EstateOwnership>
DashBoardService->>EstatePricePort: loadEstatePricesByCodes(kaptCodes)
EstatePricePort-->>DashBoardService: List<EstatePrice>
DashBoardService-->>User: List<EstatePrice>
Suggested labels
Suggested reviewers
Poem
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. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Test Coverage Report
|
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: 7
🧹 Nitpick comments (2)
src/main/java/com/zipte/platform/server/application/out/estateOwnership/EstateOwnerShipPort.java (1)
5-5: 구체적인 import 사용을 권장합니다.와일드카드 import(
import java.util.*) 대신 필요한 클래스만 구체적으로 import하는 것이 좋습니다.다음과 같이 수정하세요:
-import java.util.*; +import java.util.List;src/main/java/com/zipte/platform/server/application/service/DashBoardService.java (1)
48-97: 코드 중복을 줄이기 위한 리팩토링을 제안합니다.사용자 검증 로직이 모든 메서드에서 반복되고 있습니다. 공통 메서드로 추출하는 것을 고려해보세요.
private void validateUser(Long userId) { if (!userPort.checkExistingById(userId)) { throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); } }그리고 각 메서드에서:
validateUser(userId);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/main/java/com/zipte/platform/server/adapter/out/EstateOwnerShipAdapter.java(2 hunks)src/main/java/com/zipte/platform/server/adapter/out/FavoritePersistenceAdapter.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/out/jpa/estateOwnership/EstateOwnershipJpaRepository.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/out/jpa/favorite/FavoriteJpaRepository.java(1 hunks)src/main/java/com/zipte/platform/server/application/in/dashboard/DashBoardUseCase.java(1 hunks)src/main/java/com/zipte/platform/server/application/out/estateOwnership/EstateOwnerShipPort.java(2 hunks)src/main/java/com/zipte/platform/server/application/out/favorite/FavoritePort.java(1 hunks)src/main/java/com/zipte/platform/server/application/service/DashBoardService.java(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: test
🔇 Additional comments (10)
src/main/java/com/zipte/platform/server/adapter/out/jpa/favorite/FavoriteJpaRepository.java (1)
18-18: 메서드 추가가 적절합니다.기존 페이지네이션된 메서드와 일관성 있는 명명 규칙을 따르며, 대시보드 기능에서 사용자의 모든 즐겨찾기를 조회하는 용도로 적합합니다.
src/main/java/com/zipte/platform/server/application/out/estateOwnership/EstateOwnerShipPort.java (1)
20-21: 대시보드 기능을 위한 메서드 추가가 적절합니다.메서드 이름과 시그니처가 명확하고, 한국어 주석으로 목적이 잘 설명되어 있습니다.
src/main/java/com/zipte/platform/server/adapter/out/EstateOwnerShipAdapter.java (1)
38-44:Details
❓ Verification inconclusive
메서드 구현이 올바릅니다.
스트림 연산과 메서드 참조를 사용한 깔끔한 구현입니다. 다만
.toList()메서드는 Java 16+ 기능이므로 프로젝트의 Java 버전 호환성을 확인해 주세요.
🏁 Script executed:
#!/bin/bash # Java 버전 호환성 확인 echo "Checking Java version compatibility for .toList() method usage" fd -e java -e gradle | xargs grep -l "sourceCompatibility\|targetCompatibility\|java.version" | head -5Length of output: 240
빌드 설정 파일(pom.xml, build.gradle, gradle.properties 등)에서 Java 버전 호환성 정보를 검색하기 위해 아래 스크립트를 실행해 주세요.
🏁 Script executed:
#!/bin/bash echo "Searching for Java compatibility settings in build files" rg -n 'sourceCompatibility|targetCompatibility|java\.version|<java.version>|<maven.compiler.source>|<maven.compiler.target>' .Length of output: 251
Java 16+ 기능인 Stream#toList() 사용 시 호환성 검증 필요
EstateOwnerShipAdapter.loadMyOwnerships메서드가 Stream#toList()를 사용하므로 Java 16 이상 환경에서만 정상 작동합니다. 빌드 설정(pom.xml, build.gradle, gradle.properties 등)에 Java 버전(예: sourceCompatibility, targetCompatibility,<java.version>, Maven Compiler Plugin 설정)이 16 이상으로 지정되어 있는지 확인해 주세요.
- 파일: src/main/java/com/zipte/platform/server/adapter/out/EstateOwnerShipAdapter.java
- 코드 위치:
return repository.findByUserId(userId).stream() .map(EstateOwnershipJpaEntity::toDomain) .toList();위 설정이 명시되어 있지 않을 경우,
.toList()대신collect(Collectors.toList())사용을 고려하거나 빌드 설정을 상위 Java 버전으로 변경해 주세요.src/main/java/com/zipte/platform/server/adapter/out/jpa/estateOwnership/EstateOwnershipJpaRepository.java (1)
13-13: 표준적인 Spring Data JPA 메서드 추가입니다.메서드 명명 규칙이 Spring Data JPA 규약을 따르며, 사용자 ID로 소유권 목록을 조회하는 기능이 명확합니다.
src/main/java/com/zipte/platform/server/adapter/out/FavoritePersistenceAdapter.java (1)
58-63: 코드 변경사항이 적절합니다.페이지네이션 없이 즐겨찾기를 조회하는 새로운 메서드가 올바르게 구현되었습니다. 기존 패턴을 일관성 있게 따르고 있으며 스트림 API를 활용한 매핑도 적절합니다.
src/main/java/com/zipte/platform/server/application/out/favorite/FavoritePort.java (1)
30-30: 인터페이스 메서드 추가가 적절합니다.대시보드 기능을 위한 비페이지네이션 조회 메서드가 올바르게 정의되었습니다.
src/main/java/com/zipte/platform/server/application/in/dashboard/DashBoardUseCase.java (3)
3-9: 적절한 도메인 임포트입니다.대시보드 기능에 필요한 도메인 객체들이 적절히 임포트되었습니다.
12-17: 기능 설명 주석이 유용합니다.각 대시보드 기능에 대한 한국어 설명이 잘 작성되어 있어 코드 이해에 도움이 됩니다.
21-39: 인터페이스 메서드 정의가 적절합니다.대시보드 기능을 위한 각 메서드가 명확하게 정의되어 있으며, 반환 타입도 적절합니다.
src/main/java/com/zipte/platform/server/application/service/DashBoardService.java (1)
139-143: 스트림 API 사용이 적절합니다.flatMap을 활용한 가격 정보 조회 로직이 잘 구현되어 있습니다.
src/main/java/com/zipte/platform/server/application/service/DashBoardService.java
Outdated
Show resolved
Hide resolved
src/main/java/com/zipte/platform/server/application/service/DashBoardService.java
Outdated
Show resolved
Hide resolved
src/main/java/com/zipte/platform/server/application/service/DashBoardService.java
Outdated
Show resolved
Hide resolved
src/main/java/com/zipte/platform/server/application/service/DashBoardService.java
Outdated
Show resolved
Hide resolved
src/main/java/com/zipte/platform/server/application/service/DashBoardService.java
Outdated
Show resolved
Hide resolved
src/main/java/com/zipte/platform/server/application/service/DashBoardService.java
Outdated
Show resolved
Hide resolved
src/main/java/com/zipte/platform/server/application/service/DashBoardService.java
Show resolved
Hide resolved
- 한번에 조회
- API 및 어댑터 구현
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: 3
🧹 Nitpick comments (12)
src/main/java/com/zipte/platform/server/application/out/region/RegionPricePort.java (2)
5-5: 구체적인 import를 사용해주세요.와일드카드 import(
java.util.*) 대신 필요한 클래스만 명시적으로 import하는 것이 좋습니다.-import java.util.*; +import java.util.List; +import java.util.Optional;
20-20: 메서드에 주석을 추가해주세요.다른 메서드들과 일관성을 위해 한국어 주석을 추가해주세요.
+ /// 다중 코드 기반 조회 List<RegionPrice> loadRegionPriceByCodes(List<String> regionCodes);src/main/java/com/zipte/platform/server/adapter/out/EstatePersistenceAdapter.java (1)
58-58: null 안전성을 고려해주세요.매개변수 유효성 검증을 추가하는 것을 고려해보세요.
@Override public List<Estate> loadEstatesByCodes(List<String> kaptCodes) { + if (kaptCodes == null || kaptCodes.isEmpty()) { + return List.of(); + } return repository.findByKaptCodeIn(kaptCodes).stream() .map(EstateDocument::toDomain) .toList(); }src/main/java/com/zipte/platform/server/adapter/out/RegionPersistenceAdapter.java (1)
45-50: 입력 파라미터 검증 추가를 고려해보세요.메서드 구현이 깔끔하고 기존 패턴과 일관성이 있습니다. 하지만 입력 파라미터에 대한 검증이 없어서 null이나 빈 리스트가 전달될 경우를 고려해볼 필요가 있습니다.
다음과 같은 방식으로 검증을 추가할 수 있습니다:
@Override public List<Region> loadRegionsByCodes(List<String> codes) { + if (codes == null || codes.isEmpty()) { + return List.of(); + } return repository.findByCodeIn(codes).stream() .map(RegionJpaEntity::toDomain) .toList(); }src/main/java/com/zipte/platform/server/adapter/out/EstatePricePersistenceAdapter.java (1)
37-42: 입력 파라미터 검증 추가를 고려해보세요.구현이 명확하고 기존 코드와 일관성이 있습니다. 다른 persistence adapter와 마찬가지로 입력 파라미터 검증을 추가하면 더욱 견고한 코드가 될 것입니다.
다음과 같은 방식으로 검증을 추가할 수 있습니다:
@Override public List<EstatePrice> loadEstatePricesByCodes(List<String> kaptCodes) { + if (kaptCodes == null || kaptCodes.isEmpty()) { + return List.of(); + } return repository.findByKaptCodeIn(kaptCodes).stream() .map(EstatePriceDocument::toDomain) .toList(); }src/main/java/com/zipte/platform/server/adapter/out/RegionPricePersistenceAdapter.java (1)
54-59: 입력 파라미터 검증 추가를 고려해보세요.메서드 구현이 다른 persistence adapter들과 일관성 있게 구현되었습니다. 마찬가지로 입력 파라미터 검증을 추가하면 더 안전한 코드가 될 것입니다.
다음과 같은 방식으로 검증을 추가할 수 있습니다:
@Override public List<RegionPrice> loadRegionPriceByCodes(List<String> regionCodes) { + if (regionCodes == null || regionCodes.isEmpty()) { + return List.of(); + } return repository.findByRegionCodeIn(regionCodes).stream() .map(RegionPriceJpaEntity::toDomain) .toList(); }src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/EstateDetailResponse.java (2)
7-7: Wildcard import 대신 명시적 import 사용을 권장합니다.
java.util.*대신 필요한 클래스만 명시적으로 import하는 것이 좋습니다.다음과 같이 수정할 수 있습니다:
-import java.util.*; +import java.util.List;
40-45: 깔끔한 구현입니다. 입력 검증 추가를 고려해보세요.기존
from(Estate)메서드를 재사용하는 깔끔한 구현입니다. 다만 입력 파라미터에 대한 검증을 추가하면 더욱 견고한 코드가 될 것입니다.입력 검증을 추가할 수 있습니다:
public static List<EstateDetailResponse> from(List<Estate> estates) { + if (estates == null || estates.isEmpty()) { + return List.of(); + } return estates.stream() .map(EstateDetailResponse::from) .toList(); }src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionPriceJpaRepository.java (1)
5-5: 특정 import 사용을 권장합니다.
java.util.*와일드카드 import 대신 필요한 클래스만 명시적으로 import하는 것이 좋습니다.-import java.util.*; +import java.util.List; +import java.util.Optional;src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/RegionPriceResponse.java (1)
6-6: 특정 import 사용을 권장합니다.일관성을 위해 와일드카드 import 대신 필요한 클래스만 명시적으로 import해주세요.
-import java.util.*; +import java.util.List;src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java (2)
29-29: 주석을 업데이트해주세요."유저 아이디 추출하기 -> AOP로 한번에 처리하기?" 주석이 여러 곳에 반복되고 있습니다. 실제 구현과 일치하도록 주석을 정리하거나 TODO로 변경하는 것이 좋겠습니다.
- /// 유저 아이디 추출하기 -> AOP로 한번에 처리하기? + // TODO: AOP를 활용하여 사용자 ID 추출 로직 공통화Also applies to: 42-42, 56-56, 69-69, 83-83
80-93: 메서드명과 변수명의 일관성을 확인해주세요.
getMyHomeEstate메서드에서myEstatePrices변수를 사용하고 있는데, 메서드명에는 "Estate"가 있지만 실제로는 EstatePrice를 반환합니다. 네이밍의 일관성을 검토해보세요.메서드명을
getMyHomePrices또는 변수명을myHomePrices로 통일하는 것을 고려해보세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/EstateDetailResponse.java(2 hunks)src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/RegionPriceResponse.java(2 hunks)src/main/java/com/zipte/platform/server/adapter/out/EstatePersistenceAdapter.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/out/EstatePricePersistenceAdapter.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/out/RegionPersistenceAdapter.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/out/RegionPricePersistenceAdapter.java(2 hunks)src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionJpaRepository.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionPriceJpaRepository.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstateMongoRepository.java(1 hunks)src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstatePriceMongoRepository.java(1 hunks)src/main/java/com/zipte/platform/server/application/out/estate/EstatePricePort.java(1 hunks)src/main/java/com/zipte/platform/server/application/out/estate/LoadEstatePort.java(1 hunks)src/main/java/com/zipte/platform/server/application/out/region/RegionPort.java(1 hunks)src/main/java/com/zipte/platform/server/application/out/region/RegionPricePort.java(2 hunks)src/main/java/com/zipte/platform/server/application/service/DashBoardService.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/java/com/zipte/platform/server/application/service/DashBoardService.java
🔇 Additional comments (10)
src/main/java/com/zipte/platform/server/application/out/estate/LoadEstatePort.java (1)
26-26: 배치 로딩 메서드가 잘 구현되었습니다.
loadEstatesByCodes메서드가 기존 메서드들과 일관된 네이밍 컨벤션을 따르고 있으며, 대시보드 기능에서 여러 부동산을 효율적으로 조회할 수 있도록 설계되었습니다.src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionJpaRepository.java (1)
19-19: Spring Data JPA 컨벤션을 올바르게 따른 배치 조회 메서드입니다.
findByCodeIn메서드는 Spring Data JPA의 네이밍 컨벤션을 정확히 따르고 있으며, 여러 지역 코드를 한 번에 조회할 수 있는 효율적인 IN 쿼리를 자동 생성합니다.src/main/java/com/zipte/platform/server/application/out/region/RegionPort.java (1)
19-20: 문서화가 잘 된 배치 로딩 메서드입니다.
loadRegionsByCodes메서드는 명확한 주석과 함께 기존 메서드들과 일관된 네이밍 패턴을 따르고 있으며, 여러 지역을 효율적으로 조회할 수 있도록 설계되었습니다.src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstateMongoRepository.java (1)
32-33: MongoDB 배치 조회 메서드가 올바르게 구현되었습니다.
findByKaptCodeIn메서드는 Spring Data MongoDB의 네이밍 컨벤션을 따르고 있으며, 명확한 문서화와 함께 여러 부동산 코드를 효율적으로 조회할 수 있도록 구현되었습니다.src/main/java/com/zipte/platform/server/adapter/out/EstatePersistenceAdapter.java (1)
57-62: 구현이 기존 패턴과 일관되어 좋습니다.메서드 구현이 기존 메서드들과 동일한 패턴을 따르고 있어 일관성이 좋습니다. Stream API 사용도 적절합니다.
src/main/java/com/zipte/platform/server/adapter/out/RegionPricePersistenceAdapter.java (1)
10-10: Import 추가가 적절합니다.새로운 배치 로딩 메서드를 위해 필요한 import가 정확하게 추가되었습니다.
src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionPriceJpaRepository.java (1)
11-12: 배치 조회 메서드 구현이 적절합니다.여러 지역 코드에 대한 배치 조회 기능이 올바르게 구현되었습니다. 이는 N+1 쿼리 문제를 방지하고 성능을 향상시킬 수 있습니다.
src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/RegionPriceResponse.java (2)
40-44: 배치 변환 메서드가 잘 구현되었습니다.List를 List로 변환하는 유틸리티 메서드가 적절하게 추가되었습니다.
50-61: 가격 포맷팅 로직이 크게 개선되었습니다.한국 통화 표기법에 맞게 "억", "만원" 단위로 가격을 포맷하는 로직이 잘 구현되었습니다. 억 단위와 나머지를 분리하여 적절하게 표시하고 있습니다.
src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java (1)
19-97: 대시보드 API 구현이 전반적으로 잘 되었습니다.REST API 설계 원칙을 잘 따르고 있으며, 도메인 객체를 DTO로 변환하는 패턴도 일관성 있게 적용되었습니다. Spring Security를 활용한 인증 처리도 적절합니다.
| /// 외부 의존성 | ||
| List<EstatePrice> loadEstatePricesByCodes(List<String> kaptCodes); |
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.
🛠️ Refactor suggestion
주석을 더 명확하게 수정해주세요.
"외부 의존성"이라는 주석이 메서드의 목적을 명확히 설명하지 못합니다. 다중 코드를 이용한 배치 조회라는 목적을 반영하여 주석을 개선해주세요.
- /// 외부 의존성
+ /// 다중 코드 기반 배치 조회하기
List<EstatePrice> loadEstatePricesByCodes(List<String> kaptCodes);또한 메서드 문서화에서 다음 사항들을 명시하는 것을 고려해보세요:
- 빈 리스트 전달시 동작
- null 매개변수 처리 방식
- 존재하지 않는 코드에 대한 처리
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /// 외부 의존성 | |
| List<EstatePrice> loadEstatePricesByCodes(List<String> kaptCodes); | |
| /// 다중 코드 기반 배치 조회하기 | |
| List<EstatePrice> loadEstatePricesByCodes(List<String> kaptCodes); |
🤖 Prompt for AI Agents
In
src/main/java/com/zipte/platform/server/application/out/estate/EstatePricePort.java
around lines 18 to 19, replace the vague comment "외부 의존성" with a clear
description that this method performs batch retrieval of estate prices by
multiple kapt codes. Additionally, add JavaDoc to the method specifying how it
handles an empty list input, null parameters, and cases where some codes do not
exist, clarifying expected behavior in these scenarios.
|
|
||
| List<EstatePriceDocument> findALlByKaptCodeAndExclusiveArea(String kaptCode, double exclusiveArea); | ||
|
|
||
| List<EstatePriceDocument> findByKaptCodeIn(List<String> kaptCodes); |
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.
💡 Verification agent
🧩 Analysis chain
대용량 리스트 처리시 성능을 고려해주세요.
findByKaptCodeIn 메서드는 MongoDB의 $in 연산자를 사용하게 됩니다. 매개변수 리스트가 클 경우 성능 이슈가 발생할 수 있습니다.
다음 사항들을 검토해주세요:
- kaptCodes 리스트의 최대 크기 제한 설정
- 필요시 청크 단위로 분할 처리하는 로직 구현 고려
- 인덱스가 kaptCode 필드에 적절히 설정되어 있는지 확인
대용량 배치 조회의 성능을 검증하기 위해 다음 스크립트를 실행해보세요:
🏁 Script executed:
#!/bin/bash
# MongoDB에서 kaptCode 필드의 인덱스 확인
rg -A 5 -B 5 "kaptCode.*index" --type javaLength of output: 44
인덱스 설정 여부를 재확인하기 위해 아래 스크립트를 실행해주세요:
🏁 Script executed:
#!/bin/bash
# EstatePriceDocument 클래스 전체 내용 확인
rg "class EstatePriceDocument" -A50 --type java
# kaptCode 필드에 @Indexed 어노테이션이 붙었는지 확인
rg "@Indexed.*kaptCode" -A3 --type java
# 복합 인덱스(@CompoundIndex) 설정 여부 확인
rg "@CompoundIndex" -A5 --type javaLength of output: 6066
kaptCode 필드에 인덱스 설정 및 대용량 조회 처리 방안 마련 필요
findByKaptCodeIn 메서드는 MongoDB의 $in 연산자를 사용하므로, kaptCode 필드에 인덱스가 없으면 대용량 조회 시 심각한 성능 저하가 발생할 수 있습니다. 또한, 한 번에 전달되는 목록 크기가 크면 메모리 및 네트워크 부하가 커질 수 있습니다.
다음 사항을 반드시 검토 및 반영해주세요:
- EstatePriceDocument 클래스의
kaptCode필드에@Indexed어노테이션 추가 - 필요 시
@CompoundIndex를 통해 복합 인덱스 설정 kaptCodes리스트에 크기 제한을 두거나, 일정 단위(예: 500개)로 청크 분할 처리 로직 구현- 인덱스 적용 후 MongoDB 셸(
db.estate_price.getIndexes()) 또는 GUI 도구로 실제 인덱스 생성 여부 확인 - 적용 전·후 벤치마크를 통해 조회 성능 개선 효과 검증
🤖 Prompt for AI Agents
In
src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstatePriceMongoRepository.java
at line 13, the findByKaptCodeIn method uses MongoDB's $in operator which can
cause performance issues with large kaptCodes lists. To fix this, ensure the
kaptCode field in EstatePriceDocument class has the @Indexed annotation or a
suitable @CompoundIndex for efficient querying. Implement logic to limit the
size of kaptCodes or split it into chunks (e.g., 500 items each) before querying
to reduce memory and network load. After applying these changes, verify index
creation in MongoDB and benchmark query performance before and after.
| public ApiResponse<List<RegionResponse>> getMyRegion(@AuthenticationPrincipal PrincipalDetails principalDetails) { | ||
|
|
||
| /// 유저 아이디 추출하기 -> AOP로 한번에 처리하기? | ||
| Long userId = principalDetails.getId(); | ||
|
|
||
| List<Region> region = dashboardService.getFavoriteRegion(userId); | ||
|
|
||
| List<RegionResponse> responses = RegionResponse.from(region); | ||
| return ApiResponse.ok(responses); | ||
| } |
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.
🛠️ Refactor suggestion
사용자 ID 추출 로직의 중복을 개선해주세요.
모든 엔드포인트에서 동일한 사용자 ID 추출 로직이 반복되고 있습니다. AOP나 베이스 컨트롤러를 활용하여 중복을 제거하는 것을 고려해보세요.
AOP를 활용한 예시:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtractUserId {
}
@Aspect
@Component
public class UserIdExtractionAspect {
@Around("@annotation(ExtractUserId)")
public Object extractUserId(ProceedingJoinPoint joinPoint) throws Throwable {
// PrincipalDetails에서 userId 추출하여 메서드 파라미터로 전달
}
}🤖 Prompt for AI Agents
In src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java
around lines 27 to 36, the user ID extraction from PrincipalDetails is
duplicated across endpoints. Refactor by creating a custom annotation and an AOP
aspect that intercepts methods annotated with it, extracts the user ID from
PrincipalDetails, and injects it as a method parameter. Then update the
controller methods to use this annotation and accept the user ID directly,
removing the manual extraction code.
- happy 테스트 위주로 작성
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: 3
🧹 Nitpick comments (6)
src/test/java/com/zipte/platform/server/domain/estate/EstatePriceFixtures.java (1)
3-18: 테스트 픽스처 클래스 구조 개선 제안현재 구현은 기능적으로 올바르지만 다음과 같이 개선할 수 있습니다:
- 클래스를 final로 선언하고 private 생성자 추가
- 불필요한 빈 줄 제거
- JavaDoc 주석 추가 권장
+/** + * EstatePrice 도메인 객체를 위한 테스트 픽스처 클래스 + */ -public class EstatePriceFixtures { +public final class EstatePriceFixtures { - + private EstatePriceFixtures() { + // 유틸리티 클래스는 인스턴스화 방지 + } public static EstatePrice stub(String kaptCode) { - return EstatePrice.builder() .id("id") .kaptCode(kaptCode) .kaptName("kaptName") .exclusiveArea(0.0) .floor(1) .price("1000000") .build(); } - }src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java (1)
78-89: 변수명 일관성 개선 제안테스트 코드에서 한글 변수명과 영문 변수명이 혼재되어 있습니다. 일관성을 위해 영문 변수명 사용을 권장합니다.
- Favorite 테스트_지역1 = FavoriteFixtures.regionFavorite(userId, "분당구"); - Favorite 테스트_지역2 = FavoriteFixtures.regionFavorite(userId, "종로구"); - List<Favorite> favoriteList = List.of(테스트_지역1, 테스트_지역2); + Favorite favorite1 = FavoriteFixtures.regionFavorite(userId, "분당구"); + Favorite favorite2 = FavoriteFixtures.regionFavorite(userId, "종로구"); + List<Favorite> favoriteList = List.of(favorite1, favorite2); - List<String> codes = List.of(테스트_지역1.getRegionCode(), 테스트_지역2.getRegionCode()); + List<String> codes = List.of(favorite1.getRegionCode(), favorite2.getRegionCode()); - Region 분당구 = RegionFixtures.분당구(); - Region 종로구 = RegionFixtures.종로구(); - List<Region> regionList = List.of(분당구, 종로구); + Region bundanggu = RegionFixtures.분당구(); + Region jongnogu = RegionFixtures.종로구(); + List<Region> regionList = List.of(bundanggu, jongnogu);src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java (4)
48-54: ObjectMapper 초기화 최적화 제안ObjectMapper가 매 테스트마다 재생성되고 있습니다. 성능상 개선이 가능합니다.
- private ObjectMapper objectMapper; + private static final ObjectMapper objectMapper = new ObjectMapper() + .registerModule(new JavaTimeModule()); - @BeforeEach - void setUp() { - this.objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - }
61-64: 테스트 설명 구체화 필요DisplayName이 너무 간략하여 테스트 목적을 명확히 알기 어렵습니다.
@Test @WithMockCustomUser - @DisplayName("[happy] 지역관련") + @DisplayName("[happy] 사용자의 관심 지역 목록 조회 성공") void happy_region() throws Exception {
141-142: 변수명 일관성 개선 제안다른 테스트와의 일관성을 위해 영문 변수명 사용을 권장합니다.
- Estate 테스트1 = EstateFixtures.stub("테스트1"); - Estate 테스트2 = EstateFixtures.stub("테스트2"); + Estate estate1 = EstateFixtures.stub("테스트1"); + Estate estate2 = EstateFixtures.stub("테스트2"); - List<Estate> estates = List.of(테스트1, 테스트2); + List<Estate> estates = List.of(estate1, estate2);
67-67: 사용자 ID 상수화 제안테스트 전반에서 사용되는 사용자 ID를 상수로 정의하여 유지보수성을 높이는 것을 권장합니다.
class DashBoardApiTest { + private static final Long TEST_USER_ID = 1L; + @Autowired private MockMvc mockMvc;그리고 각 테스트에서:
- Long userId = 1L; + Long userId = TEST_USER_ID;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java(1 hunks)src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java(1 hunks)src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java(1 hunks)src/test/java/com/zipte/platform/server/domain/estate/EstateFixtures.java(1 hunks)src/test/java/com/zipte/platform/server/domain/estate/EstatePriceFixtures.java(1 hunks)src/test/java/com/zipte/platform/server/domain/region/RegionPriceFixtures.java(1 hunks)src/test/java/com/zipte/platform/server/domain/review/EstateFixtures.java(0 hunks)
💤 Files with no reviewable changes (1)
- src/test/java/com/zipte/platform/server/domain/review/EstateFixtures.java
✅ Files skipped from review due to trivial changes (2)
- src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java
- src/test/java/com/zipte/platform/server/domain/region/RegionPriceFixtures.java
| public class EstateFixtures { | ||
|
|
||
| public static Estate stub() { | ||
|
|
||
| Location location = Location.builder() | ||
| .type("Point") | ||
| .coordinates(Arrays.asList( | ||
| 127.1280, // 경도 | ||
| 37.4116) // 위도 | ||
| ) | ||
| .build(); | ||
|
|
||
| return Estate.builder() | ||
| .kaptCode("kaptCode") | ||
| .location(location) | ||
| .build(); | ||
| } | ||
|
|
||
| public static Estate stub(String kaptCode) { | ||
|
|
||
| Location location = Location.builder() | ||
| .type("Point") | ||
| .coordinates(Arrays.asList( | ||
| 127.1280, // 경도 | ||
| 37.4116) // 위도 | ||
| ) | ||
| .build(); | ||
|
|
||
| return Estate.builder() | ||
| .kaptCode(kaptCode) | ||
| .location(location) | ||
| .build(); | ||
| } | ||
|
|
||
|
|
||
|
|
||
| } |
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.
🛠️ Refactor suggestion
코드 중복 제거 및 클래스 구조 개선 필요
현재 구현에서 Location 생성 로직이 중복되고 있습니다. 다음과 같이 리팩토링을 권장합니다:
+/**
+ * Estate 도메인 객체를 위한 테스트 픽스처 클래스
+ */
-public class EstateFixtures {
+public final class EstateFixtures {
+
+ // 테스트용 고정 좌표 (강남구 일대)
+ private static final double LONGITUDE = 127.1280;
+ private static final double LATITUDE = 37.4116;
+
+ private EstateFixtures() {
+ // 유틸리티 클래스는 인스턴스화 방지
+ }
public static Estate stub() {
-
- Location location = Location.builder()
- .type("Point")
- .coordinates(Arrays.asList(
- 127.1280, // 경도
- 37.4116) // 위도
- )
- .build();
-
- return Estate.builder()
- .kaptCode("kaptCode")
- .location(location)
- .build();
+ return stub("kaptCode");
}
public static Estate stub(String kaptCode) {
-
- Location location = Location.builder()
- .type("Point")
- .coordinates(Arrays.asList(
- 127.1280, // 경도
- 37.4116) // 위도
- )
- .build();
-
return Estate.builder()
.kaptCode(kaptCode)
- .location(location)
+ .location(createDefaultLocation())
.build();
}
-
-
+ private static Location createDefaultLocation() {
+ return Location.builder()
+ .type("Point")
+ .coordinates(Arrays.asList(LONGITUDE, LATITUDE))
+ .build();
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public class EstateFixtures { | |
| public static Estate stub() { | |
| Location location = Location.builder() | |
| .type("Point") | |
| .coordinates(Arrays.asList( | |
| 127.1280, // 경도 | |
| 37.4116) // 위도 | |
| ) | |
| .build(); | |
| return Estate.builder() | |
| .kaptCode("kaptCode") | |
| .location(location) | |
| .build(); | |
| } | |
| public static Estate stub(String kaptCode) { | |
| Location location = Location.builder() | |
| .type("Point") | |
| .coordinates(Arrays.asList( | |
| 127.1280, // 경도 | |
| 37.4116) // 위도 | |
| ) | |
| .build(); | |
| return Estate.builder() | |
| .kaptCode(kaptCode) | |
| .location(location) | |
| .build(); | |
| } | |
| } | |
| /** | |
| * Estate 도메인 객체를 위한 테스트 픽스처 클래스 | |
| */ | |
| public final class EstateFixtures { | |
| // 테스트용 고정 좌표 (강남구 일대) | |
| private static final double LONGITUDE = 127.1280; | |
| private static final double LATITUDE = 37.4116; | |
| private EstateFixtures() { | |
| // 유틸리티 클래스는 인스턴스화 방지 | |
| } | |
| public static Estate stub() { | |
| return stub("kaptCode"); | |
| } | |
| public static Estate stub(String kaptCode) { | |
| return Estate.builder() | |
| .kaptCode(kaptCode) | |
| .location(createDefaultLocation()) | |
| .build(); | |
| } | |
| private static Location createDefaultLocation() { | |
| return Location.builder() | |
| .type("Point") | |
| .coordinates(Arrays.asList(LONGITUDE, LATITUDE)) | |
| .build(); | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/test/java/com/zipte/platform/server/domain/estate/EstateFixtures.java
between lines 5 and 41, the Location creation code is duplicated in both stub
methods. Refactor by extracting the Location building logic into a private
static helper method that returns the Location instance, then call this method
from both stub methods to eliminate redundancy and improve class structure.
src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java
Show resolved
Hide resolved
| @Test | ||
| @DisplayName("[happy] 나의 관심 지역 가격을 조회합니다.") | ||
| void getRegionPrice_happy() { | ||
|
|
||
| // Given | ||
| Long userId = 1L; | ||
|
|
||
| given(userPort.checkExistingById(userId)) | ||
| .willReturn(true); | ||
|
|
||
| Favorite 테스트_지역1 = FavoriteFixtures.regionFavorite(userId, "분당구"); | ||
| Favorite 테스트_지역2 = FavoriteFixtures.regionFavorite(userId, "종로구"); | ||
| List<Favorite> favoriteList = List.of(테스트_지역1, 테스트_지역2); | ||
|
|
||
| given(favoritePort.loadUserFavoriteByType(userId, FavoriteType.REGION)) | ||
| .willReturn(favoriteList); | ||
|
|
||
| List<String> codes = List.of(테스트_지역1.getRegionCode(), 테스트_지역2.getRegionCode()); | ||
|
|
||
| Region 분당구 = RegionFixtures.분당구(); | ||
| Region 종로구 = RegionFixtures.종로구(); | ||
| List<Region> regionList = List.of(분당구, 종로구); | ||
|
|
||
| given(regionPort.loadRegionsByCodes(codes)) | ||
| .willReturn(regionList); | ||
|
|
||
| // When | ||
| List<Region> response = sut.getFavoriteRegion(userId); | ||
|
|
||
| // Then | ||
| then(response) | ||
| .isNotNull() | ||
| .hasSize(2) | ||
| .containsExactlyInAnyOrder(분당구, 종로구); | ||
| } |
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.
잘못된 테스트 메서드 로직 수정 필요
getRegionPrice_happy() 테스트 메서드가 실제로는 getFavoriteRegion() 메서드를 호출하고 있어 테스트 목적과 맞지 않습니다.
@Test
@DisplayName("[happy] 나의 관심 지역 가격을 조회합니다.")
void getRegionPrice_happy() {
-
// Given
Long userId = 1L;
given(userPort.checkExistingById(userId))
.willReturn(true);
- Favorite 테스트_지역1 = FavoriteFixtures.regionFavorite(userId, "분당구");
- Favorite 테스트_지역2 = FavoriteFixtures.regionFavorite(userId, "종로구");
- List<Favorite> favoriteList = List.of(테스트_지역1, 테스트_지역2);
-
- given(favoritePort.loadUserFavoriteByType(userId, FavoriteType.REGION))
- .willReturn(favoriteList);
-
- List<String> codes = List.of(테스트_지역1.getRegionCode(), 테스트_지역2.getRegionCode());
-
- Region 분당구 = RegionFixtures.분당구();
- Region 종로구 = RegionFixtures.종로구();
- List<Region> regionList = List.of(분당구, 종로구);
-
- given(regionPort.loadRegionsByCodes(codes))
- .willReturn(regionList);
+ // RegionPrice 테스트 데이터 준비 필요
+ // getFavoriteRegionPrices() 메서드 호출로 변경 필요
// When
- List<Region> response = sut.getFavoriteRegion(userId);
+ // 올바른 메서드 호출로 변경 필요
// Then
- then(response)
- .isNotNull()
- .hasSize(2)
- .containsExactlyInAnyOrder(분당구, 종로구);
+ // RegionPrice 관련 검증으로 변경 필요
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java
between lines 105 and 139, the test method named getRegionPrice_happy()
incorrectly calls getFavoriteRegion() instead of getRegionPrice(), which does
not align with the test's intended purpose. To fix this, update the method call
inside the test from getFavoriteRegion(userId) to getRegionPrice(userId) so that
the test correctly verifies the behavior of the getRegionPrice() method.
Test Coverage Report
|
Test Coverage Report
|
Test Coverage Report
|
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: 0
🔭 Outside diff range comments (1)
.github/workflows/ci-test.yml (1)
115-126: 🛠️ Refactor suggestion테스트 커버리지 임계값 설정 검토 필요
madrapps/[email protected]액션을 사용해 커버리지 리포트를 게시 중이나,min-coverage-changed-files: 0및min-coverage-overall: 0으로 설정되어 실제 게이트 기능을 수행하지 않습니다. 의도에 맞는 최소 커버리지 기준으로 업데이트를 권장합니다.
🧹 Nitpick comments (1)
.github/workflows/ci-test.yml (1)
111-114: Build 단계에 디버깅·안정성 옵션 추가 제안
현재./gradlew clean build만 실행하고 있는데, CI 환경에서는--no-daemon,--stacktrace플래그를 추가하여 데몬 비사용과 에러 발생 시 상세 로그를 확보하면 안정성과 문제 분석이 용이해집니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/ci-test.yml(3 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ci-test.yml
79-79: the runner of "actions/cache@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🔇 Additional comments (2)
.github/workflows/ci-test.yml (2)
77-87: Gradle 캐시 설정으로 빌드 속도 최적화
actions/cache@v3를 활용해~/.gradle/caches와~/.gradle/wrapper디렉토리를 캐싱한 점이 탁월합니다. 이로 인해 반복적인 의존성 다운로드를 줄여 CI 실행 시간이 크게 단축될 것입니다.
[actionlint에서 지적한 “runner too old” 경고는 false positive이므로 무시해도 무방합니다.]🧰 Tools
🪛 actionlint (1.7.7)
79-79: the runner of "actions/cache@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
127-134: JUnit 테스트 결과 게시 구성 적절
EnricoMi/publish-unit-test-result-action@v2와if: always()설정으로 빌드 실패 시에도 테스트 리포트가 남도록 한 점이 훌륭합니다.
📌 작업한 내용
✨️ feat/ZIP-29 : 대시보드를 기능 구현
🔍 참고 사항
🖼️ 스크린샷
🔗 관련 이슈
✅ 체크리스트
Summary by CodeRabbit