227 lines
15 KiB
Markdown
227 lines
15 KiB
Markdown
# 팔로잉 해제 확인 팝업 PRD
|
||
|
||
## 문서 정보
|
||
|
||
| 항목 | 내용 |
|
||
|---|---|
|
||
| 문서 상태 | 완료 |
|
||
| 작성일 | `2026-08-18` |
|
||
| 최종 수정일 | `2026-08-18` |
|
||
| 대상 제품 | SodaLive iOS 팔로잉 리스트, V2 크리에이터 채널 |
|
||
| 작성자·결정권자 | 작성자: Sisyphus / 결정권자: 제품 담당자 |
|
||
| 관련 API Contract | 해당 없음: 기존 팔로우 API 사용 |
|
||
| 관련 구현 계획 | `docs/20260818_팔로잉_해제_확인_팝업/plan-task.md` |
|
||
| 관련 review | 없음 |
|
||
|
||
### 요구사항 상태
|
||
|
||
| 상태 | 의미 | 구현 처리 |
|
||
|---|---|---|
|
||
| 확정 | 제품·기술 결정이 완료되어 구현 기준으로 사용 | `plan-task.md`의 Task와 완료 증거로 추적 |
|
||
| 미결 | 제품·UX 결정이 더 필요함 | 권고안과 결정 주체를 기록하고 임의 구현 금지 |
|
||
| 제외 | 현재 릴리스에서 구현하지 않기로 결정 | 제외 이유와 후속 조건을 Decision Log에 기록 |
|
||
|
||
## 1. Overview
|
||
|
||
팔로잉 리스트 페이지와 V2 크리에이터 채널에서 팔로잉 해제 동작을 더 안전하게 만든다. 사용자가 팔로잉 중인 크리에이터를 해제하려 할 때 `SodaV2ActionModal`로 한 번 더 확인하고, 확인한 경우에만 기존 팔로우 해제 API 흐름을 실행한다.
|
||
|
||
## 2. Problem Statement
|
||
|
||
현재 사용자는 다음 문제를 겪는다.
|
||
|
||
- 팔로잉 리스트에서 팔로잉 중 버튼을 터치하면 알림 설정 Bottom Sheet가 먼저 열려 팔로우 해제까지 추가 선택이 필요하다.
|
||
- 크리에이터 채널에서는 팔로잉 중 버튼을 터치하면 별도 확인 없이 즉시 팔로우 해제가 진행된다.
|
||
- 두 진입점의 팔로우 해제 경험이 서로 달라 destructive action의 실수 방지가 일관되지 않다.
|
||
|
||
문제를 해결했다는 판단은 두 화면 모두 팔로우 해제 전 동일한 `SodaV2ActionModal` 확인 단계를 거치고, 사용자가 취소하면 API 호출과 상태 변경이 발생하지 않는 것으로 한다.
|
||
|
||
## 3. Goals
|
||
|
||
### 3.1 제품 목표
|
||
|
||
- 팔로잉 리스트 페이지에서 팔로잉 중 버튼을 누르면 Bottom Sheet 없이 팔로우 해제 확인 Dialog를 표시한다.
|
||
- 크리에이터 채널에서 팔로잉 중 버튼을 누르면 즉시 해제하지 않고 팔로우 해제 확인 Dialog를 표시한다.
|
||
- 확인 버튼을 누른 경우에만 기존 팔로우 해제 프로세스를 실행한다.
|
||
|
||
### 3.2 UX 목표
|
||
|
||
- 팔로잉 리스트의 팔로잉 중 버튼은 `ic_new_following_white`, `Color.gray800` 배경, 원형 스타일로 표시한다.
|
||
- 팔로우 해제 확인 Dialog는 `SodaV2ActionModal`을 사용한다.
|
||
- Dialog의 취소/확인 문구와 본문은 현재 앱 언어에 맞게 한국어, 일본어, 영어로 표시한다.
|
||
|
||
## 4. Non-Goals
|
||
|
||
- 팔로우 API, 알림 설정 API, DTO, 서버 계약은 변경하지 않는다.
|
||
- 팔로우 시작 동작과 팔로우 알림 설정 변경 UX는 이 작업에서 변경하지 않는다.
|
||
- 팔로잉 리스트 외의 `FollowCreatorItemView` 재사용 화면은 제품 범위가 확인되지 않았으므로 임의로 동작을 바꾸지 않는다. 재사용 영향은 구현 전 확인하고 필요한 경우 별도 결정으로 기록한다.
|
||
- Bottom Sheet 컴포넌트 `CreatorFollowNotifyDialog` 자체는 삭제하지 않는다.
|
||
|
||
## 5. Target Users and Permissions
|
||
|
||
| 사용자 | 목표 | 주요 작업 | 사용 환경 |
|
||
|---|---|---|---|
|
||
| 로그인 사용자 | 팔로잉 중인 크리에이터를 실수 없이 해제 | 팔로잉 리스트 또는 크리에이터 채널에서 팔로우 해제 | iOS 앱 |
|
||
|
||
권한과 인증은 기존 팔로우 API 정책을 따른다. 인증 토큰 처리와 권한 오류 처리는 기존 `UserRepository` 및 각 ViewModel의 오류 표시 정책을 변경하지 않는다.
|
||
|
||
## 6. 핵심 사용자 흐름
|
||
|
||
1. 사용자가 팔로잉 리스트 페이지에 진입한다.
|
||
2. 팔로잉 중인 크리에이터 row의 원형 팔로잉 버튼을 누른다.
|
||
3. 앱은 Bottom Sheet를 표시하지 않고 팔로우 해제 확인 Dialog를 표시한다.
|
||
4. 사용자가 `취소`를 누르면 Dialog만 닫히고 팔로우 상태는 유지된다.
|
||
5. 사용자가 `해제하기`를 누르면 Dialog를 닫고 기존 팔로우 해제 프로세스를 실행한다.
|
||
6. 사용자가 V2 크리에이터 채널의 팔로잉 중 버튼을 누른 경우도 3~5와 동일하게 동작한다.
|
||
|
||
## 7. 정보 구조와 라우팅
|
||
|
||
라우팅 변경은 없다.
|
||
|
||
- 팔로잉 리스트: 기존 `FollowCreatorView` 진입 경로 유지.
|
||
- 크리에이터 채널: 기존 `CreatorChannelView(creatorId:)` 진입 경로 유지.
|
||
- Dialog는 별도 route를 만들지 않고 현재 화면 overlay로 표시한다.
|
||
|
||
## 8. 기능 요구사항
|
||
|
||
### 8.1 팔로잉 리스트 버튼과 액션
|
||
|
||
| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 |
|
||
|---|---|---|---|---|
|
||
| `UNFOLLOW-LIST-001` | 확정 | 팔로잉 리스트에서 팔로잉 중 상태의 액션 버튼은 `ic_new_following_white` 이미지를 사용한다. | 팔로잉 중 row에 기존 `btn_following_big` 또는 `btn_following_no_alarm_big` 대신 흰색 아이콘 원형 버튼이 보인다. | `P1-T1` |
|
||
| `UNFOLLOW-LIST-002` | 확정 | 팔로잉 중 버튼 배경은 `Color.gray800`을 사용한다. | 버튼 배경 색상은 `SodaLive/Sources/UI/Theme/Color.swift`의 `gray800` 토큰을 참조한다. | `P1-T1` |
|
||
| `UNFOLLOW-LIST-003` | 확정 | 팔로잉 중 버튼 형태는 크리에이터 채널 팔로잉 중 버튼과 동일한 원형 스타일을 따른다. | 팔로잉 리스트 버튼의 touch target과 시각적 형태가 `CreatorChannelTitleBar`의 팔로잉 중 버튼과 일치한다. | `P1-T1` |
|
||
| `UNFOLLOW-LIST-004` | 확정 | 팔로잉 리스트에서 팔로잉 중 버튼을 누르면 Bottom Sheet 액션 메뉴를 표시하지 않는다. | `CreatorFollowNotifyDialog`가 팔로잉 리스트의 팔로우 해제 진입점에서 열리지 않는다. | `P1-T2` |
|
||
| `UNFOLLOW-LIST-005` | 확정 | 팔로잉 리스트에서 팔로잉 중 버튼을 누르면 팔로우 해제 확인 Dialog를 표시한다. | Dialog 확인 전에는 `creatorFollow(follow: false, notify: false)` 또는 동등한 해제 요청이 호출되지 않는다. | `P1-T2` |
|
||
|
||
### 8.2 크리에이터 채널 팔로우 해제 확인
|
||
|
||
| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 |
|
||
|---|---|---|---|---|
|
||
| `UNFOLLOW-CHANNEL-001` | 확정 | 크리에이터 채널에서 팔로잉 중 버튼을 누르면 팔로우 해제 확인 Dialog를 표시한다. | `CreatorChannelTitleBar`의 `onTapUnfollow`가 즉시 해제를 실행하지 않고 Dialog 표시 상태를 켠다. | `P2-T1` |
|
||
| `UNFOLLOW-CHANNEL-002` | 확정 | Dialog 확인 버튼을 누른 경우에만 기존 크리에이터 채널 팔로우 해제 프로세스를 실행한다. | 확인 시 `CreatorChannelViewModel.creatorFollow(follow: false, notify: false)` 흐름이 실행되고 성공 시 `isFollow=false`, `isNotify=false`로 갱신된다. | `P2-T1` |
|
||
| `UNFOLLOW-CHANNEL-003` | 확정 | Dialog 취소 버튼을 누르면 API 호출 없이 Dialog만 닫는다. | 취소 후 기존 팔로우 상태와 알림 상태가 유지된다. | `P2-T1` |
|
||
|
||
### 8.3 Dialog 문구와 다국어
|
||
|
||
| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 |
|
||
|---|---|---|---|---|
|
||
| `UNFOLLOW-DIALOG-001` | 확정 | Dialog title은 한국어 `팔로우 해제`, 일본어 `フォロー解除`, 영어 `Unfollow`를 사용한다. | 앱 언어별 title이 정확히 표시된다. | `P1-T2`, `P2-T1` |
|
||
| `UNFOLLOW-DIALOG-002` | 확정 | Dialog 본문은 크리에이터 이름을 포함하고 줄바꿈을 유지한다. | 한국어, 일본어, 영어 모두 `\n` 줄바꿈과 크리에이터 이름 치환이 적용된다. | `P1-T2`, `P2-T1` |
|
||
| `UNFOLLOW-DIALOG-003` | 확정 | 취소 버튼은 한국어 `취소`, 일본어 `キャンセル`, 영어 `Cancel`을 사용한다. | 취소 버튼이 언어별 문구로 표시되고 API 호출 없이 닫힌다. | `P1-T2`, `P2-T1` |
|
||
| `UNFOLLOW-DIALOG-004` | 확정 | 확인 버튼은 한국어 `해제하기`, 일본어 `解除する`, 영어 `Unfollow`를 사용한다. | 확인 버튼이 언어별 문구로 표시되고 팔로우 해제 요청을 실행한다. | `P1-T2`, `P2-T1` |
|
||
|
||
Dialog 본문 문구:
|
||
|
||
| 언어 | 문구 |
|
||
|---|---|
|
||
| ko | `팔로우를 해제할까요?\n{{creatorName}}의 소식을 받을 수 없어요.` |
|
||
| ja | `{{creatorName}}からの最新情報を受け取れなくなります。\nフォローを解除しますか?` |
|
||
| en | `You won't receive updates from {{creatorName}}.\nUnfollow this creator?` |
|
||
|
||
## 9. 반응형 기능 범위
|
||
|
||
| 기능 | iPhone | iPad | 비고 |
|
||
|---|---:|---:|---|
|
||
| 팔로잉 리스트 버튼 표시 | 전체 | 전체 | 기존 SwiftUI layout 유지 |
|
||
| 팔로우 해제 확인 Dialog | 전체 | 전체 | overlay 기반 표시 |
|
||
| Dynamic Type / 긴 닉네임 | 확인 필요 | 확인 필요 | Dialog 본문 줄바꿈과 clipping 수동 확인 |
|
||
|
||
## 10. UI/UX Expectations
|
||
|
||
### 10.1 디자인과 component 원칙
|
||
|
||
- 팔로잉 리스트의 팔로잉 중 버튼은 크리에이터 채널 팔로잉 중 버튼의 원형 시각 규칙을 따른다.
|
||
- 버튼 색상은 `Color.gray800`, 이미지는 `ic_new_following_white`를 사용한다.
|
||
- Dialog는 새 임의 component를 만들지 않고 기존 `SodaV2ActionModal`을 사용한다.
|
||
|
||
### 10.2 화면 상태
|
||
|
||
- Dialog 표시 중 배경 화면의 팔로우 상태는 바뀌지 않는다.
|
||
- 확인 후 API loading과 오류 toast/popup은 기존 ViewModel 정책을 따른다.
|
||
- API 실패 시 Dialog는 이미 닫힌 상태로 두고 기존 오류 표시를 사용한다.
|
||
|
||
### 10.3 접근성
|
||
|
||
- 팔로잉 중 버튼의 accessibility label은 팔로잉 상태와 팔로우 해제 의도를 알 수 있어야 한다.
|
||
- Dialog title, message, 취소, 확인 버튼이 VoiceOver에서 읽혀야 한다.
|
||
- 취소와 확인 버튼의 touch target은 기존 Dialog 기준을 유지한다.
|
||
|
||
## 11. API 계약
|
||
|
||
신규 API 계약은 없다. 기존 팔로우 상태 변경 API를 그대로 사용한다.
|
||
|
||
| 요구사항 | Method | Path | 계약 상태 | API Contract | 소유 Goal |
|
||
|---|---|---|---|---|---|
|
||
| `UNFOLLOW-LIST-005` | 기존 계약 | 기존 `UserRepository.creatorFollow` 경유 | 제공됨 | 해당 없음 | `P1-T2` |
|
||
| `UNFOLLOW-CHANNEL-002` | 기존 계약 | 기존 `UserRepository.creatorFollow` 경유 | 제공됨 | 해당 없음 | `P2-T1` |
|
||
|
||
## 12. 보안과 데이터 취급
|
||
|
||
- 인증 header와 token 저장 로직은 변경하지 않는다.
|
||
- Dialog 문구와 로그에 token, 인증 정보, 민감정보를 기록하지 않는다.
|
||
- 크리에이터 이름은 화면에 이미 표시되는 공개 프로필 이름만 사용한다.
|
||
|
||
## 13. 성능과 품질 요구사항
|
||
|
||
- Dialog 표시를 위해 새 네트워크 요청을 추가하지 않는다.
|
||
- 팔로잉 리스트 row 렌더링에서 이미지 에셋과 색상 토큰 외 추가 비동기 작업을 만들지 않는다.
|
||
- 저장소에 테스트 번들 타깃이 확인되지 않으므로 구현 검증은 focused preview/수동 확인과 `xcodebuild` 빌드 중심으로 수행한다.
|
||
|
||
## 14. 성공 기준
|
||
|
||
### 14.1 기능 수용 기준
|
||
|
||
- [x] 팔로잉 리스트에서 팔로잉 중 버튼이 `ic_new_following_white` + `Color.gray800` 원형 버튼으로 표시된다. (`UNFOLLOW-LIST-001~003`)
|
||
- [x] 팔로잉 리스트에서 팔로잉 중 버튼을 눌러도 Bottom Sheet가 뜨지 않고 확인 Dialog가 표시된다. (`UNFOLLOW-LIST-004~005`)
|
||
- [x] 크리에이터 채널에서 팔로잉 중 버튼을 누르면 확인 Dialog가 표시되고, 확인 전에는 해제 API가 호출되지 않는다. (`UNFOLLOW-CHANNEL-001`)
|
||
- [x] 두 화면 모두 취소 시 상태 변경 없이 Dialog만 닫힌다. (`UNFOLLOW-CHANNEL-003`)
|
||
- [x] 두 화면 모두 확인 시 기존 팔로우 해제 프로세스가 성공적으로 실행된다. (`UNFOLLOW-CHANNEL-002`, `UNFOLLOW-LIST-005`)
|
||
|
||
### 14.2 UI/UX 수용 기준
|
||
|
||
- [x] Dialog 문구가 한국어, 일본어, 영어에서 지정된 title/body/button으로 표시된다.
|
||
- [x] 크리에이터 이름이 Dialog 본문에 정확히 치환된다.
|
||
- [x] 긴 크리에이터 이름에서도 Dialog 본문이 잘리거나 버튼을 밀어내지 않는다.
|
||
|
||
### 14.3 추적성 완료 기준
|
||
|
||
- [x] 모든 확정 요구사항이 `plan-task.md`의 Goal로 연결된다.
|
||
- [x] 모든 미결 항목에 현재 권고와 결정 주체가 있다.
|
||
- [x] 코드 구현 전에 PRD 변경이 필요한 경우 Decision Log를 먼저 갱신한다.
|
||
|
||
## 15. Open Questions
|
||
|
||
| ID | 상태 | 결정 필요 사항 | 현재 권고 | 결정 주체 | 결정 기한/시점 | 영향 Goal |
|
||
|---|---|---|---|---|---|---|
|
||
| `OQ-001` | 해결 | 한국어 본문 `{{creatorName}}의. 소식을 받을 수 없어요.`의 마침표 위치 | 마침표를 제거해 `{{creatorName}}의 소식을 받을 수 없어요.`를 사용 | 사용자 | `2026-08-18` | `P1-T2`, `P2-T1` |
|
||
| `OQ-002` | 해결 | “V2 Dialog”의 정확한 공통 component | `SodaV2ActionModal`을 사용 | 사용자 | `2026-08-18` | `P1-T2`, `P2-T1` |
|
||
|
||
## 16. 요구사항 추적표
|
||
|
||
| 요구사항 범위 | API Contract | 계획 Phase | Goal | 자동 검증 | 수동 검증 |
|
||
|---|---|---:|---|---|---|
|
||
| `UNFOLLOW-LIST-001~003` | 해당 없음 | 1 | `P1-T1` | 빌드 | 팔로잉 리스트 버튼 시각 확인 |
|
||
| `UNFOLLOW-LIST-004~005` | 기존 팔로우 API | 1 | `P1-T2` | 빌드 | Bottom Sheet 미표시, Dialog 취소/확인 확인 |
|
||
| `UNFOLLOW-CHANNEL-001~003` | 기존 팔로우 API | 2 | `P2-T1` | 빌드 | 크리에이터 채널 Dialog 취소/확인 확인 |
|
||
| `UNFOLLOW-DIALOG-001~004` | 해당 없음 | 1, 2 | `P1-T2`, `P2-T1` | 빌드 | ko/en/ja 문구 확인 |
|
||
|
||
## 17. Decision Log
|
||
|
||
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 요구사항·계약·Goal |
|
||
|---|---|---|---|---|---|
|
||
| `2026-08-18` | `DEC-001` | 확정 | 코드 구현 없이 PRD와 구현 계획 문서만 작성한다. | 사용자 직접 지시 | 전체 |
|
||
| `2026-08-18` | `DEC-002` | 확정 | 팔로잉 리스트의 팔로잉 중 액션은 Bottom Sheet를 건너뛰고 팔로우 해제 확인 Dialog로 진입한다. | 사용자 요구사항 | `UNFOLLOW-LIST-004~005`, `P1-T2` |
|
||
| `2026-08-18` | `DEC-003` | 확정 | 영어 문구는 `Unfollow`, `You won't receive updates from {{creatorName}}.\nUnfollow this creator?`, `Cancel`, `Unfollow`로 사용한다. | 사용자 위임 | `UNFOLLOW-DIALOG-001~004` |
|
||
| `2026-08-18` | `DEC-004` | 확정 | 한국어 Dialog 본문은 `팔로우를 해제할까요?\n{{creatorName}}의 소식을 받을 수 없어요.`로 사용한다. | 사용자 결정: `OQ-001` | `UNFOLLOW-DIALOG-002`, `P1-T2`, `P2-T1` |
|
||
| `2026-08-18` | `DEC-005` | 확정 | 팔로우 해제 확인 Dialog는 `SodaV2ActionModal`을 사용한다. | 사용자 결정: `OQ-002` | `UNFOLLOW-DIALOG-001~004`, `P1-T2`, `P2-T1` |
|
||
| `2026-08-18` | `DEC-006` | 확정 | Visual QA는 에이전트가 진행하지 않고 사용자가 직접 진행한다. | 사용자 직접 지시 | `UNFOLLOW-LIST-001~005`, `UNFOLLOW-CHANNEL-001~003`, `UNFOLLOW-DIALOG-001~004` |
|
||
|
||
## 18. 변경 관리
|
||
|
||
요구사항 변경 시 다음을 확인한다.
|
||
|
||
- [x] Decision Log에 변경 이유와 날짜를 기록했다.
|
||
- [x] 관련 요구사항 상태·본문·수용 기준을 갱신했다.
|
||
- [x] `plan-task.md`의 범위·Files·체크박스·완료 증거를 코드 변경 전에 갱신했다.
|
||
- [x] 기존 Progress·검증 기록을 삭제하거나 덮어쓰지 않았다.
|