edit outer sequence
This commit is contained in:
@@ -7,9 +7,7 @@ actor "사용자\n(소상공인)" as User
|
||||
participant "Frontend\n(Web/Mobile)" as Frontend
|
||||
participant "API Gateway" as Gateway
|
||||
participant "User Service" as UserService
|
||||
database "Redis\nCache" as Redis
|
||||
database "User DB\n(PostgreSQL)" as UserDB
|
||||
participant "국세청 API\n(외부)" as NTSApi
|
||||
|
||||
== UFR-USER-010: 회원가입 플로우 ==
|
||||
|
||||
@@ -40,85 +38,36 @@ alt 중복 사용자 존재
|
||||
Frontend --> User: "이미 가입된 전화번호입니다"
|
||||
else 신규 사용자
|
||||
|
||||
' 사업자번호 검증 (Circuit Breaker 적용)
|
||||
UserService -> Redis: GET user:business:{사업자번호}
|
||||
activate Redis
|
||||
Redis --> UserService: 캐시된 검증 결과 확인
|
||||
deactivate Redis
|
||||
UserService -> UserService: 비밀번호 해싱\n(bcrypt, Cost Factor 10)
|
||||
|
||||
alt 캐시 HIT (검증 결과 있음)
|
||||
UserService -> UserService: 캐시된 검증 결과 사용\n(응답 시간: 0.1초)
|
||||
else 캐시 MISS (검증 필요)
|
||||
UserService -> NTSApi: POST /사업자번호_검증\n(사업자번호)\n[Circuit Breaker, Timeout 5초]
|
||||
activate NTSApi
|
||||
UserService -> UserService: 사업자번호 암호화\n(AES-256)
|
||||
|
||||
alt 국세청 API 정상 응답
|
||||
NTSApi --> UserService: 200 OK\n(사업자번호 유효, 영업 상태)
|
||||
deactivate NTSApi
|
||||
UserService -> UserDB: BEGIN TRANSACTION
|
||||
activate UserDB
|
||||
|
||||
UserService -> Redis: SET user:business:{사업자번호}\n검증 결과 (TTL 7일)
|
||||
activate Redis
|
||||
Redis --> UserService: 캐싱 완료
|
||||
deactivate Redis
|
||||
UserService -> UserDB: INSERT INTO users\n(name, phone_number, email,\npassword_hash, created_at)
|
||||
UserDB --> UserService: user_id 반환
|
||||
|
||||
else 국세청 API 장애 (Circuit Breaker Open)
|
||||
NTSApi --> UserService: 500 Internal Server Error\n또는 Timeout
|
||||
deactivate NTSApi
|
||||
UserService -> UserDB: INSERT INTO stores\n(user_id, store_name, industry,\naddress, business_number_encrypted,\nbusiness_hours)
|
||||
UserDB --> UserService: store_id 반환
|
||||
|
||||
UserService -> UserService: Fallback 실행:\n사업자번호 검증 스킵\n(수동 확인 안내)
|
||||
UserService -> UserDB: COMMIT TRANSACTION
|
||||
deactivate UserDB
|
||||
|
||||
note right of UserService
|
||||
**Resilience 패턴 적용**
|
||||
- Circuit Breaker: 실패율 50% 초과 시 Open
|
||||
- Retry: 최대 3회 재시도 (지수 백오프: 1초, 2초, 4초)
|
||||
- Timeout: 5초
|
||||
- Fallback: 검증 스킵 (수동 확인 안내)
|
||||
end note
|
||||
end
|
||||
end
|
||||
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)
|
||||
|
||||
alt 사업자번호 검증 실패 (휴폐업 등)
|
||||
UserService --> Gateway: 400 Bad Request\n(사업자번호 검증 실패)
|
||||
Gateway --> Frontend: 400 Bad Request
|
||||
Frontend --> User: "유효하지 않은 사업자번호입니다.\n휴폐업 여부를 확인해주세요."
|
||||
else 사업자번호 검증 성공
|
||||
UserService --> Gateway: 201 Created\n(JWT 토큰, 사용자 정보)
|
||||
deactivate UserService
|
||||
|
||||
UserService -> UserService: 비밀번호 해싱\n(bcrypt, Cost Factor 10)
|
||||
Gateway --> Frontend: 201 Created\n(JWT 토큰, 사용자 정보)
|
||||
deactivate Gateway
|
||||
|
||||
UserService -> UserService: 사업자번호 암호화\n(AES-256)
|
||||
Frontend -> Frontend: JWT 토큰 저장\n(LocalStorage 또는 Cookie)
|
||||
|
||||
UserService -> UserDB: BEGIN TRANSACTION
|
||||
activate UserDB
|
||||
Frontend --> User: "회원가입이 완료되었습니다"
|
||||
|
||||
UserService -> UserDB: INSERT INTO users\n(name, phone_number, email,\npassword_hash, created_at)
|
||||
UserDB --> UserService: user_id 반환
|
||||
|
||||
UserService -> UserDB: INSERT INTO stores\n(user_id, store_name, industry,\naddress, business_number_encrypted,\nbusiness_hours)
|
||||
UserDB --> UserService: store_id 반환
|
||||
|
||||
UserService -> UserDB: COMMIT TRANSACTION
|
||||
deactivate UserDB
|
||||
|
||||
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)
|
||||
|
||||
UserService -> Redis: SET user:session:{token}\n(user_id, role, TTL 7일)
|
||||
activate Redis
|
||||
Redis --> UserService: 세션 저장 완료
|
||||
deactivate Redis
|
||||
|
||||
UserService --> Gateway: 201 Created\n(JWT 토큰, 사용자 정보)
|
||||
deactivate UserService
|
||||
|
||||
Gateway --> Frontend: 201 Created\n(JWT 토큰, 사용자 정보)
|
||||
deactivate Gateway
|
||||
|
||||
Frontend -> Frontend: JWT 토큰 저장\n(LocalStorage 또는 Cookie)
|
||||
|
||||
Frontend --> User: "회원가입이 완료되었습니다"
|
||||
|
||||
Frontend -> Gateway: 대시보드 화면으로 이동
|
||||
deactivate Frontend
|
||||
end
|
||||
Frontend -> Gateway: 대시보드 화면으로 이동
|
||||
deactivate Frontend
|
||||
end
|
||||
|
||||
== UFR-USER-020: 로그인 플로우 ==
|
||||
@@ -159,11 +108,6 @@ else 사용자 존재
|
||||
|
||||
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)
|
||||
|
||||
UserService -> Redis: SET user:session:{token}\n(user_id, role, TTL 7일)
|
||||
activate Redis
|
||||
Redis --> UserService: 세션 저장 완료
|
||||
deactivate Redis
|
||||
|
||||
UserService -> UserDB: UPDATE users\nSET last_login_at = NOW()\nWHERE user_id = ?
|
||||
activate UserDB
|
||||
UserDB --> UserService: 업데이트 완료
|
||||
@@ -203,10 +147,7 @@ Gateway -> Gateway: JWT 토큰 검증
|
||||
Gateway -> UserService: POST /api/users/logout\n(JWT 토큰)
|
||||
activate UserService
|
||||
|
||||
UserService -> Redis: DEL user:session:{token}
|
||||
activate Redis
|
||||
Redis --> UserService: 세션 삭제 완료
|
||||
deactivate Redis
|
||||
UserService -> UserService: JWT 토큰 블랙리스트에 추가\n(만료 시까지 유효)
|
||||
|
||||
UserService --> Gateway: 200 OK\n(로그아웃 성공)
|
||||
deactivate UserService
|
||||
@@ -221,28 +162,4 @@ Frontend --> User: "안전하게 로그아웃되었습니다"
|
||||
Frontend -> Gateway: 로그인 화면으로 이동
|
||||
deactivate Frontend
|
||||
|
||||
note over User, NTSApi
|
||||
**Resilience 패턴 적용 요약**
|
||||
|
||||
**Circuit Breaker (국세청 API)**:
|
||||
- 실패율 50% 초과 시 Open
|
||||
- 30초 후 Half-Open 상태로 전환
|
||||
- 3개 요청 테스트 후 상태 결정
|
||||
|
||||
**Retry Pattern**:
|
||||
- 최대 3회 재시도
|
||||
- 지수 백오프: 1초, 2초, 4초
|
||||
- 재시도 대상: SocketTimeoutException, ConnectException
|
||||
|
||||
**Timeout Pattern**:
|
||||
- 국세청 API: 5초
|
||||
|
||||
**Fallback Pattern**:
|
||||
- 국세청 API 장애 시: 사업자번호 검증 스킵 (수동 확인 안내)
|
||||
|
||||
**Cache-Aside Pattern**:
|
||||
- 사업자번호 검증 결과 캐싱 (TTL 7일)
|
||||
- 캐시 HIT: 0.1초, MISS: 5초 (외부 API 호출)
|
||||
end note
|
||||
|
||||
@enduml
|
||||
|
||||
Reference in New Issue
Block a user