-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 마이페이지 구현 #63
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
feat: 마이페이지 구현 #63
Conversation
Walkthrough사용자 기준 열린 앨범, 내가 만든 열린 앨범, 닫힌 앨범 조회 기능(서비스·컨트롤러·Swagger), 관련 DTO/매퍼/리포지토리 쿼리 추가 및 사용자 기본정보 조회 API 추가, presigned URL 관련 기능·DTO·매퍼 제거 및 여러 DTO의 OpenAPI 메타데이터 보강이 적용되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Controller as AlbumQueryController
participant Service as AlbumQueryService
participant Repo as UserAlbumRepository
participant PhotoRepo as PhotoRepository
participant Cheese4cutRepo as Cheese4cutPhotoRepository
participant Mapper as AlbumQueryMapper
participant CDN as CdnUrlResolver
User->>Controller: GET /v1/album/open?page&size
Controller->>Service: getOpenAlbums(user, page, size)
Service->>Repo: findOpenAlbumsByUserId(userId, ACTIVE, now, pageable)
Repo-->>Service: Slice<Album>
rect rgb(230,245,255)
note right of Service: 배치로 메이커·썸네일 수집
Service->>Service: getMakers(albumIds)
Service->>PhotoRepo: findTop3RecentPhotosInEachAlbum(albumIds, NORMAL)
PhotoRepo-->>Service: List<Photo>
Service->>Cheese4cutRepo: findAllCheese4cutPhotosByAlbumIds(albumIds)
Cheese4cutRepo-->>Service: List<Cheese4cutPhoto>
Service->>CDN: resolve thumbnail URLs
CDN-->>Service: thumbnails per album
end
Service->>Mapper: toOpenAlbumPageResponse(responses, slice)
Mapper-->>Service: OpenAlbumPageResponse
Service-->>Controller: OpenAlbumPageResponse
Controller-->>User: CommonResponse.success(...)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example:
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. 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.
Actionable comments posted: 3
🧹 Nitpick comments (4)
src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java (1)
11-41: 열린 앨범 요약 DTO 정의 적절합니다마이페이지에서 필요한 정보(이벤트 날짜, 메이커 이름, 참여자 수, 만료 예정 시각, 최근 썸네일 등)를 한 번에 담도록 잘 설계되어 있고, 스키마 설명/예시도 충분히 이해하기 좋습니다.
themeEmoji예시가"U+1F36F"포맷인데, 실제 응답이 이모지 코드포인트 문자열인지 실제 이모지 문자인지 한 번만 명세와 맞춰두시면 문서-실제 값 간 혼선을 줄일 수 있을 것 같습니다.src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java (1)
41-71: 썸네일 리스트의 null/빈 리스트 표현 방식 한 번 정리 제안여기서
thumbnails.isEmpty() ? null : thumbnails로 DTO에 세팅하고, DTO 쪽 리스트 필드에는@JsonInclude(ALWAYS)가 걸려있어서:
- 썸네일이 없을 때 → JSON에
"recentPhotoThumbnails": null/"thumbnails": null로 내려가고- 일부 서비스 주석에는 “3개 미만이면 아예 제공 안 함”이라고 되어 있어, “필드가 아예 없는 것”과는 의미가 조금 달라집니다.
클라이언트에서 다루기 쉽게 하려면:
- 항상 리스트(없으면
[])로 내려주거나,- 진짜 “아예 제공 안 함”을 의미하고 싶다면
null대신 빈 리스트를 유지하고 DTO의JsonInclude전략을NON_EMPTY등으로 조정하는 방법도 있습니다.현 구조가 명확히 합의된 스펙이라면 그대로 가셔도 되지만, FE/기획과 한 번만 정리해두시면 좋겠습니다.
src/main/java/com/cheeeese/album/application/AlbumQueryService.java (2)
46-118: 쿼리 수(N+1)와 메이커 조회 방식은 추후 확장 시 최적화 여지가 있습니다현재 구현은:
- 열린/내 열린 앨범:
findOpenAlbums...로 앨범 슬라이스 조회 후, 각 앨범마다getMaker(UserRepository 조회) +getRecentThumbnails(PhotoRepository 조회)를 수행하고,- 닫힌 앨범: Cheese4cutPhoto는
albumIds기반 한 번에 모아서 잘 처리하고 있지만, 메이커는 마찬가지로 앨범별로getMaker를 호출하는 구조입니다.기본 page size가 작아서 지금은 큰 문제는 없겠지만, 향후:
- 페이지 크기 증가나 반복 호출이 잦아질 경우 User 조회/Photo 조회에서 N+1 패턴으로 인한 레이턴시가 눈에 띌 수 있고,
- 메이커가 여러 앨범에서 동일 사용자일 때도 매번 같은 유저를 재조회하게 됩니다.
향후 성능 튜닝 여지가 생기면:
- 앨범들의 makerId를 모아서 한 번에
IN조회 후 Map으로 캐싱하거나,- User를 앨범 쿼리 단계에서 fetch join 해두는 전략도 고려해볼 만합니다. 지금 단계에서는 구조는 유지하되 개선 포인트로만 인지하고 계셔도 될 것 같습니다.
120-153: 최근 썸네일 노출 정책(3개 미만 시 비노출)에 대한 요구사항 재확인 제안
getRecentThumbnails에서:
RECENT_THUMBNAIL_COUNT = 3photos.size() < 3인 경우 빈 리스트를 반환하고,- Mapper에서 빈 리스트면
recentPhotoThumbnails를null로 세팅하는 구조라,
→ 사진이 1~2장만 있는 앨범은 마이페이지에서 썸네일이 전혀 보이지 않게 됩니다.이전 PR에서 공유해주신
PhotoService.getRecentThumbnailUrls는0장 → 빈 리스트, 1~4장 → 썸네일 1장, 5장 → 5장 노출
이라는 다른 정책을 의도적으로 사용하고 있었던 것으로 기억합니다. (Based on learnings)마이페이지는 UI가 달라서 “3장 이상일 때만 모자이크 썸네일을 보여준다”는 새로운 요구사항일 수도 있지만:
- 1~2장만 있는 열린 앨범도 썸네일 카드가 전혀 안 보이는 게 의도인지,
- 클라이언트에서
nullvs[]를 어떻게 취급하는지한 번 PM/FE와 정의를 맞춰보시면 좋겠습니다. 만약 “가능한 한 썸네일을 보여준다”가 공통 원칙이라면,
photos.size() < 3조건이나 반환 방식(예: 일부라도 노출, 빈 리스트 유지 등)을 조정해야 할 수 있습니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
src/main/java/com/cheeeese/album/application/AlbumQueryService.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/ClosedAlbumPageResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/OpenAlbumPageResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java(1 hunks)src/main/java/com/cheeeese/album/infrastructure/persistence/UserAlbumRepository.java(2 hunks)src/main/java/com/cheeeese/album/presentation/AlbumQueryController.java(1 hunks)src/main/java/com/cheeeese/album/presentation/swagger/AlbumQuerySwagger.java(1 hunks)src/main/java/com/cheeeese/cheese4cut/infrastructure/persistence/Cheese4cutPhotoRepository.java(1 hunks)src/main/java/com/cheeeese/global/common/code/SuccessCode.java(1 hunks)src/main/java/com/cheeeese/user/application/UserService.java(2 hunks)src/main/java/com/cheeeese/user/dto/response/UserInfoResponse.java(1 hunks)src/main/java/com/cheeeese/user/infrastructure/mapper/UserMapper.java(2 hunks)src/main/java/com/cheeeese/user/presentation/UserController.java(2 hunks)src/main/java/com/cheeeese/user/presentation/swagger/UserSwagger.java(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-13T12:56:22.154Z
Learnt from: dahyun24
Repo: Say-Cheeeese/BE PR: 58
File: src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java:149-156
Timestamp: 2025-11-13T12:56:22.154Z
Learning: In src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java, the finalizeCheese4cut method intentionally re-sorts photos using findAllByIdInOrderByLikesDescCreatedDesc(request.photoIds()) instead of preserving the client's requested order. This is a defensive measure to ensure photos are always ordered by likes (DESC) and creation time (DESC), regardless of what order the client sends, preventing incorrect ordering from client errors.
Applied to files:
src/main/java/com/cheeeese/cheese4cut/infrastructure/persistence/Cheese4cutPhotoRepository.javasrc/main/java/com/cheeeese/album/application/AlbumQueryService.java
📚 Learning: 2025-10-31T13:17:52.523Z
Learnt from: dahyun24
Repo: Say-Cheeeese/BE PR: 35
File: src/main/java/com/cheeeese/photo/application/PhotoService.java:46-52
Timestamp: 2025-10-31T13:17:52.523Z
Learning: In src/main/java/com/cheeeese/photo/application/PhotoService.java, the getRecentThumbnailUrls method intentionally returns only the first thumbnail URL when photos.size() < 5, rather than returning all available thumbnails. This is according to product requirements: 0 photos → empty list, 1-4 photos → single thumbnail (most recent), 5 photos → all 5 thumbnails.
Applied to files:
src/main/java/com/cheeeese/album/application/AlbumQueryService.java
🧬 Code graph analysis (2)
src/main/java/com/cheeeese/album/application/AlbumQueryService.java (1)
src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java (1)
AlbumQueryMapper(13-73)
src/main/java/com/cheeeese/user/application/UserService.java (2)
src/main/java/com/cheeeese/user/infrastructure/mapper/UserMapper.java (1)
UserMapper(7-27)src/main/java/com/cheeeese/photo/application/PhotoService.java (1)
Service(38-257)
🔇 Additional comments (17)
src/main/java/com/cheeeese/user/infrastructure/mapper/UserMapper.java (1)
18-26: LGTM!User 엔티티를 UserInfoResponse DTO로 변환하는 매퍼 메서드가 명확하고 올바르게 구현되었습니다.
src/main/java/com/cheeeese/user/presentation/swagger/UserSwagger.java (1)
18-28: LGTM!API 문서화가 명확하고 완전합니다. 사용자 정보 조회 엔드포인트에 대한 설명이 적절합니다.
src/main/java/com/cheeeese/album/infrastructure/persistence/UserAlbumRepository.java (2)
26-41: LGTM!열린 앨범 조회 쿼리가 올바르게 구현되었습니다. 필터링 조건과 정렬 기준이 적절합니다.
61-74: LGTM!닫힌 앨범 조회 쿼리가 올바르게 구현되었습니다. 필터링 조건과 정렬 기준(최신순)이 적절합니다.
src/main/java/com/cheeeese/user/application/UserService.java (1)
52-54: LGTM!사용자 정보 조회 메서드가 올바르게 구현되었습니다. 매퍼로의 단순한 위임 패턴이 적절합니다.
src/main/java/com/cheeeese/user/presentation/UserController.java (1)
24-28: LGTM!사용자 정보 조회 엔드포인트가 올바르게 구현되었습니다. REST 패턴과 기존 코드 스타일을 잘 따르고 있습니다.
src/main/java/com/cheeeese/album/dto/response/OpenAlbumPageResponse.java (1)
1-26: LGTM!열린 앨범 페이지 응답 DTO가 명확하게 정의되었습니다. 페이지네이션 메타데이터 필드가 적절하게 포함되어 있습니다.
src/main/java/com/cheeeese/cheese4cut/infrastructure/persistence/Cheese4cutPhotoRepository.java (1)
11-18: LGTM!치즈네컷 사진 조회 쿼리가 올바르게 구현되었습니다. JOIN FETCH를 사용하여 N+1 문제를 방지하고 있으며, 정렬 기준도 적절합니다.
src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java (1)
1-28: LGTM!닫힌 앨범 요약 응답 DTO가 명확하게 정의되었습니다.
@JsonInclude(ALWAYS)사용으로 thumbnails 필드가 항상 포함되도록 보장하고 있습니다.src/main/java/com/cheeeese/album/dto/response/ClosedAlbumPageResponse.java (1)
8-25: 페이지 응답 DTO 구조 일관성 좋습니다
responses + listSize + isFirst/isLast/hasNext구성으로 다른 페이지 DTO들과 잘 맞고, 스키마 설명도 명확해서 그대로 사용해도 무방해 보입니다.src/main/java/com/cheeeese/user/dto/response/UserInfoResponse.java (1)
6-23: 마이페이지 사용자 정보 DTO 정의 깔끔합니다필드 구성이 마이페이지 요약 카드에 필요한 정보(앨범/사진/좋아요 수)를 잘 담고 있고, 스키마 예시도 명확해서 바로 사용 가능해 보입니다.
src/main/java/com/cheeeese/global/common/code/SuccessCode.java (1)
20-27: 성공 코드 추가 컨벤션에 잘 맞습니다새로 추가된 네 가지 SuccessCode 모두 네이밍/메시지/HttpStatus 사용이 기존 코드와 일관적이라 그대로 두셔도 좋겠습니다.
src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java (1)
15-39: 페이지 메타데이터 매핑 로직 적절합니다
Slice에서 isFirst/isLast/hasNext를 그대로 끌어와서 DTO에 싱크 맞추는 구조가 직관적이고,listSize를 실제 응답 리스트 사이즈 기준으로 두신 것도 사용성 측면에서 좋습니다.src/main/java/com/cheeeese/album/presentation/swagger/AlbumQuerySwagger.java (1)
18-68: 마이페이지 앨범 조회 스웨거 정의 명확합니다엔드포인트 분리(
/open,/open/me,/closed)와 요약/설명, 페이지 파라미터 기본값이 잘 문서화되어 있어 FE 입장에서 사용하기 편해 보입니다. 정렬 기준(만료 임박 순, 생성일 최신 순)도 설명으로 명시해 두신 점 좋습니다.src/main/java/com/cheeeese/album/presentation/AlbumQueryController.java (3)
20-26: 컨트롤러 구조가 올바르게 구성되었습니다.Spring REST 컨트롤러의 표준 패턴을 잘 따르고 있으며, API 버저닝과 의존성 주입이 적절히 설정되어 있습니다.
40-51: 엔드포인트 구현이 적절합니다.사용자가 생성한 열린 앨범 조회 로직이 올바르게 구현되어 있으며, 적절한 서비스 메서드를 호출하고 있습니다. 페이지네이션 검증은 위에서 언급한 사항을 참고하세요.
58-58: 닫힌 앨범 페이지 크기는 의도적인 설계입니다.검증 결과, 닫힌 앨범의
size=6기본값은 다음과 같이 일관되게 적용되고 있습니다:
- 컨트롤러와 Swagger 문서에서 모두
size=6으로 설정- 열린 앨범의
size=2와는 의도적으로 다른 값- 다른 엔드포인트들(사진 조회 등)과도 서로 다른 기본값을 사용
UI 요구사항에 따른 의도적인 설계로 보이므로 추가 조치가 필요하지 않습니다.
src/main/java/com/cheeeese/album/infrastructure/persistence/UserAlbumRepository.java
Show resolved
Hide resolved
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
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/main/java/com/cheeeese/album/application/AlbumQueryService.java(1 hunks)src/main/java/com/cheeeese/album/infrastructure/persistence/UserAlbumRepository.java(2 hunks)src/main/java/com/cheeeese/album/presentation/AlbumQueryController.java(1 hunks)src/main/java/com/cheeeese/album/presentation/swagger/AlbumQuerySwagger.java(1 hunks)src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java(0 hunks)src/main/java/com/cheeeese/cheese4cut/presentation/Cheese4cutController.java(0 hunks)src/main/java/com/cheeeese/cheese4cut/presentation/swagger/Cheese4cutSwagger.java(0 hunks)src/main/java/com/cheeeese/photo/application/PresignedUrlService.java(0 hunks)src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java(2 hunks)src/main/java/com/cheeeese/user/application/UserService.java(2 hunks)
💤 Files with no reviewable changes (4)
- src/main/java/com/cheeeese/photo/application/PresignedUrlService.java
- src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java
- src/main/java/com/cheeeese/cheese4cut/presentation/Cheese4cutController.java
- src/main/java/com/cheeeese/cheese4cut/presentation/swagger/Cheese4cutSwagger.java
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/java/com/cheeeese/album/infrastructure/persistence/UserAlbumRepository.java
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-13T12:56:22.154Z
Learnt from: dahyun24
Repo: Say-Cheeeese/BE PR: 58
File: src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java:149-156
Timestamp: 2025-11-13T12:56:22.154Z
Learning: In src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java, the finalizeCheese4cut method intentionally re-sorts photos using findAllByIdInOrderByLikesDescCreatedDesc(request.photoIds()) instead of preserving the client's requested order. This is a defensive measure to ensure photos are always ordered by likes (DESC) and creation time (DESC), regardless of what order the client sends, preventing incorrect ordering from client errors.
Applied to files:
src/main/java/com/cheeeese/album/application/AlbumQueryService.javasrc/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java
📚 Learning: 2025-10-31T13:17:52.523Z
Learnt from: dahyun24
Repo: Say-Cheeeese/BE PR: 35
File: src/main/java/com/cheeeese/photo/application/PhotoService.java:46-52
Timestamp: 2025-10-31T13:17:52.523Z
Learning: In src/main/java/com/cheeeese/photo/application/PhotoService.java, the getRecentThumbnailUrls method intentionally returns only the first thumbnail URL when photos.size() < 5, rather than returning all available thumbnails. This is according to product requirements: 0 photos → empty list, 1-4 photos → single thumbnail (most recent), 5 photos → all 5 thumbnails.
Applied to files:
src/main/java/com/cheeeese/album/application/AlbumQueryService.javasrc/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java
🧬 Code graph analysis (2)
src/main/java/com/cheeeese/album/application/AlbumQueryService.java (1)
src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java (1)
AlbumQueryMapper(13-73)
src/main/java/com/cheeeese/user/application/UserService.java (1)
src/main/java/com/cheeeese/user/infrastructure/mapper/UserMapper.java (1)
UserMapper(7-27)
🔇 Additional comments (16)
src/main/java/com/cheeeese/user/application/UserService.java (2)
7-7: LGTM!새로운
getUserInfo메서드를 위해 필요한 import가 올바르게 추가되었습니다.Also applies to: 10-10
43-45: LGTM!사용자 정보 조회 메서드가 올바르게 구현되었습니다. 매퍼를 통한 간단한 DTO 변환으로 단일 책임 원칙을 잘 따르고 있으며, 클래스 레벨의 읽기 전용 트랜잭션이 적절하게 적용됩니다.
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java (1)
62-71: 코드 포맷팅 정리 확인공백 제거만 있는 비기능적 변경으로 문제없습니다.
src/main/java/com/cheeeese/album/presentation/swagger/AlbumQuerySwagger.java (3)
24-38: 열린 앨범 조회 엔드포인트 정의 확인Swagger 정의가 명확하고 유효성 검증도 적절합니다. 기본 size가 2로 작지만, UI 요구사항에 따른 의도적인 설정으로 보입니다.
40-54: 내가 만든 열린 앨범 조회 엔드포인트 정의 확인Swagger 정의가 일관성 있고 적절합니다.
56-70: 닫힌 앨범 조회 엔드포인트 정의 확인닫힌 앨범에 대해 더 큰 페이지 크기(기본 6, 최대 20)를 사용하는 것은 히스토리 데이터 조회에 적합합니다.
src/main/java/com/cheeeese/album/application/AlbumQueryService.java (7)
46-59: 열린 앨범 조회 로직 확인메서드 로직이 명확하고 적절합니다.
LocalDateTime.now()를 사용하여 현재 시각 기준으로 필터링하는 것이 의도된 동작으로 보입니다.
61-74: 내가 만든 열린 앨범 조회 로직 확인메이커 역할 필터링이 올바르게 적용되었습니다.
123-140: 열린 앨범 응답 구성 로직 확인메서드 구조가 명확합니다. Line 133-134의 메이커 예외 처리는 이전 코멘트에서 언급한 것과 동일한 패턴입니다.
142-153: 메이커 조회 및 검증 로직 확인Line 149-151의 크기 검증은 모든 메이커가 존재하는지 확실히 확인합니다. 이는 데이터 정합성을 강제하는 엄격한 접근이지만, 이전 코멘트에서 언급한 대로 부분 실패 시나리오를 고려할 필요가 있습니다.
155-186: 최근 썸네일 맵 생성 로직에서 엄격한 필터링Line 180-185에서 정확히 3개의 썸네일을 가진 앨범만 반환합니다. 이는 사진이 1-2개만 있는 앨범에서는 썸네일이 전혀 표시되지 않음을 의미합니다.
Retrieved learnings에 따르면
PhotoService.getRecentThumbnailUrls에서는 "1-4 photos → single thumbnail"을 반환하는 제품 요구사항이 있었습니다. 현재 구현이 동일한 요구사항을 따르는지 확인이 필요합니다.만약 1-2개의 사진만 있는 앨범도 썸네일을 표시해야 한다면, 다음과 같이 수정하세요:
return thumbnailsMap.entrySet().stream() - .filter(entry -> entry.getValue().size() == RECENT_THUMBNAIL_COUNT) + .filter(entry -> !entry.getValue().isEmpty()) .collect(Collectors.toMap( Map.Entry::getKey, entry -> List.copyOf(entry.getValue()) ));또는 1-2개일 때는 첫 번째만 반환하는 등 특정 비즈니스 로직이 필요한 경우:
return thumbnailsMap.entrySet().stream() + .filter(entry -> !entry.getValue().isEmpty()) .collect(Collectors.toMap( Map.Entry::getKey, - entry -> List.copyOf(entry.getValue()) + entry -> { + List<String> thumbnails = entry.getValue(); + if (thumbnails.size() < RECENT_THUMBNAIL_COUNT) { + return List.of(thumbnails.get(0)); // 1-2개일 때는 첫 번째만 + } + return List.copyOf(thumbnails); + } ));
33-44: 서비스 구성 및 상수 정의 확인읽기 전용 트랜잭션 설정과 의존성 구성이 적절합니다.
76-121: 닫힌 앨범 조회 로직은 현재 올바르게 구현되어 있습니다.검증 결과:
데이터 정합성 보장: Album 엔티티의
makerId필드는@Column(nullable=false)로 선언되어 있으므로, 데이터베이스 제약으로 인해 makerId는 절대 null이 될 수 없습니다.메이커 누락 시나리오: FK 제약이 명시적으로 적용되어 있다면, 외래키 제약을 위반하는 고아 레코드(orphaned records)는 발생할 수 없습니다. 현재 설계에서 메이커가 누락된 앨범은 데이터베이스 수준에서 차단됩니다.
Fail-fast 원칙 준수: 방어적 프로그래밍의 좋은 예시는 가드 문(guard statements)을 통해 예상치 못한 상황에 빠르게 대응하여 fail-fast 원칙을 따르는 것입니다. getMakers 메서드의 예외 발생은 데이터 무결성 위반에 대한 올바른 대응입니다.
오류 처리: null이 유효하지 않으면 예외를 던져야 하고, 예외가 발생한 곳을 정확히 추적할 수 있습니다. null을 다음 레이어로 전달하면 null의 출처를 잃어버립니다.
현재 코드의 UserException 발생은 데이터 정합성을 보장하는 적절한 방어 프로그래밍이므로, 메이커 정보를 null로 처리하거나 앨범을 제외하는 제안은 필요하지 않습니다.
Likely an incorrect or invalid review comment.
src/main/java/com/cheeeese/album/presentation/AlbumQueryController.java (3)
29-40: 열린 앨범 조회 엔드포인트 구현 확인이전 리뷰 코멘트에서 요청된 페이지네이션 파라미터 유효성 검증(
@Min,@Max)이 올바르게 적용되었습니다.
42-53: 내가 만든 열린 앨범 조회 엔드포인트 구현 확인유효성 검증이 적절하게 적용되었고, 구현이 일관성 있습니다.
55-66: 닫힌 앨범 조회 엔드포인트 구현 확인닫힌 앨범에 더 큰 최대 크기(20)를 허용하는 것이 적절하며, 유효성 검증이 올바르게 구성되었습니다.
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java
Outdated
Show resolved
Hide resolved
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/com/cheeeese/photo/dto/response/PhotoPageResponse.java (1)
21-34: 예제 JSON의 필드명likesCnt↔ 실제 응답 필드likeCnt불일치예제 JSON에서는
"likesCnt"를 사용하지만, 실제PhotoListResponse레코드 필드는likeCnt입니다. API 문서를 보고 구현하는 클라이언트 입장에서 혼동이 생길 수 있어, 예제를 실제 필드명에 맞춰 정리하는 게 좋아 보입니다.- "likesCnt": 1, + "likeCnt": 1,
🧹 Nitpick comments (14)
src/main/java/com/cheeeese/photo/dto/response/PhotoLikedResponse.java (1)
7-15: 설명 문구 개선을 고려해보세요.
@Schema의description이 "내가 띱한 사진 목록 조회 API"로 되어 있는데, 이는 엔드포인트가 아닌 응답 DTO 클래스에 대한 설명입니다. "내가 띱한 사진 응답" 또는 "내가 띱한 사진 정보"와 같이 DTO 자체를 설명하는 문구가 더 정확할 수 있습니다.
requiredProperties는 모든 필드를 올바르게 포함하고 있으며, 일관된 패턴을 따르고 있습니다.선택적으로 다음과 같이 수정할 수 있습니다:
@Schema( - description = "내가 띱한 사진 목록 조회 API", + description = "내가 띱한 사진 응답", requiredProperties = { "photoId", "thumbnailUrl", "isDownloaded", "isRecentlyDownloaded" } )src/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutFinalResponse.java (1)
9-15: PR 목적과의 관련성을 확인해주세요.이 파일 변경사항은 OpenAPI 문서화를 개선하는 내용이지만, PR의 주요 목적인 "마이페이지 구현"과 직접적인 연관성이 명확하지 않습니다.
참고: Java record의 모든 컴포넌트는 기본적으로 required이므로
requiredProperties명시는 선택사항입니다. 명시적 문서화를 위해 추가하는 것은 괜찮지만, 마이페이지 기능과 관련이 없다면 별도 PR로 분리하는 것을 고려해보세요.src/main/java/com/cheeeese/auth/dto/request/AuthReissueRequest.java (1)
7-12: OpenAPI 스키마 메타데이터 개선이 적절합니다.
requiredProperties속성 추가로 API 문서에서 필수 필드를 명시적으로 표현하고 있습니다.선택적으로 런타임 검증 일관성을 위해 필드에 Bean Validation 어노테이션 추가를 고려해보세요:
public record AuthReissueRequest( @Schema( description = "유효한 refreshToken", example = "eyJh.eqi57hK" ) @NotBlank(message = "refreshToken은 필수입니다") String refreshToken ) { }이렇게 하면 OpenAPI 스키마 생성과 런타임 검증을 모두 처리할 수 있습니다.
src/main/java/com/cheeeese/album/dto/response/AlbumParticipantResponse.java (1)
12-24: OpenAPI required 속성과 Java 레벨 검증의 불일치를 해결하는 것을 권장합니다.
requiredProperties에 명시된 필드들이 OpenAPI 스키마 상으로는 필수로 표시되지만, Java 코드 레벨에서는 참조 타입(String, LocalDate, Integer 등)이면서 검증 어노테이션(@NotNull 등)이 없어 null 값이 가능합니다. 특히maxParticipantCount와currentParticipantCount는 boxed Integer 타입이므로 null이 될 수 있습니다.API 계약과 구현 간의 일관성을 위해 필수 필드에
@NotNull또는jakarta.validation.constraints.NotNull어노테이션 추가를 고려해주세요.예시:
public record AlbumParticipantResponse( @Schema(description = "만료 여부", example = "false") boolean isExpired, @Schema(description = "앨범 제목", example = "졸업식") + @NotNull String title, @Schema(description = "앨범 테마 이모지 (또는 이미지 URL)", example = "U+1F9C0") + @NotNull String themeEmoji,src/main/java/com/cheeeese/album/dto/response/NewEnterResponse.java (1)
51-71: 내부 레코드의 스키마 문서화가 잘 추가되었습니다.
RecentPhotoResponse의requiredProperties가 실제 필드와 일치하며,@NotNull어노테이션과 함께 사용되어 문서화와 검증이 일관되게 구현되었습니다.다만, 외부 레코드
NewEnterResponse의 필드들은@Schema의requiredProperties에 명시되어 있지만@NotNull어노테이션이 없습니다. 내부 레코드와의 일관성을 위해 외부 레코드의 필드에도@NotNull어노테이션을 추가하는 것을 고려해보세요.외부 레코드 필드에
@NotNull추가 예시:@NotNull @Schema(description = "참여 상태 (항상 NEW)", example = "NEW") AlbumJoinStatus joinStatus, @NotNull @Schema(description = "앨범 제목", example = "여름 바캉스") String title, // ... 나머지 필드들에도 동일하게 적용src/main/java/com/cheeeese/album/dto/request/AlbumCreationRequest.java (1)
9-17: DTO 필드에 검증 어노테이션 추가 검토 (선택사항)컨트롤러에서
@Valid어노테이션을 사용하여 요청을 검증하고 있으므로, 현재 null 값 허용 문제는 이 엔드포인트를 통할 때 완화됩니다. 다만 DTO 자체에 검증 어노테이션을 추가하면 다음과 같은 이점이 있습니다:
- 필드별 검증 규칙을 명시적으로 문서화
- 다른 컨트롤러나 서비스에서 재사용할 때 일관된 검증 보장
- IDE와 유효성 검사 도구의 지원 향상
필요에 따라 다음과 같은 검증 어노테이션 추가를 검토하세요:
@NotBlank(message = "앨범 테마 이모지는 필수입니다") String themeEmoji, @NotBlank(message = "앨범 이름은 필수입니다") String title, @Positive(message = "참여자 수는 양수여야 합니다") int participant, @NotNull(message = "행사 날짜는 필수입니다") LocalDate eventDatesrc/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java (1)
58-66: 정렬 기준에 id 추가를 고려하면 결과 안정성이 올라갑니다 (선택 사항)현재는
ORDER BY p.createdAt DESC하나만 사용하고 있어서 같은 시각에 생성된 사진이 많을 경우 반환 순서가 DB 실행 계획에 따라 약간씩 달라질 수 있습니다. 필요하다면 아래처럼p.id를 함께 포함해 두면, 네이티브 쿼리(created_at DESC, photo_id DESC)와도 정렬 기준이 맞고 결과가 더 안정적으로 유지될 것 같습니다.- ORDER BY p.createdAt DESC + ORDER BY p.createdAt DESC, p.id DESCsrc/main/java/com/cheeeese/album/dto/response/AlbumCreationResponse.java (1)
9-18: 코드 포맷 개선을 고려하세요.
@Schema어노테이션의 닫는 괄호와public record선언 사이에 줄바꿈이 없어 가독성이 떨어집니다.다음과 같이 수정하는 것을 권장합니다:
@Schema( description = "앨범 생성 응답", requiredProperties = { "themeEmoji", "title", "eventDate", "currentPhotoCnt", "code" } -)public record AlbumCreationResponse( +) +public record AlbumCreationResponse(src/main/java/com/cheeeese/album/dto/response/AlbumInvitationResponse.java (1)
9-20: 코드 포맷 개선을 고려하세요.
@Schema어노테이션의 닫는 괄호와public record선언 사이에 줄바꿈이 없어 가독성이 떨어집니다.다음과 같이 수정하는 것을 권장합니다:
@Schema( description = "앨범 초대장 확인 응답 DTO", requiredProperties = { "title", "themeEmoji", "eventDate", "expiredAt", "makerName", "makerProfileImage", "isExpired" } -)public record AlbumInvitationResponse( +) +public record AlbumInvitationResponse(src/main/java/com/cheeeese/user/dto/response/UserInfoResponse.java (1)
6-16: 코드 포맷 개선을 고려하세요.
@Schema어노테이션의 닫는 괄호와public record선언 사이에 줄바꿈이 없어 가독성이 떨어집니다.다음과 같이 수정하는 것을 권장합니다:
@Builder @Schema( description = "사용자 기본 정보 응답", requiredProperties = { "profileImage", "name", "albumCount", "photoCount", "likesCount" } -)public record UserInfoResponse( +) +public record UserInfoResponse(src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java (1)
10-19: 코드 포맷 개선을 고려하세요.
@Schema어노테이션의 닫는 괄호와public record선언 사이에 줄바꿈이 없어 가독성이 떨어집니다.다음과 같이 수정하는 것을 권장합니다:
@Builder @Schema( description = "닫힌 앨범 요약 정보", requiredProperties = { "code", "title", "makerName", "eventDate" } ) + public record ClosedAlbumSummaryResponse(src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java (1)
50-52: JsonInclude 설정과 매퍼 로직의 불일치
@JsonInclude(JsonInclude.Include.ALWAYS)로 인해recentPhotoThumbnails가 null이어도 항상 직렬화되지만,AlbumQueryMapper.toOpenAlbumSummaryResponse(line 42)에서는thumbnails.isEmpty() ? null : thumbnails로 빈 리스트를 명시적으로 null로 변환합니다.빈 썸네일 리스트를 클라이언트에 전달하는 의도라면
ALWAYS대신 다음을 권장합니다:- @JsonInclude(JsonInclude.Include.ALWAYS) + @JsonInclude(JsonInclude.Include.NON_NULL) @Schema(description = "최근 업로드된 사진 썸네일 3장") List<String> recentPhotoThumbnails또는 매퍼에서 null 대신 빈 리스트를 반환하도록 수정하세요.
src/main/java/com/cheeeese/album/application/AlbumQueryService.java (2)
103-118: 메이커 검증을 더 일찍 수행하여 실패 빠르게 처리Lines 107-108에서 메이커가 없을 때 예외를 던지지만, 이는 이미
cheese4cutPhotoRepository에서 모든 사진을 조회하고 그룹핑한 이후입니다.buildOpenAlbumResponses(line 128)처럼 응답 생성 전에 메이커 맵을 먼저 검증하면 불필요한 데이터베이스 조회를 방지할 수 있습니다.다음과 같이 리팩토링을 권장합니다:
} Map<Long, User> makerMap = getMakers(expiredAlbums.getContent()); + // getMakers already validates all makers exist List<Cheese4cutPhoto> allCheese4cutPhotos = cheese4cutPhotoRepository.findAllCheese4cutPhotosByAlbumIds(albumIds); Map<Long, List<Cheese4cutPhoto>> cheese4cutPhotoMap = allCheese4cutPhotos.stream() .collect(Collectors.groupingBy( c4p -> c4p.getCheese4cut().getAlbum().getId(), Collectors.toList() )); List<ClosedAlbumSummaryResponse> responses = expiredAlbums.getContent().stream() .map(album -> { List<Cheese4cutPhoto> c4pList = cheese4cutPhotoMap.getOrDefault(album.getId(), List.of()); - User maker = Optional.ofNullable(makerMap.get(album.getMakerId())) - .orElseThrow(() -> new UserException(UserErrorCode.USER_NOT_FOUND)); + User maker = makerMap.get(album.getMakerId()); // Already validated by getMakers List<String> thumbnails = c4pList.stream()
169-178: 수동 그룹핑을 Collectors.groupingBy로 리팩토링 권장Lines 171-178의 수동 루프는
Collectors.groupingBy를 사용하면 더 간결하고 가독성이 높아집니다.- Map<Long, List<String>> thumbnailsMap = new HashMap<>(); - - for (Photo photo : photos) { - Long albumId = photo.getAlbum().getId(); - List<String> thumbnails = thumbnailsMap.computeIfAbsent(albumId, key -> new ArrayList<>()); - - if (thumbnails.size() < RECENT_THUMBNAIL_COUNT) { - thumbnails.add(cdnUrlResolver.resolveThumbnail(photo.getThumbnailUrl())); - } - } + Map<Long, List<String>> thumbnailsMap = photos.stream() + .collect(Collectors.groupingBy( + photo -> photo.getAlbum().getId(), + Collectors.collectingAndThen( + Collectors.mapping( + photo -> cdnUrlResolver.resolveThumbnail(photo.getThumbnailUrl()), + Collectors.toList() + ), + list -> list.stream().limit(RECENT_THUMBNAIL_COUNT).collect(Collectors.toList()) + ) + ));참고: 리포지토리 쿼리
findTop3RecentPhotosInEachAlbum이 이미 앨범당 최대 3개로 제한한다면,limit(RECENT_THUMBNAIL_COUNT)부분은 생략 가능합니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (31)
src/main/java/com/cheeeese/album/application/AlbumQueryService.java(1 hunks)src/main/java/com/cheeeese/album/dto/request/AlbumCreationRequest.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/AlbumCreationResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/AlbumInvitationResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/AlbumMakerInfo.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/AlbumParticipantListResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/AlbumParticipantResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/ClosedAlbumPageResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/ExistingEnterResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/NewEnterResponse.java(2 hunks)src/main/java/com/cheeeese/album/dto/response/OpenAlbumPageResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/UploadAvailableCountResponse.java(1 hunks)src/main/java/com/cheeeese/auth/dto/request/AuthReissueRequest.java(1 hunks)src/main/java/com/cheeeese/auth/dto/response/AuthExchangeResponse.java(1 hunks)src/main/java/com/cheeeese/auth/dto/response/AuthReissueResponse.java(1 hunks)src/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutFinalResponse.java(1 hunks)src/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutPresignedUrlResponse.java(0 hunks)src/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutPreviewResponse.java(2 hunks)src/main/java/com/cheeeese/cheese4cut/infrastructure/mapper/Cheese4cutMapper.java(0 hunks)src/main/java/com/cheeeese/photo/dto/request/PhotoDownloadRequest.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoDetailResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoDownloadResponse.java(2 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoLikedPageResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoLikedResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoListResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoPageResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoPresignedUrlResponse.java(1 hunks)src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java(2 hunks)src/main/java/com/cheeeese/user/dto/response/UserInfoResponse.java(1 hunks)
💤 Files with no reviewable changes (2)
- src/main/java/com/cheeeese/cheese4cut/infrastructure/mapper/Cheese4cutMapper.java
- src/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutPresignedUrlResponse.java
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/java/com/cheeeese/album/dto/response/ClosedAlbumPageResponse.java
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-31T13:17:52.523Z
Learnt from: dahyun24
Repo: Say-Cheeeese/BE PR: 35
File: src/main/java/com/cheeeese/photo/application/PhotoService.java:46-52
Timestamp: 2025-10-31T13:17:52.523Z
Learning: In src/main/java/com/cheeeese/photo/application/PhotoService.java, the getRecentThumbnailUrls method intentionally returns only the first thumbnail URL when photos.size() < 5, rather than returning all available thumbnails. This is according to product requirements: 0 photos → empty list, 1-4 photos → single thumbnail (most recent), 5 photos → all 5 thumbnails.
Applied to files:
src/main/java/com/cheeeese/photo/dto/response/PhotoListResponse.javasrc/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.javasrc/main/java/com/cheeeese/album/application/AlbumQueryService.javasrc/main/java/com/cheeeese/album/dto/response/NewEnterResponse.java
📚 Learning: 2025-11-13T12:56:22.154Z
Learnt from: dahyun24
Repo: Say-Cheeeese/BE PR: 58
File: src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java:149-156
Timestamp: 2025-11-13T12:56:22.154Z
Learning: In src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java, the finalizeCheese4cut method intentionally re-sorts photos using findAllByIdInOrderByLikesDescCreatedDesc(request.photoIds()) instead of preserving the client's requested order. This is a defensive measure to ensure photos are always ordered by likes (DESC) and creation time (DESC), regardless of what order the client sends, preventing incorrect ordering from client errors.
Applied to files:
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.javasrc/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutPreviewResponse.javasrc/main/java/com/cheeeese/album/application/AlbumQueryService.javasrc/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutFinalResponse.java
🧬 Code graph analysis (1)
src/main/java/com/cheeeese/album/application/AlbumQueryService.java (1)
src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java (1)
AlbumQueryMapper(13-73)
🔇 Additional comments (25)
src/main/java/com/cheeeese/auth/dto/response/AuthExchangeResponse.java (1)
7-17: LGTM! OpenAPI 문서화가 적절히 추가되었습니다.클래스 레벨의
@Schema어노테이션이 올바르게 추가되어 API 명세를 개선합니다.requiredProperties에 명시된 모든 필드가 실제 레코드의 필드와 일치하며, 문서화 목적으로 적절합니다.src/main/java/com/cheeeese/album/dto/response/ExistingEnterResponse.java (1)
9-19: API 문서 명세가 정확하게 개선되었습니다.레코드의 모든 필드를
requiredProperties에 명시적으로 선언하여 OpenAPI 스키마가 더 명확해졌습니다. 필드 이름도 모두 정확하게 일치합니다.src/main/java/com/cheeeese/auth/dto/response/AuthReissueResponse.java (1)
7-13: OpenAPI 스키마 메타데이터 개선이 적절합니다.
requiredProperties선언이 레코드 구조와 정확히 일치하며, API 문서화를 개선합니다. PR 전반에 걸친 일관된 메타데이터 개선 패턴의 일부로 보입니다.src/main/java/com/cheeeese/album/dto/response/UploadAvailableCountResponse.java (1)
7-14: LGTM! OpenAPI 스키마 메타데이터가 올바르게 추가되었습니다.클래스 레벨의
@Schema어노테이션이 올바르게 적용되었으며,requiredProperties에 나열된 모든 속성명이 레코드 필드명과 정확히 일치합니다. 이는 API 문서의 명확성을 향상시키고 API 소비자에게 명시적인 계약을 제공합니다.src/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutFinalResponse.java (1)
24-31: LGTM!내부 record에 대한 OpenAPI 스키마 정의가 올바르게 추가되었습니다. 모든 필드가
requiredProperties에 정확히 나열되어 있고, API 문서의 명확성을 향상시킵니다.src/main/java/com/cheeeese/cheese4cut/dto/response/Cheese4cutPreviewResponse.java (2)
10-18: requiredProperties에 myRole 필드 누락 확인 필요
requiredProperties배열에myRole필드가 포함되어 있지 않습니다. 33번 라인에 정의된myRole필드가 API 응답에서 항상 존재해야 하는 필수 필드라면requiredProperties에 추가해야 합니다.만약
myRole이 선택적(optional) 필드로 의도된 것이라면 현재 구현이 올바르지만, 그렇지 않다면 다음과 같이 수정이 필요합니다:@Schema( description = "치즈네컷 확정 전 미리보기 응답 DTO (좋아요 TOP 4)", requiredProperties = { "isFinalized", "previewPhotos", "uniqueLikesCount", - "participant" + "participant", + "myRole" } )
myRole필드가 응답에서 항상 존재하는지 확인해 주세요.
37-44: LGTM!중첩 레코드
PreviewPhotoInfo의 Swagger 스키마 메타데이터가 올바르게 추가되었습니다. 모든 필드가requiredProperties에 포함되어 있고, 명확한 설명이 제공되어 있습니다.src/main/java/com/cheeeese/album/dto/response/NewEnterResponse.java (1)
11-23: OpenAPI 스키마 문서화가 잘 추가되었습니다.
requiredProperties에 명시된 8개의 필드가 실제 레코드 필드와 정확히 일치하며, API 문서 품질을 향상시키는 좋은 개선사항입니다.src/main/java/com/cheeeese/album/dto/response/AlbumParticipantListResponse.java (2)
10-15: LGTM! 필수 속성 메타데이터가 올바르게 추가되었습니다.레코드의 실제 컴포넌트와
requiredProperties목록이 일치합니다. OpenAPI 스키마 문서화가 개선되었습니다.
21-29: 코드 리뷰 주석은 부정확합니다.User 엔티티의
profileImage필드는@Column(name = "profile_image", nullable = false)로 선언되어 있어, 데이터베이스 수준에서 null 값을 허용하지 않습니다. 따라서 사용자가 프로필 이미지를 설정하지 않아도 프로필 이미지 값이 null이 되는 상황은 발생할 수 없습니다. ParticipantInfo에서profileImage를 필수 필드(requiredProperties)로 지정한 것은 올바른 결정이며, 현재 구현은 정확합니다.Likely an incorrect or invalid review comment.
src/main/java/com/cheeeese/photo/dto/response/PhotoListResponse.java (1)
7-17: 클래스 레벨 스키마 requiredProperties 지정 좋습니다레코드 필드들과 requiredProperties 키가 일치하고, 마이페이지/사진 목록 API 스펙을 더 명확하게 해줘서 좋습니다. 런타임 동작 변화도 없어서 부담 없이 적용 가능해 보입니다.
src/main/java/com/cheeeese/photo/dto/response/PhotoLikedPageResponse.java (1)
9-18: 페이지 응답 DTO 스키마 메타데이터 정리 잘 되어 있습니다페이지네이션 공통 필드들을 requiredProperties로 명시해서 OpenAPI 문서 일관성이 높아졌습니다. 다른 페이지 응답 DTO들과 패턴도 맞아서 유지보수에 유리해 보입니다.
src/main/java/com/cheeeese/album/dto/response/AlbumMakerInfo.java (1)
6-12: 앨범 메이커 DTO 필수 필드 명시가 명확합니다makerName, makerProfileImage 두 필드를 requiredProperties로 고정해 둔 점이 직관적이고, 실제 레코드 필드와도 정확히 일치해서 문서/응답 간 혼동 여지가 없어 보입니다.
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java (1)
73-93: 앨범당 최대 3개 사진을 가져오는 네이티브 쿼리 설계가 목적에 잘 부합합니다
ROW_NUMBER() OVER (PARTITION BY album_id ORDER BY created_at DESC, photo_id DESC)로 앨범별 최신 3장만 뽑고, 밖에서ORDER BY t.album_id ASC, t.rn ASC로 정렬해 주는 구조가 이전에 논의되었던 “앨범당 TOP N만 가져오기” 성능 이슈를 잘 해소해 주는 구현으로 보입니다.List<Photo>를 반환하도록 설계된 것도 JPA 엔티티 매핑 관점에서 자연스럽습니다.src/main/java/com/cheeeese/photo/dto/response/PhotoPageResponse.java (1)
9-18: 사진 페이지 응답 DTO 스키마 일관성 좋습니다페이지 공통 필드(responses, listSize, isFirst, isLast, hasNext)를 requiredProperties로 명시한 덕분에 다른 페이지 DTO들과의 스펙 일관성이 좋아졌고, 문서 생성 시에도 필수 정보가 잘 드러날 것 같습니다.
src/main/java/com/cheeeese/user/dto/response/UserInfoResponse.java (1)
17-31: 잘 구현되었습니다!사용자 기본 정보를 담는 DTO의 구조와 필드 정의가 적절합니다. primitive 타입(
long)을 사용하여 null 불가능한 카운트 값을 표현한 것도requiredProperties와 일치합니다.src/main/java/com/cheeeese/photo/dto/response/PhotoDetailResponse.java (1)
7-19: 잘 작성되었습니다!
@Schema어노테이션과public record선언 사이의 포맷이 적절하며,requiredProperties가 모든 필드를 올바르게 포함하고 있습니다.src/main/java/com/cheeeese/photo/dto/response/PhotoPresignedUrlResponse.java (1)
9-26: 잘 작성되었습니다!외부 record와 내부 record 모두에 대한
@Schema어노테이션이 적절하게 구성되어 있으며,requiredProperties가 올바르게 정의되어 있습니다.src/main/java/com/cheeeese/photo/dto/response/PhotoDownloadResponse.java (1)
10-50: 잘 작성되었습니다!외부 record와 내부 nested record 모두에 대한
@Schema어노테이션이 적절하게 구성되어 있으며,requiredProperties가 모든 필수 필드를 올바르게 정의하고 있습니다.src/main/java/com/cheeeese/album/dto/response/OpenAlbumPageResponse.java (1)
8-34: 잘 작성되었습니다!페이지네이션을 위한 DTO 구조가 적절하며,
listSize,isFirst,isLast,hasNext등의 메타데이터 필드가 잘 정의되어 있습니다.@Schema어노테이션과requiredProperties도 올바르게 구성되었습니다.src/main/java/com/cheeeese/album/application/AlbumQueryService.java (5)
46-59: LGTM!페이지네이션과 활성 앨범 필터링 로직이 올바르게 구현되었습니다.
61-74: LGTM!MAKER 역할로 필터링하여 사용자가 생성한 앨범만 조회하는 로직이 정확합니다.
131-139: LGTM!메이커 맵을 먼저 검증한 후 응답을 생성하는 흐름이 올바릅니다. 다만 Line 133-134의
Optional.ofNullable은getMakers에서 이미 모든 메이커의 존재를 검증했으므로 기술적으로는 불필요하지만, 방어적 코딩 관점에서 허용 가능합니다.
142-153: LGTM!메이커를 일괄 조회하고 누락된 메이커가 있을 경우 즉시 실패하는 패턴이 우수합니다. N+1 쿼리를 방지하고 조기 실패를 보장합니다.
180-185: 필터링 로직 확인: 정확히 3개 썸네일만 반환하는 것이 확실함검증 결과, 라인 181의 필터가 정확히
entry.getValue().size() == RECENT_THUMBNAIL_COUNT(=3)을 강제하고 있음을 확인했습니다.문제점:
- 라인 175: 루프는
thumbnails.size() < RECENT_THUMBNAIL_COUNT조건으로 1~3개까지 수락- 라인 181: 필터는
size == 3조건으로 정확히 3개만 반환- 결과: 사진이 1~2개인 앨범은 썸네일이 표시되지 않음
모순 사항:
1-3개까지 수집한 후 정확히 3개만 필터링하는 로직이 의도와 일치하는지 제품 팀에 확인이 필요합니다.의도가 "가능한 만큼의 썸네일 표시"라면 라인 181의 필터를 제거하세요:
- return thumbnailsMap.entrySet().stream() - .filter(entry -> entry.getValue().size() == RECENT_THUMBNAIL_COUNT) - .collect(Collectors.toMap( + return thumbnailsMap.entrySet().stream() + .collect(Collectors.toMap( Map.Entry::getKey, entry -> List.copyOf(entry.getValue()) ));
src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java
Outdated
Show resolved
Hide resolved
src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java
Show resolved
Hide resolved
src/main/java/com/cheeeese/photo/dto/request/PhotoDownloadRequest.java
Outdated
Show resolved
Hide resolved
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
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java(1 hunks)src/main/java/com/cheeeese/photo/dto/request/PhotoDownloadRequest.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/java/com/cheeeese/photo/dto/request/PhotoDownloadRequest.java
🔇 Additional comments (5)
src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java (2)
11-19: 스키마 일관성 개선 확인됨이전 리뷰에서 논의된
@JsonInclude.ALWAYS와requiredProperties불일치 문제가 현재 코드에서는 해결된 것으로 보입니다.thumbnails필드가nullable=true로 선언되어 있고requiredProperties에서 제외되어 있어 일관성이 확보되었습니다.
27-28: NPE 우려는 부당함 - 호출 코드에서 null 체크 완료
AlbumQueryService.java107-108줄에서 이미Optional.ofNullable(makerMap.get(album.getMakerId())).orElseThrow(...)로maker가 null이 아님을 보장합니다. null인 경우 매퍼 호출 전에 예외를 던지므로, 매퍼의maker.getName()호출(67줄)은 안전합니다.
makerName을 필수 속성으로 유지하는 것이 올바릅니다.Likely an incorrect or invalid review comment.
src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java (2)
15-26: 페이지 응답 매핑 로직 확인됨
listSize를responses.size()로 설정하여 실제 반환된 항목 수를 나타내고, 페이지네이션 메타데이터(isFirst,isLast,hasNext)를Slice에서 올바르게 가져오고 있습니다.
28-39: 페이지 응답 매핑 로직 확인됨
toOpenAlbumPageResponse와 동일한 패턴으로 페이지네이션 메타데이터를 올바르게 처리하고 있습니다.src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java (1)
11-24: 리뷰 의견 재검토 완료: 이전 지적 사항이 코드에 반영되어 있습니다.코드 검증 결과,
maker파라미터는toOpenAlbumSummaryResponse호출 시점에서 null이 될 수 없습니다:
- AlbumQueryService.getMakers(): makerIds 크기와 조회된 makers 맵 크기를 검증하며, 불일치 시 UserException을 던집니다 (lines 149-150)
- 호출 지점: 모든 mapper 호출 전에
Optional.ofNullable(makerMap.get(...)).orElseThrow()를 사용하여 null 체크를 수행합니다 (lines 107-108, 133-134)
maker는 이미 null-safe하게 처리되고 있으며,requiredProperties에makerName을 포함한 것이 정확합니다.Likely an incorrect or invalid review comment.
src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java
Show resolved
Hide resolved
src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java
Show resolved
Hide resolved
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
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java
- src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java
🔇 Additional comments (1)
src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java (1)
19-34: Record 구조가 잘 정의되었습니다.과거 리뷰 논의에서 제기된
thumbnails필드의@JsonInclude관련 이슈가 적절히 해결된 것으로 보입니다. 현재 구현에서는:
thumbnails가requiredProperties에서 제외되어 선택적 필드로 처리됨nullable = true로 명시되어 null 값 허용이 명확함- 별도의
@JsonInclude애너테이션 없이 기본 직렬화 동작 사용이는 개발자의 의도와 일치하며, OpenAPI 스키마와 실제 동작 간의 일관성이 유지됩니다.
Based on learnings
src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java
Show resolved
Hide resolved
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
🧹 Nitpick comments (2)
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java (1)
79-99: 앨범별 TOP3 네이티브 쿼리 설계는 좋아 보이며, 스키마/DB 호환성만 한번 확인해 주세요전반적으로는 이전에 지적되던 “페이지네이션 없이 모든 COMPLETED 사진을 가져오는” 문제를 잘 해소하는 구현입니다. DB 단에서 앨범별 TOP3만 뽑아오도록 제한해서 성능 측면에서도 합리해 보입니다.
다만, 아래 몇 가지는 한 번만 체크해 주시면 좋겠습니다.
ORDER BY p.created_at DESC, p.photo_id DESC에서 실제 컬럼명이 정말photo_id인지 확인이 필요합니다. 만약 PK 컬럼이id라면 런타임 SQL 에러가 날 수 있으니, 스키마에 맞춰 컬럼명을 맞춰 주세요.- 네이티브 쿼리에서
SELECT *로 서브쿼리(t) 결과를 반환하고, 반환 타입을List<Photo>로 받고 있습니다. 보통 매핑에 필요한 컬럼들만 있으면 추가 컬럼(rn)은 무시되지만, 사용하는 JPA 구현체/네이밍 전략에 따라 미묘한 이슈가 생길 수도 있어 통합 테스트로 한 번 호출을 검증해 두는 게 안전합니다.ROW_NUMBER()윈도우 함수는 DB 버전 의존성이 있으니, 운영 DB(MySQL 8+, PostgreSQL 등)가 해당 함수를 지원하는지 이미 확인하셨다면 괜찮고, 아니라면 다른 방식(서브쿼리 + LIMIT 등)도 고려가 필요합니다.albumIds리스트가 매우 커질 가능성이 있다면, 호출부에서 입력 크기 제한이나 상위 앨범 목록 자체의 페이징도 함께 고려해 두면 장기적으로 안전합니다.구현 방향 자체는 좋고, 이전 성능 이슈에 대한 해결책으로 적절해 보입니다. 위 항목들만 한번 실제 스키마/환경 기준으로 검증해 주세요.
src/main/java/com/cheeeese/photo/dto/response/PhotoDetailResponse.java (1)
9-21: @Schema 설명 문구 개선을 고려하세요.현재 description이 "사진 상세 조회 API"로 되어 있는데, 이 클래스는 API 자체가 아닌 응답 DTO입니다. "사진 상세 조회 응답" 또는 "사진 상세 정보"와 같이 더 정확한 표현으로 변경하는 것이 좋습니다.
제안하는 수정:
@Schema( - description = "사진 상세 조회 API", + description = "사진 상세 정보", requiredProperties = {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
src/main/java/com/cheeeese/cheese4cut/presentation/Cheese4cutController.java(0 hunks)src/main/java/com/cheeeese/global/common/code/SuccessCode.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoDetailResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoLikedPageResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoLikedResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoListResponse.java(1 hunks)src/main/java/com/cheeeese/photo/dto/response/PhotoPageResponse.java(1 hunks)src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java(1 hunks)src/main/java/com/cheeeese/user/application/UserService.java(2 hunks)src/main/java/com/cheeeese/user/infrastructure/mapper/UserMapper.java(2 hunks)src/main/java/com/cheeeese/user/presentation/UserController.java(2 hunks)src/main/java/com/cheeeese/user/presentation/swagger/UserSwagger.java(2 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/com/cheeeese/cheese4cut/presentation/Cheese4cutController.java
🚧 Files skipped from review as they are similar to previous changes (5)
- src/main/java/com/cheeeese/user/presentation/UserController.java
- src/main/java/com/cheeeese/photo/dto/response/PhotoLikedPageResponse.java
- src/main/java/com/cheeeese/photo/dto/response/PhotoListResponse.java
- src/main/java/com/cheeeese/global/common/code/SuccessCode.java
- src/main/java/com/cheeeese/user/infrastructure/mapper/UserMapper.java
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-13T12:56:22.154Z
Learnt from: dahyun24
Repo: Say-Cheeeese/BE PR: 58
File: src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java:149-156
Timestamp: 2025-11-13T12:56:22.154Z
Learning: In src/main/java/com/cheeeese/cheese4cut/application/Cheese4cutService.java, the finalizeCheese4cut method intentionally re-sorts photos using findAllByIdInOrderByLikesDescCreatedDesc(request.photoIds()) instead of preserving the client's requested order. This is a defensive measure to ensure photos are always ordered by likes (DESC) and creation time (DESC), regardless of what order the client sends, preventing incorrect ordering from client errors.
Applied to files:
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java
📚 Learning: 2025-10-31T13:17:52.523Z
Learnt from: dahyun24
Repo: Say-Cheeeese/BE PR: 35
File: src/main/java/com/cheeeese/photo/application/PhotoService.java:46-52
Timestamp: 2025-10-31T13:17:52.523Z
Learning: In src/main/java/com/cheeeese/photo/application/PhotoService.java, the getRecentThumbnailUrls method intentionally returns only the first thumbnail URL when photos.size() < 5, rather than returning all available thumbnails. This is according to product requirements: 0 photos → empty list, 1-4 photos → single thumbnail (most recent), 5 photos → all 5 thumbnails.
Applied to files:
src/main/java/com/cheeeese/photo/infrastructure/persistence/PhotoRepository.java
🧬 Code graph analysis (1)
src/main/java/com/cheeeese/user/application/UserService.java (1)
src/main/java/com/cheeeese/user/infrastructure/mapper/UserMapper.java (1)
UserMapper(11-44)
🔇 Additional comments (5)
src/main/java/com/cheeeese/photo/dto/response/PhotoLikedResponse.java (1)
7-15: API 스키마 문서화 개선이 좋습니다.Swagger 스키마에
requiredProperties를 명시적으로 추가하여 API 문서화와 검증이 개선되었습니다.name과imageUrl이 필수 속성 목록에서 제외된 것으로 보아 이들이 선택적 필드임을 나타냅니다.다음을 확인해 주세요:
name과imageUrl필드가 실제로 null 가능한지, 비즈니스 로직과 일치하는지 검증 부탁드립니다.src/main/java/com/cheeeese/photo/dto/response/PhotoPageResponse.java (1)
9-18: 페이지네이션 스키마 문서화 개선이 적절합니다.모든 페이지네이션 메타데이터 필드(
responses,listSize,isFirst,isLast,hasNext)를 필수 속성으로 명시하여 API 계약을 명확히 했습니다. 페이지네이션 응답에서 이러한 필드들은 항상 존재해야 하므로 적절한 변경입니다.src/main/java/com/cheeeese/user/presentation/swagger/UserSwagger.java (1)
20-31: 잘 구현되었습니다!Swagger 문서가 명확하고, 메서드 시그니처가 기존 패턴과 일관성있게 작성되었습니다. API 설명도 충분히 상세합니다.
src/main/java/com/cheeeese/user/application/UserService.java (1)
68-70: 잘 구현되었습니다!사용자 정보 조회 로직이 간결하고 명확합니다. Mapper를 통한 변환 방식이 기존 코드 패턴과 일관성있게 작성되었습니다.
src/main/java/com/cheeeese/photo/dto/response/PhotoDetailResponse.java (1)
11-20: photoId는Longwrapper 타입이 아닌longprimitive 타입으로 변경하세요.
PhotoDetailResponse의photoId는requiredProperties에 필수 필드로 선언되어 있지만,Long(nullable) 타입으로 정의되어 있습니다. 검증 결과, Photo 엔티티의 ID는@Column(nullable = false)와@GeneratedValue(strategy = GenerationType.IDENTITY)로 설정되어 있고,PhotoQueryService의getPhotoDetail()메서드에서photoRepository.findByIdAndAlbum_Code().orElseThrow()로 조회되므로 실행 시점에 null이 될 수 없습니다. 따라서 null 처리 검증은 불필요하지만, 타입 선언의 일관성을 위해longprimitive 타입으로 변경하는 것이 좋습니다.// 현재 Long photoId, // 권장 long photoId,
zyovn
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.
ㅅ고하셧습니다~
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
🧹 Nitpick comments (3)
src/main/java/com/cheeeese/photo/dto/request/PhotoDownloadRequest.java (1)
14-14: 검증 어노테이션이 올바르게 구현되었습니다.
@NotBlank와@NotEmpty어노테이션이 적절하게 추가되어 이전 리뷰의 요구사항을 완벽히 충족합니다. 에러 메시지도 명확하고 프로젝트 컨벤션을 따릅니다.선택사항: 다운로드 수량 제한 고려
대량 다운로드로 인한 성능 문제나 남용을 방지하기 위해
photoIds에 최대 개수 제한을 추가하는 것을 고려해보세요:@Schema(description = "사진 고유 ID", example = "[1, 2, 3]") @NotEmpty(message = "사진 ID 목록은 비어있을 수 없습니다") +@Size(max = 100, message = "한 번에 최대 100개의 사진만 다운로드할 수 있습니다") List<Long> photoIds참고: 이는 선택적 개선사항이며, 비즈니스 요구사항에 따라 적용 여부를 결정하세요.
Also applies to: 18-18
src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java (2)
15-39: 두 페이지 응답 매퍼 간 코드 중복
toOpenAlbumPageResponse와toClosedAlbumPageResponse메서드가 거의 동일한 구조를 가지고 있습니다. 제네릭을 활용한 통합 메서드로 리팩토링을 고려할 수 있지만, 현재 구현도 타입 안전성을 제공하며 충분히 명확합니다.
41-71: 파라미터 null 안전성 강화 고려
album과thumbnails파라미터에 대한 null 검증이 없어, null이 전달될 경우 NPE가 발생할 수 있습니다:
- Lines 47-54, 65-69:
album.getCode(),album.getTitle()등 호출 전 null 체크 없음- Lines 55, 69:
thumbnails.isEmpty()호출 전 null 체크 없음 (null이면 NPE 발생)서비스 계층에서 유효성을 보장하고 있다면 현재 구현도 문제없지만, 방어적 코딩 차원에서 다음과 같은 개선을 고려할 수 있습니다:
public static OpenAlbumSummaryResponse toOpenAlbumSummaryResponse( Album album, User maker, List<String> thumbnails ){ return OpenAlbumSummaryResponse.builder() .code(album.getCode()) .themeEmoji(album.getThemeEmoji()) .title(album.getTitle()) .eventDate(album.getEventDate()) .makerName(maker.getName()) .currentParticipant(album.getCurrentParticipant()) .participant(album.getParticipant()) .expiredAt(album.getExpiredAt()) .recentPhotoThumbnails(thumbnails == null || thumbnails.isEmpty() ? null : thumbnails) .build(); }참고:
maker는 이전 리뷰에서 논의된 바와 같이 서비스 계층에서 검증되므로 null 체크가 불필요합니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java(1 hunks)src/main/java/com/cheeeese/album/infrastructure/mapper/AlbumQueryMapper.java(1 hunks)src/main/java/com/cheeeese/photo/dto/request/PhotoDownloadRequest.java(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/java/com/cheeeese/album/dto/response/OpenAlbumSummaryResponse.java
🔇 Additional comments (2)
src/main/java/com/cheeeese/photo/dto/request/PhotoDownloadRequest.java (1)
4-5: 이전 리뷰 피드백이 정확히 반영되었습니다.Jakarta Validation 제약 조건 import가 올바르게 추가되었습니다. 이제 Swagger 문서의
requiredProperties와 실제 런타임 검증 로직이 일치합니다.src/main/java/com/cheeeese/album/dto/response/ClosedAlbumSummaryResponse.java (1)
10-35: LGTM! 이전 논의사항이 잘 반영되었습니다.이전 리뷰에서 논의된 사항들이 적절히 처리되었습니다:
thumbnails필드:nullable = true가 추가되어 null 값 허용이 명시됨makerName필드: 서비스 계층에서 검증되어 null이 될 수 없으므로requiredProperties에 포함된 것이 적절함- 스키마 정의가 실제 동작과 일치함
🔗 연관된 이슈
🚀 변경 유형
📝 작업 내용
📸 스크린샷
💬 리뷰 요구사항
📜 리뷰 규칙
Reviewer는 아래 P5 Rule을 참고하여 리뷰를 진행합니다.
P5 Rule을 통해 Reviewer는 Reviewee에게 리뷰의 의도를 보다 정확히 전달할 수 있습니다.
Summary by CodeRabbit
New Features
Chores
Removed