Files
sodalive-backend-spring-boot/docs/20261028_일반이벤트상세조회/prd.md
T

55 lines
4.4 KiB
Markdown

# 일반용 이벤트 상세 조회 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 계약을 프롬프트 형태로 제공한다. 구현된 서버 계약만 명시하고 새로운 화면/서버 기능을 추가하지 않는다.