Skip to content

Conversation

@sjk4618
Copy link
Member

@sjk4618 sjk4618 commented Dec 16, 2025

🔥Pull requests

⛳️ 작업한 브랜치

👷 작업한 내용

  • 행사 siteMap 조회 api 구현 및 siteMap 등록 추가

🚨 참고 사항

@coderabbitai
Copy link

coderabbitai bot commented Dec 16, 2025

📝 Walkthrough

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 이벤트에 사이트맵 이미지 관리 기능 추가
    • 이벤트 생성 및 수정 시 사이트맵 이미지 업로드 지원
    • 사이트맵 이미지 조회 API 엔드포인트 추가
    • 이벤트 상세 정보에 사이트맵 이미지 포함
  • 개선사항

    • 이벤트 이미지를 시퀀스 순서대로 정렬하여 제공

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

관리자 이벤트에 사이트맵 이미지 필드를 추가하고, 사이트맵 이미지 엔티티·리포지토리·컴포넌트·서비스·컨트롤러·예외·응답 DTO를 새로 도입해 생성/수정 시 저장·삭제 로직을 적용하고 공개 조회 엔드포인트를 추가했습니다.

Changes

Cohort / File(s) Summary
Admin Event DTOs
src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/req/AdminEventUpdateRequest.java, src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/req/AdminEventWithTicketCreateRequest.java, src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/res/AdminEventDetailResponse.java
관리자 DTO/레코드에 siteMapImages 컴포넌트(타입: List<AdminEventImageRequest> / List<AdminEventImageInfo>, @Valid) 추가 및 팩토리/레코드 서명과 호출부 업데이트
Admin Event Service
src/main/java/com/permitseoul/permitserver/domain/admin/event/api/service/AdminEventService.java
SiteMapImageSaver/Remover/Retriever 의존성 추가, 생성·수정 시 사이트맵 이미지 저장/삭제 로직 추가, 상세 응답에 사이트맵 이미지 포함, 이미지 널/빈 처리 변경
Public Event Service
src/main/java/com/permitseoul/permitserver/domain/event/api/service/EventService.java
이벤트 이미지 목록을 sequence 기준으로 정렬하여 매핑하도록 변경
Entity Column Definition
src/main/java/com/permitseoul/permitserver/domain/eventimage/core/domain/entity/EventImageEntity.java, src/main/java/com/permitseoul/permitserver/domain/eventtimetable/blockmedia/domain/entity/TimetableBlockMediaEntity.java
이미지/미디어 URL 컬럼에 columnDefinition = "TEXT" 추가 (영속성 매핑 타입 변경)
SiteMapImage 도메인 & 엔티티
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/EventSiteMapImage.java, src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/entity/EventSiteMapImageEntity.java
사이트맵 이미지 도메인 모델 및 JPA 엔티티 추가(필드, 생성 팩토리, TEXT 컬럼 매핑)
SiteMapImage 리포지토리
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/repository/EventSiteMapImageRepository.java
이벤트별 사이트맵 이미지 조회(findAllByEventId) 및 이벤트별 일괄 삭제(@Modifying + @Query deleteAllByEventId) 메서드 추가
SiteMapImage 컴포넌트
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageSaver.java, .../SiteMapImageRemover.java, .../SiteMapImageRetriever.java
저장·삭제·조회 책임 컴포넌트 추가(레포지토리 위임 및 엔티티↔도메인 변환)
SiteMapImage API Layer
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/controller/EventSiteMapImageController.java, src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/service/EventSiteMapImageService.java, src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/dto/res/EventSiteMapGetResponse.java, src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/exception/SiteMapImageApiException.java
공개 조회 API GET /api/events/{eventId}/sitemap 추가, 서비스 로직(이벤트 조회 → 사이트맵 이미지 조회 → 정렬·매핑), 전용 예외 및 응답 DTO 구현
SiteMapImage 공통 예외 및 핸들러
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/SiteMapImageBaseException.java, src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/EventSiteMapExceptionHandler.java
사이트맵 이미지 기본 예외 추상 클래스 추가 및 API 전용 예외 처리기 등록
Global Error Code
src/main/java/com/permitseoul/permitserver/global/response/code/ErrorCode.java
NOT_FOUND_SITE_MAP_IMAGE(HttpStatus.NOT_FOUND, 40429, "sitemap image를 찾을 수 없습니다.") 상수 추가

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller as EventSiteMapImageController
    participant Service as EventSiteMapImageService
    participant EventRetriever as EventRetriever
    participant Retriever as SiteMapImageRetriever
    participant Repo as EventSiteMapImageRepository

    Client->>Controller: GET /api/events/{eventId}/sitemap
    Controller->>Service: getEventSiteMapImages(eventId)
    Service->>EventRetriever: getEvent(eventId)
    EventRetriever-->>Service: Event or throw
    alt Event not found
        Service-->>Controller: throw SiteMapImageApiException(NOT_FOUND_EVENT)
    else
        Service->>Retriever: findAllEventSiteMapImagesByEventId(eventId)
        Retriever->>Repo: findAllByEventId(eventId)
        Repo-->>Retriever: List<EventSiteMapImageEntity>
        Retriever-->>Service: List<EventSiteMapImage>
        alt No images
            Service-->>Controller: throw SiteMapImageApiException(NOT_FOUND_SITE_MAP_IMAGE)
        else
            Service->>Service: sort by sequence & map to DTO
            Service-->>Controller: EventSiteMapGetResponse
            Controller-->>Client: 200 OK (wrapped)
        end
    end
Loading
sequenceDiagram
    participant AdminService as AdminEventService
    participant EventRepo as EventRepository
    participant ImageSaver as ImageSaver
    participant SiteMapSaver as SiteMapImageSaver
    participant SiteMapRemover as SiteMapImageRemover
    participant SiteMapRepo as EventSiteMapImageRepository

    AdminService->>EventRepo: save(event)
    EventRepo-->>AdminService: savedEvent
    AdminService->>ImageSaver: saveEventImages(images)
    AdminService->>SiteMapSaver: saveEventSiteMapImages(siteMapImages)
    SiteMapSaver->>SiteMapRepo: saveAll(entities)
    SiteMapRepo-->>SiteMapSaver: saved entities
    alt Update with new siteMapImages
        AdminService->>SiteMapRemover: deleteAllSiteMapImages(eventId)
        SiteMapRemover->>SiteMapRepo: deleteAllByEventId(eventId)
        AdminService->>SiteMapSaver: saveEventSiteMapImages(newEntities)
        SiteMapSaver->>SiteMapRepo: saveAll(newEntities)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • 집중 검토 대상:
    • AdminEventService.java: 새 의존성 주입, 트랜잭션 경계, save/update 시 사이트맵 이미지 처리(삭제 후 저장) 로직
    • EventSiteMapImageService.java: 예외 변환(EventNotfound → SiteMapImageApiException) 및 빈 이미지 처리 흐름
    • EventSiteMapImageRepository.java: @Modifying 쿼리의 clear/flush 옵션과 배치 영향
    • DTO 변경 영향: AdminEventWithTicketCreateRequest 레코드 서명 변경에 따른 호출부(컨트롤러/서비스) 영향 범위
    • 엔티티 컬럼 변경: columnDefinition = "TEXT" 적용에 따른 DB 영향

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.17% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 행사 siteMap 조회 API 구현 및 siteMap 등록 추가라는 변경의 핵심 목표를 명확하게 반영하고 있습니다.
Description check ✅ Passed PR 설명은 행사 siteMap 조회 API 구현 및 siteMap 등록 추가와 관련된 작업 내용을 제시하고 있어 변경사항과 연관성이 있습니다.
Linked Issues check ✅ Passed PR의 모든 변경사항(siteMap 조회 API 엔드포인트, 등록/수정/조회 기능, 관련 엔티티 및 서비스)이 #199의 요구사항을 충족합니다.
Out of Scope Changes check ✅ Passed 이미지 URL 컬럼 타입 변경(TEXT) 및 이미지 정렬 로직 추가는 siteMap 기능 구현을 지원하는 범위 내 변경이며, 모두 #199 요구사항과 관련됩니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#199

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/service/EventSiteMapImageService.java (1)

40-42: 예외 원인(cause) 체이닝 누락

원본 예외(EventNotfoundException)의 정보가 새로운 예외로 전달되지 않아 디버깅 시 원인 추적이 어려울 수 있습니다.

         } catch (EventNotfoundException e) {
-            throw new SiteMapImageApiException(ErrorCode.NOT_FOUND_EVENT);
+            throw new SiteMapImageApiException(ErrorCode.NOT_FOUND_EVENT, e);
         }

SiteMapImageApiException 생성자가 Throwable cause를 받는지 확인이 필요합니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/EventSiteMapImage.java (1)

12-14: 필드 네이밍 불일치 확인 필요

siteMapImagesId는 camelCase로 "Map"을 사용하고, sitemapImageUrl은 소문자 "sitemap"을 사용합니다. 일관성을 위해 통일하는 것이 좋습니다.

-    private final long siteMapImagesId;
-    private final int sequence;
-    private final String sitemapImageUrl;
+    private final long siteMapImageId;
+    private final int sequence;
+    private final String siteMapImageUrl;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fe4484 and ffe2b92.

📒 Files selected for processing (19)
  • src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/req/AdminEventUpdateRequest.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/req/AdminEventWithTicketCreateRequest.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/res/AdminEventDetailResponse.java (3 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/admin/event/api/service/AdminEventService.java (7 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/event/api/service/EventService.java (3 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/eventimage/core/domain/entity/EventImageEntity.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/eventtimetable/blockmedia/domain/entity/TimetableBlockMediaEntity.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/SiteMapImageBaseException.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/controller/EventSiteMapImageController.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/dto/res/EventSiteMapGetResponse.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/exception/SiteMapImageApiException.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/service/EventSiteMapImageService.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageRemover.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageRetriever.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageSaver.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/EventSiteMapImage.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/entity/EventSiteMapImageEntity.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/repository/EventSiteMapImageRepository.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/global/response/code/ErrorCode.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: sjk4618
Repo: PERMIT-SEOUL/permit-server PR: 48
File: src/main/java/com/permitseoul/permitserver/domain/guest/core/domain/entity/GuestEntity.java:31-37
Timestamp: 2025-07-15T09:37:32.765Z
Learning: sjk4618 prefers to implement factory methods or public constructors for entities when they are actually needed, rather than creating them proactively.
🧬 Code graph analysis (6)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageRemover.java (1)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageSaver.java (1)
  • Component (10-18)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/service/EventSiteMapImageService.java (2)
src/main/java/com/permitseoul/permitserver/domain/event/core/exception/EventNotfoundException.java (1)
  • EventNotfoundException (3-4)
src/main/java/com/permitseoul/permitserver/domain/event/api/service/EventService.java (1)
  • RequiredArgsConstructor (29-131)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/entity/EventSiteMapImageEntity.java (3)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/EventSiteMapImage.java (1)
  • Getter (8-25)
src/main/java/com/permitseoul/permitserver/domain/eventimage/core/domain/entity/EventImageEntity.java (1)
  • Entity (6-36)
src/main/java/com/permitseoul/permitserver/domain/eventtimetable/blockmedia/domain/entity/TimetableBlockMediaEntity.java (1)
  • Entity (10-41)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/controller/EventSiteMapImageController.java (1)
src/main/java/com/permitseoul/permitserver/global/response/ApiResponseUtil.java (1)
  • ApiResponseUtil (7-29)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/exception/SiteMapImageApiException.java (1)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/SiteMapImageBaseException.java (1)
  • SiteMapImageBaseException (3-4)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageSaver.java (1)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageRemover.java (1)
  • Component (7-15)
🔇 Additional comments (21)
src/main/java/com/permitseoul/permitserver/global/response/code/ErrorCode.java (1)

90-90: LGTM!

새로운 에러 코드가 올바르게 추가되었습니다. 순차 번호(40429)와 메시지 형식이 기존 패턴과 일관성 있게 유지되고 있습니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/SiteMapImageBaseException.java (1)

1-4: LGTM!

도메인 특화 기본 예외 클래스가 적절하게 정의되었습니다. 추상 클래스로 선언하여 직접 인스턴스화를 방지하고 마커 타입으로서의 역할을 수행합니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/entity/EventSiteMapImageEntity.java (1)

9-42: 엔티티 구조가 잘 설계되었습니다.

JPA 어노테이션 설정, 팩토리 메서드 패턴, protected 기본 생성자 등이 코드베이스의 다른 엔티티들과 일관성 있게 구현되어 있습니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageRemover.java (1)

7-14: LGTM!

컴포넌트가 단일 책임 원칙에 따라 잘 설계되었습니다. 리포지토리 삭제 로직을 캡슐화하여 재사용성과 테스트 용이성을 제공합니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageSaver.java (1)

10-17: LGTM!

컴포넌트가 일괄 저장 로직을 명확하게 캡슐화하고 있으며, SiteMapImageRemover와 대칭적인 구조로 일관성을 유지하고 있습니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/controller/EventSiteMapImageController.java (1)

14-26: LGTM!

REST 컨트롤러가 명확하고 일관성 있게 구현되었습니다. 기존의 @EventIdPathVariable 어노테이션을 활용하여 검증을 처리하고, ApiResponseUtil을 통해 표준화된 응답 형식을 유지하고 있습니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/exception/SiteMapImageApiException.java (1)

8-12: LGTM!

API 예외 클래스가 간결하고 명확하게 구현되었습니다. ErrorCode를 캡슐화하여 일관된 에러 처리 패턴을 따르고 있습니다.

src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/req/AdminEventUpdateRequest.java (1)

54-57: LGTM!

새로운 siteMapImages 필드가 적절하게 추가되었습니다. 기존 images 필드와 동일한 타입(List<AdminEventImageRequest>)을 재사용하고 @Valid 어노테이션으로 중첩 검증을 보장하여 일관성을 유지하고 있습니다.

src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/req/AdminEventWithTicketCreateRequest.java (1)

90-93: LGTM! siteMapImages 필드 추가가 적절합니다.

siteMapImages@Valid로 중첩 검증이 적용되었고, images 필드와 달리 @NotNull 제약이 없어 선택적 필드로 처리됩니다. 사이트맵 이미지가 필수가 아닌 경우 이 설계가 적절합니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/service/EventSiteMapImageService.java (1)

26-43: 전체 구조 승인

기존 EventService.getEventDetail() 패턴과 일관성 있게 구현되었습니다. 예외 변환, 정렬, DTO 매핑 로직이 적절합니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/dto/res/EventSiteMapGetResponse.java (1)

6-21: LGTM! DTO 구조가 적절합니다.

Java record를 활용한 간결한 DTO 설계와 팩토리 메서드 패턴이 기존 코드베이스(AdminEventImageInfo.of)와 일관성을 유지합니다.

src/main/java/com/permitseoul/permitserver/domain/admin/event/api/dto/res/AdminEventDetailResponse.java (1)

24-25: LGTM! siteMapImages 필드 추가가 일관성 있게 구현되었습니다.

기존 AdminEventImageInfo를 재사용하여 사이트맵 이미지를 표현하고, 팩토리 메서드에도 적절히 반영되었습니다. 레코드 필드, 팩토리 메서드 시그니처, 생성자 호출의 파라미터 순서가 일치합니다.

Also applies to: 44-45, 63-64

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/component/SiteMapImageRetriever.java (1)

17-25: LGTM! 방어적 null 처리가 적용되었습니다.

Optional.ofNullable을 사용한 null 안전 처리가 적절합니다. Spring Data JPA 리포지토리는 일반적으로 빈 컬렉션을 반환하지만, 이 방어적 코딩은 안전성을 보장합니다. 엔티티-도메인 변환도 깔끔합니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/repository/EventSiteMapImageRepository.java (1)

13-15: LGTM!

@ModifyingclearAutomaticallyflushAutomatically 옵션이 적절히 설정되어 있어 벌크 삭제 후 영속성 컨텍스트 동기화가 보장됩니다.

src/main/java/com/permitseoul/permitserver/domain/admin/event/api/service/AdminEventService.java (4)

65-67: LGTM!

사이트맵 이미지 관련 컴포넌트들이 적절히 의존성으로 주입되었습니다.


100-105: LGTM!

사이트맵 이미지 조회 및 정렬 로직이 기존 이벤트 이미지 처리 패턴과 일관성 있게 구현되었습니다.


200-206: 사이트맵 이미지 전체 삭제 시나리오 확인 필요

현재 구현에서 eventSiteMapImages가 null 또는 빈 리스트일 경우 기존 이미지가 보존됩니다. 만약 모든 사이트맵 이미지를 삭제해야 하는 요구사항이 있다면, 이 로직으로는 불가능합니다. 의도된 동작인지 확인해 주세요.


216-228: LGTM!

saveEventImages와 동일한 패턴으로 구현되었으며, IntStream을 활용한 시퀀스 할당과 URL trim 처리가 적절합니다.

src/main/java/com/permitseoul/permitserver/domain/event/api/service/EventService.java (1)

58-60: 이미지 순서 정렬 로직이 올바르게 구현되었습니다.

sequence 기준으로 이미지를 정렬하여 UI에 일관된 순서로 표시되도록 보장한 점이 좋습니다. 데이터베이스에서 순서가 보장되지 않을 수 있으므로 애플리케이션 레벨에서 명시적으로 정렬하는 것이 안전한 접근 방식입니다.

src/main/java/com/permitseoul/permitserver/domain/eventimage/core/domain/entity/EventImageEntity.java (1)

19-19: 데이터베이스 스키마 변경이 반영되었는지 확인하세요.

image_url 컬럼에 columnDefinition = "TEXT"를 추가한 코드 변경은 적절합니다. 그러나 이 프로젝트는 Flyway나 Liquibase 같은 명시적 마이그레이션 도구를 사용하지 않으므로, 다음 중 하나를 확인해야 합니다:

  • Hibernate의 spring.jpa.hibernate.ddl-auto 설정이 update 또는 create로 구성되어 있는지 확인
  • 또는 데이터베이스 스키마를 수동으로 업데이트하여 image_url 컬럼이 TEXT 타입으로 생성되었는지 검증

기존 프로덕션 데이터가 있다면 호환성을 사전에 확인하세요.

src/main/java/com/permitseoul/permitserver/domain/eventtimetable/blockmedia/domain/entity/TimetableBlockMediaEntity.java (1)

29-29: mediaUrl 컬럼의 TEXT 타입 정의 확인 완료

mediaUrl 컬럼에 columnDefinition = "TEXT"가 올바르게 적용되었으며, EventImageEntityimage_url 컬럼과 일관된 패턴입니다. 다만, 이 프로젝트에는 명시적인 데이터베이스 마이그레이션 스크립트(Flyway/Liquibase)가 없습니다. Hibernate의 자동 DDL 생성 기능을 사용하고 있으므로, spring.jpa.hibernate.ddl-auto 설정이 올바르게 구성되어 있는지 확인하세요.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a 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 (1)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/service/EventSiteMapImageService.java (1)

25-43: 이벤트 조회가 불필요하게 중복되어 있습니다.

Line 28에서 Event 엔티티를 조회하지만, Line 29에서는 이미 파라미터로 받은 eventId와 동일한 event.getEventId()를 사용하고 있습니다. 이는 불필요한 데이터베이스 조회를 발생시킵니다.

만약 이벤트 존재 여부 검증이 목적이라면, 다음과 같이 개선할 수 있습니다:

  • 옵션 1: eventId를 직접 사용하고, SiteMapImageRetriever에서 이벤트가 없을 때 예외를 던지도록 구현
  • 옵션 2: 이벤트 존재 여부만 확인하는 경량 메서드 사용 (예: eventRetriever.validateEventExists(eventId))

옵션 1 적용 (권장):

     @Transactional(readOnly = true)
     public EventSiteMapGetResponse getEventSiteMapImages(final long eventId) {
         try {
-            final Event event = eventRetriever.findEventById(eventId);
-            final List<EventSiteMapImage> eventSiteMapImages = siteMapImageRetriever.findAllEventSiteMapImagesByEventId(event.getEventId());
+            final List<EventSiteMapImage> eventSiteMapImages = siteMapImageRetriever.findAllEventSiteMapImagesByEventId(eventId);
             if (ObjectUtils.isEmpty(eventSiteMapImages)) {
                 throw new SiteMapImageApiException(ErrorCode.NOT_FOUND_SITE_MAP_IMAGE);
             }

옵션 2 적용 (이벤트 검증이 반드시 필요한 경우):

     @Transactional(readOnly = true)
     public EventSiteMapGetResponse getEventSiteMapImages(final long eventId) {
         try {
-            final Event event = eventRetriever.findEventById(eventId);
-            final List<EventSiteMapImage> eventSiteMapImages = siteMapImageRetriever.findAllEventSiteMapImagesByEventId(event.getEventId());
+            eventRetriever.validateEventExists(eventId);  // 경량 검증 메서드 사용
+            final List<EventSiteMapImage> eventSiteMapImages = siteMapImageRetriever.findAllEventSiteMapImagesByEventId(eventId);
             if (ObjectUtils.isEmpty(eventSiteMapImages)) {
                 throw new SiteMapImageApiException(ErrorCode.NOT_FOUND_SITE_MAP_IMAGE);
             }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ffe2b92 and b97d691.

📒 Files selected for processing (2)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/dto/res/EventSiteMapGetResponse.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/service/EventSiteMapImageService.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/dto/res/EventSiteMapGetResponse.java
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: sjk4618
Repo: PERMIT-SEOUL/permit-server PR: 48
File: src/main/java/com/permitseoul/permitserver/domain/guest/core/domain/entity/GuestEntity.java:31-37
Timestamp: 2025-07-15T09:37:32.765Z
Learning: sjk4618 prefers to implement factory methods or public constructors for entities when they are actually needed, rather than creating them proactively.

Copy link

@coderabbitai coderabbitai bot left a 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/permitseoul/permitserver/domain/sitemapimage/api/EventSiteMapExceptionHandler.java (2)

10-11: 클래스명과 스코프의 일관성을 고려하세요.

클래스명은 EventSiteMapExceptionHandler로 이벤트에 특화된 것처럼 보이지만, basePackages는 범용적인 sitemapimage 패키지를 대상으로 하고 있습니다. 만약 이 핸들러가 이벤트 관련 사이트맵 이미지에만 특화되어 있다면 패키지 구조나 스코프도 그에 맞춰 조정하거나, 범용적으로 사용할 예정이라면 클래스명을 SiteMapImageExceptionHandler로 변경하는 것이 더 명확합니다.

-public class EventSiteMapExceptionHandler {
+public class SiteMapImageExceptionHandler {

13-16: 로깅 추가를 고려하세요.

예외 핸들러에 로그를 추가하면 프로덕션 환경에서 디버깅에 도움이 됩니다. 또한 JavaDoc을 추가하여 핸들러의 목적과 동작을 문서화하는 것도 권장됩니다.

+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
 @RestControllerAdvice(basePackages = "com.permitseoul.permitserver.domain.sitemapimage")
 public class EventSiteMapExceptionHandler {
 
+    /**
+     * SiteMapImageApiException을 처리하여 표준화된 API 에러 응답을 반환합니다.
+     *
+     * @param e 발생한 SiteMapImageApiException
+     * @return 에러 코드를 포함한 표준 응답
+     */
     @ExceptionHandler(SiteMapImageApiException.class)
     public ResponseEntity<BaseResponse<?>> handleSiteMapImageApiException(final SiteMapImageApiException e) {
+        log.warn("SiteMapImageApiException occurred: {}", e.getErrorCode(), e);
         return ApiResponseUtil.failure(e.getErrorCode());
     }
 }
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/entity/EventSiteMapImageEntity.java (1)

38-42: 팩토리 메서드에 입력 검증 추가를 고려하세요.

create 메서드가 입력 파라미터에 대한 검증 없이 엔티티를 생성하고 있습니다. 다음과 같은 검증을 추가하면 런타임 오류를 방지할 수 있습니다:

  • sitemapImageUrl이 null이거나 빈 문자열인지 확인
  • sequence 값의 유효 범위 확인 (예: 음수 불가)
  • eventId 값의 유효성 확인 (예: 양수 여부)

서비스 레이어에서 이미 검증이 이루어지고 있다면 무시하셔도 됩니다.

필요시 다음과 같은 검증을 추가할 수 있습니다:

 public static EventSiteMapImageEntity create(final String sitemapImageUrl,
                                              final int sequence,
                                              final long eventId) {
+    if (sitemapImageUrl == null || sitemapImageUrl.isBlank()) {
+        throw new IllegalArgumentException("sitemapImageUrl은 null이거나 빈 값일 수 없습니다");
+    }
+    if (sequence < 0) {
+        throw new IllegalArgumentException("sequence는 음수일 수 없습니다");
+    }
+    if (eventId <= 0) {
+        throw new IllegalArgumentException("eventId는 양수여야 합니다");
+    }
     return new EventSiteMapImageEntity( sitemapImageUrl, sequence, eventId);
 }
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b97d691 and 09fe235.

📒 Files selected for processing (2)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/EventSiteMapExceptionHandler.java (1 hunks)
  • src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/entity/EventSiteMapImageEntity.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: sjk4618
Repo: PERMIT-SEOUL/permit-server PR: 48
File: src/main/java/com/permitseoul/permitserver/domain/guest/core/domain/entity/GuestEntity.java:31-37
Timestamp: 2025-07-15T09:37:32.765Z
Learning: sjk4618 prefers to implement factory methods or public constructors for entities when they are actually needed, rather than creating them proactively.
🧬 Code graph analysis (1)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/EventSiteMapExceptionHandler.java (1)
src/main/java/com/permitseoul/permitserver/global/response/ApiResponseUtil.java (1)
  • ApiResponseUtil (7-29)
🔇 Additional comments (3)
src/main/java/com/permitseoul/permitserver/domain/sitemapimage/api/EventSiteMapExceptionHandler.java (1)

1-9: LGTM!

패키지 구조와 임포트 구성이 적절합니다.

src/main/java/com/permitseoul/permitserver/domain/sitemapimage/core/domain/entity/EventSiteMapImageEntity.java (2)

15-18: 이전 리뷰 피드백이 반영되었습니다.

ID 필드가 이제 private으로 올바르게 선언되어 캡슐화가 유지되고 있습니다. 이전 리뷰에서 지적된 사항이 잘 수정되었습니다.


26-27: EventSiteMapImage 삭제 로직이 서비스 레이어에 구현되어 있습니다.

eventId가 JPA 관계 매핑 없이 primitive long으로 저장되는 것은 의도된 설계입니다. 이 설계 선택은 다음과 같이 검증되었습니다:

  • AdminEventService.updateEvent() 메서드에서 sitemap 이미지 업데이트 시 siteMapImageRemover.deleteAllSiteMapImages(eventId)를 호출하여 기존 이미지를 삭제합니다.
  • EventSiteMapImageRepository@Modifying 애노테이션을 사용한 쿼리로 deleteAllByEventId(eventId) 메서드를 구현하며, clearAutomatically=trueflushAutomatically=true 옵션으로 트랜잭션을 안전하게 관리합니다.
  • 수동 FK 관리는 잘 구현되어 있습니다.

이 설계는 순환 참조를 방지하면서도 필요한 삭제 로직을 서비스 레이어에서 명시적으로 관리하는 합리적인 접근입니다.

@sjk4618 sjk4618 merged commit 20e6423 into dev Dec 17, 2025
2 checks passed
@sjk4618 sjk4618 deleted the feat/#199 branch December 17, 2025 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 행사 siteMap 조회 api 구현 및 siteMap 등록 추가

2 participants