12 KiB
12 KiB
선물 보내기 페이지 생성 프롬프트
이 문서는 Android/iOS 앱의 선물 보내기 페이지를 생성하거나 기존 생성 UI에 API 연동을 붙일 때 사용하는 프롬프트다.
참고 Figma:
- 빈 입력 상태:
2481:18904 - 입력 완료 및 CTA 활성화 상태:
2481:18957
전제:
- 크리에이터 닉네임과
memberId를 받아선물 보내기화면으로 이동하는 흐름은 이미 생성되어 있다. - 새 진입 흐름을 만들지 않는다.
- Figma에 있는 UI 구조와 문구를 유지한다.
- Android/iOS 각각의 기존 디자인 시스템, 컴포넌트, API client, 상태 관리, toast/dialog, navigation 패턴을 재사용한다.
- 모든 API 응답은 공통 envelope를 사용하며 실제 payload는
data에 있다. - request/response 설명은 모바일 공통 JSON 기준이다.
모바일 앱 구현 프롬프트
Android/iOS 앱의 선물 보내기 페이지를 Figma 기준으로 생성하고 API 연동을 구현해줘.
중요 전제:
- 크리에이터 닉네임과 memberId를 받아 이 화면으로 이동하는 기능은 이미 구현되어 있다.
- 이 작업에서는 이동 경로를 새로 만들지 말고, 전달받은 값만 화면과 API request에 연결한다.
- 전달받은 크리에이터 닉네임은 `받는 크리에이터` 영역에 표시한다.
- 전달받은 memberId는 선물 신청 API의 `recipientMemberId`로 보낸다.
Figma 참고 상태:
- 빈 입력 상태: node `2481:18904`
- 입력 완료 및 최하단 CTA 활성화 상태: node `2481:18957`
화면 구조:
1. 상단
- 타이틀: `선물 보내기`
- 뒤로가기 버튼은 기존 앱 패턴을 사용한다.
2. 안내 배너
- 제목: `선물 보내기 베타 서비스 안내`
- 본문: `베타 기간 동안은 일부 기능만 제공됩니다. 크리에이터에게 마음을 잘 전할 수 있도록 더 넓어진 선물 보내기로 곧 다시 만나요!`
3. 받는 크리에이터
- 이전 화면에서 전달받은 크리에이터 닉네임을 표시한다.
- Figma의 프로필 row 형태를 유지한다.
- memberId는 화면 표시용이 아니라 API request용으로만 사용한다.
4. 선물 사이즈
- 화면 진입 시 `GET /api/v2/gifts/form-options`를 호출해 `sizes`를 가져온다.
- 조회된 `sizes`를 사이즈 카드 목록에 바인딩한다.
- 카드에는 `name`, 사이즈 설명, 캔 가격을 표시한다.
- 서버 응답에는 사이즈 설명 필드가 없으므로 설명 문구는 앱에서 코드별로 매핑한다.
- `SMALL`: `세 변의 합 100cm 이하 · 5kg 이하`
- `MEDIUM`, `LARGE`: 정책 문구가 앱에 이미 있으면 기존 문구를 사용하고, 없으면 이름과 가격만 표시한다.
- 가격은 `salePriceCan`을 표시하고 submit 금액도 `salePriceCan`을 사용한다.
- `basePriceCan`과 `salePriceCan`이 다르면 기존 앱 할인/정가 표시 패턴이 있을 때만 정가를 함께 보여준다.
- 기본 선택은 서버가 내려준 첫 번째 사이즈로 둔다.
5. 카테고리
- 화면 진입 시 같은 `GET /api/v2/gifts/form-options` 응답의 `categories`를 사용한다.
- Figma의 select field를 유지한다.
- 빈 상태 문구: `카테고리 선택`
- 선택 후에는 선택한 카테고리 `name`을 표시한다.
- 카테고리 선택 UI는 기존 Android/iOS 앱 패턴에 맞는 bottom sheet, picker, dialog 중 이미 쓰는 방식을 사용한다.
- `requiresDamageWaiver=true`인 카테고리를 선택한 경우에만 카테고리 아래에 파손 면책 동의 row를 표시한다.
- 파손 면책 동의 문구: `파손 및 분실 면책 사항에 동의합니다. (필수)`
- `requiresDamageWaiver=false` 카테고리를 선택하면 파손 면책 동의 row를 숨기고 `damageWaiverAgreed=false`로 초기화한다.
6. 보내는 사람
- 이름 input → `senderName`
- 휴대폰 번호 input → `senderPhoneNumber`
- 우편번호 input → `senderZipCode`
- 주소 input → `senderAddress`
- 상세 주소 input → `senderAddressDetail`
- `우편번호 검색` 버튼은 기존 주소 검색 기능과 연결한다.
- 주소 검색 결과로 우편번호와 기본 주소를 채운다.
- 기본 주소는 사용자가 직접 수정하지 못하게 하는 기존 패턴이 있으면 그 패턴을 따른다.
7. 이용 약관 동의
- Figma의 발송 규정 요약 박스와 체크박스 2개를 유지한다.
- `소다라이브 크리에이터 상품 전달 이용약관에 동의합니다. (필수)` → `senderTermsAgreed`
- `상품 전달을 위한 개인정보 수집·이용에 동의합니다. (필수)` → `senderPrivacyAgreed`
8. 하단 CTA
- 빈 상태 또는 필수값 누락 상태는 Figma 빈 상태처럼 비활성 버튼을 표시한다.
- 활성 조건을 모두 만족하면 Figma 활성 상태처럼 soda 색상 CTA로 바꾼다.
- 활성 CTA 문구는 선택된 사이즈의 `salePriceCan`을 사용해 `{salePriceCan}캔으로 선물 보내기`로 표시한다.
- submit 중에는 중복 탭을 막고 loading 상태를 표시한다.
화면 진입 시 처리:
- 이미 전달받은 `creatorNickname`과 `memberId`를 읽는다.
- 둘 중 하나라도 없으면 기존 앱의 오류 처리 또는 뒤로가기 패턴을 따른다.
- 즉시 `GET /api/v2/gifts/form-options`를 호출한다.
- 로딩 중에는 기존 화면 스켈레톤/로딩 패턴을 사용한다.
- 조회 실패 시 toast/dialog와 재시도 동작을 기존 패턴으로 제공한다.
- `sizes` 또는 `categories`가 비어 있으면 선물 신청을 막고 CTA를 비활성화한다.
CTA 활성 조건:
- `memberId`가 있다.
- 사이즈가 선택되어 있다.
- 카테고리가 선택되어 있다.
- 이름이 입력되어 있다.
- 휴대폰 번호가 입력되어 있다.
- 우편번호가 입력되어 있다.
- 주소가 입력되어 있다.
- 이용약관 동의가 true다.
- 개인정보 수집·이용 동의가 true다.
- 선택한 카테고리의 `requiresDamageWaiver=true`이면 파손 면책 동의가 true다.
검증 실패 처리:
- CTA는 기본적으로 위 조건을 만족할 때만 활성화한다.
- 그래도 submit 시점에 한 번 더 validation 한다.
- 누락된 필드는 기존 앱의 input error, toast, dialog 중 현재 화면 패턴에 맞춰 안내한다.
- validation 실패 시 `POST /api/v2/gifts`를 호출하지 않는다.
폼 옵션 조회 API:
- Method: `GET`
- URL: `/api/v2/gifts/form-options`
- Request: 없음
- Response envelope 예시:
```json
{
"success": true,
"data": {
"sizes": [],
"categories": []
},
"message": ""
}
- Response
data예시:
{
"sizes": [
{
"sizeCode": "SMALL",
"name": "소형",
"basePriceCan": 100,
"salePriceCan": 80
}
],
"categories": [
{
"categoryId": 1,
"name": "아크릴",
"requiresDamageWaiver": true
}
]
}
폼 옵션 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
sizes |
array | 선택 가능한 선물 사이즈 목록 |
sizes[].sizeCode |
string | 사이즈 코드. SMALL, MEDIUM, LARGE |
sizes[].name |
string | 사이즈 표시명 |
sizes[].basePriceCan |
number | 기본 가격, 단위는 캔 |
sizes[].salePriceCan |
number | 실제 결제 가격, 단위는 캔 |
categories |
array | 선택 가능한 활성 카테고리 목록 |
categories[].categoryId |
number | 카테고리 ID |
categories[].name |
string | 카테고리 표시명 |
categories[].requiresDamageWaiver |
boolean | 파손 면책 동의 필요 여부 |
선물 신청 접수 API:
- Method:
POST - URL:
/api/v2/gifts - 인증: 로그인 회원 필요. 기존 앱 인증 토큰/세션 처리 방식을 사용한다.
- Request body 예시:
{
"recipientMemberId": 100,
"senderName": "김소다",
"senderPhoneNumber": "01000000000",
"senderZipCode": "12345",
"senderAddress": "서울시 강남구 ...",
"senderAddressDetail": "123동 456호",
"sizeCode": "SMALL",
"categoryId": 1,
"senderTermsAgreed": true,
"senderPrivacyAgreed": true,
"damageWaiverAgreed": true
}
Request body 필드:
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
recipientMemberId |
number | Y | 화면 진입 시 전달받은 memberId |
senderName |
string | Y | 보내는 사람 이름 |
senderPhoneNumber |
string | Y | 보내는 사람 휴대폰 번호 |
senderZipCode |
string | Y | 보내는 사람 우편번호 |
senderAddress |
string | Y | 보내는 사람 기본 주소 |
senderAddressDetail |
string 또는 null | N | 보내는 사람 상세 주소 |
sizeCode |
string | Y | 선택한 사이즈 코드 |
categoryId |
number | Y | 선택한 카테고리 ID |
senderTermsAgreed |
boolean | Y | 이용약관 동의 여부. 반드시 true |
senderPrivacyAgreed |
boolean | Y | 개인정보 수집·이용 동의 여부. 반드시 true |
damageWaiverAgreed |
boolean | Y | 파손 면책 동의 여부. 필요한 카테고리에서는 true, 필요 없는 카테고리에서는 false |
- Response
data예시:
{
"applicationNo": "A-1002609300001",
"status": "RECEIVED",
"statusName": "접수 완료",
"priceCan": 80,
"trackingDeadlineAt": "2026-10-02T03:00:00Z"
}
Response data 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
applicationNo |
string | 선물 신청번호 |
status |
string | 신청 상태 코드 |
statusName |
string | 신청 상태 표시명 |
priceCan |
number | 실제 차감된 캔 금액 |
trackingDeadlineAt |
string | 운송장 등록 기한. UTC ISO 문자열 |
성공 처리:
- 신청 성공 시 기존 앱의 완료 dialog 또는 완료 화면 패턴을 사용한다.
- 최소 표시값은
applicationNo,statusName,priceCan,trackingDeadlineAt이다. - 성공 이후 이동 CTA가 필요하면 기존 선물함 또는 선물 상세 이동 패턴을 사용한다.
실패 처리:
- 서버 오류 메시지가 있으면 기존 앱 에러 노출 방식으로 표시한다.
- 잔액 부족, 유효하지 않은 카테고리, 파손 면책 미동의, 약관 미동의 등의 오류는 서버 메시지를 우선 사용한다.
- 실패 시 입력값은 유지한다.
테스트/검증:
- 화면 진입 시
GET /api/v2/gifts/form-options가 호출되는지 확인한다. - 전달받은 크리에이터 닉네임이 받는 크리에이터 영역에 표시되는지 확인한다.
- 전달받은 memberId가
POST /api/v2/gifts의recipientMemberId로 들어가는지 확인한다. - 빈 상태에서는 CTA가 비활성화되는지 확인한다.
- 필수 입력과 필수 동의를 모두 완료하면 CTA가 활성화되고
{salePriceCan}캔으로 선물 보내기가 표시되는지 확인한다. requiresDamageWaiver=true카테고리 선택 시 파손 면책 동의 row가 표시되고 동의 전에는 CTA가 비활성인지 확인한다.requiresDamageWaiver=false카테고리 선택 시 파손 면책 동의 row가 숨겨지고 request의damageWaiverAgreed가 false인지 확인한다.- submit 성공 시 요청 body와 성공 처리 값을 확인한다.
- submit 실패 시 입력값이 유지되고 기존 앱 방식으로 오류가 표시되는지 확인한다.
---
## API 요약
| 목적 | Method | URL | Request | Response data |
|---|---|---|---|---|
| 폼 옵션 조회 | GET | `/api/v2/gifts/form-options` | 없음 | 사이즈 목록, 카테고리 목록 |
| 선물 신청 접수 | POST | `/api/v2/gifts` | 선물 신청 JSON body | 신청번호, 상태, 차감 금액, 운송장 등록 기한 |
## Figma 반영 메모
- 빈 상태 Figma는 카테고리 미선택, 보내는 사람 정보 미입력, 약관 미동의, 하단 CTA 비활성 상태다.
- 활성 상태 Figma는 크리에이터 닉네임 표시, 카테고리 선택, 파손 면책 동의 노출, 보내는 사람 정보 입력, 약관 동의, 하단 CTA 활성 상태다.
- Figma의 하단 버튼 텍스트는 캔 금액이 포함된 형태이므로 API의 `salePriceCan`으로 동적으로 표시한다.
- Figma의 select, checkbox, radio, bottom action bar, safe area는 각 플랫폼의 기존 컴포넌트로 대응한다.