# 일반용 이벤트 상세 조회 PRD ## 문서 정보 - 작성일: 2026-10-28 - 상태: 구현 및 검증 완료 (운영 배포 제외) - 결정권자: 사용자; 구현 담당: Sisyphus - 구현 계획: [plan-task.md](plan-task.md) - 클라이언트 전달 계약: [api-client-prompt.md](api-client-prompt.md) - 최종 리뷰: [reviews/event-detail-review.md](reviews/event-detail-review.md), APPROVE ## 목표와 범위 이벤트 ID만으로 일반용 이벤트 정보를 조회할 수 있도록 `GET /api/v2/events/{id}`를 추가한다. 기존 목록과 동일한 노출 조건으로 상세 이미지와 외부 이동 링크를 반환한다. 관리자 상세 API, 기존 `/event` 계약 변경, 프론트엔드, DB 변경, 신규 의존성은 제외한다. ## 확정 요구사항 | ID | 요구사항 | 수용 기준 | |---|---|---| | EVT-001 | 비로그인 가능한 v2 단건 조회 | 정상 ID 요청은 HTTP 200, `success=true`, 단일 EventItem 반환 | | EVT-002 | 기존 목록과 동일한 노출 정책 | 활성, 시작/종료 시각 포함 범위, 국가별 언어, 성인 인증 조건 일치 | | EVT-003 | 기존 응답 필드 재사용 | id, thumbnailImageUrl, detailImageUrl, popupImageUrl, link 보존 | | EVT-004 | 미존재와 비노출 동일 처리 | HTTP 200, `success=false`, `data=null`, 기존 invalid_request 메시지 | | EVT-005 | 인접 API 보안 유지 | 익명 쓰기·하위 추가 경로·기존 팝업·관리자 요청은 계속 보호 | ## API 계약 - Method/path: `GET /api/v2/events/{id}`. ID는 양수 Long. - 인증: 선택적 기존 JWT. 인증이 없으면 비성인 기준. 잘못된 JWT 처리는 기존 보안 정책 유지. - 성공: `ApiResponse.ok(EventItem)`. 응답 필드는 기존 목록 항목과 동일하며 제목/기간 필드를 추가하지 않는다. - 이미지: `https://`로 시작하면 그대로, 나머지 문자열은 기존 CloudFront 호스트와 `/`를 앞에 붙인다. nullable 이미지는 null 유지. - `link`: 저장값 그대로 반환하고 서버에서 이동하거나 URL을 요청하지 않는다. - 양수가 아닌 ID, 미존재, 비노출: `SodaException(messageKey = "common.error.invalid_request")`로 기존 HTTP 200 실패 envelope 사용. - 숫자가 아니거나 Long 범위를 넘는 ID: 기존 Spring 바인딩과 공통 오류 처리 유지. 새 parser/handler 없음. ## 노출 정책 - `isActive == true`, `startDate <= now <= endDate`. - `MemberContentPreferenceService.resolveCountryCode(member)` 결과가 JP면 JA, 그 외 KO. - 관리자 역할은 성인 조건만 생략하며 활성/기간/언어는 생략하지 않는다. - 비로그인 및 인증 기록 없는 일반 회원: 이벤트 `isAdult`가 null 또는 false. - 인증 기록 있는 일반 회원: 이벤트 `isAdult`가 null 또는 true. 기존 목록처럼 false 이벤트는 제외한다. - ID로 단건 조회하며 전체 목록을 가져와 검색하지 않는다. ## 검증 시나리오 | 시나리오 | 이진 성공 조건 | 실제 검증 표면 | |---|---|---| | S1 정상 | 익명 KO/JP, null/HTTPS/상대 이미지, 외부 link가 기존 항목과 동일 | RANDOM_PORT + TestRestTemplate 실제 HTTP 및 H2 | | S2 경계/권한 | 미존재·비활성·예정·종료·언어 불일치·성인 제한에서 데이터 미노출; 일반/인증/관리자 정책 일치 | 실제 HTTP + 인증 MockMvc + 실제 DB | | S3 회귀 | 기존 목록 응답 유지, 익명 팝업/관리자/POST·PUT·DELETE·추가 하위 경로 거부 | 실제 HTTP, 기존 event/admin 통합 테스트 | ## Decision Log - 사용자 확정: 관리자 상세 불필요, 일반 상세만 추가; v2 경로 `/api/v2/events/{id}` 승인; 나머지 기존 정책 적용. - 구현 선택: 기존 EventItem/엔티티/repository 재사용, v2 controller와 read-only service만 추가. 단건 로드 후 정책 확인으로 불필요한 port/DTO 계층을 만들지 않는다. - 구현 선택: 미조회 오류는 기존 이벤트 수정/삭제와 공통 예외 관례를 따른다. 별도 HTTP 404 계약을 만들지 않는다. - 사용자의 ulw 지시에 따라 실제 HTTP 증거, 전체 테스트/빌드와 독립 리뷰를 수행한다. 런타임/도구 제한은 숨기지 않는다. - 후속 사용자 요청: 최종 결과에 클라이언트 개발자가 사용할 API 계약을 프롬프트 형태로 제공한다. 구현된 서버 계약만 명시하고 새로운 화면/서버 기능을 추가하지 않는다.