ShopOnboarding
docs/domain/shop-onboarding.md
ShopOnboarding
개요
샵 레벨의 온보딩(MAKITT HAPPEN / MAKITT EXPLODE) 진행 상태를 관리하는 도메인. 각 샵별로 비즈니스 정보, 정책, 디자인, 물류, 배송, 결제, 상품, 가격 등의 설정 완료 여부를 추적합니다.
UserOnboarding(MAKITT BEGIN)이 사용자 레벨 온보딩이라면, ShopOnboarding은 샵 레벨 온보딩으로 Shop 파티션 하위에 저장됩니다.
마켓별 추적 지원: perMarket=true인 step은 각 마켓(국가)별로 독립적인 완료 상태를 관리합니다.
서버 패키지: com.makitt.core.domain.shop
DynamoDB Entity
ShopOnboarding
Shop 파티션 하위의 온보딩 상태 엔티티.
키 구조:
| 키 | 패턴 | 예시 |
|---|---|---|
| PK | SHOP#{shopId} | SHOP#shop123 |
| SK | ONBOARDING | ONBOARDING |
필드:
| 필드 | DynamoDB Attribute | 타입 | 필수 | 설명 |
|---|---|---|---|---|
| pk | PK | String | O | Partition Key |
| sk | SK | String | O | Sort Key |
| entityType | entity_type | String | O | "SHOP_ONBOARDING" 고정 |
| shopId | shop_id | String | O | Shop 고유 ID |
| marketCodes | market_codes | List<String> | X | 마켓 코드 목록 (예: ["KR", "US", "JP"]) |
| steps | steps | List<OnboardingStep> | O | 단계별 상태 (HAPPEN + EXPLODE 전체) |
| createdAt | created_at | Instant | O | 생성 시각 |
| updatedAt | updated_at | Instant | O | 수정 시각 |
Factory Methods:
ShopOnboarding.create(shopId)— 마켓 없이 기본 생성 (모든 step PENDING)ShopOnboarding.create(shopId, marketCodes)— 마켓 목록과 함께 생성.perMarket=true인 step은 각 마켓별marketStatuses초기화.
Nested Objects
OnboardingStep
UserOnboarding과 동일한 OnboardingStep 엔티티를 재사용합니다.
| 필드 | DynamoDB Attribute | 타입 | 설명 |
|---|---|---|---|
| stepId | step_id | String | 단계 ID (enum name) |
| status | status | StepStatus | 전체 완료 상태 (perMarket이면 모든 마켓 완료 시 자동 COMPLETED) |
| completedAt | completed_at | Instant | 완료 시각 (null이면 미완료) |
| subSteps | sub_steps | List<OnboardingSubStep> | sub-step 목록 (없으면 null) |
| perMarket | per_market | Boolean | 마켓별 추적 여부 (null이면 false 취급) |
| marketStatuses | market_statuses | Map<String, String> | 마켓코드 → StepStatus (예: {"KR": "COMPLETED", "US": "PENDING"}) |
| marketCompletedAt | market_completed_at | Map<String, String> | 마켓코드 → ISO timestamp |
OnboardingSubStep
| 필드 | DynamoDB Attribute | 타입 | 설명 |
|---|---|---|---|
| subStepId | sub_step_id | String | sub-step ID |
| status | status | StepStatus | 완료 상태 |
| mandatory | mandatory | Boolean | 필수 여부 |
| completedAt | completed_at | Instant | 완료 시각 |
Enums
ShopOnboardingStep
MAKITT HAPPEN (8 steps) — 샵 운영을 위한 핵심 설정:
| 값 | 설명 | mandatory | perMarket |
|---|---|---|---|
BUSINESS_INFO_SET | 사업자 정보 설정 | O | O |
POLICIES_SET | 반품/환불 정책 설정 | O | O |
SHOP_DESIGN_SET | 샵 디자인 설정 | O | X |
LOGISTICS_SET | 물류 제공업체 설정 | X | O |
SHIPPING_SET | 배송 지역/요금 설정 | O | O |
PAYMENT_SET | 결제 수단 설정 | O | O |
PRODUCT_REGISTERED | 상품 등록 | O | X |
PRICING_SET | 가격/세금 설정 | O | O |
MAKITT EXPLODE (6 steps) — 마케팅/고객 관리 확장 설정 (전부 optional):
| 값 | 설명 | mandatory | perMarket |
|---|---|---|---|
PROMOTIONS | 프로모션 설정 | X | O |
MEMBER_TIERS | 회원 등급 설정 | X | X |
REWARDS | 리워드 프로그램 | X | X |
COUPONS | 쿠폰 설정 | X | O |
SOCIAL_LOGIN | 소셜 로그인 설정 | X | O |
CRM | CRM/세그먼트 설정 | X | X |
StepStatus
| 값 | 설명 |
|---|---|
PENDING | 미완료 |
COMPLETED | 완료 |
마켓별 추적 (perMarket)
perMarket=true인 step은 각 마켓(국가)별로 독립적인 완료 상태를 가집니다.
동작 원리
- perMarket=false: 기존
status필드만 사용 (글로벌 단위) - perMarket=true:
marketStatuses에 마켓별 상태 저장. 모든 마켓이 COMPLETED일 때 전체status가 자동 COMPLETED.
마켓 동기화
Shop의 마켓 목록이 변경되면 syncMarkets()를 호출하여 동기화:
- 추가된 마켓: perMarket step에 PENDING 상태로 추가
- 제거된 마켓: perMarket step에서 해당 마켓 제거 → 전체 status 재계산
Progress 계산
전체 progress (가중치 기반):
총 단위 = Σ(perMarket ? marketCount : 1) (각 step 별)
완료 단위 = Σ(perMarket ? completedMarketCount : (completed ? 1 : 0))
progress = completedUnits / totalUnits × 100
예: 8 HAPPEN steps, 3 markets, 6 perMarket + 2 global
- 총 단위 = (6 × 3) + (2 × 1) = 20
- 전부 완료 시 20/20 = 100%
마켓별 progress:
마켓별 단위 = perMarket step 수 + global step 수
마켓별 완료 = Σ(perMarket ? isCompletedForMarket(code) : isCompleted())
API
온보딩 상태 조회
| 메서드 | 엔드포인트 | 설명 |
|---|---|---|
| GET | /api/v1/shops/{shopId}/onboarding | 온보딩 상태 조회 |
응답:
{ "shopId": "shop123", "steps": [ { "stepId": "BUSINESS_INFO_SET", "status": "PENDING", "completedAt": null, "subSteps": null, "perMarket": true, "marketStatuses": { "KR": "COMPLETED", "US": "PENDING", "JP": "PENDING" }, "marketCompletedAt": { "KR": "2025-01-15T09:00:00Z" } }, { "stepId": "SHOP_DESIGN_SET", "status": "COMPLETED", "completedAt": "2025-01-16T10:00:00Z", "subSteps": null, "perMarket": false, "marketStatuses": null, "marketCompletedAt": null } ], "happenProgressPercent": 45, "explodeProgressPercent": 0, "marketCodes": ["KR", "US", "JP"], "happenMarketProgressMap": { "KR": 75, "US": 25, "JP": 25 }, "explodeMarketProgressMap": { "KR": 0, "US": 0, "JP": 0 }, "createdAt": "2025-01-10T00:00:00Z", "updatedAt": "2025-01-16T10:00:00Z" }
단계 완료
| 메서드 | 엔드포인트 | 설명 |
|---|---|---|
| POST | /api/v1/shops/{shopId}/onboarding/steps/{stepId}/complete | step 완료 (글로벌) |
| POST | /api/v1/shops/{shopId}/onboarding/steps/{stepId}/complete?marketCode=KR | step 마켓별 완료 |
| POST | /api/v1/shops/{shopId}/onboarding/steps/{stepId}/sub-steps/{subStepId}/complete | sub-step 완료 |
marketCodequery param이 있으면 해당 마켓만 완료 처리marketCode가 없으면 글로벌 완료
Key Builder
클래스: com.makitt.core.common.dynamodb.key.ShopKey (Shop과 공유)
// ShopOnboarding Keys (Shop 파티션에 추가)
ShopKey.pk(shopId) → "SHOP#{shopId}" (Shop과 동일 PK)
ShopKey.onboardingSk() → "ONBOARDING"
서버 아키텍처
ShopController (makitt-api)
|
v (DTO <-> VO)
ShopApplication (makitt-application) -- Shop과 동일 Application 클래스에서 관리
|
v (VO)
ShopOnboardingService (makitt-core/service)
|
v (DynamoDB 조작)
ShopOnboardingRepository (makitt-core/repository)
|
v
ShopOnboarding (makitt-core/entity)
패키지 구조:
makitt-core/
com.makitt.core.domain.shop/
entity/
ShopOnboarding.java # DynamoDB Entity
ShopOnboardingStep.java # 단계 Enum (HAPPEN + EXPLODE)
service/
ShopOnboardingService.java # 상태 조회 + 완료 + 마켓 동기화
repository/
ShopOnboardingRepository.java # DynamoDB Repository
vo/
ShopOnboardingResponseVo.java # API 응답 VO
makitt-core/
com.makitt.core.domain.user/
entity/
OnboardingStep.java # 공유 Nested Object (UserOnboarding과 재사용)
OnboardingSubStep.java # 공유 Sub-step Object
StepStatus.java # 상태 Enum
makitt-application/
com.makitt.application.shop/
ShopApplication.java # Shop + ShopOnboarding 통합 관리
makitt-api/
com.makitt.api.controller.shop/
ShopController.java # Shop + ShopOnboarding 엔드포인트
주요 서비스 메서드:
// 조회 / 생성 ShopOnboardingService.getOrCreate(shopId) ShopOnboardingService.getOrCreate(shopId, marketCodes) // 글로벌 완료 ShopOnboardingService.completeStep(shopId, step) ShopOnboardingService.completeSubStep(shopId, parentStep, subStepId) // 마켓별 완료 ShopOnboardingService.completeStepForMarket(shopId, step, marketCode) // 마켓 동기화 ShopOnboardingService.syncMarkets(shopId, newMarketCodes) // 삭제 ShopOnboardingService.deleteByShopId(shopId)
Phase 구조 (클라이언트)
클라이언트에서 온보딩은 3단계 Phase로 구성:
MAKITT BEGIN (UserOnboarding)
↓ 완료 시 언락
MAKITT HAPPEN (ShopOnboarding HAPPEN steps) ← BEGIN 완료 후 활성화
MAKITT EXPLODE (ShopOnboarding EXPLODE steps) ← BEGIN 완료 후 활성화 (HAPPEN과 독립)
- HAPPEN과 EXPLODE는 서로 독립적. BEGIN만 완료하면 둘 다 활성화.
- 클라이언트의
OnboardingDashboard에서 탭으로 전환. - 마켓 선택 시 선택된 마켓들의 평균 progress를 표시.
관련 엔티티
| 엔티티 | 관계 | 설명 |
|---|---|---|
| Shop | 동일 PK (SHOP#{shopId}) | Shop 파티션 내 별도 아이템 |
| ShopVersion | 동일 PK (SHOP#{shopId}) | HCS 디자인 버전 |
| UserOnboarding | 선행 도메인 | BEGIN 완료 후 HAPPEN/EXPLODE 활성화 |
| OnboardingStep | 공유 엔티티 | UserOnboarding과 동일 구조 재사용 |
참조
- Domain: Shop
- Domain: UserOnboarding
- Domain: User