Skip to content

feat: 행사 API 추가#534

Draft
dh2906 wants to merge 7 commits intodevelopfrom
feat/festival-api
Draft

feat: 행사 API 추가#534
dh2906 wants to merge 7 commits intodevelopfrom
feat/festival-api

Conversation

@dh2906
Copy link
Copy Markdown
Contributor

@dh2906 dh2906 commented Apr 13, 2026

🔍 개요


🚀 주요 변경 내용


💬 참고 사항

  • 미완성 상태입니다

  • AI한테 디자인만 주고 구현시킨거라 수정, 검토할 사항이 많아요

  • 로컬 브랜치를 정리하기 위해 임시로 올려둡니다


✅ Checklist (완료 조건)

  • 코드 스타일 가이드 준수
  • 테스트 코드 포함됨
  • Reviewers / Assignees / Labels 지정 완료
  • 보안 및 민감 정보 검증 (API 키, 환경 변수, 개인정보 등)

dh2906 added 7 commits April 12, 2026 17:07
- 행사 화면 설계를 실제 구현으로 이어갈 수 있도록 event, program, booth, map, mini_event, content 테이블을 먼저 정의한다.
- 읽기 API를 단계적으로 붙일 수 있게 엔티티와 저장소를 최소 필드 중심으로 맞춰 두고 기존 도메인 패턴과 정합성을 유지한다.
- 행사 기능이 없는 현재 코드베이스에서 목업 응답으로 흐르지 않도록 DB 스키마와 조회 기반을 먼저 고정한다.
- 디자인에서 우선 필요한 행사 홈, 프로그램, 부스, 맵, 미니 이벤트, 콘텐츠 조회 계약을 이벤트 전용 API로 정리한다.
- 응답 DTO와 서비스 골격을 먼저 고정해 이후 구현 단계가 문서와 코드에서 같은 스펙을 따르도록 만든다.
- 행사 미존재 상황은 공용 응답 코드로 통일해 이후 세부 조회 구현에서도 동일한 예외 처리 기준을 유지한다.
- 부스 맵, 미니 이벤트, 콘텐츠 목록이 실제 저장소 조회 결과를 그대로 응답하도록 연결해 행사 화면의 남은 읽기 API를 닫는다.
- 맵 구역 값은 부스 목록과 같은 기준을 재사용해 프론트가 별도 변환 로직 없이 화면 상태를 맞출 수 있게 한다.
- 콘텐츠 필터는 enum 이름과 정확히 맞는 경우만 허용해 의도하지 않은 부분 일치로 잘못된 목록이 섞이는 상황을 막는다.
- 행사 홈, 부스 맵, 미니 이벤트, 콘텐츠 조회가 저장소 결과를 기대한 응답 DTO로 변환하는지 확인한다.
- 페이지 계산과 카테고리 필터처럼 목록 조회에서 깨지기 쉬운 규칙을 테스트로 고정한다.
- protected 생성자를 가진 엔티티도 서비스 단위 테스트에서 안전하게 다룰 수 있도록 fixture 생성 방식을 정리한다.
- EventController를 실제 REST 빈으로 열어 행사 조회 엔드포인트가 애플리케이션 컨텍스트에서 정상 매핑되도록 맞춘다.
- 홈, 부스 맵, 콘텐츠 조회 시나리오를 HTTP 레벨에서 검증해 서비스 테스트만으로 놓치기 쉬운 직렬화와 파라미터 바인딩을 함께 고정한다.
- event 테이블군에 대한 최소한의 통합 안전망을 추가해 이후 조회 스펙 확장 시 회귀를 빠르게 감지할 수 있게 한다.
- 행사 상태 필드를 EventStatus enum으로 맞춰 모델 타입 일관성을 회복했다
- 목록 조회의 수동 페이지 계산을 공통화해 같은 계산 로직이 여러 메서드에서 다시 갈라지지 않게 했다
- 사용되지 않는 EventQueryRepository를 제거해 현재 구현 범위와 맞지 않는 빈 껍데기를 정리했다
@dh2906 dh2906 self-assigned this Apr 13, 2026
@dh2906 dh2906 added the 기능 새로운 기능을 개발합니다. label Apr 13, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

📝 Walkthrough

Walkthrough

Event 도메인에 대한 REST API 엔드포인트 세트를 추가합니다. EventApi 인터페이스, EventController 구현, 관련 DTO 클래스, JPA 엔티티, 리포지토리, 서비스 로직, DB 마이그레이션 및 통합/단위 테스트를 포함합니다.

Changes

Cohort / File(s) Summary
컨트롤러 및 API 인터페이스
src/main/java/gg/agit/konect/domain/event/controller/EventApi.java, src/main/java/gg/agit/konect/domain/event/controller/EventController.java
REST API 엔드포인트 인터페이스(EventApi) 정의 및 구현(EventController). 이벤트 홈, 프로그램, 부스, 부스 맵, 미니 이벤트, 컨텐츠 조회 6개 엔드포인트 제공.
응답 DTO
src/main/java/gg/agit/konect/domain/event/dto/EventHomeResponse.java, src/main/java/gg/agit/konect/domain/event/dto/EventProgramsResponse.java, src/main/java/gg/agit/konect/domain/event/dto/EventBoothsResponse.java, src/main/java/gg/agit/konect/domain/event/dto/EventBoothMapResponse.java, src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventsResponse.java, src/main/java/gg/agit/konect/domain/event/dto/EventContentsResponse.java, src/main/java/gg/agit/konect/domain/event/dto/...SummaryResponse.java
페이지네이션 메타데이터, 중첩된 요약 응답 클래스, 사용자 상태 정보를 포함하는 이뮤터블 DTO 레코드들.
Enum 타입
src/main/java/gg/agit/konect/domain/event/enums/EventProgramType.java, src/main/java/gg/agit/konect/domain/event/enums/EventProgressStatus.java, src/main/java/gg/agit/konect/domain/event/enums/EventStatus.java, src/main/java/gg/agit/konect/domain/event/enums/EventContentType.java, src/main/java/gg/agit/konect/domain/event/enums/EventBoothMapItemStatus.java
프로그램 타입(ALL, POINT, RESONANCE), 진행 상태(UPCOMING, ONGOING, ENDED), 이벤트 상태(DRAFT, PUBLISHED, ENDED), 컨텐츠 타입(ARTICLE, IMAGE, VIDEO), 부스 맵 항목 상태(OPEN, CLOSED, HIDDEN) 정의.
JPA 엔티티
src/main/java/gg/agit/konect/domain/event/model/Event.java, src/main/java/gg/agit/konect/domain/event/model/EventProgram.java, src/main/java/gg/agit/konect/domain/event/model/EventBooth.java, src/main/java/gg/agit/konect/domain/event/model/EventBoothMap.java, src/main/java/gg/agit/konect/domain/event/model/EventBoothMapItem.java, src/main/java/gg/agit/konect/domain/event/model/EventMiniEvent.java, src/main/java/gg/agit/konect/domain/event/model/EventContent.java
이벤트, 프로그램, 부스, 부스 맵, 부스 맵 항목, 미니 이벤트, 컨텐츠 엔티티. 외래키 관계 및 Lombok 주석 포함.
리포지토리
src/main/java/gg/agit/konect/domain/event/repository/EventRepository.java, src/main/java/gg/agit/konect/domain/event/repository/EventProgramRepository.java, src/main/java/gg/agit/konect/domain/event/repository/EventBoothRepository.java, src/main/java/gg/agit/konect/domain/event/repository/EventBoothMapRepository.java, src/main/java/gg/agit/konect/domain/event/repository/EventBoothMapItemRepository.java, src/main/java/gg/agit/konect/domain/event/repository/EventMiniEventRepository.java, src/main/java/gg/agit/konect/domain/event/repository/EventContentRepository.java
Spring Data 리포지토리 인터페이스. 파생 쿼리 메서드(findBy*, countBy*, orderBy) 정의.
서비스 레이어
src/main/java/gg/agit/konect/domain/event/service/EventService.java
트랜잭션 읽기 전용 서비스. 6개 공개 메서드로 이벤트 데이터 조회 및 DTO 매핑 구현. 페이지네이션 로직, 필터링, enum 변환, 존 추출 포함. 이벤트 부재 시 NOT_FOUND_EVENT 예외 발생.
전역 응답 코드
src/main/java/gg/agit/konect/global/code/ApiResponseCode.java
이벤트 미발견(404) 응답 코드 추가: "행사를 찾을 수 없습니다."
데이터베이스 마이그레이션
src/main/resources/db/migration/V70__add_event_tables.sql
event, event_program, event_booth, event_booth_map, event_booth_map_item, event_mini_event, event_content 테이블 생성. CASCADE 삭제, enum 컬럼, 타임스탬프, 제약 조건 포함.
통합 테스트
src/test/java/gg/agit/konect/integration/domain/event/EventApiTest.java
3개 엔드포인트의 통합 테스트(/home, /booth-map, /contents). 성공/실패 시나리오, 페이지네이션, 필터링, 404 오류 검증.
단위 테스트
src/test/java/gg/agit/konect/unit/domain/event/service/EventServiceTest.java
EventService 메서드의 단위 테스트(getEventHome, getEventBoothMap, getEventMiniEvents, getEventContents, 예외). 목 리포지토리, 반사 기반 픽스처 헬퍼.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant EventController
    participant EventService
    participant EventRepo as Repository Layer
    participant Database

    Client->>EventController: GET /events/{eventId}/home
    EventController->>EventService: getEventHome(eventId, userId)
    EventService->>EventRepo: findById(eventId)
    EventRepo->>Database: SELECT event WHERE id = ?
    Database-->>EventRepo: Event entity
    EventRepo-->>EventService: Event
    EventService->>EventRepo: countByEventId(eventId)
    EventRepo->>Database: COUNT queries (programs, booths, etc.)
    Database-->>EventRepo: counts
    EventRepo-->>EventService: counts
    EventService->>EventService: assemble EventHomeResponse
    EventService-->>EventController: EventHomeResponse
    EventController-->>Client: ResponseEntity.ok(EventHomeResponse)
Loading
sequenceDiagram
    participant Client
    participant EventController
    participant EventService
    participant EventRepo as Repository Layer
    participant Database

    Client->>EventController: GET /events/{eventId}/booth-map
    EventController->>EventService: getEventBoothMap(eventId)
    EventService->>EventRepo: findByEventId(eventId)
    EventRepo->>Database: SELECT event_booth_map WHERE event_id = ?
    Database-->>EventRepo: EventBoothMap entity
    EventRepo-->>EventService: EventBoothMap
    EventService->>EventRepo: findAllByEventBoothMapIdOrderByIdAsc(mapId)
    EventRepo->>Database: SELECT event_booth_map_item WHERE event_booth_map_id = ?
    Database-->>EventRepo: EventBoothMapItem list
    EventRepo-->>EventService: items
    EventService->>EventService: extract zones, map to DTOs
    EventService-->>EventController: EventBoothMapResponse
    EventController-->>Client: ResponseEntity.ok(EventBoothMapResponse)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • #345: 새 이벤트 통합 테스트가 의존하는 IntegrationTestSupport 및 테스트 설정 인프라 수정.

Suggested labels

테스트

Poem

🐰 부스와 프로그램이 줄지어
이벤트 API가 춤춘다 팡팡!
데이터베이스는 신나게 노래하고
테스트 코드가 안녕을 말한다
행사의 마법이 펼쳐진다 ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 변경 사항의 핵심을 간결하게 요약하고 있습니다. '행사 API 추가'는 전체 PR의 주요 목적을 명확하게 반영합니다.
Description check ✅ Passed 설명은 미완성 상태임을 명시하고 있으나, 변경 사항과 관련된 내용입니다. PR이 행사 API 추가에 관한 것이고 설명도 이를 인정하고 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/festival-api

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.

@dh2906 dh2906 marked this pull request as draft April 13, 2026 01:19
);
}

public EventMiniEventsResponse getEventMiniEvents(Integer eventId, Integer page, Integer limit, Integer userId) {
}

public EventProgramsResponse getEventPrograms(Integer eventId, EventProgramType type, Integer page, Integer limit,
Integer userId) {
private final EventMiniEventRepository eventMiniEventRepository;
private final EventContentRepository eventContentRepository;

public EventHomeResponse getEventHome(Integer eventId, Integer userId) {
@github-actions
Copy link
Copy Markdown

🧪 JaCoCo Coverage Report (Changed Files)

Summary

  • Overall Coverage: 83.7% ✅
  • Covered Lines: 231 / 276
  • Changed Files: 33

Coverage by File

Class Coverage Lines Status
EventController
gg.agit.konect.domain.event.controller
50.0% 3/6 ⚠️
EventService
gg.agit.konect.domain.event.service
67.4% 87/129 ⚠️
ApiResponseCode
gg.agit.konect.global.code
100.0% 121/121
EventProgramType
gg.agit.konect.domain.event.enums
100.0% 4/4
EventBoothMapItemStatus
gg.agit.konect.domain.event.enums
100.0% 4/4
EventStatus
gg.agit.konect.domain.event.enums
100.0% 4/4
EventProgressStatus
gg.agit.konect.domain.event.enums
100.0% 4/4
EventContentType
gg.agit.konect.domain.event.enums
100.0% 4/4

📊 View Workflow Run

Copy link
Copy Markdown

@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: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventSummaryResponse.java`:
- Around line 3-10: EventMiniEventSummaryResponse.joined is currently hardcoded
to false in EventService (the DTO population around the block that constructs
EventMiniEventSummaryResponse), which breaks semantics; update the code that
builds EventMiniEventSummaryResponse in EventService to compute the real
participation state for the current user (e.g., call your participant lookup
like EventParticipantRepository.existsByUserIdAndMiniEventId(userId,
miniEventId) or a service wrapper) and pass that boolean into the record, or if
real-time participation cannot be supported yet, change the DTO signature
(EventMiniEventSummaryResponse) to use Boolean joined (nullable) or remove the
field to avoid misleading clients. Ensure you reference
EventMiniEventSummaryResponse and the method in EventService that maps/creates
the DTO so the change is applied where the DTO is instantiated.

In `@src/main/java/gg/agit/konect/domain/event/model/Event.java`:
- Around line 40-41: Event 엔티티의 private String notice 필드(Event.java)와 Flyway
마이그레이션 V70__add_event_tables.sql의 event 테이블 스키마가 불일치합니다; 해결하려면 둘 중 하나를 선택해 일치시켜
주세요: (1) 영구 해결로 V70 또는 새로운 Flyway 마이그레이션에 event.notice 컬럼(예: TEXT 타입) 추가하거나, (2)
모델 우선이라면 Event 클래스에서 notice 필드와 관련 게터/세터/사용처를 제거하여 엔티티를 스키마에 맞추세요; 변경 후 마이그레이션을
실행하고 관련 저장/조회 테스트 및 통합 시나리오를 검증해 오류(Unknown column) 재발생이 없는지 확인하세요.

In
`@src/main/java/gg/agit/konect/domain/event/repository/EventContentRepository.java`:
- Line 11: The repository method currently loads all contents into memory;
change EventContentRepository's method signature
findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId) to a Pageable-based
query returning Page<EventContent>, e.g. add a Pageable parameter and return
Page<EventContent>, and update any callers to pass a Pageable and handle the
Page result; apply the same pattern for EventProgramRepository,
EventMiniEventRepository, and EventBoothRepository (adjust method signatures to
accept Pageable and return Page<T> and update their callers accordingly).

In
`@src/main/java/gg/agit/konect/domain/event/repository/EventMiniEventRepository.java`:
- Line 11: In EventMiniEventRepository change the method signature
findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId) to return a Page
and accept a Pageable (i.e., Page<EventMiniEvent>
findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId, Pageable pageable))
so DB-level pagination is used; update any callers (service code using
findAllByEventIdOrderByDisplayOrderAscIdAsc) to pass a PageRequest
(PageRequest.of(page, size, sort)) instead of paging in memory. Ensure imports
for org.springframework.data.domain.Page and Pageable are added and adjust any
variable handling from List to Page.

In `@src/main/java/gg/agit/konect/domain/event/service/EventService.java`:
- Around line 120-122: The getEventBoothMap method currently treats a missing
booth map as NOT_FOUND_EVENT; first call the existing getEvent(eventId) to
validate the event exists, then query
eventBoothMapRepository.findByEventId(eventId) and if the map is absent handle
it separately (either throw a new error like
CustomException.of(NOT_FOUND_EVENT_MAP) or return an empty/nullable
EventBoothMapResponse per API contract) instead of reusing NOT_FOUND_EVENT;
update references in getEventBoothMap, and ensure any new error code or empty
response behavior is consistent with the API.
- Around line 51-69: getEventHome currently returns a hard-coded
EventHomeResponse.UserStatus(0,0); instead, look up the actual user aggregates
using the provided userId and populate UserStatus (e.g., call repository methods
to compute participation count and points for the given user/event inside
getEventHome) and pass those values into new EventHomeResponse.UserStatus(...);
if userId is null or the aggregates are not ready, avoid returning the
misleading zeros by either omitting the userStatus field from the response
contract or returning null/Optional as per the API contract; update getEventHome
and any related response construction logic (EventHomeResponse and
EventHomeResponse.UserStatus usage) to reflect this change.
- Around line 72-81: The current getEventPrograms loads all EventProgram rows
via eventProgramRepository.findAllByEventIdOrderByDisplayOrderAscIdAsc and then
paginates in-memory using paginate; change this to push sorting, filtering and
paging into the DB by adding repository methods that accept a Pageable (e.g.
Page<EventProgram> findByEventIdAndTypeOrderByDisplayOrderAscIdAsc(Integer
eventId, EventProgramType type, Pageable p) and Page<EventProgram>
findByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId, Pageable p)) or use a
single method with optional type criteria, construct a PageRequest with
Sort.by("displayOrder").ascending().and(Sort.by("id").ascending()) in
getEventPrograms, call the repository to get a Page<EventProgram>, and convert
page.getContent() and page metadata into your PagedResult instead of using
paginate; apply the same change for other places that call
eventProgramRepository.findAllByEventIdOrderByDisplayOrderAscIdAsc and paginate
(the other methods referenced in the review).

In `@src/main/resources/db/migration/V70__add_event_tables.sql`:
- Line 1: The migration uses CREATE TABLE IF NOT EXISTS (e.g., the statement
"CREATE TABLE IF NOT EXISTS event") which must be changed to fail on schema
drift; remove all occurrences of "IF NOT EXISTS" in this file so each CREATE
TABLE is unconditional, and ensure every CREATE TABLE statement (including the
ones at the other noted occurrences) is updated accordingly; if this migration
has already been applied in production and cannot be safely changed, add a
blocking comment on the PR stating the risk instead of editing the deployed
migration.
- Around line 15-30: Add composite indexes to cover the common lookup + sort
pattern: create an index on (event_id, display_order, id) for the event_program,
event_mini_event, and event_content tables to avoid filesort on queries that
filter by event_id and order by display_order,id; update the
V70__add_event_tables.sql migration by adding appropriate CREATE INDEX
statements (or inline INDEX definitions) referencing the exact table names
event_program, event_mini_event, event_content and the columns event_id,
display_order, id.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 320b07d6-ab1c-45e6-8d2e-e2ee44f07a2b

📥 Commits

Reviewing files that changed from the base of the PR and between ebe0efc and e7057a5.

📒 Files selected for processing (36)
  • src/main/java/gg/agit/konect/domain/event/controller/EventApi.java
  • src/main/java/gg/agit/konect/domain/event/controller/EventController.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothMapResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventContentSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventContentsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventHomeResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventProgramSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventProgramsResponse.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventBoothMapItemStatus.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventContentType.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventProgramType.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventProgressStatus.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventStatus.java
  • src/main/java/gg/agit/konect/domain/event/model/Event.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBooth.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBoothMap.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBoothMapItem.java
  • src/main/java/gg/agit/konect/domain/event/model/EventContent.java
  • src/main/java/gg/agit/konect/domain/event/model/EventMiniEvent.java
  • src/main/java/gg/agit/konect/domain/event/model/EventProgram.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothMapItemRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothMapRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventContentRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventMiniEventRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventProgramRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventRepository.java
  • src/main/java/gg/agit/konect/domain/event/service/EventService.java
  • src/main/java/gg/agit/konect/global/code/ApiResponseCode.java
  • src/main/resources/db/migration/V70__add_event_tables.sql
  • src/test/java/gg/agit/konect/integration/domain/event/EventApiTest.java
  • src/test/java/gg/agit/konect/unit/domain/event/service/EventServiceTest.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Code Style Check
  • GitHub Check: coverage
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (3)
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.

  • 코멘트는 반드시 한국어로 작성한다.
  • 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
  • 각 코멘트 첫 줄에 심각도를 [LEVEL: high|medium|low] 형식으로 반드시 표기한다.
  • 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
  • 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
  • 가능하면 재현 조건 및 실패 시나리오도 포함한다.
  • 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
  • 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
  • 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
  • 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
  • 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.

Files:

  • src/main/java/gg/agit/konect/domain/event/enums/EventContentType.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventBoothMapItemStatus.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventStatus.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventProgressStatus.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventProgramType.java
  • src/main/java/gg/agit/konect/global/code/ApiResponseCode.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventContentsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventContentSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventProgramSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventRepository.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventProgramsResponse.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothMapItemRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothMapRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventProgramRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventContentRepository.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothMapResponse.java
  • src/main/java/gg/agit/konect/domain/event/model/EventProgram.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBooth.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventHomeResponse.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBoothMap.java
  • src/main/java/gg/agit/konect/domain/event/model/EventContent.java
  • src/main/java/gg/agit/konect/domain/event/model/EventMiniEvent.java
  • src/main/java/gg/agit/konect/domain/event/controller/EventController.java
  • src/main/java/gg/agit/konect/domain/event/model/Event.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventMiniEventRepository.java
  • src/main/java/gg/agit/konect/domain/event/service/EventService.java
  • src/main/java/gg/agit/konect/domain/event/controller/EventApi.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBoothMapItem.java
**/*

⚙️ CodeRabbit configuration file

**/*: 공통 리뷰 톤 가이드:

  • 모든 코멘트는 첫 줄에 [LEVEL: ...] 태그를 포함한다.
  • 과장된 표현 없이 사실 기반으로 작성한다.
  • 한 코멘트에는 하나의 이슈만 다룬다.
  • 코드 예시가 필요하면 최소 수정 예시를 제시한다.
  • 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.

Files:

  • src/main/java/gg/agit/konect/domain/event/enums/EventContentType.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventBoothMapItemStatus.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventStatus.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventProgressStatus.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/enums/EventProgramType.java
  • src/main/java/gg/agit/konect/global/code/ApiResponseCode.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventContentsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventsResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventContentSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventProgramSummaryResponse.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventRepository.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventProgramsResponse.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothMapItemRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothMapRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventBoothRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventProgramRepository.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventContentRepository.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventBoothMapResponse.java
  • src/main/java/gg/agit/konect/domain/event/model/EventProgram.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBooth.java
  • src/main/java/gg/agit/konect/domain/event/dto/EventHomeResponse.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBoothMap.java
  • src/main/java/gg/agit/konect/domain/event/model/EventContent.java
  • src/main/java/gg/agit/konect/domain/event/model/EventMiniEvent.java
  • src/main/java/gg/agit/konect/domain/event/controller/EventController.java
  • src/test/java/gg/agit/konect/integration/domain/event/EventApiTest.java
  • src/main/java/gg/agit/konect/domain/event/model/Event.java
  • src/test/java/gg/agit/konect/unit/domain/event/service/EventServiceTest.java
  • src/main/java/gg/agit/konect/domain/event/repository/EventMiniEventRepository.java
  • src/main/resources/db/migration/V70__add_event_tables.sql
  • src/main/java/gg/agit/konect/domain/event/service/EventService.java
  • src/main/java/gg/agit/konect/domain/event/controller/EventApi.java
  • src/main/java/gg/agit/konect/domain/event/model/EventBoothMapItem.java
src/main/resources/db/migration/**/*.sql

⚙️ CodeRabbit configuration file

src/main/resources/db/migration/**/*.sql: Flyway 마이그레이션 리뷰 규칙:

  • 버전 파일명 규칙(V{number}__{description}.sql) 위반 여부를 우선 확인한다.
  • 이미 배포된 마이그레이션 수정/재번호 부여 위험이 있으면 반드시 차단 코멘트를 남긴다.
  • 파괴적 변경(drop, rename 등)은 롤백 가능성과 운영 영향 관점에서 검토한다.

Files:

  • src/main/resources/db/migration/V70__add_event_tables.sql
🔇 Additional comments (1)
src/main/java/gg/agit/konect/domain/event/repository/EventProgramRepository.java (1)

11-11: [LEVEL: medium] 프로그램 페이지 조회 엔드포인트가 타입 필터링 없이 전체 프로그램을 DB에서 로드한 후 메모리에서 필터링과 페이지네이션을 처리하고 있습니다.
데이터 증가 시 불필요한 메모리 사용과 응답시간 증가가 발생합니다. 특히 getEventPrograms(), getEventBooths(), getEventContents() 등 여러 메서드에서 반복되는 패턴입니다.
필터 조건을 DB 쿼리에 포함시켜 매칭되는 항목만 로드하도록 개선하되, 페이지네이션과 totalCount 계산이 필터 후 기준이 되도록 조정하세요. 간단한 Pageable 추가만으로는 부족하며 필터링 로직도 함께 리팩토링이 필요합니다.

Comment on lines +3 to +10
public record EventMiniEventSummaryResponse(
Integer miniEventId,
String title,
String thumbnailUrl,
String description,
String reward,
String status,
boolean joined
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

[LEVEL: medium] Line 10의 joined 값이 현재 구현에서 상수로 고정되어 응답 의미가 깨집니다.
문제: src/main/java/gg/agit/konect/domain/event/service/EventService.java Line 241-251에서 EventMiniEventSummaryResponse.joined에 항상 false를 주입해 DTO가 사용자 참여 상태를 표현하지 못합니다.
영향: 실제 참여 사용자도 미참여로 내려가 버튼 상태/UX가 잘못될 수 있습니다.
제안: 참여 여부를 사용자 기준으로 조회해 채우거나, 기능 미지원 단계라면 joined를 nullable로 변경(또는 필드 제거)해 오해를 방지하세요. As per coding guidelines, "확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/gg/agit/konect/domain/event/dto/EventMiniEventSummaryResponse.java`
around lines 3 - 10, EventMiniEventSummaryResponse.joined is currently hardcoded
to false in EventService (the DTO population around the block that constructs
EventMiniEventSummaryResponse), which breaks semantics; update the code that
builds EventMiniEventSummaryResponse in EventService to compute the real
participation state for the current user (e.g., call your participant lookup
like EventParticipantRepository.existsByUserIdAndMiniEventId(userId,
miniEventId) or a service wrapper) and pass that boolean into the record, or if
real-time participation cannot be supported yet, change the DTO signature
(EventMiniEventSummaryResponse) to use Boolean joined (nullable) or remove the
field to avoid misleading clients. Ensure you reference
EventMiniEventSummaryResponse and the method in EventService that maps/creates
the DTO so the change is applied where the DTO is instantiated.

Comment on lines +40 to +41
@Column(name = "notice", columnDefinition = "TEXT")
private String notice;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

[LEVEL: high]
문제: Line [40-41]의 notice 필드는 엔티티에만 존재하고, src/main/resources/db/migration/V70__add_event_tables.sql Line [1-13]의 event 테이블에는 해당 컬럼이 없어 스키마 불일치입니다.
영향: 이벤트 조회/저장 시 notice가 포함된 SQL이 실행되면 운영 DB에서 Unknown column 'notice'로 500 오류가 발생할 수 있습니다(마이그레이션 직후 바로 재현 가능).
제안: Flyway 마이그레이션으로 event.notice를 추가하거나 엔티티에서 필드를 제거해 스키마와 모델을 반드시 일치시켜 주세요; As per coding guidelines "보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/gg/agit/konect/domain/event/model/Event.java` around lines 40 -
41, Event 엔티티의 private String notice 필드(Event.java)와 Flyway 마이그레이션
V70__add_event_tables.sql의 event 테이블 스키마가 불일치합니다; 해결하려면 둘 중 하나를 선택해 일치시켜 주세요:
(1) 영구 해결로 V70 또는 새로운 Flyway 마이그레이션에 event.notice 컬럼(예: TEXT 타입) 추가하거나, (2) 모델
우선이라면 Event 클래스에서 notice 필드와 관련 게터/세터/사용처를 제거하여 엔티티를 스키마에 맞추세요; 변경 후 마이그레이션을
실행하고 관련 저장/조회 테스트 및 통합 시나리오를 검증해 오류(Unknown column) 재발생이 없는지 확인하세요.


public interface EventContentRepository extends Repository<EventContent, Integer> {

List<EventContent> findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the EventContentRepository file
find . -name "EventContentRepository.java" -type f

Repository: BCSDLab/KONECT_BACK_END

Length of output: 149


🏁 Script executed:

# Check if the file exists and examine its contents
cat -n src/main/java/gg/agit/konect/domain/event/repository/EventContentRepository.java

Repository: BCSDLab/KONECT_BACK_END

Length of output: 563


🏁 Script executed:

# Search for usages of findAllByEventIdOrderByDisplayOrderAscIdAsc in the service layer
rg "findAllByEventIdOrderByDisplayOrderAscIdAsc" --type java -A 3 -B 3

Repository: BCSDLab/KONECT_BACK_END

Length of output: 8450


🏁 Script executed:

# Check for existing Pageable usage patterns in the codebase to verify alignment
rg "Page<.*> find" src/main/java --type java | head -10

Repository: BCSDLab/KONECT_BACK_END

Length of output: 1484


🏁 Script executed:

# Look at service layer handling of EventContent
find . -name "*EventContent*Service*.java" -type f

Repository: BCSDLab/KONECT_BACK_END

Length of output: 49


🏁 Script executed:

# Check for Spring Data pagination patterns in the codebase
rg "Pageable" src/main/java --type java -l | head -5

Repository: BCSDLab/KONECT_BACK_END

Length of output: 490


[LEVEL: medium] 현재 구조에서는 전체 콘텐츠를 메모리에 로드한 후 필터링과 페이징을 처리하므로, 행사당 콘텐츠가 많을 경우 불필요한 I/O와 메모리 사용이 발생합니다. Pageable 기반 메서드로 변경하여 데이터베이스 레이어에서 페이징을 처리하는 것이 권장되며, 동일한 패턴이 EventProgramRepository, EventMiniEventRepository, EventBoothRepository에도 적용되어 있으므로 함께 개선하면 좋습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/gg/agit/konect/domain/event/repository/EventContentRepository.java`
at line 11, The repository method currently loads all contents into memory;
change EventContentRepository's method signature
findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId) to a Pageable-based
query returning Page<EventContent>, e.g. add a Pageable parameter and return
Page<EventContent>, and update any callers to pass a Pageable and handle the
Page result; apply the same pattern for EventProgramRepository,
EventMiniEventRepository, and EventBoothRepository (adjust method signatures to
accept Pageable and return Page<T> and update their callers accordingly).


public interface EventMiniEventRepository extends Repository<EventMiniEvent, Integer> {

List<EventMiniEvent> findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "EventMiniEventRepository.java" | head -5

Repository: BCSDLab/KONECT_BACK_END

Length of output: 151


🏁 Script executed:

find . -type f -name "*EventMiniEvent*Service*.java" -o -name "*EventService*.java" | grep -i service | head -10

Repository: BCSDLab/KONECT_BACK_END

Length of output: 215


🏁 Script executed:

find . -type f -name "*.java" -path "*/event/*" | grep -E "(Service|Repository)" | head -20

Repository: BCSDLab/KONECT_BACK_END

Length of output: 795


🏁 Script executed:

cat -n ./src/main/java/gg/agit/konect/domain/event/repository/EventMiniEventRepository.java

Repository: BCSDLab/KONECT_BACK_END

Length of output: 571


🏁 Script executed:

cat -n ./src/main/java/gg/agit/konect/domain/event/service/EventService.java

Repository: BCSDLab/KONECT_BACK_END

Length of output: 12787


[LEVEL: medium] Line 11 메서드가 eventId의 모든 데이터를 조회한 후 서비스에서 메모리 기반으로 페이징하므로, 데이터 증가 시 불필요한 전체 로드와 메모리 사용량 증가가 발생합니다. DB 레벨 페이징으로 전환하여 필요한 데이터만 조회하도록 하세요. Page<EventMiniEvent> findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId, Pageable pageable) 형태로 변경하고 서비스에서 PageRequest를 사용하면 됩니다.

최소 수정 예시
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.repository.Repository;

 public interface EventMiniEventRepository extends Repository<EventMiniEvent, Integer> {

-    List<EventMiniEvent> findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId);
+    Page<EventMiniEvent> findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId, Pageable pageable);

     int countByEventId(Integer eventId);
 }
📝 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.

Suggested change
List<EventMiniEvent> findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId);
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
public interface EventMiniEventRepository extends Repository<EventMiniEvent, Integer> {
Page<EventMiniEvent> findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId, Pageable pageable);
int countByEventId(Integer eventId);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/gg/agit/konect/domain/event/repository/EventMiniEventRepository.java`
at line 11, In EventMiniEventRepository change the method signature
findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId) to return a Page
and accept a Pageable (i.e., Page<EventMiniEvent>
findAllByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId, Pageable pageable))
so DB-level pagination is used; update any callers (service code using
findAllByEventIdOrderByDisplayOrderAscIdAsc) to pass a PageRequest
(PageRequest.of(page, size, sort)) instead of paging in memory. Ensure imports
for org.springframework.data.domain.Page and Pageable are added and adjust any
variable handling from List to Page.

Comment on lines +51 to +69
public EventHomeResponse getEventHome(Integer eventId, Integer userId) {
Event event = getEvent(eventId);

return new EventHomeResponse(
event.getId(),
event.getTitle(),
event.getSubtitle(),
event.getPosterImageUrl(),
event.getStartAt(),
event.getEndAt(),
event.getNotice(),
new EventHomeResponse.Summary(
eventProgramRepository.countByEventId(eventId),
eventBoothRepository.countByEventId(eventId),
eventMiniEventRepository.countByEventId(eventId),
eventContentRepository.countByEventId(eventId)
),
new EventHomeResponse.UserStatus(0, 0)
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

[LEVEL: medium] 사용자 상태를 상수값으로 고정하고 있습니다.
실제 참여 이력이나 포인트가 있는 사용자로 호출해도 userStatus가 항상 0, 0으로 내려가 홈 화면이 잘못 표시됩니다.
userId 기준의 실제 집계값을 조회해서 채우거나, 아직 준비되지 않았다면 해당 필드를 응답 계약에서 제외해 주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/gg/agit/konect/domain/event/service/EventService.java` around
lines 51 - 69, getEventHome currently returns a hard-coded
EventHomeResponse.UserStatus(0,0); instead, look up the actual user aggregates
using the provided userId and populate UserStatus (e.g., call repository methods
to compute participation count and points for the given user/event inside
getEventHome) and pass those values into new EventHomeResponse.UserStatus(...);
if userId is null or the aggregates are not ready, avoid returning the
misleading zeros by either omitting the userStatus field from the response
contract or returning null/Optional as per the API contract; update getEventHome
and any related response construction logic (EventHomeResponse and
EventHomeResponse.UserStatus usage) to reflect this change.

Comment on lines +72 to +81
public EventProgramsResponse getEventPrograms(Integer eventId, EventProgramType type, Integer page, Integer limit,
Integer userId) {
getEvent(eventId);

List<EventProgram> filteredPrograms = eventProgramRepository.findAllByEventIdOrderByDisplayOrderAscIdAsc(
eventId).stream()
.filter(program -> type == EventProgramType.ALL || program.getType() == type)
.toList();

PagedResult<EventProgram> pagedPrograms = paginate(filteredPrograms, page, limit);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

[LEVEL: medium] 전체 목록을 메모리로 읽은 뒤 애플리케이션에서 페이지를 자르고 있습니다.
현재 구현은 한 페이지만 요청해도 행사 전체 데이터를 모두 로딩하므로 데이터가 늘면 응답 지연과 메모리 사용량이 함께 커집니다.
정렬·필터링·페이지네이션을 Repository 쿼리(Pageable 또는 전용 조회 메서드)로 내려서 필요한 범위만 조회하도록 바꿔 주세요.

Also applies to: 96-106, 145-149, 166-174, 193-199

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/gg/agit/konect/domain/event/service/EventService.java` around
lines 72 - 81, The current getEventPrograms loads all EventProgram rows via
eventProgramRepository.findAllByEventIdOrderByDisplayOrderAscIdAsc and then
paginates in-memory using paginate; change this to push sorting, filtering and
paging into the DB by adding repository methods that accept a Pageable (e.g.
Page<EventProgram> findByEventIdAndTypeOrderByDisplayOrderAscIdAsc(Integer
eventId, EventProgramType type, Pageable p) and Page<EventProgram>
findByEventIdOrderByDisplayOrderAscIdAsc(Integer eventId, Pageable p)) or use a
single method with optional type criteria, construct a PageRequest with
Sort.by("displayOrder").ascending().and(Sort.by("id").ascending()) in
getEventPrograms, call the repository to get a Page<EventProgram>, and convert
page.getContent() and page metadata into your PagedResult instead of using
paginate; apply the same change for other places that call
eventProgramRepository.findAllByEventIdOrderByDisplayOrderAscIdAsc and paginate
(the other methods referenced in the review).

Comment on lines +120 to +122
public EventBoothMapResponse getEventBoothMap(Integer eventId) {
EventBoothMap boothMap = eventBoothMapRepository.findByEventId(eventId)
.orElseThrow(() -> CustomException.of(NOT_FOUND_EVENT));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

[LEVEL: medium] 부스 맵 부재를 행사 미존재와 같은 오류로 처리하고 있습니다.
행사는 존재하지만 맵만 아직 등록되지 않은 경우에도 NOT_FOUND_EVENT가 반환되어 클라이언트가 잘못된 예외 분기를 타게 됩니다.
먼저 getEvent(eventId)로 행사를 검증하고, 맵이 없는 경우는 별도 오류 코드나 빈 응답 등 현재 API 규약에 맞는 처리로 분리해 주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/gg/agit/konect/domain/event/service/EventService.java` around
lines 120 - 122, The getEventBoothMap method currently treats a missing booth
map as NOT_FOUND_EVENT; first call the existing getEvent(eventId) to validate
the event exists, then query eventBoothMapRepository.findByEventId(eventId) and
if the map is absent handle it separately (either throw a new error like
CustomException.of(NOT_FOUND_EVENT_MAP) or return an empty/nullable
EventBoothMapResponse per API contract) instead of reusing NOT_FOUND_EVENT;
update references in getEventBoothMap, and ensure any new error code or empty
response behavior is consistent with the API.

@@ -0,0 +1,113 @@
CREATE TABLE IF NOT EXISTS event
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

[LEVEL: high] Flyway 마이그레이션에서 IF NOT EXISTS를 제거해야 합니다.
문제: CREATE TABLE IF NOT EXISTS가 스키마 드리프트를 숨겨 비정상 DB 상태를 마이그레이션 실패로 드러내지 못합니다.
영향: 운영 DB에 같은 테이블이 일부 다른 스키마로 이미 존재해도 배포가 통과되어, 이후 애플리케이션 쿼리에서 런타임 장애가 발생할 수 있습니다.
제안: 이 파일의 모든 IF NOT EXISTS를 제거해 불일치 시 즉시 실패하도록 바꾸세요 (As per coding guidelines, "이미 배포된 마이그레이션 수정/재번호 부여 위험이 있으면 반드시 차단 코멘트를 남긴다.").

Also applies to: 15-15, 32-32, 50-50, 64-64, 82-82, 98-98

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/db/migration/V70__add_event_tables.sql` at line 1, The
migration uses CREATE TABLE IF NOT EXISTS (e.g., the statement "CREATE TABLE IF
NOT EXISTS event") which must be changed to fail on schema drift; remove all
occurrences of "IF NOT EXISTS" in this file so each CREATE TABLE is
unconditional, and ensure every CREATE TABLE statement (including the ones at
the other noted occurrences) is updated accordingly; if this migration has
already been applied in production and cannot be safely changed, add a blocking
comment on the PR stating the risk instead of editing the deployed migration.

Comment on lines +15 to +30
CREATE TABLE IF NOT EXISTS event_program
(
id INT AUTO_INCREMENT PRIMARY KEY,
event_id INT NOT NULL,
type ENUM ('POINT', 'RESONANCE') NOT NULL,
title VARCHAR(100) NOT NULL,
description VARCHAR(255) NOT NULL,
thumbnail_url VARCHAR(255),
reward_point INT,
status ENUM ('UPCOMING', 'ONGOING', 'ENDED') NOT NULL,
display_order INT NOT NULL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,

FOREIGN KEY (event_id) REFERENCES event (id) ON DELETE CASCADE
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

[LEVEL: medium] 조회 패턴에 맞는 복합 인덱스가 없어 성능 저하 위험이 있습니다.
문제: event_id 조건과 display_order, id 정렬을 함께 쓰는 목록 조회 대비 복합 인덱스가 없습니다.
영향: 데이터가 증가하면 filesort가 발생해 /programs, /mini-events, /contents 응답 지연이 커질 수 있습니다.
제안: event_program, event_mini_event, event_content(event_id, display_order, id) 인덱스를 추가하세요 (As per coding guidelines, "보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.").

최소 수정 예시
+CREATE INDEX idx_event_program_event_order
+    ON event_program (event_id, display_order, id);
+
+CREATE INDEX idx_event_mini_event_event_order
+    ON event_mini_event (event_id, display_order, id);
+
+CREATE INDEX idx_event_content_event_order
+    ON event_content (event_id, display_order, id);

Also applies to: 82-96, 98-113

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/db/migration/V70__add_event_tables.sql` around lines 15 -
30, Add composite indexes to cover the common lookup + sort pattern: create an
index on (event_id, display_order, id) for the event_program, event_mini_event,
and event_content tables to avoid filesort on queries that filter by event_id
and order by display_order,id; update the V70__add_event_tables.sql migration by
adding appropriate CREATE INDEX statements (or inline INDEX definitions)
referencing the exact table names event_program, event_mini_event, event_content
and the columns event_id, display_order, id.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

기능 새로운 기능을 개발합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant