MAKITTDocs

UserOnboarding

docs/domain/user-onboarding.md

UserOnboarding

개요

사용자 레벨의 초기 온보딩(MAKITT BEGIN) 진행 상태를 관리하는 도메인. 계정 인증, 프로필 설정, 조직 설정, 사업자 정보, 물류계정, 최초 샵 생성까지의 단계를 추적하여 /home 대시보드의 온보딩 아코디언 UI에 상태를 제공합니다.

MAKITT HAPPEN / EXPLODE는 샵 레벨의 온보딩이므로 ShopOnboarding 도메인에서 별도로 관리합니다.

User 엔티티와 동일한 파티션(PK)에 저장하되, SK를 ONBOARDING으로 분리하여 Single Table Design을 유지합니다.

서버 패키지: com.makitt.core.domain.user


DynamoDB Entity

UserOnboarding

User 파티션 하위의 온보딩 상태 엔티티.

키 구조:

패턴예시
PKUSER#{userId}USER#abc123
SKONBOARDINGONBOARDING

필드:

필드DynamoDB Attribute타입필수설명
pkPKStringOPartition Key
skSKStringOSort Key
entityTypeentity_typeStringO"USER_ONBOARDING" 고정
userIduser_idStringO사용자 고유 ID
stepsstepsList<OnboardingStep>O단계별 상태 (ordered list)
createdAtcreated_atInstantO생성 시각
updatedAtupdated_atInstantO수정 시각

Factory Methods:

  • UserOnboarding.create(userId) — 사용자 가입 시 기본 상태로 생성 (ACCOUNT_VERIFIED만 COMPLETED, 나머지는 PENDING + sub-step 초기화)

Nested Objects

OnboardingStep

필드DynamoDB Attribute타입설명
stepIdstep_idString단계 ID (enum name)
statusstatusStepStatus완료 상태 (sub-step이 있으면 mandatory sub-step 전부 완료 시 자동 COMPLETED)
completedAtcompleted_atInstant완료 시각 (null이면 미완료)
subStepssub_stepsList<OnboardingSubStep>sub-step 목록 (없으면 null)

OnboardingSubStep

필드DynamoDB Attribute타입설명
subStepIdsub_step_idStringsub-step ID (enum name)
statusstatusStepStatus완료 상태
mandatorymandatoryBoolean필수 여부 (true면 부모 step 완료 조건에 포함)
completedAtcompleted_atInstant완료 시각 (null이면 미완료)

Enums

UserOnboardingStep (상위 단계)

설명sub-step 여부자동 완료
ACCOUNT_VERIFIED계정 인증XO (가입 시 자동)
PROFILE_COMPLETION프로필 완성OX (mandatory sub-step 전부 완료 시)
ORGANIZATION_COMPLETION조직 설정 완성OX (mandatory sub-step 전부 완료 시)
FIRST_SHOP_CREATED최초 샵 생성XX

ProfileSubStep

설명mandatory
NAME_SET이름 설정 (firstName, lastName)O
PHONE_VERIFIED핸드폰 인증X (추후 mandatory 전환 예정)
PASSWORD_SET비밀번호 설정X (OAuth 유저 불필요)
PREFERENCES_SET언어, 타임존 설정X

OrgSubStep

설명mandatory
ORG_INFO_SET조직 기본정보O
BUSINESS_INFO_SET사업자 정보 입력O
LOGISTICS_CONNECTED물류계정 연결X

StepStatus

설명
PENDING미완료
COMPLETED완료

단계 간 의존성

각 상위 단계는 기본적으로 독립적으로 진행할 수 있되, FIRST_SHOP_CREATED만 선행 조건이 존재한다.

ACCOUNT_VERIFIED          ──(자동 완료)

PROFILE_COMPLETION        ──┐  (sub-steps: NAME_SET*, PHONE_VERIFIED, PASSWORD_SET, PREFERENCES_SET)
                            ├──▶  FIRST_SHOP_CREATED  (선행 조건: 둘 다 COMPLETED)
ORGANIZATION_COMPLETION   ──┘  (sub-steps: ORG_INFO_SET*, BUSINESS_INFO_SET*, LOGISTICS_CONNECTED)

* = mandatory
  • PROFILE_COMPLETION, ORGANIZATION_COMPLETION은 순서 무관, 독립적으로 진행 가능
  • 각 상위 step의 status는 mandatory sub-step이 전부 COMPLETED일 때 자동으로 COMPLETED
  • FIRST_SHOP_CREATEDPROFILE_COMPLETIONORGANIZATION_COMPLETION이 모두 COMPLETED여야 진행 가능
  • 클라이언트에서 FIRST_SHOP_CREATED의 선행 조건 미충족 시 해당 항목을 비활성 표시하고, 어떤 선행 조건이 필요한지 안내

상태 자동 업데이트

각 도메인의 저장 API가 성공하면 해당 sub-step을 자동으로 업데이트한다. mandatory sub-step이 전부 완료되면 부모 step도 자동 COMPLETED.

트리거 API업데이트 대상판단 조건
사용자 가입 완료ACCOUNT_VERIFIED → COMPLETED가입 시 자동
PUT /api/v1/users/me/profile (이름)PROFILE_COMPLETION > NAME_SET → COMPLETEDfirstName, lastName이 non-null
핸드폰 인증 APIPROFILE_COMPLETION > PHONE_VERIFIED → COMPLETED핸드폰 인증 완료
비밀번호 설정 APIPROFILE_COMPLETION > PASSWORD_SET → COMPLETED비밀번호 설정 완료
PUT /api/v1/users/me/profile (환경설정)PROFILE_COMPLETION > PREFERENCES_SET → COMPLETEDlanguage, timezone이 non-null
Organization 생성/수정 APIORGANIZATION_COMPLETION > ORG_INFO_SET → COMPLETEDOrganization 데이터 존재
사업자 정보 저장 APIORGANIZATION_COMPLETION > BUSINESS_INFO_SET → COMPLETED사업자 정보 존재
물류계정 연결 APIORGANIZATION_COMPLETION > LOGISTICS_CONNECTED → COMPLETED물류계정 존재
Shop 생성 APIFIRST_SHOP_CREATED → COMPLETEDShop 1개 이상 존재

구현 방식: 각 도메인 서비스에서 UserOnboardingService.completeSubStep(userId, stepId, subStepId)을 호출. 내부에서 mandatory sub-step 완료 여부를 체크하여 부모 step status를 자동 갱신.


API

온보딩 상태 조회

GET /api/v1/users/me/onboarding-status

인증: Bearer Token 필요

응답:

{ "steps": [ { "stepId": "ACCOUNT_VERIFIED", "status": "COMPLETED", "blockedBy": [], "completedAt": "2025-01-15T09:00:00Z", "subSteps": null }, { "stepId": "PROFILE_COMPLETION", "status": "PENDING", "blockedBy": [], "completedAt": null, "subSteps": [ { "subStepId": "NAME_SET", "status": "PENDING", "mandatory": true, "completedAt": null }, { "subStepId": "PHONE_VERIFIED", "status": "PENDING", "mandatory": false, "completedAt": null }, { "subStepId": "PASSWORD_SET", "status": "PENDING", "mandatory": false, "completedAt": null }, { "subStepId": "PREFERENCES_SET", "status": "PENDING", "mandatory": false, "completedAt": null } ] }, { "stepId": "ORGANIZATION_COMPLETION", "status": "PENDING", "blockedBy": [], "completedAt": null, "subSteps": [ { "subStepId": "ORG_INFO_SET", "status": "PENDING", "mandatory": true, "completedAt": null }, { "subStepId": "BUSINESS_INFO_SET", "status": "PENDING", "mandatory": true, "completedAt": null }, { "subStepId": "LOGISTICS_CONNECTED", "status": "PENDING", "mandatory": false, "completedAt": null } ] }, { "stepId": "FIRST_SHOP_CREATED", "status": "PENDING", "blockedBy": ["PROFILE_COMPLETION", "ORGANIZATION_COMPLETION"], "completedAt": null, "subSteps": null } ], "progressPercent": 25 }
  • blockedBy: 해당 단계를 진행하기 위해 먼저 완료해야 하는 미완료 단계 목록. 빈 배열이면 바로 진행 가능.
  • 부모 step status: mandatory sub-step이 전부 COMPLETED이면 자동으로 COMPLETED.
  • progressPercent 계산: completedStepCount / totalStepCount * 100 (4개 상위 step 기준)

Key Builder

클래스: com.makitt.core.common.dynamodb.key.UserKey (기존 확장)

// UserOnboarding Keys (User 파티션에 추가)
UserKey.pk(userId)                → "USER#{userId}"    (User와 동일 PK)
UserKey.onboardingSk()            → "ONBOARDING"

서버 아키텍처

UserOnboardingController (makitt-api)     -- GET /api/v1/users/me/onboarding-status
    |
    v  (DTO <-> VO)
UserOnboardingApplication (makitt-application)
    |
    v  (VO)
UserOnboardingService (makitt-core/service)
    |
    v  (DynamoDB 조작)
UserOnboardingRepository (makitt-core/repository)
    |
    v
UserOnboarding (makitt-core/entity)

패키지 구조:

makitt-core/
  com.makitt.core.domain.user/
    entity/
      UserOnboarding.java          # DynamoDB Entity
      OnboardingStep.java          # 단계 Nested Object
      UserOnboardingStep.java      # 단계 Enum
      StepStatus.java              # 완료 상태 Enum
    service/
      UserOnboardingService.java   # 상태 조회 + completeStep() + 의존성 체크
    repository/
      UserOnboardingRepository.java  # DynamoDB Repository

makitt-application/
  com.makitt.application.user/
    UserOnboardingApplication.java
    vo/
      OnboardingStatusResponseVo.java

makitt-api/
  com.makitt.api.controller.user/
    UserOnboardingController.java
    dto/
      OnboardingStatusResponse.java

연동 포인트 (각 도메인에서 호출):

// 예: UserProfileApplication.updateProfile() 내부 — 이름 저장 시 userOnboardingService.completeSubStep(userId, UserOnboardingStep.PROFILE_COMPLETION, ProfileSubStep.NAME_SET); // 예: OrganizationApplication.create() 내부 userOnboardingService.completeSubStep(userId, UserOnboardingStep.ORGANIZATION_COMPLETION, OrgSubStep.ORG_INFO_SET); // 예: BusinessInfoApplication.save() 내부 userOnboardingService.completeSubStep(userId, UserOnboardingStep.ORGANIZATION_COMPLETION, OrgSubStep.BUSINESS_INFO_SET); // 예: ShopApplication.createShop() 내부 // → 내부에서 PROFILE_COMPLETION, ORGANIZATION_COMPLETION 완료 여부를 체크 userOnboardingService.completeStep(userId, UserOnboardingStep.FIRST_SHOP_CREATED);

관련 엔티티

엔티티관계설명
User동일 PK (USER#{userId})User 파티션 내 별도 아이템
OrganizationcompleteSubStep 트리거조직 생성 시 ORG_INFO_SET, 사업자 정보 시 BUSINESS_INFO_SET 완료
ShopcompleteStep 트리거샵 생성 시 FIRST_SHOP_CREATED 완료 (선행 조건 체크)
ShopOnboarding후속 도메인MAKITT HAPPEN / EXPLODE는 샵 레벨에서 관리

참조