90 lines
7.2 KiB
Markdown
90 lines
7.2 KiB
Markdown
# 이벤트 상세 API 연동 PRD
|
|
|
|
## 문서 정보
|
|
| 항목 | 내용 |
|
|
|---|---|
|
|
| 문서 상태 | 클라이언트 구현·로컬 검증 완료 |
|
|
| 작성일 / 최종 수정일 | 2026-10-29 |
|
|
| 대상 제품 | SodaLive iOS 이벤트 상세 |
|
|
| 작성자·결정권자 | 사용자 계약, 구현 에이전트에 실행 위임 |
|
|
| 관련 API Contract | [api-contract.md](api-contract.md) |
|
|
| 관련 구현 계획 | [plan-task.md](plan-task.md) |
|
|
| 관련 review | [phase1-event-detail-api.md](reviews/phase1-event-detail-api.md) |
|
|
|
|
## 1. Overview
|
|
기존 이벤트 진입점에서 ID만 전달하고 상세 API의 최신 단일 이벤트를 표시한다. 후속 딥링크도 ID만으로 진입할 수 있도록 payload 보존을 제거한다.
|
|
|
|
## 2. Problem Statement
|
|
기존 상세 화면은 목록 payload를 직접 표시하고 optional 상세 이미지를 강제 해제한다. 목록에 없는 이벤트의 독립 조회와 접근 불가 판단이 불가능하다. 이전 이벤트 목록 중복 로딩 개선 문서와는 별개의 신규 작업이다.
|
|
|
|
## 3. Goals
|
|
양수 Int ID로 익명/인증 상세 조회를 수행하고 loading, loaded, unavailable, 네트워크·응답 error를 구별한다. 기존 이미지 비율, 참여 버튼 모양·위치, toast와 navigation bar를 유지한다.
|
|
|
|
## 4. Non-Goals
|
|
딥링크 parser/등록, 목록·팝업 조회와 로그인 게이트 변경, 공통 인증/URL 정책 리팩터링, 새 UI·의존성, 자동 외부 이동, payload fallback은 제외한다. 서버도 동시 구현 중이므로 사용자 지시에 따라 클라이언트 구현 후 실서버 연결 테스트는 하지 않는다. 현재 브랜치에서 직접 작업하며 worktree를 만들지 않는다.
|
|
|
|
## 5. Target Users and Permissions
|
|
공개 상세는 비로그인 사용자도 조회한다. 토큰이 있으면 Bearer를 전달한다. 기존 진입점의 로그인 게이트는 유지한다. 401의 세션 초기화·main 이동은 기존 AuthPlugin 소유다.
|
|
|
|
## 6. 핵심 사용자 흐름
|
|
1. 기존 목록·팝업·배너에서 이벤트를 선택한다.
|
|
2. `AppStep.eventDetail(eventId: Int)`로 이동하고 상세를 한 번 요청한다.
|
|
3. 유효한 응답은 optional 상세 이미지와 안전한 참여 링크를 표시한다. 이미지 없는 link-only도 정상이다.
|
|
4. 비양수 ID 또는 HTTP 200 success=false는 해당 상세 화면만 닫는다. 네트워크/HTTP/파싱 오류는 toast로 알린다.
|
|
5. 화면 이탈 시 취소하고 지연 응답·중복 응답의 화면 변경을 차단한다.
|
|
|
|
## 7. 정보 구조와 라우팅
|
|
`AppStep.eventDetail(eventId: Int)` → `EventDetailView(eventId:)` → 소유 StateObject VM → 기존 EventRepository/EventApi. iOS 16.6+의 Int는 signed 64-bit이며 Int.max까지 손실 없이 전달한다. 실제 딥링크 추가는 후속 범위다.
|
|
|
|
## 8. 기능 요구사항
|
|
| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 |
|
|
|---|---|---|---|---|
|
|
| EVT-001 | 확정 | 모든 기존 진입점은 ID만 전달 | 7개 호출 및 destination 변경, 선택·인증 분기 보존 | §1, P1-T2 |
|
|
| EVT-002 | 확정 | 공개 v2 상세 GET | requestPlain, 빈 토큰 Authorization 없음, 기존 list/popup 불변 | §1, P1-T1 |
|
|
| EVT-003 | 확정 | status → success → 단일 object 순서 검증 | false의 data 모양 무시, malformed success는 error | §2, P1-T1 |
|
|
| EVT-004 | 확정 | 생명주기·링크 안전성 | cancel/중복 로딩·dismiss 방지, HTTP(S)+host만 참여 가능 | §3, P1-T1/P1-T2 |
|
|
|
|
## 10. UI/UX Expectations
|
|
기존 7개 관련 화면과 BaseView, DetailNavigationBar, GiftBoxCardView 및 Color/Spacing/Radius/FontModifier를 확인했다. 기존 화면은 black/gray22, Pretendard 기반 appFont, 13.3pt 레거시 간격을 사용한다. 재설계 없이 상세 이미지 scaledToFit과 기존 버튼 값을 보존한다. 참여 action은 동일 외형의 plain Button으로 바꾼다. popup 이미지 fallback·가짜 제목/날짜는 없다.
|
|
|
|
## 11. API 계약
|
|
[api-contract.md](api-contract.md)의 확정 계약을 사용한다. DTO는 기존 EventItem 그대로 재사용한다.
|
|
|
|
## 12. 보안과 데이터 취급
|
|
외부 응답은 status와 envelope/필수 필드/일치 ID를 검증한다. 외부 참여 URL은 로컬에서 절대 HTTP(S)+비어 있지 않은 host만 허용한 뒤 기존 canOpenURL/open을 사용한다. 이는 좁은 scheme 경계이며 도메인 신뢰·리디렉션 안전성을 보증하지 않는다. 토큰/응답 본문을 추가 로깅하지 않는다.
|
|
|
|
## 13. 성능과 품질 요구사항
|
|
실제 Combine과 production API/repository/VM/DTO를 swiftc CLI로 검사한다. 같은 loaded 화면은 재조회하지 않는다. 새 VM은 두 앱 타깃에 등록한다. 빌드·시뮬레이터·최종 리뷰는 상위 실행자 검증 대상으로 명확히 구분한다.
|
|
|
|
## 14. 성공 기준
|
|
- [x] 집중 CLI에서 요청·인증·ID 경계·상태·URL·취소/중복·main delivery 검증 통과.
|
|
- [x] 모든 ID-only 탐색 호출과 두 target membership 확인.
|
|
- [x] RED/GREEN 실제 결과와 미실행 검증을 계획 문서에 기록.
|
|
|
|
## 15. Open Questions
|
|
없음. 사용자 계약을 구현 기준으로 확정했다.
|
|
|
|
## 16. 요구사항 추적표
|
|
EVT-001~004는 api-contract §1~3, P1-T1/P1-T2/P1-GATE 및 `work/tests/check-event-detail.sh`로 추적한다. 네이티브 화면 검증은 상위 실행자 담당이다.
|
|
|
|
## 17. Decision Log
|
|
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 |
|
|
|---|---|---|---|---|---|
|
|
| 2026-10-29 | DEC-001 | 확정 | payload 대신 Int ID만 라우팅 | 향후 이벤트 딥링크가 예정되어 독립 조회 필요 | EVT-001 |
|
|
| 2026-10-29 | DEC-002 | 확정 | 기존 EventItem 재사용, thumbnail 필수, link-only 정상 | 사용자 확정 계약 | EVT-003 |
|
|
| 2026-10-29 | DEC-003 | 확정 | unavailable은 View-scoped dismiss, AuthPlugin 유지 | AppState.back은 live sheet를 우선 닫음 | EVT-004 |
|
|
| 2026-10-29 | DEC-004 | 확정 | 현재 브랜치 직접 작업, 실서버 연결 테스트 제외 | 사용자 후속 지시, 서버 동시 구현 중 | 구현·검증 범위 |
|
|
|
|
## 후속 요구사항: 목록 이미지 원본 비율 - 2026-10-29
|
|
| ID | 상태 | 요구사항 | 수용 기준 | Goal 연결 |
|
|
|---|---|---|---|---|
|
|
| EVT-005 | 확정 | 기존 이벤트 목록 이미지를 원본 비율로 표시 | 기존 너비 유지, scaledToFit과 높이 없는 frame으로 이미지 전체 표시 | P2-T1 |
|
|
|
|
### 후속 결정
|
|
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 |
|
|
|---|---|---|---|---|---|
|
|
| 2026-10-29 | DEC-005 | 확정 | 목록의 표시 modifier만 변경하고 downsampling은 유지 | 사용자 명시 요청; Kingfisher는 max(width, height)로 다운샘플링하며 원본 비율을 유지 | EVT-005 |
|
|
- 기존 간격·탭·상태·API·상세 화면은 변경하지 않는다. 서버/CDN 호출은 하지 않는다.
|
|
- 순수 UI modifier 변경으로 새 로직 테스트 seam이 없어 TDD 예외로 처리한다. 소스 문자열 의사 테스트는 추가하지 않으며 로컬 렌더·빌드·리뷰 증거는 상위 실행자 검증 대기다.
|
|
- 후속 검증 완료: 독립 macOS SwiftUI 원본 비율 렌더 6/6, 양 앱 Debug 시뮬레이터 빌드, 로컬 회귀 14개 PASS 및 [Phase 2 리뷰](reviews/phase2-event-list-image-aspect.md) APPROVE. 실제 iOS 앱 화면 조작·서버/CDN 테스트는 수행하지 않았다.
|