Milestone: Henriette 4-Market Shop Launch (KR / SG / US / JP)
docs/milestone/henriette-4-market-launch.md
id: henriette-4-market-launch status: active created: 2025-02-05 target: TBD
Milestone: Henriette 4-Market Shop Launch (KR / SG / US / JP)
목표
중소 화주사 Henriette가 MAKITT 플랫폼을 사용하여 한국, 싱가포르, 미국, 일본 4개 마켓에 대해 상품 등록 → 주문 → 결제 → 배송 → CRM까지의 전체 커머스 플로우를 운영할 수 있도록 한다.
이는 MAKITT의 첫 번째 실전 검증(Production Validation)이며, 플랫폼의 multi-market commerce 역량을 증명하는 마일스톤이다.
완료 조건
- Henriette가 makitt-web에서 4개 마켓별 Shop을 생성하고 각각의 설정을 완료
- 국가별 결제 수단(Toss/Stripe/PayPal)이 실제 결제까지 동작
- 상품 등록, 컬렉션 구성, 재고 관리가 가능
- 고객이 makitt-shop에서 상품 탐색 → 장바구니 → 체크아웃 → 결제 완료
- ARGO 물류 연동: 입고, 출고, 배송 트래킹, 반품/교환
- Builder + AI Agent로 Henriette shop을 standard commerce 수준으로 구축
- Onboarding 절차가 seamless하게 진행 경과를 보여줌
- 주문/배송/고객 관리(CRM)가 makitt-web에서 가능
현재 상태 요약
makitt-client
| 영역 | 상태 | 비고 |
|---|---|---|
| Onboarding (3D) | ✅ 구현완료 | Scene 0-6, AI Wizard, 국가 선택 |
| Shop 생성/설정 | ✅ 구현완료 | 비즈니스 정보, 브랜드, 정책, 도메인 |
| Payment 설정 | ✅ 구현완료 | Stripe/Toss/PayPal 프로세서 UI |
| Product CRUD | ✅ 구현완료 | 상품, 변형, SKU, 필터 |
| Collection CRUD | ✅ 구현완료 | 수동/자동 컬렉션 |
| Order 관리 | ✅ 구현완료 | 시뮬레이션 모드 포함 |
| Customer CRM | ✅ 구현완료 | 세그먼트, 메시징, 문의 |
| Logistics UI | ✅ 구현완료 | VendorConnectionWizard, 대시보드 |
| Shop Checkout | ⚠️ 부분구현 | 기본 폼만, 실제 결제 연동 미완 |
| Builder Commerce | ⚠️ 부분구현 | Primitive만, Business Component 미정의 |
| Token Refresh | ⚠️ 부분구현 | 암시적 세션 체크만, 명시적 리프레시 없음 |
| i18n | ⚠️ 부분구현 | KO/EN만, JP 없음 (standard-commerce는 KO/EN/JA) |
makitt-server
| 영역 | 상태 | 비고 |
|---|---|---|
| Product/SKU/Collection | ✅ 구현완료 | DynamoDB 엔티티 + CRUD API |
| Order 라이프사이클 | ✅ 구현완료 | PAYMENT_PENDING → DELIVERED 전체 |
| Checkout/Cart | ✅ 구현완료 | TTL 체크아웃, 카트 엔티티 |
| Stripe 결제 | ✅ 구현완료 | PaymentIntent + Webhook |
| Shop/Org 설정 | ✅ 구현완료 | 다중 프로세서, 인증 설정 |
| Customer/Auth | ✅ 구현완료 | Email/OTP/OAuth, RefreshToken |
| Asset/Media | ✅ 구현완료 | S3 업로드, Presigned URL |
| Toss 결제 | ❌ 미구현 | ProcessorType 정의만, 구현체 없음 |
| PayPal 결제 | ❌ 미구현 | ProcessorType 정의만, 구현체 없음 |
| 배송 추적 | ⚠️ 부분구현 | trackingNumber/URL 저장만, 캐리어 API 없음 |
| 세금 계산 | ❌ 미구현 | CheckoutPolicy 프레임워크만 |
| ARGO OMS 연동 | ❌ 미구현 | Kafka 컨슈머 없음 |
| ARGO WMS 연동 | ❌ 미구현 | 인바운드/아웃바운드 미구현 |
ARGO 연동
| 영역 | 상태 | 비고 |
|---|---|---|
| VMS 벤더 등록 | ⚠️ 부분구현 | FeignClient 구현, 워크플로 미완 |
| CMS SKU 동기화 | ✅ 작동중 | Kafka cms-sku-info-change 컨슈머 |
| OMS 주문 수집 | ✅ 문서화 | Shopify 주문 플로우 설계완료 |
| WMS 입고 | ❌ 미구현 | 설계만 |
| WMS 출고 | ⚠️ 부분구현 | Order Drop 트리거만 |
| WMS 재고 | ❌ 미구현 | |
| SSO 연동 | ❌ 미구현 | ArgoSugarClient만, ARGO API 필요 |
makitt-ai-agent
| 영역 | 상태 | 비고 |
|---|---|---|
| Multi-Agent (12개) | ✅ 구현완료 | LangGraph 기반, SSE 스트리밍 |
| Shop 생성 | ✅ 구현완료 | 이름/URL/설명 생성 |
| Product 생성 | ✅ 구현완료 | 카테고리별 가격/설명 |
| Blog 콘텐츠 | ✅ 구현완료 | Markdown + SEO |
| Builder (HCS) | ✅ 구현완료 | 컴포넌트 JSON 생성 |
| Image 생성 | ✅ 구현완료 | Gemini/Imagen, S3 업로드 |
| 서버 연동 | ❌ 미구현 | 결과를 클라이언트에 반환만, server 직접 저장 없음 |
Epics
E01: Multi-Market Onboarding Flow
국가별 설정을 포함한 seamless onboarding 절차 구축
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-client, makitt-server |
| 현재 상태 | 3D 온보딩 씬 구현완료, 국가 선택 존재. 하지만 국가 선택 후 마켓별 설정(약관, 세금, 배송, 결제)으로 이어지는 guided flow 없음. 진행경과 트래킹 UI 없음 |
| 목표 | Henriette가 KR/SG/US/JP 각 마켓에 대해 Shop 생성 → 마켓 설정 → 결제 연동 → 물류 연동 → 상품 등록까지 단계별 진행률을 확인하며 완료 |
핵심 작업:
- 온보딩 Progress Tracker (Stepper UI) 설계 및 구현
- 국가별 필수 설정 항목 정의 (약관, 세금, 배송정책, 결제수단)
- 온보딩 상태 저장 API (makitt-server)
- 물류(ARGO) 연동 단계를 온보딩에 통합
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 온보딩 시작 | |||
| 1.1 | 로그인 후 최초 진입 | 신규 가입 후 첫 로그인 | /onboarding 페이지로 자동 리다이렉트되고, 상단에 "Shop 설정 (1/6)" 형태의 Progress Bar가 표시됨 |
| 1.2 | 온보딩 Progress Bar | Step 1 "기본 정보" 진행 중 | Step 1이 파란색으로 하이라이트되고, Step 2~6은 회색으로 표시됨 |
| 1.3 | 온보딩 Progress Bar | Step 1 완료 후 | Step 1에 ✓ 체크 아이콘이 표시되고, Step 2가 하이라이트됨 |
| 2. 국가 선택 분기 | |||
| 2.1 | /onboarding/country | "한국" 카드 클릭 | 다음 화면에서 "사업자등록번호", "통신판매업 신고번호" 입력 필드가 표시됨 |
| 2.2 | /onboarding/country | "미국" 카드 클릭 | 다음 화면에서 "Tax ID (EIN)", "Business State" 드롭다운이 표시됨 |
| 2.3 | /onboarding/country | "일본" 카드 클릭 | 다음 화면에서 "特定商取引法表記" 섹션과 "法人番号" 입력 필드가 표시됨 |
| 2.4 | /onboarding/country | "싱가포르" 카드 클릭 | 다음 화면에서 "UEN (Unique Entity Number)", "GST 등록 여부" 토글이 표시됨 |
| 3. 필수 입력 검증 | |||
| 3.1 | /onboarding/business-info (한국) | 사업자등록번호 입력 없이 "다음" 클릭 | "사업자등록번호를 입력해주세요" 빨간색 에러 메시지가 해당 필드 하단에 표시됨 |
| 3.2 | /onboarding/business-info (한국) | 사업자등록번호 "123-45-67890" 입력 후 "다음" 클릭 | 에러 없이 다음 단계로 이동하고, Progress Bar의 현재 단계에 ✓ 표시됨 |
| 3.3 | /onboarding/business-info (미국) | Tax ID 입력 없이 "다음" 클릭 | "Tax ID is required" 에러 메시지 표시됨 |
| 4. 이탈 후 복귀 | |||
| 4.1 | /onboarding/payment (Step 4) | 브라우저 탭 닫기 후 재로그인 | /onboarding/payment 페이지로 자동 이동되고, Step 1~3에 ✓ 표시됨 |
| 4.2 | /onboarding/payment (Step 4) | 재로그인 후 Step 2 "비즈니스 정보" 클릭 | Step 2 화면에서 이전에 입력한 사업자등록번호가 그대로 표시됨 |
| 5. 물류 연동 단계 | |||
| 5.1 | /onboarding/logistics (Step 5) | 해당 단계 진입 | "ARGO 물류 연동" 모달이 자동으로 열리고, "연동 시작" / "나중에 하기" 버튼이 표시됨 |
| 5.2 | /onboarding/logistics 모달 | "나중에 하기" 클릭 | 모달 닫히고, Step 5에 "건너뜀" 뱃지가 표시되며, Step 6으로 이동 |
| 5.3 | /onboarding/logistics 모달 | "연동 시작" 클릭 | ARGO 벤더 등록 위자드가 시작되고, 이메일 입력 폼이 표시됨 |
| 6. 온보딩 완료 | |||
| 6.1 | /onboarding/complete | 모든 필수 단계(Step 1~4, 6) 완료 | "축하합니다! Shop 설정이 완료되었습니다" 메시지와 함께 완료 화면 표시 |
| 6.2 | /onboarding/complete | "대시보드로 이동" 버튼 클릭 | /dashboard 페이지로 이동하고, 상단에 "온보딩 완료됨" 토스트 알림 표시 |
| 7. 건너뛴 단계 재설정 | |||
| 7.1 | /dashboard | 좌측 메뉴 "설정 > 물류" 클릭 | /settings/logistics 페이지에서 "ARGO 연동" 섹션이 "미연동" 상태로 표시됨 |
| 7.2 | /settings/logistics | "연동하기" 버튼 클릭 | ARGO 연동 위자드 모달이 열림 |
E02: Country-Specific Shop Configuration
4개 마켓별 약관, 세금, 배송정책, 통화 설정 체계 구축
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-client, makitt-server |
| 현재 상태 | Shop에 localization(language, timezone, currency) 필드 존재. 정책 페이지 구현됨. 하지만 국가별 세금 규정, 필수 약관 템플릿, 배송정책 가이드 없음 |
| 목표 | 각 마켓의 법적/규제 요구사항에 맞는 설정을 제공하고, 기본값을 자동 적용 |
핵심 작업:
- 국가별 필수 약관 템플릿 (KR: 전자상거래법, US: Terms of Service, JP: 특정상거래법, SG: Consumer Protection)
- 세금 정책 엔진 (KR: VAT 10%, US: Sales Tax 주별, JP: 소비세 10%, SG: GST 9%)
- 국가별 기본 배송정책 템플릿
- 통화 설정 자동화 (KRW, USD, JPY, SGD)
- 국가별 규제 research 문서 작성 (
docs/research/regulations/)
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 한국 약관 템플릿 | |||
| 1.1 | makitt-web > 설정 > 정책 > 약관 | 국가 "한국"인 Shop에서 약관 페이지 최초 진입 | "이용약관" 에디터에 전자상거래법 기반 기본 템플릿 텍스트가 미리 채워져 있음 |
| 1.2 | makitt-web > 설정 > 정책 > 약관 | 국가 "한국"인 Shop에서 탭 전환 | "개인정보처리방침", "청약철회/환불정책" 탭에도 각각 기본 템플릿이 채워져 있음 |
| 2. 일본 약관 템플릿 | |||
| 2.1 | makitt-web > 설정 > 정책 > 약관 | 국가 "일본"인 Shop에서 약관 페이지 진입 | "特定商取引法に基づく表記" 템플릿이 표시되고, 사업자명/주소/전화번호/반품조건 입력 필드가 포함됨 |
| 3. 미국 약관 템플릿 | |||
| 3.1 | makitt-web > 설정 > 정책 > 약관 | 국가 "미국"인 Shop에서 약관 페이지 진입 | "Terms of Service"와 "Privacy Policy" 탭에 영문 기본 템플릿이 채워져 있음 |
| 4. 싱가포르 약관 템플릿 | |||
| 4.1 | makitt-web > 설정 > 정책 > 약관 | 국가 "싱가포르"인 Shop에서 약관 페이지 진입 | "Terms and Conditions" 템플릿에 Lemon Law(6개월 내 결함 시 환불/교환) 관련 조항이 포함되어 있음 |
| 5. 한국 세금 계산 | |||
| 5.1 | makitt-web > 상품 > 상품 등록 | 한국 Shop에서 가격 "10000" 입력 | 가격 필드 우측에 "VAT 포함: ₩11,000" 또는 "VAT: ₩1,000" 정보가 표시됨 |
| 5.2 | makitt-shop > 체크아웃 | 한국 Shop에서 ₩10,000 상품 결제 진행 | 주문 요약에 "상품가격: ₩10,000", "VAT (10%): ₩1,000", "총액: ₩11,000"이 각각 표시됨 |
| 6. 미국 세금 계산 | |||
| 6.1 | makitt-shop > 체크아웃 > 배송지 입력 | 미국 Shop에서 State 드롭다운 클릭 | 50개 주 목록이 표시되고, "California", "Oregon" 등 선택 가능 |
| 6.2 | makitt-shop > 체크아웃 > 배송지 입력 | State에서 "California" 선택 | 주문 요약에 "Sales Tax (7.25%): $7.25" (상품 $100 기준)가 자동 계산되어 표시됨 |
| 6.3 | makitt-shop > 체크아웃 > 배송지 입력 | State에서 "Oregon" 선택 | 주문 요약에 "Sales Tax: $0.00" 표시 (면세주) |
| 7. 일본 세금 계산 | |||
| 7.1 | makitt-shop > 체크아웃 | 일본 Shop에서 ¥1,000 상품 결제 진행 | 주문 요약에 "소비세 (10%): ¥100", "합계: ¥1,100"이 표시됨 |
| 8. 싱가포르 세금 계산 | |||
| 8.1 | makitt-shop > 체크아웃 | GST 등록된 싱가포르 Shop에서 SGD 100 상품 결제 | 주문 요약에 "GST (9%): SGD 9.00", "Total: SGD 109.00"이 표시됨 |
| 8.2 | makitt-shop > 체크아웃 | GST 미등록 싱가포르 Shop에서 SGD 100 상품 결제 | 주문 요약에 "GST: SGD 0.00", "Total: SGD 100.00"이 표시됨 |
| 9. 통화 자동 설정 | |||
| 9.1 | makitt-web > 설정 > 일반 | 온보딩에서 국가 "한국" 선택 후 Shop 설정 확인 | "기본 통화" 필드가 "KRW (₩)"로 자동 설정되어 있음 |
| 9.2 | makitt-web > 설정 > 일반 | 온보딩에서 국가 "미국" 선택 후 Shop 설정 확인 | "기본 통화" 필드가 "USD ($)"로 자동 설정됨 |
| 9.3 | makitt-web > 설정 > 일반 | 온보딩에서 국가 "일본" 선택 후 Shop 설정 확인 | "기본 통화" 필드가 "JPY (¥)"로 자동 설정됨 |
| 9.4 | makitt-web > 설정 > 일반 | 온보딩에서 국가 "싱가포르" 선택 후 Shop 설정 확인 | "기본 통화" 필드가 "SGD (S$)"로 자동 설정됨 |
| 10. 배송정책 템플릿 | |||
| 10.1 | makitt-web > 설정 > 정책 > 배송 | 한국 Shop에서 배송정책 페이지 진입 | "국내 택배" 템플릿이 표시되고, 기본 배송비(예: 3,000원), 무료배송 기준, 배송기간(1~3일) 필드가 포함됨 |
| 10.2 | makitt-web > 설정 > 정책 > 배송 | 미국 Shop에서 배송정책 페이지 진입 | "Domestic Shipping"과 "International Shipping" 두 섹션이 표시됨 |
| 11. 약관 편집 및 미리보기 | |||
| 11.1 | makitt-web > 설정 > 정책 > 약관 | 이용약관 텍스트 수정 후 "미리보기" 버튼 클릭 | 우측 패널에 수정된 약관이 Shop에 표시될 형태로 렌더링되어 표시됨 |
| 12. 필수 약관 검증 | |||
| 12.1 | makitt-web > 설정 > 정책 > 약관 | 이용약관 내용을 전부 삭제하고 "저장" 클릭 | "이용약관을 입력해주세요" 빨간색 에러 메시지가 표시되고 저장이 실패함 |
| 12.2 | makitt-web > 설정 > 정책 > 약관 | 개인정보처리방침을 비운 상태로 "저장" 클릭 | 해당 탭에 빨간색 경고 아이콘이 표시되고 저장이 실패함 |
| 12.3 | makitt-web > 빌더 > 게시 | 필수 약관이 모두 입력된 상태에서 "게시" 클릭 | 정상적으로 게시가 진행됨 |
E03: Payment Processor Full Integration
Toss Payments, Stripe, PayPal 실결제 연동 완성
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-server, makitt-client, @makitt/payments |
| 현재 상태 | Stripe PaymentIntent 구현완료. Toss/PayPal은 ProcessorType enum 정의만. 프론트에서 프로세서 설정 UI 구현완료. @makitt/payments 패키지에 Stripe SDK만 래핑 |
| 목표 | 4개 마켓에서 실결제 가능: KR(Toss+카카오페이/네이버페이), US(Stripe+Apple Pay/Google Pay), JP(Stripe), SG(Stripe+PayPal) |
핵심 작업:
- Toss Payments: TossPaymentProcessor 구현 (server), Toss SDK 연동 (client payments 패키지)
- PayPal: PayPalPaymentProcessor 구현, 체크아웃 버튼 통합
- Stripe 확장: 일본 엔화(JPY) 결제 검증, Apple Pay/Google Pay 마켓별 활성화
- 국가별 결제수단 자동 추천 로직
- Webhook 통합 (Toss confirm callback, PayPal IPN)
- 결제 테스트 환경 (Sandbox/Test 모드)
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. Toss Payments (한국 고객) | |||
| 1.1 | makitt-shop > 체크아웃 > 결제 | 한국 Shop에서 "토스페이" 버튼 클릭 | 토스 결제창이 새 팝업 창으로 열리고, 결제 금액(예: ₩11,000)이 표시됨 |
| 1.2 | 토스 결제창 | 카드 정보 입력 후 "결제하기" 클릭 | 팝업이 닫히고 /order/confirmation/{orderId} 페이지로 리다이렉트되어 "주문이 완료되었습니다" 메시지 표시 |
| 1.3 | 토스 결제창 | "취소" 버튼 클릭 | 팝업이 닫히고 /checkout 페이지로 돌아오며 "결제가 취소되었습니다" 빨간색 토스트 알림 표시 |
| 1.4 | 토스 결제창 | 잔액 부족 카드로 결제 시도 | "카드 잔액이 부족합니다" 메시지가 표시되고 결제 실패 |
| 2. PayPal (싱가포르 고객) | |||
| 2.1 | makitt-shop > 체크아웃 > 결제 | 싱가포르 Shop에서 "PayPal" 버튼 클릭 | PayPal 로그인 팝업이 열리고 결제 금액이 "SGD 109.00" 형식으로 표시됨 |
| 2.2 | PayPal 팝업 | PayPal 계정 로그인 후 "Pay Now" 클릭 | 팝업이 닫히고 주문 확인 페이지로 이동, "Payment completed via PayPal" 메시지 표시 |
| 2.3 | PayPal 팝업 | "Cancel and return" 클릭 | 팝업이 닫히고 /cart 장바구니 페이지로 이동 |
| 3. Apple Pay / Google Pay (미국 고객) | |||
| 3.1 | makitt-shop > 체크아웃 > 결제 | Safari 브라우저에서 미국 Shop 체크아웃 페이지 진입 | 결제 수단 목록에 Apple Pay 아이콘 버튼이 표시됨 |
| 3.2 | makitt-shop > 체크아웃 > 결제 | Apple Pay 버튼 클릭 | Touch ID/Face ID 인증 시트가 표시되고, 결제 금액 "$107.25" 표시 |
| 3.3 | makitt-shop > 체크아웃 > 결제 | Chrome/Firefox 브라우저에서 미국 Shop 진입 | Apple Pay 버튼이 표시되지 않고, 신용카드/Google Pay만 표시됨 |
| 3.4 | makitt-shop > 체크아웃 > 결제 | Chrome 브라우저에서 Google Pay 버튼 클릭 | Google Pay 결제 시트가 표시됨 |
| 4. Stripe JPY (일본 고객) | |||
| 4.1 | makitt-shop > 체크아웃 > 결제 | 일본 Shop에서 "신용카드" 선택 | Stripe Elements 카드 입력 폼(카드번호/유효기간/CVC)이 표시됨 |
| 4.2 | makitt-shop > 체크아웃 > 결제 | 카드 정보 입력 후 총액 확인 | 금액이 "¥1,100" (소수점 없이)로 표시됨 |
| 5. 결제수단 자동 추천 (판매자) | |||
| 5.1 | makitt-web > 설정 > 결제 | 한국 Shop에서 결제 설정 페이지 진입 | "추천 결제수단" 섹션에 "토스페이", "카카오페이", "네이버페이"가 체크된 상태로 표시됨 |
| 5.2 | makitt-web > 설정 > 결제 | 미국 Shop에서 결제 설정 페이지 진입 | "추천 결제수단" 섹션에 "Stripe", "Apple Pay", "Google Pay"가 표시됨 |
| 5.3 | makitt-web > 설정 > 결제 | 싱가포르 Shop에서 결제 설정 페이지 진입 | "추천 결제수단" 섹션에 "Stripe", "PayPal"이 표시됨 |
| 6. 테스트 모드 (판매자) | |||
| 6.1 | makitt-web > 설정 > 결제 | "테스트 모드" 토글 ON | 페이지 상단에 노란색 "테스트 모드 활성화됨" 배너가 표시됨 |
| 6.2 | makitt-shop > 체크아웃 | 테스트 모드 Shop에서 Stripe 테스트 카드 "4242 4242 4242 4242" 입력 후 결제 | 실제 과금 없이 결제 성공, 주문 확인 페이지 표시 |
| 6.3 | makitt-web > 주문 목록 | 테스트 모드에서 생성된 주문 확인 | 주문 목록에서 해당 주문에 "테스트" 주황색 뱃지가 표시됨 |
| 7. 결제 실패 처리 (고객) | |||
| 7.1 | makitt-shop > 체크아웃 > 결제 | 잔액 부족 카드로 결제 시도 | "잔액이 부족합니다. 다른 결제 수단을 선택해주세요" 빨간색 에러 메시지 표시, 결제 버튼 재활성화 |
| 7.2 | makitt-shop > 체크아웃 > 결제 | 유효기간 만료 카드 입력 | "카드 유효기간이 만료되었습니다" 에러 메시지 표시 |
| 7.3 | makitt-shop > 체크아웃 > 결제 | 결제 실패 후 | 결제 수단 선택 영역이 유지되어 다른 카드 또는 다른 결제수단 선택 가능 |
| 8. 결제 내역 조회 (판매자) | |||
| 8.1 | makitt-web > 주문 > 결제 내역 | 페이지 진입 | 전체 결제 목록이 테이블로 표시되고, 컬럼: 날짜/주문번호/결제수단/금액/상태 |
| 8.2 | makitt-web > 주문 > 결제 내역 | "결제수단" 필터에서 "Toss" 선택 | Toss로 결제된 건만 필터링되어 표시됨 |
| 8.3 | makitt-web > 주문 > 결제 내역 | "상태" 필터에서 "실패" 선택 | 결제 실패 건만 필터링되어 표시됨 |
E04: Checkout & Cart End-to-End Flow
고객이 상품 선택부터 결제 완료까지의 전체 체크아웃 플로우
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-client (shop), makitt-server |
| 현재 상태 | makitt-shop에 Cart UI/상태 구현됨. Checkout 기본 폼만 존재. 서버에 Cart/Checkout 엔티티 완비. 하지만 실제 결제 프로세서 연동, 배송지 검증, 배송옵션 선택, 세금 계산이 shop에서 미연동 |
| 목표 | makitt-shop에서 완전한 장바구니 → 체크아웃 → 결제 → 주문확인 플로우 |
핵심 작업:
- Cart: 수량 변경, 재고 검증, 가격 계산 (통화별)
- Checkout Step 1: 배송지 입력/검증 (국가별 주소 포맷)
- Checkout Step 2: 배송옵션 선택 + 배송비 계산
- Checkout Step 3: 결제수단 선택 + 결제 처리 (E03 연동)
- Checkout Step 4: 주문 확인 + 이메일 알림
- 세금 자동 계산 연동 (E02 세금 엔진)
- 게스트 체크아웃 지원
- 중복 결제 방지 (Idempotency key)
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 장바구니 추가 | |||
| 1.1 | makitt-shop > 상품 상세 | "장바구니 추가" 버튼 클릭 | 헤더의 장바구니 아이콘에 빨간색 뱃지로 수량 "1"이 표시됨 |
| 1.2 | makitt-shop > 상품 상세 | 같은 상품 "장바구니 추가" 2번 더 클릭 | 장바구니 아이콘 뱃지가 "3"으로 업데이트됨 |
| 2. 장바구니 수량 변경 | |||
| 2.1 | makitt-shop > /cart | 상품 수량 "+" 버튼 클릭 (현재 1개) | 수량이 "2"로 변경되고, 소계(예: ₩10,000 → ₩20,000)와 총액이 즉시 재계산됨 |
| 2.2 | makitt-shop > /cart | 수량 입력 필드에 직접 "5" 입력 | 수량이 5개로 변경되고 가격이 재계산됨 |
| 3. 재고 검증 | |||
| 3.1 | makitt-shop > /cart | 재고 3개인 상품의 수량을 "5"로 변경 시도 | 수량이 3으로 자동 조정되고 "재고가 3개 남았습니다" 메시지 표시 |
| 3.2 | makitt-shop > 상품 상세 | 재고 0인 상품 페이지 진입 | "품절" 뱃지 표시, "장바구니 추가" 버튼 비활성화(회색) |
| 4. 배송지 입력 - 한국 | |||
| 4.1 | makitt-shop > /checkout (Step 1) | 한국 Shop에서 배송지 입력 폼 확인 | 필드: 수령인, 연락처, 우편번호(검색 버튼), 주소, 상세주소 순서로 표시됨 |
| 4.2 | makitt-shop > /checkout (Step 1) | "우편번호 검색" 버튼 클릭 | 다음/카카오 주소 검색 모달이 열림 |
| 4.3 | makitt-shop > /checkout (Step 1) | 주소 검색 결과에서 주소 선택 | 우편번호(예: 06234), 기본주소(예: 서울특별시 강남구...)가 자동 입력됨 |
| 5. 배송지 입력 - 미국 | |||
| 5.1 | makitt-shop > /checkout (Step 1) | 미국 Shop에서 배송지 입력 폼 확인 | 필드: Name, Address Line 1, Address Line 2, City, State(드롭다운), ZIP Code |
| 5.2 | makitt-shop > /checkout (Step 1) | ZIP Code에 "9021" (4자리) 입력 후 다음 클릭 | "Please enter a valid 5-digit ZIP code" 에러 메시지 표시 |
| 6. 배송지 입력 - 일본 | |||
| 6.1 | makitt-shop > /checkout (Step 1) | 일본 Shop에서 배송지 입력 폼 확인 | 필드: 郵便番号, 都道府県(드롭다운), 市区町村, 番地, 建物名 순서로 표시됨 |
| 7. 배송옵션 선택 | |||
| 7.1 | makitt-shop > /checkout (Step 2) | 페이지 진입 | "일반 배송 (3-5일)" ₩3,000, "빠른 배송 (1-2일)" ₩5,000 옵션이 라디오 버튼으로 표시됨 |
| 7.2 | makitt-shop > /checkout (Step 2) | "빠른 배송" 선택 | 주문 요약 영역의 "배송비"가 ₩3,000 → ₩5,000으로 변경되고 총액 재계산됨 |
| 8. 결제 및 주문 생성 | |||
| 8.1 | makitt-shop > /checkout (Step 3) | 결제 수단 선택 후 "결제하기" 클릭 | 결제 처리 후 /order/confirmation/{orderId} 페이지로 이동 |
| 8.2 | makitt-shop > /order/confirmation | 주문 완료 후 | 이메일로 "주문 확인" 메일이 발송됨 (제목: "[Shop명] 주문이 완료되었습니다 - #{주문번호}") |
| 9. 게스트 체크아웃 | |||
| 9.1 | makitt-shop > /checkout | 비로그인 상태에서 체크아웃 진입 | "로그인" / "게스트로 계속" 버튼 2개가 표시됨 |
| 9.2 | makitt-shop > /checkout | "게스트로 계속" 클릭 | 이메일 입력 필드만 표시되고, 이메일 입력 후 배송지 입력으로 진행 가능 |
| 10. 중복 결제 방지 | |||
| 10.1 | makitt-shop > /checkout (Step 3) | "결제하기" 버튼 빠르게 3번 클릭 | 첫 클릭 후 버튼이 "처리 중..." 텍스트로 변경되고 비활성화됨, 주문은 1건만 생성됨 |
| 11. 장바구니 유지 | |||
| 11.1 | makitt-shop > /cart | 상품 3개를 장바구니에 담은 후 브라우저 탭 닫기 → 재접속 | 장바구니에 동일한 3개 상품이 유지되어 있음 |
| 12. 주문 확인 페이지 | |||
| 12.1 | makitt-shop > /order/confirmation | 주문 완료 후 페이지 확인 | 주문번호(예: ORD-20250205-001), 상품 목록(이미지/이름/수량/가격), 배송지, 결제금액이 모두 표시됨 |
E05: Product Catalog & Collection System
상품 등록, 변형 관리, 컬렉션 구성의 완결
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-client, makitt-server |
| 현재 상태 | Product/SKU/Collection CRUD 전체 구현됨. VariantGroup, SellableUnit 엔티티 완비. 하지만 multi-market 상품 (다중 통화 가격, 국가별 표시), 대량 상품 등록, 상품-SKU-재고 연결 플로우 미완 |
| 목표 | Henriette가 4개 마켓에 걸쳐 상품을 효율적으로 등록/관리하고, 마켓별 가격/설명을 설정 |
핵심 작업:
- Multi-currency 가격 설정 (상품당 KRW/USD/JPY/SGD)
- 상품 다국어 설명 (KO/EN/JA)
- Bulk product import (CSV/Excel)
- 상품 → SellableUnit → SKU → ARGO StoreItem 매핑 플로우 완성
- Collection에 국가별 노출 규칙
- AI Agent 상품 생성 → makitt-server 직접 저장 연동
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 다중 통화 가격 설정 | |||
| 1.1 | makitt-web > 상품 > 상품 등록 | 가격 섹션에서 "마켓별 가격 설정" 토글 ON | KRW, USD, JPY, SGD 각각의 가격 입력 필드가 표시됨 |
| 1.2 | makitt-web > 상품 > 상품 등록 | KRW: 10000, USD: 10, JPY: 1000, SGD: 15 입력 후 저장 | 4개 통화의 가격이 모두 저장됨 |
| 1.3 | makitt-shop (한국) > 상품 상세 | 해당 상품 페이지 진입 | 가격이 "₩10,000"으로 표시됨 |
| 1.4 | makitt-shop (일본) > 상품 상세 | 동일 상품 페이지 진입 | 가격이 "¥1,000"으로 표시됨 |
| 2. 다국어 상품 설명 | |||
| 2.1 | makitt-web > 상품 > 상품 등록 | 설명 섹션에서 언어 탭 확인 | "한국어", "English", "日本語" 탭이 표시됨 |
| 2.2 | makitt-web > 상품 > 상품 등록 | 각 탭에서 해당 언어로 설명 입력 후 저장 | 3개 언어의 설명이 모두 저장됨 |
| 2.3 | makitt-shop (일본) > 상품 상세 | 해당 상품 페이지 진입 | 일본어 설명이 표시됨, 한국어 설명은 표시되지 않음 |
| 3. CSV 대량 상품 등록 | |||
| 3.1 | makitt-web > 상품 | 상단 "가져오기" 버튼 클릭 | CSV 업로드 모달이 열리고 "템플릿 다운로드" 링크가 표시됨 |
| 3.2 | CSV 업로드 모달 | 10개 상품 데이터가 포함된 CSV 파일 드래그&드롭 | 파일 검증 후 "10개 상품 등록 예정" 미리보기 표시 |
| 3.3 | CSV 업로드 모달 | "등록하기" 클릭 | 프로그레스 바와 함께 등록 진행, 완료 시 "10개 상품이 등록되었습니다" 메시지 |
| 3.4 | CSV 업로드 모달 | 3번째 행에 가격 누락된 CSV 업로드 | "행 3: 가격 필드가 비어있습니다" 에러 메시지와 함께 해당 행이 빨간색으로 표시됨 |
| 4. 상품-SKU-ARGO 매핑 | |||
| 4.1 | makitt-web > 상품 > 상품 등록 | SKU 코드 "HEN-001" 입력 후 저장 | 상품 저장과 동시에 "ARGO StoreItem 동기화 중..." 로딩 표시 후 "연동 완료" |
| 4.2 | makitt-web > 상품 > 상품 상세 | "재고/물류" 탭 클릭 | "ARGO StoreItem ID: {id}", "현재 재고: {수량}" 정보가 표시됨 |
| 5. 컬렉션 국가별 노출 | |||
| 5.1 | makitt-web > 상품 > 컬렉션 > 새 컬렉션 | 컬렉션 생성 폼 확인 | "노출 대상 마켓" 체크박스: 한국, 미국, 일본, 싱가포르 |
| 5.2 | makitt-web > 상품 > 컬렉션 > 새 컬렉션 | "한국", "일본"만 체크하고 저장 | 컬렉션 목록에서 해당 컬렉션에 "KR, JP" 뱃지 표시 |
| 5.3 | makitt-shop (미국) > 컬렉션 목록 | 해당 컬렉션 URL 접근 | "Collection not found" 404 페이지 표시 |
| 5.4 | makitt-shop (한국) > 컬렉션 목록 | 해당 컬렉션 URL 접근 | 컬렉션과 포함된 상품이 정상 표시됨 |
| 6. AI 상품 생성 | |||
| 6.1 | makitt-web > 상품 | "AI로 상품 생성" 버튼 클릭 | AI Agent 대화창 모달이 열림 |
| 6.2 | AI Agent 대화창 | "여성용 니트 스웨터 상품을 만들어줘" 입력 | AI가 상품명, 설명, 가격, 카테고리를 생성하고 미리보기 표시 |
| 6.3 | AI Agent 대화창 | "저장하기" 클릭 | 모달 닫히고 상품 목록에 새 상품이 즉시 추가되어 표시됨 |
| 7. 상품 변형 관리 | |||
| 7.1 | makitt-web > 상품 > 상품 등록 | "변형 추가" 버튼 클릭 | "옵션 타입" 선택 드롭다운: 색상, 사이즈, 소재 등 |
| 7.2 | makitt-web > 상품 > 상품 등록 | 색상(빨강, 파랑), 사이즈(S, M, L) 추가 | 변형 조합 매트릭스: 6개 조합(빨강-S, 빨강-M, ... 파랑-L) 표시 |
| 7.3 | makitt-web > 상품 > 상품 등록 | 저장 후 상품 상세 확인 | SKU 목록에 6개의 SKU가 자동 생성됨 (예: HEN-001-RED-S) |
| 8. 자동 컬렉션 | |||
| 8.1 | makitt-web > 상품 > 컬렉션 > 새 컬렉션 | "자동 컬렉션" 타입 선택 | 조건 설정 UI 표시: 가격 범위, 카테고리, 태그, 재고 상태 |
| 8.2 | makitt-web > 상품 > 컬렉션 > 새 컬렉션 | 조건: "가격 ₩10,000 이상", "카테고리: 의류" 설정 후 저장 | 조건에 맞는 상품이 컬렉션에 자동 포함, "상품 수: {N}개" 표시 |
| 8.3 | makitt-web > 상품 > 상품 등록 | 새 상품(의류, ₩15,000) 등록 | 해당 자동 컬렉션에 새 상품이 자동으로 추가됨 |
| 9. 상품 삭제 | |||
| 9.1 | makitt-web > 상품 > 상품 상세 | "삭제" 버튼 클릭 | "이 상품을 삭제하시겠습니까? 관련 SKU와 재고 정보도 비활성화됩니다" 확인 모달 |
| 9.2 | 삭제 확인 모달 | "삭제" 클릭 | 상품 목록으로 이동, 해당 상품이 목록에서 사라지고 "상품이 삭제되었습니다" 토스트 |
E06: Builder Commerce Components & Primitives
Builder에서 체크아웃, 장바구니, 상품 등의 Business Component 정의 및 누락 Primitive 구현
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-client (builder, renderer, compiler) |
| 현재 상태 | 62개 TreeNode 컴포넌트 타입 존재. cart/checkout/product는 primitive level로만 존재. standard-commerce에 41페이지 참조 구현 있음. 하지만 실제 결제 연동, 재고 표시, 배송옵션 표시가 Builder 컴포넌트에 없음 |
| 목표 | Henriette shop을 standard-commerce 수준으로 Builder에서 구축 가능하게 함 |
핵심 작업:
- Business Components 정의:
cart-view: 장바구니 표시 + 수량 변경 + 가격 계산checkout-form: 배송지/결제/주문확인 단계별 폼product-detail: 변형 선택 + 가격 표시 + 재고 상태 + 장바구니 추가collection-grid: 필터/정렬 + 페이지네이션order-status: 주문상태/배송추적 표시customer-auth: 로그인/회원가입 폼
- 누락 Primitive 구현:
- quantity-input, price-display, rating-stars, badge, breadcrumb, pagination, search-bar, filter-sidebar, toast-notification
- Business Component ↔ 데이터 바인딩 규격 정의
- 조작 방식: Builder에서 Business Component의 설정 패널 (결제수단 표시, 배송옵션 등)
- Compiler에서 Business Component → 실제 동작 코드 렌더링
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. cart-view 컴포넌트 | |||
| 1.1 | Builder > 컴포넌트 패널 | "Commerce" 카테고리에서 "Cart View" 드래그하여 캔버스에 드롭 | 캔버스에 장바구니 UI 미리보기(샘플 상품 2개 포함)가 표시됨 |
| 1.2 | Builder > 캔버스 | cart-view 컴포넌트 선택 | 우측 속성 패널에 "빈 장바구니 메시지", "체크아웃 버튼 텍스트" 설정 필드 표시 |
| 1.3 | makitt-shop (게시 후) | cart-view가 있는 페이지에서 상품 수량 "+" 클릭 | 수량이 1→2로 변경되고 소계/총액이 실시간 재계산됨 |
| 2. checkout-form 컴포넌트 | |||
| 2.1 | Builder > 컴포넌트 패널 | "Checkout Form" 드래그하여 캔버스에 드롭 | 3단계(배송지→결제→확인) 스텝퍼 UI와 폼이 미리보기로 표시됨 |
| 2.2 | Builder > 캔버스 | checkout-form 선택 후 속성 패널 확인 | "게스트 체크아웃 허용", "결제수단 표시 설정" 토글이 표시됨 |
| 2.3 | Builder > 속성 패널 | "결제수단 표시 설정" 클릭 | 체크박스: "신용카드", "Apple Pay", "PayPal" 등 선택 가능 |
| 3. product-detail 컴포넌트 | |||
| 3.1 | Builder > 컴포넌트 패널 | "Product Detail" 드래그하여 캔버스에 드롭 | 상품 이미지, 이름, 가격, 변형 선택 드롭다운, "장바구니 추가" 버튼이 포함된 UI 표시 |
| 3.2 | Builder > 캔버스 | product-detail 선택 후 속성 패널 확인 | "재고 표시", "리뷰 표시", "관련 상품 표시" 토글이 표시됨 |
| 3.3 | makitt-shop (게시 후) | product-detail에서 색상 "빨강" → "파랑" 변경 | 가격이 해당 변형 가격으로 변경되고, 재고 수량이 업데이트됨 |
| 3.4 | makitt-shop (게시 후) | 재고 0인 변형 선택 | "품절" 뱃지 표시, "장바구니 추가" 버튼 비활성화 |
| 4. collection-grid 컴포넌트 | |||
| 4.1 | Builder > 컴포넌트 패널 | "Collection Grid" 드래그하여 캔버스에 드롭 | 상품 카드 4x3 그리드와 좌측 필터 사이드바가 표시됨 |
| 4.2 | Builder > 캔버스 | collection-grid 선택 후 속성 패널 확인 | "그리드 열 수", "필터 표시", "정렬 옵션" 설정 가능 |
| 4.3 | makitt-shop (게시 후) | collection-grid 필터에서 "가격: ₩10,000 이하" 선택 | 조건에 맞는 상품만 필터링되어 그리드에 표시됨 |
| 4.4 | makitt-shop (게시 후) | 정렬 드롭다운에서 "가격 낮은 순" 선택 | 상품이 가격 오름차순으로 재정렬됨 |
| 5. order-status 컴포넌트 | |||
| 5.1 | Builder > 컴포넌트 패널 | "Order Status" 드래그하여 캔버스에 드롭 | 주문 상태 타임라인(주문완료→배송준비→배송중→배송완료) UI 표시 |
| 5.2 | makitt-shop (게시 후) | order-status가 있는 마이페이지에서 주문 확인 | 현재 주문 상태가 하이라이트되고, 운송장번호/배송추적 링크가 표시됨 |
| 6. customer-auth 컴포넌트 | |||
| 6.1 | Builder > 컴포넌트 패널 | "Customer Auth" 드래그하여 캔버스에 드롭 | 로그인 폼(이메일/비밀번호)과 "회원가입" 링크가 표시됨 |
| 6.2 | Builder > 캔버스 | customer-auth 선택 후 속성 패널 확인 | "소셜 로그인 표시" 토글, "비밀번호 찾기 표시" 토글 |
| 6.3 | makitt-shop (게시 후) | customer-auth에서 이메일/비밀번호 입력 후 "로그인" 클릭 | 로그인 성공 시 마이페이지로 리다이렉트 |
| 7. Primitive 컴포넌트 | |||
| 7.1 | Builder > 컴포넌트 패널 > Primitives | "Quantity Input" 드래그하여 캔버스에 드롭 | -/+ 버튼이 있는 수량 입력 필드가 표시됨 |
| 7.2 | Builder > 컴포넌트 패널 > Primitives | "Pagination" 드래그하여 캔버스에 드롭 | "< 1 2 3 ... 10 >" 형태의 페이지 네비게이션이 표시됨 |
| 7.3 | Builder > 컴포넌트 패널 > Primitives | "Search Bar" 드래그하여 캔버스에 드롭 | 검색 아이콘과 입력 필드가 표시됨 |
| 8. 게시 및 렌더링 | |||
| 8.1 | Builder | cart-view, product-detail 포함 페이지에서 "게시" 클릭 | 게시 완료 후 Shop에서 실제 API와 연동되어 동작함 |
| 8.2 | makitt-shop (게시 후) | product-detail에서 "장바구니 추가" 클릭 후 cart-view 페이지 이동 | 방금 추가한 상품이 장바구니에 표시됨 |
E07: Asset System for Builder
Builder에서 사용할 이미지/미디어 에셋 관리 체계
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-client (builder, web), makitt-server |
| 현재 상태 | Asset/MediaAsset 엔티티 구현됨. S3 업로드/Presigned URL 동작. content/media 페이지 존재. AI Agent 이미지 생성 가능. 하지만 Builder 내 에셋 브라우저 없음, 에셋 카테고리/태그 없음, 이미지 최적화(리사이즈, WebP 변환) 없음 |
| 목표 | Builder에서 에셋을 효율적으로 탐색/삽입하고, Henriette 브랜드 에셋을 체계적으로 관리 |
핵심 작업:
- Builder 내 에셋 브라우저 패널 (검색, 필터, 드래그&드롭)
- 에셋 카테고리/태그 관리 (product, banner, logo, lifestyle 등)
- 이미지 최적화 파이프라인 (리사이즈, WebP 변환, CDN 캐시)
- AI 이미지 생성 → 에셋 라이브러리 직접 저장
- 브랜드 에셋 팩 (Henriette 로고, 컬러, 폰트)
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 에셋 브라우저 열기 | |||
| 1.1 | Builder > 캔버스 | Image 컴포넌트 선택 후 우측 속성 패널에서 "이미지 선택" 클릭 | 에셋 브라우저 모달이 열리고, 기존 업로드된 이미지 목록이 그리드로 표시됨 |
| 1.2 | Builder > 에셋 브라우저 | 상단 검색창에 "banner" 입력 | 파일명 또는 태그에 "banner"가 포함된 이미지만 필터링되어 표시됨 |
| 2. 카테고리 필터 | |||
| 2.1 | Builder > 에셋 브라우저 | 좌측 카테고리 목록 확인 | "전체", "상품", "배너", "로고", "라이프스타일" 카테고리가 표시됨 |
| 2.2 | Builder > 에셋 브라우저 | "로고" 카테고리 클릭 | 로고 카테고리로 분류된 이미지만 표시됨 |
| 3. 드래그&드롭 삽입 | |||
| 3.1 | Builder > 에셋 브라우저 | 이미지 썸네일을 드래그하여 캔버스의 Image 컴포넌트에 드롭 | 에셋 브라우저가 닫히고, Image 컴포넌트에 선택한 이미지가 적용됨 |
| 4. 이미지 업로드 및 최적화 | |||
| 4.1 | Builder > 에셋 브라우저 | "업로드" 버튼 클릭 후 5MB PNG 파일 선택 | 업로드 진행 표시 후, "이미지가 업로드되었습니다" 메시지 |
| 4.2 | makitt-web > 콘텐츠 > 미디어 | 방금 업로드한 이미지 상세 확인 | "원본: PNG 5MB", "최적화: WebP 500KB" 정보가 표시됨 |
| 4.3 | makitt-web > 콘텐츠 > 미디어 | 이미지 상세에서 "사이즈" 탭 확인 | "Thumbnail (150x150)", "Medium (600x600)", "Large (1200x1200)" 버전이 생성됨 |
| 5. AI 이미지 생성 | |||
| 5.1 | Builder > 에셋 브라우저 | "AI로 생성" 버튼 클릭 | AI 이미지 생성 대화창이 열림 |
| 5.2 | AI 이미지 생성 대화창 | "파란색 니트 스웨터 제품 사진" 프롬프트 입력 후 "생성" 클릭 | 로딩 후 4개의 이미지 후보가 표시됨 |
| 5.3 | AI 이미지 생성 대화창 | 이미지 선택 후 "저장" 클릭 | 대화창 닫히고, 에셋 브라우저에 "ai-generated" 태그와 함께 이미지 추가됨 |
| 6. 태그 관리 | |||
| 6.1 | makitt-web > 콘텐츠 > 미디어 | 이미지 선택 후 "태그 편집" 클릭 | 태그 입력 필드가 표시됨, 기존 태그가 칩으로 표시됨 |
| 6.2 | makitt-web > 콘텐츠 > 미디어 | 새 태그 "winter-2025" 입력 후 저장 | 태그가 추가되고, 에셋 브라우저에서 "winter-2025" 검색 시 해당 이미지 표시됨 |
| 7. 브랜드 에셋 팩 | |||
| 7.1 | makitt-web > 설정 > 브랜드 | "로고" 섹션에서 이미지 업로드 | 로고가 브랜드 에셋으로 등록됨 |
| 7.2 | Builder > 캔버스 | Image 컴포넌트 선택 | 속성 패널에 "브랜드 로고 사용" 퀵 버튼이 표시됨 |
| 7.3 | Builder > 속성 패널 | "브랜드 로고 사용" 클릭 | 등록된 브랜드 로고가 즉시 적용됨 |
| 8. 에셋 삭제 경고 | |||
| 8.1 | makitt-web > 콘텐츠 > 미디어 | 사용 중인 이미지의 "삭제" 버튼 클릭 | "이 이미지를 사용하는 페이지: 홈페이지, 상품상세" 경고 메시지와 함께 확인 모달 |
| 9. 최근 사용 에셋 | |||
| 9.1 | Builder > 에셋 브라우저 | 모달 열기 | "최근 사용" 섹션이 상단에 표시되고, 최근 사용한 5개 이미지가 나열됨 |
E08: ARGO Logistics Onboarding & Integration
ARGO VMS/OMS/WMS 연동을 통한 물류 seamless 온보딩
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-server, makitt-client, argo/* |
| 현재 상태 | ArgoVmsClient/ArgoCmsClient/ArgoSugarClient FeignClient 구현. ArgoVendorMapping 엔티티 존재. Kafka SKU sync 작동. 하지만 벤더 등록 워크플로 미완, OMS 주문 동기화 미구현, WMS 입고/출고/재고 미구현, SSO 미구현 |
| 목표 | Henriette가 onboarding 과정에서 ARGO 물류를 원클릭으로 연동하고, 주문→출고→배송이 자동으로 흐름 |
핵심 작업:
- Phase 0: VMS 벤더 등록
- Organization → ARGO Vendor 자동 프로비저닝
- 기존 벤더 연결 (이메일 기반 조회)
- 벤더 상태 변경 Kafka 컨슈머
- Phase 1: SSO 연동
- ArgoSugarClient SSO 토큰 교환
- ARGO 대시보드 seamless 접근 (makitt-web에서)
- ARGO 측 API 개발 요청 조율
- Phase 2: OMS 주문 동기화
- MAKITT 주문 → ARGO OMS 전송 (Kafka Producer)
- 주문 상태 변경 수신 (ARGO → MAKITT)
- 주문 취소/변경 양방향 동기화
- Phase 3: WMS 연동
- 입고(ASN) 생성 및 추적
- 출고 자동 트리거 (주문 확정 시)
- 재고 수량 실시간 동기화
- 기본 창고 자동 할당
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 벤더 등록 위자드 | |||
| 1.1 | makitt-web > 설정 > 물류 | "ARGO 연동 시작" 버튼 클릭 | ARGO 벤더 등록 위자드 모달이 열리고, Step 1 "연동 방식 선택" 화면 표시 |
| 1.2 | 위자드 Step 1 | "신규 벤더 등록" 선택 후 "다음" 클릭 | Organization 정보(상호, 대표자, 연락처, 주소)가 자동으로 채워진 폼 표시 |
| 1.3 | 위자드 Step 1 | "기존 벤더 연결" 선택 | 이메일 입력 필드 표시, "ARGO에 등록된 이메일을 입력하세요" |
| 1.4 | 위자드 Step 2 | 기존 벤더 이메일 입력 후 "조회" 클릭 | "벤더명: {name}, 등록일: {date}" 정보가 표시되고 "연결하기" 버튼 활성화 |
| 2. 벤더 승인 상태 | |||
| 2.1 | makitt-web > 설정 > 물류 | 벤더 등록 후 페이지 확인 | ARGO 연동 상태: "승인 대기중" (노란색 뱃지) |
| 2.2 | makitt-web > 설정 > 물류 | ARGO에서 승인 완료 후 페이지 새로고침 | ARGO 연동 상태: "연결됨" (초록색 뱃지), "ARGO 대시보드" 버튼 활성화 |
| 3. SSO 접속 | |||
| 3.1 | makitt-web > 설정 > 물류 | "ARGO 대시보드" 버튼 클릭 | 새 탭에서 ARGO OMS 대시보드가 열리고, 별도 로그인 없이 자동 인증됨 |
| 4. 주문 동기화 | |||
| 4.1 | makitt-shop > 체크아웃 | 고객이 결제 완료 | makitt-web 주문 목록에 새 주문 표시, 상태: "결제 완료" |
| 4.2 | (ARGO OMS 시스템) | - | ARGO OMS에 동일 주문이 자동 생성됨 (Kafka 메시지 전송) |
| 4.3 | (ARGO OMS 시스템) | ARGO에서 주문 상태를 "배송 준비" 변경 | makitt-web 주문 상태가 자동으로 "배송 준비"로 업데이트됨 |
| 5. 주문 취소 동기화 | |||
| 5.1 | makitt-web > 주문 > 주문 상세 | "주문 취소" 버튼 클릭 | 확인 모달: "ARGO OMS에도 취소가 반영됩니다" |
| 5.2 | 취소 확인 모달 | "취소 확인" 클릭 | 주문 상태 "취소됨"으로 변경, ARGO OMS에도 취소 반영 |
| 6. 입고(ASN) 생성 | |||
| 6.1 | makitt-web > 물류 > 입고 | "입고 요청" 버튼 클릭 | ASN 생성 폼: SKU 선택, 수량, 예정 입고일 입력 필드 |
| 6.2 | ASN 생성 폼 | SKU "HEN-001" 선택, 수량 100, 예정일 2025-02-10 입력 후 "생성" | "ASN-20250205-001 생성 완료" 메시지, 입고 목록에 상태 "입고 예정"으로 추가 |
| 6.3 | makitt-web > 물류 > 입고 | ASN 상태 확인 (ARGO WMS 입고 완료 후) | 상태가 "입고 완료"로 변경, 입고 수량 100개 표시 |
| 7. 자동 출고 | |||
| 7.1 | (자동 프로세스) | 고객 주문 결제 완료 시 | ARGO WMS에 출고 요청 자동 생성, makitt-web 주문 상세에 "출고 요청됨" 표시 |
| 8. 재고 동기화 | |||
| 8.1 | makitt-web > 상품 > 상품 상세 > 재고 탭 | ARGO WMS 재고 변경 후 확인 | "ARGO 재고: 80개", "마지막 동기화: 2025-02-05 14:30:22" 표시 |
| 8.2 | makitt-web > 상품 > 상품 상세 > 재고 탭 | "동기화" 버튼 클릭 | 즉시 ARGO WMS에서 최신 재고를 가져와 업데이트 |
| 9. 기본 창고 자동 할당 | |||
| 9.1 | makitt-web > 설정 > 물류 | 신규 판매자 ARGO 연동 완료 후 | "기본 창고: 인천 물류센터"가 자동 할당되어 표시됨 |
| 10. 물류 상태 대시보드 | |||
| 10.1 | makitt-web > 대시보드 | 페이지 진입 | "물류 연동" 카드에 상태(연결됨/오류), 오늘 출고건, 재고 부족 알림 표시 |
| 10.2 | makitt-web > 대시보드 | ARGO 연결 오류 발생 시 | "물류 연동" 카드가 빨간색으로 변경, "연결 오류 - 재연결 시도" 메시지 |
E09: Order Management & Delivery Tracking
주문 라이프사이클 완성 및 배송 추적 연동
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-server, makitt-client (web, shop) |
| 현재 상태 | Order 엔티티에 full lifecycle (PAYMENT_PENDING→DELIVERED) 구현. trackingNumber/trackingCarrier/trackingUrl 필드 존재. 하지만 실제 캐리어 API 연동 없음, 실시간 배송상태 업데이트 없음, 주문 확인 이메일 없음 |
| 목표 | Henriette와 고객 모두 주문상태를 실시간으로 확인하고, 배송 추적이 seamless하게 동작 |
핵심 작업:
- 캐리어 API 연동 (CJ대한통운/KR, DHL/SG,JP, USPS+FedEx/US)
- 배송상태 자동 업데이트 (Webhook 또는 Polling)
- 주문 확인/발송/배달완료 이메일 알림
- makitt-shop 주문 조회 페이지 (마이페이지)
- makitt-web 주문 관리 대시보드 개선 (필터, 벌크 처리)
- ARGO OMS 배송 상태 동기화 (E08과 연계)
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 주문 확인 이메일 | |||
| 1.1 | makitt-shop > 체크아웃 | 고객이 결제 완료 | 5분 이내에 고객 이메일로 주문 확인 메일이 발송됨. 메일 제목: "[Shop명] 주문이 완료되었습니다 - #{주문번호}" |
| 1.2 | (이메일) | 고객이 주문 확인 이메일 열람 | 메일 본문에 주문번호, 주문 상품 목록(이미지/이름/수량/가격), 배송지, 결제 금액이 포함됨 |
| 2. 발송 알림 이메일 | |||
| 2.1 | makitt-web > 주문 > 주문 상세 | 판매자가 운송장번호 입력 후 "발송 처리" 클릭 | 고객에게 발송 알림 이메일 발송됨. 메일 제목: "[Shop명] 상품이 발송되었습니다" |
| 2.2 | (이메일) | 고객이 발송 알림 이메일 열람 | 메일 본문에 운송장번호, 택배사명, "배송 추적하기" 버튼(링크)이 포함됨 |
| 3. 배달 완료 이메일 | |||
| 3.1 | (자동 프로세스) | 캐리어 API에서 배송완료 상태 수신 | 고객에게 배달 완료 이메일 발송됨. 메일 제목: "[Shop명] 배송이 완료되었습니다" |
| 3.2 | (이메일) | 고객이 배달 완료 이메일 열람 | 메일 본문에 "리뷰 작성하기" 버튼과 "문제가 있으신가요?" 고객센터 링크가 포함됨 |
| 4. 한국 배송 추적 (CJ대한통운) | |||
| 4.1 | makitt-web > 주문 > 주문 상세 | 한국 주문에 CJ대한통운 운송장번호 입력 | "CJ대한통운" 택배사가 자동 감지되어 표시됨 |
| 4.2 | makitt-web > 주문 > 주문 상세 | 배송 추적 정보 확인 | "집화 처리 → 간선 상차 → 배송 출발 → 배송 완료" 타임라인이 표시됨 |
| 4.3 | makitt-shop > 마이페이지 > 주문 상세 | 고객이 "배송 추적" 클릭 | 동일한 배송 타임라인이 모달 또는 페이지로 표시됨 |
| 5. 미국 배송 추적 (USPS/FedEx) | |||
| 5.1 | makitt-web > 주문 > 주문 상세 | 미국 주문에 USPS 운송장번호 입력 | "USPS" 택배사가 자동 감지됨 |
| 5.2 | makitt-web > 주문 > 주문 상세 | FedEx 운송장번호 입력 | "FedEx" 택배사가 자동 감지됨 |
| 5.3 | makitt-shop > 마이페이지 > 주문 상세 | 고객이 "Track Package" 클릭 | "Shipped → In Transit → Out for Delivery → Delivered" 타임라인 표시 |
| 6. 싱가포르/일본 배송 추적 (DHL) | |||
| 6.1 | makitt-web > 주문 > 주문 상세 | 싱가포르/일본 주문에 DHL 운송장번호 입력 | "DHL Express" 택배사가 자동 감지됨 |
| 6.2 | makitt-shop > 마이페이지 > 주문 상세 | 고객이 배송 추적 확인 | DHL 배송 상태와 예상 배송일이 표시됨 |
| 7. 고객 주문 목록 (마이페이지) | |||
| 7.1 | makitt-shop > 마이페이지 > 주문내역 | 로그인한 고객이 페이지 진입 | 본인의 전체 주문 목록이 최신순으로 표시됨. 컬럼: 주문번호, 주문일, 상태, 총액 |
| 7.2 | makitt-shop > 마이페이지 > 주문내역 | 특정 주문 행 클릭 | /my/orders/{orderId} 주문 상세 페이지로 이동 |
| 8. 고객 주문 상세 | |||
| 8.1 | makitt-shop > 마이페이지 > 주문 상세 | 주문 상세 페이지 진입 | 주문 상품 목록(이미지/이름/옵션/수량/가격), 배송지, 결제 금액 내역이 표시됨 |
| 8.2 | makitt-shop > 마이페이지 > 주문 상세 | "배송 추적" 버튼 클릭 | 배송 상태 타임라인이 표시됨. 각 단계에 날짜/시간 포함 |
| 8.3 | makitt-shop > 마이페이지 > 주문 상세 | 배송 추적에서 현재 단계 확인 | 현재 단계가 파란색으로 하이라이트되고, 이전 단계에는 ✓ 표시 |
| 9. 판매자 주문 필터링 | |||
| 9.1 | makitt-web > 주문 | 주문 목록 페이지 진입 | 상단에 상태 필터 탭: "전체", "결제대기", "준비중", "배송중", "배송완료", "취소/반품" |
| 9.2 | makitt-web > 주문 | "배송중" 탭 클릭 | 배송중 상태의 주문만 필터링되어 표시됨. 주문 수(예: "배송중 (15)")가 탭에 표시됨 |
| 9.3 | makitt-web > 주문 | "검색" 입력란에 주문번호 입력 | 해당 주문번호를 포함하는 주문만 검색됨 |
| 9.4 | makitt-web > 주문 | 날짜 필터에서 "최근 7일" 선택 | 최근 7일 내 주문만 표시됨 |
| 10. 일괄 발송 처리 | |||
| 10.1 | makitt-web > 주문 | 주문 목록에서 체크박스로 3개 주문 선택 | 상단에 "3개 선택됨" 표시, "일괄 발송" 버튼 활성화 |
| 10.2 | makitt-web > 주문 | "일괄 발송" 버튼 클릭 | 운송장번호 일괄 입력 모달 표시. 각 주문별 운송장번호 입력 필드 |
| 10.3 | 일괄 발송 모달 | 3개 운송장번호 입력 후 "발송 처리" 클릭 | "3건 발송 처리 완료" 메시지. 3개 주문 모두 "배송중" 상태로 변경 |
| 10.4 | makitt-web > 주문 | 일괄 발송 후 | 3명의 고객에게 각각 발송 알림 이메일 발송됨 |
| 11. 운송장 입력 및 알림 | |||
| 11.1 | makitt-web > 주문 > 주문 상세 | "운송장 입력" 버튼 클릭 | 택배사 선택 드롭다운(CJ대한통운, 한진, 롯데, 로젠 등)과 운송장번호 입력 필드 표시 |
| 11.2 | makitt-web > 주문 > 주문 상세 | 택배사 "CJ대한통운", 운송장 "123456789012" 입력 후 저장 | 주문 상태가 "배송중"으로 변경, 고객에게 발송 알림 이메일 발송 |
| 12. ARGO OMS 배송 상태 동기화 | |||
| 12.1 | (ARGO OMS 시스템) | ARGO에서 주문 상태를 "배송중"으로 변경 | makitt-web 해당 주문 상태가 자동으로 "배송중"으로 업데이트됨 |
| 12.2 | (ARGO OMS 시스템) | ARGO에서 배송완료 처리 | makitt-web 해당 주문 상태가 "배송완료"로 업데이트되고, 배달 완료 이메일 발송 |
| 12.3 | makitt-web > 주문 > 주문 상세 | ARGO 연동 주문 확인 | "ARGO 연동" 뱃지와 "ARGO OMS에서 보기" 링크가 표시됨 |
| 13. 판매자 주문 상세 | |||
| 13.1 | makitt-web > 주문 > 주문 상세 | 페이지 진입 | 고객 정보(이름, 이메일, 연락처), 배송지 전체 주소가 표시됨 |
| 13.2 | makitt-web > 주문 > 주문 상세 | 결제 내역 섹션 확인 | 결제수단, 결제일시, 결제금액(상품/배송/세금/총액)이 표시됨 |
| 13.3 | makitt-web > 주문 > 주문 상세 | 주문 상품 섹션 확인 | 각 상품의 이미지, 이름, 옵션(색상/사이즈), 수량, 단가, 소계가 표시됨 |
E10: Inventory, Inbound & Stock Management
재고 관리, 입고 프로세스, 재고 동기화
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-server, makitt-client |
| 현재 상태 | SKU 엔티티에 재고 관련 필드 존재. Logistics UI에 인바운드/인벤토리 페이지 구현됨. ARGO SKU sync Kafka 동작. 하지만 실시간 재고 차감/복구 로직 없음, 입고 프로세스 미구현, 재고 부족 알림 없음 |
| 목표 | Henriette의 상품 재고가 ARGO WMS와 실시간 동기화되고, 주문 시 자동 차감 |
핵심 작업:
- 재고 차감 로직 (Checkout 확정 시 차감, 취소 시 복구)
- ARGO WMS 재고 수량 실시간 동기화 (Kafka)
- 입고(ASN) 생성 UI 및 API
- 재고 부족 알림 (임계값 설정)
- 상품 목록에서 재고 상태 표시 (품절, 소량)
- SKU ↔ SellableUnit ↔ Product 재고 연결
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 재고 차감 - 결제 시 | |||
| 1.1 | makitt-shop > 체크아웃 | 고객이 재고 10개인 상품 2개 결제 완료 | makitt-web 상품 상세 > 재고 탭에서 재고가 "10 → 8"로 변경됨 |
| 1.2 | makitt-shop > 상품 상세 | 재고 차감 후 상품 상세 페이지 새로고침 | "8개 남음" 메시지가 표시됨 |
| 2. 재고 복구 - 취소 시 | |||
| 2.1 | makitt-web > 주문 > 주문 상세 | 판매자가 결제 완료된 주문(상품 2개) "취소" 버튼 클릭 | 확인 모달: "주문을 취소하면 재고가 복구됩니다" |
| 2.2 | 취소 확인 모달 | "취소 확인" 클릭 | 주문 상태 "취소됨"으로 변경, 재고 "8 → 10"으로 복구 |
| 3. 동시 주문 재고 검증 | |||
| 3.1 | makitt-shop > 체크아웃 | 재고 1개인 상품을 고객 A, B가 동시에 결제 시도 | 먼저 결제 완료한 고객은 주문 성공, 늦은 고객에게 "재고가 부족합니다. 장바구니를 확인해주세요" 에러 메시지 표시 |
| 3.2 | makitt-shop > 장바구니 | 재고 부족 에러 후 장바구니 이동 | 해당 상품에 "품절" 뱃지가 표시되고, 수량 조절 불가 |
| 4. ARGO WMS 재고 수신 | |||
| 4.1 | (Kafka 메시지) | ARGO WMS에서 SKU 재고 변경 이벤트 발생 (100→80) | makitt-server의 해당 SKU 재고가 80으로 자동 업데이트됨 |
| 4.2 | makitt-web > 상품 > 상품 상세 > 재고 탭 | 재고 동기화 후 페이지 확인 | "ARGO 재고: 80개", "마지막 동기화: 2025-02-05 14:30:22" 표시 |
| 5. ARGO WMS 연결 오류 | |||
| 5.1 | makitt-web > 대시보드 | ARGO WMS Kafka 연결 끊김 | "물류 연동" 카드가 빨간색으로 변경, "재고 동기화 오류" 메시지 표시 |
| 5.2 | makitt-web > 설정 > 물류 | 연결 오류 상태 확인 | ARGO 연동 상태: "오류" (빨간색 뱃지), "마지막 동기화: {timestamp}", "재연결 시도" 버튼 표시 |
| 6. 입고(ASN) 생성 | |||
| 6.1 | makitt-web > 물류 > 입고 | "입고 요청" 버튼 클릭 | ASN 생성 폼 표시: SKU 검색/선택, 수량 입력, 예정 입고일 날짜 선택 |
| 6.2 | ASN 생성 폼 | SKU "HEN-001" 선택, 수량 100, 예정일 2025-02-10 입력 | 각 필드에 입력값이 표시됨 |
| 6.3 | ASN 생성 폼 | "제출" 버튼 클릭 | "ASN-20250205-001 생성 완료. ARGO WMS에 전송됨" 메시지, 입고 목록으로 이동 |
| 7. 입고 상태 추적 | |||
| 7.1 | makitt-web > 물류 > 입고 | 입고 목록 확인 | 방금 생성한 ASN이 "입고 예정" 상태(노란색 뱃지)로 표시됨 |
| 7.2 | (ARGO WMS 시스템) | ARGO WMS에서 입고 완료 처리 | makitt-web 입고 목록에서 해당 ASN 상태가 "입고 완료" (초록색 뱃지)로 변경 |
| 7.3 | makitt-web > 상품 > 상품 상세 > 재고 탭 | 입고 완료 후 확인 | 재고가 100개 증가하여 표시됨 |
| 8. 재고 부족 임계값 설정 | |||
| 8.1 | makitt-web > 상품 > 상품 상세 > 재고 탭 | "재고 알림 설정" 버튼 클릭 | "재고 임계값" 입력 필드 표시 (기본값: 10) |
| 8.2 | 재고 알림 설정 | 임계값 "5"로 변경 후 저장 | "알림 설정이 저장되었습니다" 메시지 |
| 9. 재고 부족 알림 | |||
| 9.1 | (자동 프로세스) | SKU 재고가 임계값(5개) 이하로 감소 | 판매자 이메일로 "재고 부족 알림: {상품명} - 현재 재고 3개" 메일 발송 |
| 9.2 | makitt-web > 대시보드 | 재고 부족 발생 후 | "재고 부족 상품" 섹션에 해당 상품이 표시됨. "상품명 |
| 9.3 | makitt-web > 대시보드 | "재고 부족 상품" 섹션에서 상품 클릭 | 해당 상품 상세 페이지로 이동 |
| 10. 재고 상태 표시 (판매자) | |||
| 10.1 | makitt-web > 상품 | 상품 목록 확인 | 재고 0인 상품에 빨간색 "품절" 뱃지 표시 |
| 10.2 | makitt-web > 상품 | 상품 목록 확인 | 재고가 임계값 이하인 상품에 주황색 "소량" 뱃지 표시 |
| 10.3 | makitt-web > 상품 | "재고 상태" 필터 드롭다운 클릭 | "전체", "정상", "소량", "품절" 옵션 표시 |
| 10.4 | makitt-web > 상품 | "품절" 필터 선택 | 재고 0인 상품만 필터링되어 표시됨 |
| 11. 재고 상태 표시 (Shop) | |||
| 11.1 | makitt-shop > 상품 상세 | 재고 0인 상품 페이지 진입 | 가격 옆에 빨간색 "품절" 뱃지 표시, "장바구니 추가" 버튼 비활성화(회색) |
| 11.2 | makitt-shop > 상품 상세 | 재고 3개인 상품 페이지 진입 | "3개 남음" 메시지가 주황색으로 표시됨 |
| 11.3 | makitt-shop > 컬렉션 | 상품 그리드 확인 | 품절 상품 카드에 "SOLD OUT" 오버레이 표시 |
| 12. 변형별 재고 표시 | |||
| 12.1 | makitt-web > 상품 > 상품 상세 > 재고 탭 | 변형이 있는 상품(색상: 빨강/파랑, 사이즈: S/M/L) 확인 | 6개 SKU 각각의 재고가 테이블로 표시됨. 예: "빨강-S: 10개, 빨강-M: 5개..." |
| 12.2 | makitt-shop > 상품 상세 | 변형 상품에서 색상 "빨강" 선택 | 사이즈 옵션 중 재고 0인 "S"가 비활성화(취소선)되고, "M", "L"은 선택 가능 |
| 12.3 | makitt-shop > 상품 상세 | 비활성화된 "빨강-S" 옵션에 마우스 호버 | "품절" 툴팁 표시 |
| 13. 수동 재고 조정 | |||
| 13.1 | makitt-web > 상품 > 상품 상세 > 재고 탭 | "재고 조정" 버튼 클릭 | 재고 조정 모달: 현재 재고, 조정 수량(+/-), 조정 사유 입력 필드 |
| 13.2 | 재고 조정 모달 | "+10", 사유 "실사 후 수정" 입력 후 저장 | "재고가 조정되었습니다" 메시지, 재고 이력에 조정 기록 추가 |
E11: Returns, Exchanges & Refunds
반품, 교환, 환불 프로세스
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-server, makitt-client (web, shop) |
| 현재 상태 | Order 엔티티에 refund(amount, reason) 메서드 존재. Logistics UI에 반품 페이지 있음. 하지만 반품 요청 플로우, 교환 처리, 부분 환불, ARGO WMS 반품 입고 연동 미구현 |
| 목표 | 고객 반품요청 → 승인 → 반품배송 → 입고확인 → 환불/교환 전체 플로우 |
핵심 작업:
- 반품 요청 API (고객 → 판매자)
- 반품 승인/거절 워크플로 (makitt-web)
- 반품 배송 라벨 생성 (캐리어 연동)
- ARGO WMS 반품 입고 연동
- 부분 환불 / 전체 환불 처리 (결제 프로세서별)
- 교환 처리 (재출고 트리거)
- 고객 마이페이지에서 반품/교환 상태 확인
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 반품 요청 (고객) | |||
| 1.1 | makitt-shop > 마이페이지 > 주문 상세 | 배송 완료된 주문에서 "반품 요청" 버튼 클릭 | 반품 요청 폼이 표시됨 |
| 1.2 | 반품 요청 폼 | "반품 사유" 드롭다운 클릭 | "단순 변심", "상품 불량/파손", "오배송", "상품 설명과 다름", "기타" 옵션 표시 |
| 1.3 | 반품 요청 폼 | 사유 "상품 불량/파손" 선택 | "사진 첨부" 필드와 "상세 설명" 텍스트 입력 필드가 추가로 표시됨 |
| 1.4 | 반품 요청 폼 | 사유 선택, 상세 설명 입력 후 "제출" 클릭 | "반품 요청이 접수되었습니다. 판매자 확인 후 안내드리겠습니다" 메시지 표시 |
| 1.5 | (이메일) | 반품 요청 접수 후 | 고객에게 "반품 요청 접수 확인" 이메일 발송, 판매자에게 "새 반품 요청" 알림 이메일 발송 |
| 2. 반품 기간 제한 | |||
| 2.1 | makitt-shop > 마이페이지 > 주문 상세 | 배송 완료 7일 이내 주문 확인 | "반품 요청" 버튼이 활성화 상태, 남은 기간 "반품 가능 (D-3)" 표시 |
| 2.2 | makitt-shop > 마이페이지 > 주문 상세 | 배송 완료 8일 이상 지난 주문 확인 | "반품 요청" 버튼 비활성화(회색), "반품 기간이 만료되었습니다 (배송 완료 후 7일 이내)" 메시지 표시 |
| 3. 반품 승인 (판매자) | |||
| 3.1 | makitt-web > 주문 > 반품/교환 | 페이지 진입 | 반품 요청 목록 테이블: 요청일, 주문번호, 고객명, 상품, 사유, 상태 컬럼 |
| 3.2 | makitt-web > 주문 > 반품/교환 | 특정 반품 요청 행 클릭 | 반품 상세 모달: 고객 정보, 주문 상품, 반품 사유, 첨부 사진(있는 경우), "승인"/"거절" 버튼 |
| 3.3 | 반품 상세 모달 | "승인" 버튼 클릭 | "반품이 승인되었습니다" 메시지, 고객에게 반품 승인 이메일 발송 |
| 4. 반품 거절 (판매자) | |||
| 4.1 | 반품 상세 모달 | "거절" 버튼 클릭 | 거절 사유 입력 필드 표시 |
| 4.2 | 반품 상세 모달 | 거절 사유 "반품 기간 초과" 입력 후 "거절 확인" 클릭 | "반품이 거절되었습니다" 메시지, 고객에게 거절 사유 포함 이메일 발송 |
| 4.3 | makitt-shop > 마이페이지 > 주문 상세 | 고객이 거절된 반품 요청 확인 | 반품 상태 "거절됨", 거절 사유가 표시됨 |
| 5. 반품 배송 라벨 | |||
| 5.1 | makitt-web > 주문 > 반품/교환 > 상세 | 반품 승인된 건에서 "반품 라벨 생성" 클릭 | 반품용 운송장이 생성되고-"운송장번호: {number}" 표시 |
| 5.2 | (이메일) | 반품 라벨 생성 후 | 고객에게 "반품 라벨" 이메일 발송, PDF 첨부 또는 다운로드 링크 포함 |
| 5.3 | makitt-shop > 마이페이지 > 주문 상세 | 반품 승인 후 페이지 확인 | "반품 라벨 다운로드" 버튼과 반품 안내 메시지 표시 |
| 6. 반품 배송 추적 | |||
| 6.1 | makitt-shop > 마이페이지 > 주문 상세 | 고객이 반품 상품 발송 후 "반품 발송 완료" 클릭 | 반품 운송장번호 입력 필드 표시 (판매자 생성 라벨 사용 시 자동 입력) |
| 6.2 | makitt-shop > 마이페이지 > 주문 상세 | 운송장번호 입력 후 "확인" 클릭 | 반품 상태가 "반품 배송중"으로 변경됨 |
| 6.3 | makitt-web > 주문 > 반품/교환 > 상세 | 판매자가 반품 배송중인 건 확인 | "반품 배송중", 운송장번호, 배송 추적 링크 표시 |
| 7. 반품 입고 확인 | |||
| 7.1 | (ARGO WMS 시스템) | ARGO WMS에서 반품 상품 입고 스캔 | makitt-web 해당 반품 요청 상태가 "입고 완료"로 자동 변경 |
| 7.2 | (이메일) | 반품 입고 완료 후 | 판매자에게 "반품 상품 검수 필요" 알림 이메일 발송 |
| 7.3 | makitt-web > 주문 > 반품/교환 > 상세 | 입고 완료된 반품 확인 | "상품 검수" 섹션: "상태 양호"/"상태 불량" 라디오 버튼, 검수 메모 입력 필드 |
| 8. 검수 후 재고 처리 | |||
| 8.1 | 반품 상세 | "상태 양호" 선택 후 "검수 완료" 클릭 | "검수가 완료되었습니다. 재고가 복구됩니다" 메시지, 해당 SKU 재고 +1 |
| 8.2 | 반품 상세 | "상태 불량" 선택, "파손으로 인한 폐기" 메모 입력 후 "검수 완료" 클릭 | "검수가 완료되었습니다. 불량 처리되어 재고가 복구되지 않습니다" 메시지 |
| 9. 환불 처리 | |||
| 9.1 | makitt-web > 주문 > 반품/교환 > 상세 | 검수 완료 후 "환불 처리" 버튼 클릭 | 환불 처리 모달: 원 결제금액, 환불 유형(전체/부분), 환불 금액 표시 |
| 9.2 | 환불 처리 모달 | "전체 환불" 선택 후 "환불 실행" 클릭 | "환불이 처리되었습니다. 원 결제수단으로 ₩11,000이 환불됩니다" 메시지 |
| 9.3 | 환불 처리 모달 | "부분 환불" 선택, 금액 "5000" 입력 후 "환불 실행" 클릭 | "환불이 처리되었습니다. ₩5,000이 환불됩니다" 메시지 |
| 9.4 | (이메일) | 환불 처리 후 | 고객에게 "환불 완료" 이메일 발송: 환불 금액, 결제수단, 예상 환불 일정 포함 |
| 10. 환불 내역 기록 | |||
| 10.1 | makitt-web > 주문 > 주문 상세 | 환불 완료된 주문 확인 | "환불 내역" 섹션: 환불일, 환불 금액, 환불 사유, 처리자 표시 |
| 10.2 | makitt-shop > 마이페이지 > 주문 상세 | 고객이 환불 완료된 주문 확인 | "환불 완료" 상태, "환불 금액: ₩11,000", "환불 수단: 신용카드" 표시 |
| 11. 교환 요청 (고객) | |||
| 11.1 | 반품 요청 폼 | "반품/환불" / "교환" 옵션 중 "교환" 선택 | "교환 희망 옵션" 선택 UI 추가 표시 |
| 11.2 | 반품 요청 폼 | 교환 희망 옵션 "색상: 파랑 / 사이즈: M" 선택 | 선택한 옵션이 표시됨, 해당 옵션 재고 여부 확인 메시지 |
| 11.3 | 반품 요청 폼 | 교환 희망 옵션이 품절인 경우 | "선택하신 옵션은 현재 품절입니다. 다른 옵션을 선택하시거나 환불을 요청해주세요" 메시지 |
| 12. 교환 승인 및 처리 | |||
| 12.1 | makitt-web > 주문 > 반품/교환 > 상세 | 교환 요청 건 확인 | "교환 요청", 교환 희망 옵션 "파랑/M"이 표시됨 |
| 12.2 | makitt-web > 주문 > 반품/교환 > 상세 | "승인" 클릭 | 교환 승인됨, 고객에게 "교환 승인" 이메일 발송 |
| 12.3 | (자동 프로세스) | 반품 상품 입고 완료 후 | 교환 상품(파랑/M) 출고가 자동으로 ARGO WMS에 요청됨 |
| 12.4 | (이메일) | 교환 상품 출고 시 | 고객에게 "교환 상품 발송" 이메일 발송, 새 운송장번호 포함 |
| 13. 반품/교환 상태 확인 (고객) | |||
| 13.1 | makitt-shop > 마이페이지 > 반품/교환 | 페이지 진입 | 본인의 반품/교환 요청 목록: 요청일, 주문번호, 상품, 유형(반품/교환), 상태 |
| 13.2 | makitt-shop > 마이페이지 > 반품/교환 | 특정 요청 클릭 | 상세 페이지: 진행 타임라인(요청→승인→반품배송중→입고완료→환불완료/교환발송) |
| 13.3 | makitt-shop > 마이페이지 > 반품/교환 상세 | 타임라인 확인 | 각 단계에 날짜/시간 표시, 현재 단계 하이라이트, 완료 단계 ✓ 표시 |
E12: CRM & Customer Experience
고객 관리, 세그먼트, 마이페이지 완성
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-client (web, shop), makitt-server |
| 현재 상태 | Customer CRUD/세그먼트/메시징/문의 UI 구현됨. Shop에서 CustomerAuth(OTP/OAuth) 구현됨. 하지만 고객 마이페이지(주문내역, 주소관리, 위시리스트, 포인트) makitt-shop에서 미연동, 고객 세그먼트 기반 마케팅 미구현 |
| 목표 | Henriette shop 고객이 회원가입 → 주문 → 마이페이지 관리를 할 수 있고, Henriette가 CRM 도구로 고객을 관리 |
핵심 작업:
- makitt-shop 마이페이지 구현 (주문내역, 주소록, 위시리스트)
- 고객 인증 플로우 완성 (회원가입 → 이메일 인증 → 로그인)
- 고객 데이터 분석 대시보드 (makitt-web)
- 주문 알림 (이메일/SMS)
- standard-commerce 마이페이지 → Builder Business Component로 변환
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. 고객 마이페이지 - 주문내역 | |||
| 1.1 | makitt-shop > 마이페이지 > 주문내역 | 로그인 후 페이지 진입 | 본인의 전체 주문 목록이 최신순으로 표시됨. 컬럼: 주문번호, 주문일, 상태, 총 금액 |
| 1.2 | makitt-shop > 마이페이지 > 주문내역 | 주문 행 클릭 | 주문 상세 페이지로 이동, 상품 목록(이미지/이름/옵션/수량/가격), 배송지, 결제 내역 표시 |
| 1.3 | makitt-shop > 마이페이지 > 주문내역 | 기간 필터 드롭다운 클릭 | "최근 3개월", "최근 6개월", "최근 1년", "전체" 옵션 표시 |
| 1.4 | makitt-shop > 마이페이지 > 주문내역 | "최근 3개월" 선택 | 3개월 이내 주문만 필터링되어 표시됨 |
| 2. 고객 마이페이지 - 주소록 | |||
| 2.1 | makitt-shop > 마이페이지 > 주소록 | 페이지 진입 | 저장된 배송 주소 목록 표시, "새 주소 추가" 버튼 |
| 2.2 | makitt-shop > 마이페이지 > 주소록 | "새 주소 추가" 클릭 | 주소 입력 폼 표시: 수령인, 연락처, 주소 필드 (국가별 형식) |
| 2.3 | makitt-shop > 마이페이지 > 주소록 | 한국 Shop에서 주소 입력 폼 확인 | 필드: 수령인, 연락처, 우편번호(검색), 주소, 상세주소 |
| 2.4 | makitt-shop > 마이페이지 > 주소록 | 미국 Shop에서 주소 입력 폼 확인 | 필드: Name, Phone, Address Line 1, Address Line 2, City, State(드롭다운), ZIP Code |
| 2.5 | makitt-shop > 마이페이지 > 주소록 | 기존 주소 "수정" 버튼 클릭 | 해당 주소 정보가 채워진 편집 폼 표시 |
| 2.6 | makitt-shop > 마이페이지 > 주소록 | 기존 주소 "삭제" 버튼 클릭 | "이 주소를 삭제하시겠습니까?" 확인 모달 표시 |
| 2.7 | makitt-shop > 마이페이지 > 주소록 | 특정 주소의 "기본 배송지로 설정" 클릭 | 해당 주소에 "기본" 뱃지 표시, 이전 기본 주소의 뱃지 제거 |
| 2.8 | makitt-shop > 체크아웃 | 기본 배송지 설정 후 체크아웃 진입 | 배송지 입력 폼에 기본 배송지가 자동으로 채워져 있음 |
| 3. 고객 마이페이지 - 위시리스트 | |||
| 3.1 | makitt-shop > 상품 상세 | 로그인한 고객이 "♡ 찜하기" 버튼 클릭 | 아이콘이 "♥"로 변경, "위시리스트에 추가되었습니다" 토스트 메시지 |
| 3.2 | makitt-shop > 상품 상세 | 이미 찜한 상품에서 "♥" 버튼 클릭 | 아이콘이 "♡"로 변경, "위시리스트에서 제거되었습니다" 토스트 메시지 |
| 3.3 | makitt-shop > 마이페이지 > 위시리스트 | 페이지 진입 | 위시리스트 상품 목록: 상품 이미지, 이름, 가격, "장바구니 담기", "삭제" 버튼 |
| 3.4 | makitt-shop > 마이페이지 > 위시리스트 | "장바구니 담기" 버튼 클릭 | "장바구니에 추가되었습니다" 메시지, 장바구니 아이콘 뱃지 숫자 증가 |
| 3.5 | makitt-shop > 마이페이지 > 위시리스트 | "삭제" 버튼 클릭 | 해당 상품이 위시리스트에서 즉시 제거됨 |
| 3.6 | makitt-shop > 마이페이지 > 위시리스트 | 품절 상품 확인 | 상품 카드에 "품절" 뱃지 표시, "장바구니 담기" 버튼 비활성화 |
| 4. 고객 회원가입 및 인증 | |||
| 4.1 | makitt-shop > 회원가입 | "회원가입" 버튼 클릭 후 이메일/비밀번호 입력 후 "가입하기" | "인증 이메일을 발송했습니다. 이메일을 확인해주세요" 메시지 표시 |
| 4.2 | (이메일) | 인증 이메일 열람 | 메일 제목: "[Shop명] 이메일 인증을 완료해주세요", "인증하기" 버튼 포함 |
| 4.3 | (이메일) | "인증하기" 버튼 클릭 | 브라우저에서 Shop 페이지 열림, "이메일 인증이 완료되었습니다!" 메시지 표시 |
| 4.4 | makitt-shop > 로그인 | 미인증 계정으로 로그인 시도 | "이메일 인증이 필요합니다. [인증 메일 재발송]" 메시지 표시 |
| 4.5 | makitt-shop > 로그인 | "인증 메일 재발송" 클릭 | "인증 이메일을 다시 발송했습니다" 메시지, 새 인증 이메일 발송 |
| 5. 비밀번호 찾기 | |||
| 5.1 | makitt-shop > 로그인 | "비밀번호를 잊으셨나요?" 링크 클릭 | 이메일 입력 폼 표시 |
| 5.2 | makitt-shop > 비밀번호 찾기 | 가입된 이메일 입력 후 "재설정 링크 발송" 클릭 | "비밀번호 재설정 이메일을 발송했습니다" 메시지 |
| 5.3 | (이메일) | 재설정 이메일의 "비밀번호 재설정" 링크 클릭 | 새 비밀번호 입력 페이지로 이동 |
| 5.4 | makitt-shop > 비밀번호 재설정 | 새 비밀번호 입력 후 "변경하기" 클릭 | "비밀번호가 변경되었습니다. 새 비밀번호로 로그인해주세요" 메시지, 로그인 페이지로 이동 |
| 6. 판매자 CRM 대시보드 | |||
| 6.1 | makitt-web > CRM > 대시보드 | 페이지 진입 | 총 고객 수 카드: "1,234명" 형태로 표시 |
| 6.2 | makitt-web > CRM > 대시보드 | 신규 가입 차트 확인 | 일별/주별/월별 탭 전환 가능, 막대 차트로 가입자 수 추이 표시 |
| 6.3 | makitt-web > CRM > 대시보드 | "고객 구매 순위" 섹션 확인 | 상위 10명 고객 목록: 순위, 이름, 이메일, 총 구매 금액 |
| 6.4 | makitt-web > CRM > 대시보드 | "재구매율" 카드 확인 | "재구매율: 35%" (2회 이상 주문 고객 / 전체 주문 고객) 표시 |
| 7. 판매자 고객 목록 | |||
| 7.1 | makitt-web > CRM > 고객 | 페이지 진입 | 고객 목록 테이블: 이름, 이메일, 가입일, 주문 횟수, 총 구매 금액 |
| 7.2 | makitt-web > CRM > 고객 | 검색창에 이메일 "test@example.com" 입력 | 해당 이메일의 고객만 검색 결과로 표시됨 |
| 7.3 | makitt-web > CRM > 고객 | 검색창에 이름 "김철수" 입력 | 이름에 "김철수"가 포함된 고객 목록 표시 |
| 7.4 | makitt-web > CRM > 고객 | 고객 행 클릭 | 고객 상세 페이지: 기본 정보, 주문 이력, 활동 로그 |
| 8. 이메일 템플릿 커스터마이징 | |||
| 8.1 | makitt-web > 설정 > 알림 | 페이지 진입 | 이메일 템플릿 목록: "주문 확인", "배송 시작", "배송 완료", "환불 완료" 등 |
| 8.2 | makitt-web > 설정 > 알림 | "주문 확인" 템플릿 클릭 | 이메일 편집기: 제목, 본문(HTML/텍스트), 미리보기 영역 |
| 8.3 | makitt-web > 설정 > 알림 | 편집기에서 "{{shop_name}}", "{{order_number}}" 등 변수 확인 | 사용 가능한 변수 목록이 우측 패널에 표시됨 |
| 8.4 | makitt-web > 설정 > 알림 | "브랜드 설정 적용" 버튼 클릭 | 템플릿에 Shop 로고, 브랜드 컬러가 적용되어 미리보기 업데이트 |
| 8.5 | makitt-web > 설정 > 알림 | "저장" 후 "테스트 발송" 클릭 | 판매자 이메일로 테스트 이메일 발송, "테스트 이메일이 발송되었습니다" 메시지 |
| 9. 고객 세그먼트 생성 | |||
| 9.1 | makitt-web > CRM > 세그먼트 | "새 세그먼트" 버튼 클릭 | 세그먼트 생성 폼: 이름, 조건 설정 UI |
| 9.2 | 세그먼트 생성 폼 | "조건 추가" 클릭 | 조건 유형 드롭다운: "총 구매 금액", "구매 횟수", "가입일", "마지막 구매일", "마지막 주문일" |
| 9.3 | 세그먼트 생성 폼 | 조건 "총 구매 금액 >= ₩100,000" 설정 | 우측에 "해당 고객 수: 234명" 실시간 표시 |
| 9.4 | 세그먼트 생성 폼 | 조건 "마지막 구매일 <= 30일 전" 추가 | 두 조건이 AND로 결합, "해당 고객 수: 89명"으로 업데이트 |
| 9.5 | makitt-web > CRM > 세그먼트 | 저장된 세그먼트 행 클릭 | 세그먼트 상세: 조건 요약, 포함된 고객 목록 표시 |
| 9.6 | 세그먼트 상세 | "CSV 내보내기" 버튼 클릭 | "customers_segment_VIP_20250205.csv" 파일 다운로드 시작 |
E13: Shop Infrastructure & Platform Stability
Shop JSON 분리, 버전 관리, 토큰 리프레시, 중복요청 방지
| 항목 | 내용 |
|---|---|
| 문서 | epic.md |
| Status | backlog |
| Repos | makitt-client (web, shop, builder), makitt-server |
| 현재 상태 | Shop 데이터가 단일 JSON으로 관리됨. 버전 관리 없음. Web의 token refresh가 암시적 세션 체크만. Shop의 customer token도 동일. 중복 요청 방지 메커니즘 없음 |
| 목표 | 프로덕션 안정성 확보: 데이터 무결성, 인증 견고성, 동시성 제어 |
핵심 작업:
- Shop JSON 분리: 페이지별/섹션별 JSON 분리 (빌드 최적화, 부분 업데이트)
- 버전 관리: Shop publish 시 version snapshot, rollback 기능
- Token Refresh (Web): Access/Refresh token 분리, 자동 갱신 interceptor
- Token Refresh (Shop): Customer token 갱신, 만료 시 재인증 플로우
- 중복 요청 방지: Idempotency key 기반 (주문, 결제 등 critical operations)
- Optimistic Locking: 동시 편집 충돌 방지 (Shop 설정, 상품 편집)
- API Rate Limiting: 남용 방지
Acceptance Criteria:
| # | 화면/메뉴 | 사용자 행동 | 예상 결과 |
|---|---|---|---|
| 1. Shop JSON 분리 - 부분 업데이트 | |||
| 1.1 | Builder > 홈페이지 | 홈페이지만 수정 후 "게시" 클릭 | "홈페이지 게시 완료" 메시지, 상품 상세 페이지 등 다른 페이지는 재빌드되지 않음 |
| 1.2 | (S3 콘솔) | 게시 후 S3 버킷 확인 | shops/{shopId}/pages/home.json만 업데이트됨, 다른 페이지 JSON의 타임스탬프 변경 없음 |
| 2. Shop JSON 분리 - 지연 로딩 | |||
| 2.1 | makitt-shop > 홈페이지 | Shop 첫 진입 시 | 홈페이지 JSON만 로드됨 (Network 탭에서 home.json 요청 확인) |
| 2.2 | makitt-shop > 홈페이지 | 상품 상세 페이지 링크 클릭 | 해당 시점에 product-detail.json 로드됨 |
| 2.3 | makitt-shop > 상품 상세 | 뒤로가기로 홈페이지 복귀 | 홈페이지가 캐시에서 즉시 표시됨, 재요청 없음 |
| 3. Shop 버전 관리 - 게시 | |||
| 3.1 | Builder > "게시" 버튼 | 첫 번째 게시 실행 | "v1 게시 완료" 메시지, Shop 설정에서 "현재 버전: v1" 표시 |
| 3.2 | Builder > "게시" 버튼 | 수정 후 두 번째 게시 실행 | "v2 게시 완료" 메시지, 버전 번호 자동 증가 |
| 4. Shop 버전 관리 - 히스토리 | |||
| 4.1 | makitt-web > 설정 > Shop > 버전 히스토리 | 페이지 진입 | 버전 목록 테이블: 버전, 게시일시, 게시자, 변경 내용 요약 |
| 4.2 | makitt-web > 버전 히스토리 | 각 버전 행 옆 "미리보기" 클릭 | 새 탭에서 해당 버전의 Shop이 미리보기로 표시됨 |
| 5. Shop 버전 관리 - 롤백 | |||
| 5.1 | makitt-web > 버전 히스토리 | v1 버전의 "롤백" 버튼 클릭 | 확인 모달: "v1 버전으로 롤백하시겠습니까? 현재 게시된 내용이 v1으로 대체됩니다" |
| 5.2 | 롤백 확인 모달 | "롤백 실행" 클릭 | "v1 버전으로 롤백되었습니다" 메시지, 현재 버전이 "v3 (v1에서 롤백)"으로 표시 |
| 5.3 | makitt-web > 버전 히스토리 | 롤백 후 목록 확인 | 기존 버전(v1, v2, v3) 히스토리 모두 유지됨 |
| 6. Token Refresh (Web - 판매자) | |||
| 6.1 | makitt-web | 판매자가 30분간 작업 중 (Access Token 25분 경과) | 백그라운드에서 자동으로 새 Access Token 발급, 작업 중단 없음 |
| 6.2 | makitt-web | Token 갱신 직후 API 요청 | 갱신된 새 Token으로 정상 응답, 401 에러 없음 |
| 6.3 | makitt-web | Refresh Token 만료(예: 7일 후) 상태에서 API 요청 | "세션이 만료되었습니다. 다시 로그인해주세요" 모달 표시 |
| 6.4 | 세션 만료 모달 | "로그인" 버튼 클릭 | 로그인 페이지로 이동, 작업 중이던 페이지 URL이 리다이렉트 파라미터로 저장됨 |
| 6.5 | makitt-web | 상품 편집 중 세션 만료 발생 | 편집 중인 내용이 로컬 스토리지에 자동 저장, 재로그인 후 "저장되지 않은 변경사항이 있습니다. 복원하시겠습니까?" 메시지 |
| 7. Token Refresh (Shop - 고객) | |||
| 7.1 | makitt-shop | 로그인한 고객이 1시간 후 마이페이지 접근 (Access Token 만료) | 자동으로 Refresh Token 사용하여 새 Token 발급, 마이페이지 정상 로드 |
| 7.2 | makitt-shop | Refresh Token 만료 상태에서 마이페이지 접근 | "로그인이 필요합니다" 메시지 표시, 로그인 페이지로 이동 |
| 7.3 | makitt-shop | 재로그인 후 | 장바구니에 담긴 상품이 그대로 유지됨 |
| 8. 중복 결제 방지 (고객) | |||
| 8.1 | makitt-shop > 체크아웃 | 고객이 "결제" 버튼 빠르게 3번 클릭 | 첫 클릭 후 버튼이 즉시 비활성화(회색)되고 "처리 중..." 텍스트로 변경 |
| 8.2 | makitt-shop > 체크아웃 | 결제 완료 후 주문 목록 확인 | 주문이 1건만 생성됨, 중복 주문 없음 |
| 8.3 | makitt-shop > 체크아웃 | 결제 요청 중 네트워크 오류로 재시도 | 동일한 Idempotency Key 사용 시 기존 결제 결과 반환, 중복 결제 없음 |
| 9. 중복 상태 변경 방지 (판매자) | |||
| 9.1 | makitt-web > 주문 상세 | "발송 처리" 버튼 빠르게 2번 클릭 | 첫 클릭 후 버튼 비활성화, 상태 변경은 1회만 발생 |
| 9.2 | makitt-web > 주문 상세 | 발송 처리 후 히스토리 확인 | "발송 처리" 로그가 1건만 기록됨 |
| 10. 동시 편집 충돌 방지 - 상품 | |||
| 10.1 | makitt-web > 상품 상세 | 판매자 A가 상품 편집 중, 판매자 B도 같은 상품 편집 페이지 진입 | 판매자 B에게 "현재 [A 이름]님이 편집 중입니다" 알림 표시 (실시간 락은 아님) |
| 10.2 | makitt-web > 상품 상세 | 판매자 A가 저장 후, 판매자 B가 "저장" 클릭 | "다른 사용자가 수정했습니다. 변경사항을 확인하세요" 에러 모달 표시 |
| 10.3 | 충돌 에러 모달 | "내 변경사항 덮어쓰기" 클릭 | B의 변경사항으로 저장됨, "저장되었습니다" 메시지 |
| 10.4 | 충돌 에러 모달 | "최신 버전 불러오기" 클릭 | A의 변경사항이 로드됨, B의 작업 내용은 사라짐 |
| 10.5 | 충돌 에러 모달 | "비교하기" 클릭 | 좌우 분할 화면에서 "내 변경사항" vs "서버 버전" 비교 표시 |
| 11. 동시 편집 충돌 방지 - Shop 설정 | |||
| 11.1 | makitt-web > 설정 > Shop | 두 명이 동시에 설정 편집 후 저장 시도 | 나중에 저장하는 사람에게 동일한 충돌 에러 모달 표시 |
| 12. API Rate Limiting | |||
| 12.1 | (API 호출) | 동일 IP에서 1분 내 100회 이상 API 호출 | HTTP 429 응답, 응답 본문: {"error": "요청이 너무 많습니다. 잠시 후 다시 시도해주세요"} |
| 12.2 | (API 응답 헤더) | Rate Limit 초과 응답 확인 | X-RateLimit-Limit: 100, X-RateLimit-Remaining: 0, X-RateLimit-Reset: 1707123456 (Unix timestamp) |
| 12.3 | makitt-shop > 상품 목록 | 일반 사용자가 페이지 빠르게 새로고침 10회 | Rate Limit에 걸리지 않고 정상 응답 (일반 사용 패턴은 허용) |
| 12.4 | (API 호출) | Rate Limit 해제 시간(1분) 후 재요청 | 정상 응답 반환 |
Epic 의존성 그래프
E02 (Country Config) ─────────┐
├──→ E04 (Checkout/Cart)
E03 (Payment) ────────────────┤
│
E01 (Onboarding) ──→ E08과 통합 │
│
E08 (ARGO Logistics) ──→ E09 (Order/Delivery)
──→ E10 (Inventory)
──→ E11 (Returns)
E05 (Product/Collection) ──→ E06 (Builder Components)
E07 (Asset System) ──────→ E06 (Builder Components)
E04 (Checkout) ──→ E09 (Order/Delivery)
E09 (Order) ──→ E11 (Returns)
E04 + E09 + E12 (CRM)
E13 (Infrastructure) ──→ 모든 epic에 선행 또는 병행
권장 실행 순서
| 순서 | Epic | 이유 |
|---|---|---|
| 1 | E13 (Infrastructure) | 모든 작업의 안정성 기반, 병행 가능 |
| 2 | E02 (Country Config) | 국가별 설정이 결제/세금/배송의 기반 |
| 3 | E03 (Payment) | 결제 없이 체크아웃 불가 |
| 4 | E05 (Product/Collection) | 상품 없이 주문 불가 |
| 5 | E04 (Checkout/Cart) | E02+E03 위에 구축 |
| 6 | E08 (ARGO Logistics) | 물류 없이 배송 불가 |
| 7 | E07 (Asset System) | Builder 작업 전 에셋 체계 필요 |
| 8 | E06 (Builder Components) | E05+E07 위에 구축 |
| 9 | E10 (Inventory) | E08 위에 구축 |
| 10 | E09 (Order/Delivery) | E04+E08 위에 구축 |
| 11 | E12 (CRM) | E04+E09 위에 구축 |
| 12 | E11 (Returns) | E09+E10 위에 구축 |
| 13 | E01 (Onboarding) | 모든 기능 완성 후 통합 플로우 |
참고: E01(Onboarding)은 설계는 초기에, 구현은 다른 epic들이 완성된 후에 통합 테스트와 함께 진행하는 것을 권장. 개별 설정 기능이 먼저 존재해야 onboarding flow가 의미있음.