Conversation
📝 WalkthroughSummary by CodeRabbit릴리스 노트
✏️ Tip: You can customize this high-level summary in your review settings. Walkthrough토스 페이먼츠 API에 Idempotency-Key 헤더가 추가되고, 게스트 티켓 이메일의 이벤트 타입 표시와 제목 포맷이 변경되었으며, 이벤트 썸네일 조회가 개별 호출에서 배치 조회(Map)로 전환되고 관련 시그니처/레포지토리 메서드가 추가 및 조정되었습니다. 일부 코드 정렬·포맷 변경도 포함됩니다. Changes
Sequence DiagramsequenceDiagram
participant Client as Client
participant EventService as EventService
participant ImageRetriever as EventImageRetriever
participant ImageRepo as EventImageRepository
participant DB as Database
Client->>EventService: getAllVisibleEvents()
EventService->>EventService: collect eventIds
EventService->>ImageRetriever: findAllThumbnailsByEventIds(eventIds)
ImageRetriever->>ImageRepo: findAllThumbnailsByEventIds(eventIds)
ImageRepo->>DB: SELECT ... WHERE eventId IN (...) AND sequence = 0
DB-->>ImageRepo: EventImageEntity List
ImageRepo-->>ImageRetriever: EventImageEntity List
ImageRetriever->>ImageRetriever: collect to Map<Long, EventImage>
ImageRetriever-->>EventService: Map<Long, EventImage>
EventService->>EventService: filteringEventByEventType(events, type, thumbnailMap)
EventService-->>Client: List<EventAllResponse.EventInfo> (with thumbnails)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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.
Actionable comments posted: 1
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/permitseoul/permitserver/domain/payment/api/service/PaymentService.java (1)
331-336:⚠️ Potential issue | 🔴 CriticalToss Payments 취소 API의 멱등키 사용 규칙을 수정해야 합니다.
Toss Payments 공식 API 스펙에 따르면
Idempotency-Key는 요청마다 고유한 랜덤 값으로 생성해야 하며, 최대 300자, 유효 기간 15일입니다. 현재 코드는paymentKey를 직접 멱등키로 사용하고 있는데, 이는 명시적으로 권장되지 않는 방식입니다.
- 문제: 동일 결제에 대해 다른 취소 사유나 재시도가 필요한 경우, 동일한 멱등키를 재사용하면 이전 취소 응답이 반환되거나 요청이 거부될 수 있습니다.
- 해결책: 각 취소 요청마다 고유한 멱등키를 생성하고 저장하는 로직이 필요합니다.
orderId또는 고유한 취소 ID 기반으로 일관성 있게 생성하되, 단순히paymentKey를 재사용하지 마세요.
🤖 Fix all issues with AI agents
In
`@src/main/java/com/permitseoul/permitserver/domain/eventimage/core/component/EventImageRetriever.java`:
- Around line 28-39: findAllThumbnailsByEventIds currently throws
EventImageNotFoundException even when the input eventIds list is empty; change
the method (EventImageRetriever.findAllThumbnailsByEventIds) to return an empty
map immediately if eventIds is null or empty instead of querying, and only throw
EventImageNotFoundException when eventIds was provided (non-empty) but the
repository call (eventImageRepository.findAllThumbnailsByEventIds) returned an
empty result; use a null/empty check on the eventIds parameter and return
Collections.emptyMap() (or Map.of()) for empty input, leaving the existing
collect/exception logic for the non-empty case.
🧹 Nitpick comments (2)
.gitignore (1)
47-54: 중복된 Load Tests 섹션을 하나로 정리해 주세요.
### Load Tests ###블록과load-tests/항목이 두 번 반복되어 있습니다. 중복을 제거하고 새 경로만 해당 블록에 포함시키면 유지보수성이 좋아집니다.♻️ 정리 예시
### Load Tests ### load-tests/ -### Load Tests ### -load-tests/ src/main/java/com/permitseoul/permitserver/domain/reservation/api/controller/PerformanceTestController.java src/main/java/com/permitseoul/permitserver/domain/reservation/api/service/ReservationDBLockTestService.java src/main/java/com/permitseoul/permitserver/domain/reservation/api/service/ReservationPerformanceTestService.javasrc/main/java/com/permitseoul/permitserver/domain/admin/util/GuestTicketEmailSender.java (1)
58-58: ZWSP 리터럴을 이스케이프 표기로 명시해 가독성 개선 권장.
보이지 않는 문자라 유지보수 시 혼란이 생길 수 있어\u200B표기가 안전합니다.♻️ 제안 변경
- helper.setSubject("[" + eventType.getDisplayName() + "] Guest Ticket Info"); //Gmail thread subject가 맨앞 "[]" 태그를 무시/정규화하는 경우가 있어, Zero-width space(U+200B)로 패턴 인식을 회피 + helper.setSubject("\u200B[" + eventType.getDisplayName() + "] Guest Ticket Info"); //Gmail thread subject가 맨앞 "[]" 태그를 무시/정규화하는 경우가 있어, Zero-width space(U+200B)로 패턴 인식을 회피
| @Transactional(readOnly = true) | ||
| public Map<Long, EventImage> findAllThumbnailsByEventIds(final List<Long> eventIds) { | ||
| final Map<Long, EventImage> eventImageMap = eventImageRepository.findAllThumbnailsByEventIds(eventIds).stream() | ||
| .collect(Collectors.toMap( | ||
| EventImageEntity::getEventId, | ||
| EventImage::fromEntity, | ||
| (a, b) -> a) | ||
| ); | ||
| if(ObjectUtils.isEmpty(eventImageMap)) { | ||
| throw new EventImageNotFoundException(); | ||
| } | ||
| return eventImageMap; |
There was a problem hiding this comment.
eventIds가 비어 있을 때 예외가 발생할 수 있습니다.
빈 입력에서도 map이 empty라 EventImageNotFoundException이 발생해, 이벤트 0건 상태에서 404가 날 수 있습니다. 빈 입력은 빈 맵 반환으로 처리하는 편이 안전합니다.
🐛 제안 수정
`@Transactional`(readOnly = true)
public Map<Long, EventImage> findAllThumbnailsByEventIds(final List<Long> eventIds) {
+ if (ObjectUtils.isEmpty(eventIds)) {
+ return Map.of();
+ }
final Map<Long, EventImage> eventImageMap = eventImageRepository.findAllThumbnailsByEventIds(eventIds).stream()
.collect(Collectors.toMap(
EventImageEntity::getEventId,
EventImage::fromEntity,
(a, b) -> a)
);
if(ObjectUtils.isEmpty(eventImageMap)) {
throw new EventImageNotFoundException();
}
return eventImageMap;
}🤖 Prompt for AI Agents
In
`@src/main/java/com/permitseoul/permitserver/domain/eventimage/core/component/EventImageRetriever.java`
around lines 28 - 39, findAllThumbnailsByEventIds currently throws
EventImageNotFoundException even when the input eventIds list is empty; change
the method (EventImageRetriever.findAllThumbnailsByEventIds) to return an empty
map immediately if eventIds is null or empty instead of querying, and only throw
EventImageNotFoundException when eventIds was provided (non-empty) but the
repository call (eventImageRepository.findAllThumbnailsByEventIds) returned an
empty result; use a null/empty check on the eventIds parameter and return
Collections.emptyMap() (or Map.of()) for empty input, leaving the existing
collect/exception logic for the non-empty case.
🔥Pull requests
⛳️ 작업한 브랜치
👷 작업한 내용
🚨 참고 사항