14 KiB
14 KiB
선물함 리스트 페이지 생성 프롬프트
이 문서는 Android/iOS 앱의 선물함 리스트 페이지를 생성할 때 사용하는 프롬프트다.
참고 Figma:
- 팬 모드, 신청한 내역이 있을 때:
2481:19382 - 팬 모드, 신청한 내역이 없을 때:
2520:35587 - 크리에이터 모드, 받은 선물 내역이 없을 때:
2531:36283 - 크리에이터 모드, 받은 선물 내역이 있을 때:
2531:36194 - 크리에이터 모드, 받은 선물 상태별 카드 표시:
2531:36237
전제:
- Android/iOS 각각의 기존 디자인 시스템, 컴포넌트, API client, 상태 관리, toast/dialog, navigation 패턴을 재사용한다.
- Figma의 visual structure를 기준으로 구현하되, 아래 사용자 요구사항을 Figma보다 우선한다.
- 상단 뒤로가기 내비게이션 영역은 고정한다.
- 상단 뒤로가기 내비게이션 영역을 제외한 전체 콘텐츠 영역은 스크롤되어야 한다.
신청 내역,선물 내역섹션 타이틀은 표시하지 않는다.- 리스트는 신청일/취소일 최신순으로 보여야 한다.
- request/response 설명은 모바일 공통 JSON 기준이다.
모바일 앱 구현 프롬프트
Android/iOS 앱의 선물함 리스트 페이지를 Figma 기준으로 생성하고 API 연동을 구현해줘.
Figma는 두 관점의 상태를 보여준다.
- 보낸 선물 관점: 사용자가 본인이 신청한 선물 내역을 확인하는 상태다. Figma `2481:19382`, `2520:35587`를 기준으로 한다.
- 받은 선물 관점: 사용자가 본인이 받을 선물 내역을 확인하는 상태다. Figma `2531:36283`, `2531:36194`, `2531:36237`를 기준으로 한다.
- 실제 선물함 API는 두 관점을 나누어 호출하지 않고 `type=ALL`로 한 번 호출한다.
- 응답 item의 `direction` 값이 `SENT`이면 보낸 선물 카드로, `RECEIVED`이면 받은 선물 카드로 렌더링한다.
- 각 카드에는 상대방 프로필 이미지와 닉네임을 표시한다.
- `direction=SENT`: 상대방은 선물을 받는 크리에이터다.
- `direction=RECEIVED`: 상대방은 선물을 보낸 팬이다.
중요 요구사항:
- 상단 뒤로가기 내비게이션은 고정한다.
- 상단 내비게이션 아래의 전체 콘텐츠만 스크롤되게 한다.
- Figma에 보이는 `신청 내역`, `선물 내역` 섹션 타이틀은 실제 구현에서 표시하지 않는다.
- 선물함 리스트는 신청일/취소일 최신순으로 정렬한다.
- 현재 API 응답만으로 취소일 기준 정렬/표시는 완전하지 않으므로, API가 취소일을 내려주지 않으면 서버 응답 순서를 우선 사용하고 취소 건 날짜 라벨은 `createdAt` 기준으로 표시한다. 취소일 표시가 필수이면 API 보강이 필요하다.
API 호출:
- 선물함 리스트는 항상 `GET /api/v2/gifts?type=ALL&page=0&size=20`로 조회한다.
- `SENT`, `RECEIVED`로 따로 호출하지 않는다.
- `items[].direction`으로 보낸 선물/받은 선물 UI를 결정한다.
- 페이지 진입 시 첫 페이지를 조회한다.
- `hasNext=true`이면 스크롤 하단에서 다음 page를 추가 조회한다.
- pull-to-refresh가 기존 앱에 있으면 page를 0으로 초기화하고 다시 조회한다.
공통 레이아웃:
1. 상단 고정 내비게이션
- 타이틀: `선물함`
- 뒤로가기 버튼은 기존 앱 패턴을 사용한다.
- 이 영역은 스크롤되지 않는다.
2. 스크롤 콘텐츠
- nav 아래부터 시작한다.
- 안내 배너, 빈 상태, 리스트, 하단 여백 또는 하단 문의 버튼까지 스크롤 영역에 포함한다.
- iOS safe area와 Android navigation bar 여백은 기존 앱 패턴을 따른다.
보낸 선물 UI:
- `direction=SENT`인 item에 적용한다.
- 사용자가 신청한 선물 내역을 보여준다.
- 보낸 선물만 있는 상태는 Figma `2481:19382`를 따른다.
- 상단 안내 배너를 표시한다.
- 제목: `사서함을 통해 안전하게 전달됩니다`
- 본문: `크리에이터 및 팬의 주소는 공개되지 않습니다. 선물은 소다라이브 사서함에 도착한 뒤 크리에이터에게 전달됩니다.`
- `신청 내역` 섹션 타이틀은 표시하지 않는다.
- 카드 구성:
- 상단 왼쪽: `statusName`
- 상단 오른쪽: 날짜 라벨
- 기본: `{createdAt} 신청`
- 상태가 `CANCELED`이고 취소일 필드가 있으면 `{canceledAt} 취소`
- 현재 리스트 API에는 `canceledAt`이 없으므로 기존 API만 사용할 때는 `{createdAt} 취소` 또는 `{createdAt} 신청` 중 제품 정책에 맞춰 하나로 통일한다.
- 프로필 row 내부: `counterpartProfileImageUrl`, `counterpartNickname`을 사용해 받는 크리에이터 프로필을 표시한다.
- 프로필 row 아래 보조 문구: `sizeName · categoryName`
- 프로필 이미지가 없으면 기존 앱의 기본 프로필 이미지를 표시한다.
- 우측 chevron
- 탭 시 선물 상세 페이지로 이동하며 `applicationNo`를 전달한다.
- 리스트가 비어 있고 보낸 선물 관점으로 진입한 화면이면 Figma `2520:35587`를 따른다.
- 상단 안내 배너만 표시한다.
- 별도 empty title/body를 추가하지 않는다.
받은 선물 UI:
- `direction=RECEIVED`인 item에 적용한다.
- 사용자가 받을 선물 내역을 보여준다.
- 리스트가 비어 있고 받은 선물 관점으로 진입한 화면이면 Figma `2531:36283`를 따른다.
- 가운데 empty title: `전달 예정인 선물이 없어요`
- empty body: `베타 기간에는 팬이 선물을 보내는 기능만 제공돼요. 더 다양해진 선물 기능으로 곧 다시 만나요!`
- 버튼: `의견 남기기`
- 의견 남기기 동작은 기존 앱의 문의/피드백 이동 패턴을 사용한다.
- 받은 선물이 있는 상태는 Figma `2531:36194`, `2531:36237`를 따른다.
- 상단 안내 배너를 표시한다.
- 제목: `배송지 입력 기간 안내`
- 본문: `알림을 받은 날부터 7일 이내에 배송지를 입력해 주세요. 기한 내 입력하지 않으면 선물이 반송됩니다.`
- `선물 내역` 섹션 타이틀은 표시하지 않는다.
- 배송지 입력이 필요한 선물이 있으면 파란 안내 배너를 리스트 상단에 표시한다.
- 제목: `팬이 보낸 선물이 있어요!`
- 본문: `선물이 늦지 않게 전달될 수 있도록 배송지를 입력해 주세요.`
- 보조 문구: `*n일 이내로 입력하지 않으면 선물이 사라져요.`
- 현재 리스트 API에는 배송지 입력 마감일이 없으므로 정확한 n일 계산이 필요하면 API 보강이 필요하다.
- 배너 탭 시 배송지 입력이 필요한 첫 번째 선물 상세로 이동한다.
- 카드 구성:
- 상단 왼쪽 프로필 row 내부: `counterpartProfileImageUrl`, `counterpartNickname`을 사용해 보낸 팬 프로필을 표시한다.
- 상단 오른쪽: `{createdAt} 신청`
- 본문 메인: 상태 표시 문구
- 본문 서브: 상태 보조 문구가 필요한 경우만 표시
- 우측 chevron
- 탭 시 선물 상세 페이지로 이동하며 `applicationNo`를 전달한다.
- 리스트 하단에는 Figma처럼 `문의하기` 하단 버튼을 둘 수 있다. 기존 앱 정책상 고정 버튼이면 하단 safe area를 포함하고, 스크롤 콘텐츠 내부 버튼이면 콘텐츠 하단에 둔다.
상태 표시 매핑:
보낸 선물 카드:
| API status | 표시 문구 |
|---|---|
| `RECEIVED` | `운송장 등록 필요` |
| `TRACKING_REGISTERED` | `발송 확인` |
| `ARRIVED_AT_MAILBOX` | `사서함 도착` |
| `INSPECTION_COMPLETED` | `선물 검수 완료` |
| `DELIVERED` | `전달 완료` |
| `UNDELIVERABLE` | `전달 불가` |
| `CANCELED` | `신청 취소` |
받은 선물 카드:
| API status | 메인 문구 | 서브 문구 |
|---|---|---|
| `TRACKING_REGISTERED` | `배송지 입력 필요` | `전달 예정` |
| `ARRIVED_AT_MAILBOX` | `선물 검수` | `선물 확인 중` |
| `INSPECTION_COMPLETED` | `선물 검수 완료` | `배송 중` |
| `DELIVERED` | `전달 완료` | 없음 |
| `UNDELIVERABLE` | `전달 불가` | 없음 |
API 명세:
선물함 리스트 조회 API:
- Method: `GET`
- URL: `/api/v2/gifts`
- 인증: 로그인 필요
- Query:
- `type`: `ALL`, `SENT`, `RECEIVED`
- `page`: 0부터 시작
- `size`: 페이지 크기. 기본 20
- 이 페이지에서는 `type=ALL`만 사용한다.
- Response envelope 예시:
```json
{
"success": true,
"data": {
"totalCount": 1,
"items": [],
"page": 0,
"size": 20,
"hasNext": false
},
"message": ""
}
Response data 예시:
{
"totalCount": 2,
"items": [
{
"applicationNo": "A-1002609300001",
"direction": "SENT",
"status": "RECEIVED",
"statusName": "접수 완료",
"priceCan": 80,
"categoryName": "아크릴/스탠드",
"sizeName": "소형",
"counterpartMemberId": 200,
"counterpartNickname": "달빛수집가",
"counterpartProfileImageUrl": "https://example.com/profile.png",
"createdAt": "2026-09-18T03:00:00Z"
}
],
"page": 0,
"size": 20,
"hasNext": false
}
Response data 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
totalCount |
number | 전체 개수 |
items |
array | 선물함 리스트 |
items[].applicationNo |
string | 선물 신청번호. 상세 이동 ID |
items[].direction |
string | SENT 또는 RECEIVED |
items[].status |
string | 선물 상태 코드 |
items[].statusName |
string | 서버 상태 표시명 |
items[].priceCan |
number | 사용된 캔 |
items[].categoryName |
string | 카테고리명 |
items[].sizeName |
string | 사이즈명 |
items[].counterpartMemberId |
number | 상대방 회원 ID. SENT에서는 받는 크리에이터, RECEIVED에서는 보낸 팬 |
items[].counterpartNickname |
string | 상대방 닉네임 |
items[].counterpartProfileImageUrl |
string 또는 null | 상대방 프로필 이미지 URL. 없으면 기본 프로필 이미지 표시 |
items[].createdAt |
string 또는 null | 신청일. UTC ISO 문자열 |
page |
number | 현재 페이지 |
size |
number | 페이지 크기 |
hasNext |
boolean | 다음 페이지 존재 여부 |
정렬:
- 현재 서버 API는
createdAt desc, id desc로 정렬한다. - 요구사항은 신청일/취소일 최신순이다.
- 취소일 최신순까지 정확히 맞추려면 리스트 API가
canceledAt또는displayedAt같은 정렬 기준 시각을 내려주고 그 기준으로 정렬해야 한다. - API 보강 전에는 서버 응답 순서를 그대로 사용하고, 클라이언트에서 임의 재정렬하지 않는다.
상대방 프로필 표시 규칙:
counterpartNickname은 카드의 프로필 row 이름으로 표시한다.counterpartProfileImageUrl이 있으면 해당 이미지를 원형 프로필 이미지로 표시한다.counterpartProfileImageUrl이null이거나 빈 값이면 기존 앱의 기본 프로필 이미지를 표시한다.direction=SENT에서는 받는 크리에이터 정보로 해석한다.direction=RECEIVED에서는 보낸 팬 정보로 해석한다.
현재 API만으로 부족한 Figma 표시값:
- 취소일
canceledAt - 배송지 입력 마감일 또는 남은 일수
추가 API 보강이 가능하면 리스트 item에 아래 필드를 추가해달라고 요청한다.
{
"canceledAt": "2026-09-18T03:00:00Z",
"recipientAddressDeadlineAt": "2026-09-25T03:00:00Z",
"sortAt": "2026-09-18T03:00:00Z"
}
canceledAt: 취소 상태의 취소일 표시용recipientAddressDeadlineAt: 크리에이터 배송지 입력 안내 배너의 남은 일수 계산용sortAt: 신청/취소 최신순 정렬 기준. 취소 건은 취소일, 그 외에는 신청일
로딩/에러/빈 상태:
- 최초 로딩 중에는 기존 앱 리스트 스켈레톤 또는 loading 패턴을 사용한다.
- 실패 시 기존 앱 toast/dialog와 재시도 버튼을 사용한다.
- 빈 상태는 진입 관점에 따라 다르게 표시한다.
- 보낸 선물 관점으로 진입한 화면이면 안내 배너만 남긴다.
- 받은 선물 관점으로 진입한 화면이면 중앙 empty UI와
의견 남기기버튼을 표시한다.
테스트/검증:
- 선물함 진입 시
type=ALL로 API를 한 번 호출하는지 확인한다. direction=SENTitem은 보낸 선물 카드 UI로 표시되는지 확인한다.direction=RECEIVEDitem은 받은 선물 카드 UI로 표시되는지 확인한다.- 각 item의
counterpartNickname,counterpartProfileImageUrl이 프로필 row에 표시되는지 확인한다. counterpartProfileImageUrl=null이면 기본 프로필 이미지가 표시되는지 확인한다.- 상단 내비게이션은 고정되고 아래 콘텐츠만 스크롤되는지 확인한다.
신청 내역,선물 내역텍스트가 실제 화면에 노출되지 않는지 확인한다.- 리스트 item 탭 시
applicationNo로 상세 화면 이동이 되는지 확인한다. - 빈 상태가 진입 관점에 맞는 Figma 기준으로 표시되는지 확인한다.
hasNext=true일 때 다음 page를 추가 조회하는지 확인한다.- API 실패 시 입력/스크롤 상태를 깨지 않고 오류와 재시도를 제공하는지 확인한다.
---
## API 요약
| 목적 | Method | URL | Query | Response data |
|---|---|---|---|---|
| 선물함 리스트 조회 | GET | `/api/v2/gifts` | `type=ALL`, `page`, `size` | 선물 리스트, 페이지 정보 |
## Figma 반영 메모
- 보낸 선물 리스트 있음: 안내 배너 + 카드 리스트. 단, 실제 구현에서는 `신청 내역` 타이틀을 제거한다.
- 보낸 선물 관점 empty: 안내 배너만 표시한다.
- 받은 선물 관점 empty: 중앙 empty UI와 `의견 남기기` 버튼을 표시한다.
- 받은 선물 리스트 있음: 안내 배너 + 배송지 입력 CTA 배너 + 카드 리스트. 단, 실제 구현에서는 `선물 내역` 타이틀을 제거한다.
- 받은 선물 상태별 카드는 `배송지 입력 완료/전달 예정`, `전달 완료`, `전달 불가`, `선물 검수/선물 확인 중`, `선물 검수 완료/배송 중` 패턴을 사용한다.