edit outer sequence

This commit is contained in:
cherry2250 2025-10-22 17:32:19 +09:00
parent 7a1fcc96de
commit a8c6397edf
3 changed files with 64 additions and 189 deletions

View File

@ -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,49 +38,6 @@ alt 중복 사용자 존재
Frontend --> User: "이미 가입된 전화번호입니다"
else 신규 사용자
' 사업자번호 검증 (Circuit Breaker 적용)
UserService -> Redis: GET user:business:{사업자번호}
activate Redis
Redis --> UserService: 캐시된 검증 결과 확인
deactivate Redis
alt 캐시 HIT (검증 결과 있음)
UserService -> UserService: 캐시된 검증 결과 사용\n(응답 시간: 0.1초)
else 캐시 MISS (검증 필요)
UserService -> NTSApi: POST /사업자번호_검증\n(사업자번호)\n[Circuit Breaker, Timeout 5초]
activate NTSApi
alt 국세청 API 정상 응답
NTSApi --> UserService: 200 OK\n(사업자번호 유효, 영업 상태)
deactivate NTSApi
UserService -> Redis: SET user:business:{사업자번호}\n검증 결과 (TTL 7일)
activate Redis
Redis --> UserService: 캐싱 완료
deactivate Redis
else 국세청 API 장애 (Circuit Breaker Open)
NTSApi --> UserService: 500 Internal Server Error\n또는 Timeout
deactivate NTSApi
UserService -> UserService: Fallback 실행:\n사업자번호 검증 스킵\n(수동 확인 안내)
note right of UserService
**Resilience 패턴 적용**
- Circuit Breaker: 실패율 50% 초과 시 Open
- Retry: 최대 3회 재시도 (지수 백오프: 1초, 2초, 4초)
- Timeout: 5초
- Fallback: 검증 스킵 (수동 확인 안내)
end note
end
end
alt 사업자번호 검증 실패 (휴폐업 등)
UserService --> Gateway: 400 Bad Request\n(사업자번호 검증 실패)
Gateway --> Frontend: 400 Bad Request
Frontend --> User: "유효하지 않은 사업자번호입니다.\n휴폐업 여부를 확인해주세요."
else 사업자번호 검증 성공
UserService -> UserService: 비밀번호 해싱\n(bcrypt, Cost Factor 10)
UserService -> UserService: 사업자번호 암호화\n(AES-256)
@ -101,11 +56,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 --> Gateway: 201 Created\n(JWT 토큰, 사용자 정보)
deactivate UserService
@ -119,7 +69,6 @@ else 신규 사용자
Frontend -> Gateway: 대시보드 화면으로 이동
deactivate Frontend
end
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

View File

@ -10,11 +10,13 @@ participant "Analytics Service" as Analytics
participant "Redis Cache\n(TTL 5분)" as Redis
participant "Analytics DB" as AnalyticsDB
participant "Kafka\n(Event Topics)" as Kafka
box "외부 시스템" #LightGray
participant "우리동네TV API" as WooriAPI
participant "지니TV API" as GenieAPI
participant "SNS APIs\n(Instagram/Naver/Kakao)" as SNSAPI
end box
note over AnalyticsDB
**배치 처리로 수집된 데이터**
- 외부 채널 통계는 배치 작업으로
주기적으로 수집하여 DB에 저장
- 목업 데이터로 시작, 점진적으로 실제 API 연동
end note
== 1. 대시보드 조회 - Cache HIT 시나리오 ==
@ -83,56 +85,28 @@ AnalyticsDB --> Analytics: 이벤트 통계\n- 총 참여자 수\n- 예상 ROI\n
deactivate AnalyticsDB
|||
== 2.2. 외부 채널 API 병렬 호출 (Circuit Breaker 적용) ==
== 2.2. 배치 수집된 채널 통계 데이터 조회 ==
par 병렬 채널 API 호출
Analytics -> WooriAPI: GET /stats/{eventId}\n+ API Key\n[Circuit Breaker]
activate WooriAPI
alt Circuit Breaker CLOSED (정상)
WooriAPI --> Analytics: 200 OK\n- 노출 수: 5,000\n- 조회 수: 1,200
deactivate WooriAPI
Analytics -> AnalyticsDB: SELECT channel_stats\nWHERE event_id = {id}
activate AnalyticsDB
note right of Analytics
**Resilience 패턴**
- Circuit Breaker: 실패율 50% 초과 시 Open
- Timeout: 10초
- Retry: 최대 3회 (지수 백오프)
- Fallback: 캐시된 이전 데이터 반환
**배치 처리 방식**
- 외부 API는 별도 배치 작업으로 주기적 수집
- 수집된 데이터는 DB에 저장
- 대시보드에서는 DB 데이터만 조회
- 응답 시간 단축 및 외부 API 의존성 제거
end note
else Circuit Breaker OPEN (장애)
Analytics -> Analytics: **Fallback 실행**\n캐시된 이전 데이터 사용
AnalyticsDB --> Analytics: 채널별 통계 데이터\n- 우리동네TV: 노출 5,000, 조회 1,200\n- 지니TV: 노출 10,000, 클릭 500\n- Instagram: 좋아요 300, 댓글 50\n- Naver: 조회 2,000\n- Kakao: 공유 100
deactivate AnalyticsDB
note right of Analytics
Circuit Breaker OPEN 상태
- 빠른 실패로 응답 시간 단축
- 30초 후 Half-Open으로 전환
**목업 데이터 활용**
- 초기에는 목업 데이터로 시작
- 점진적으로 실제 배치 작업 구현
- 배치 주기: 10분마다 수집
end note
end
else
Analytics -> GenieAPI: GET /campaign/{eventId}/stats\n+ API Key\n[Circuit Breaker]
activate GenieAPI
alt 정상 응답
GenieAPI --> Analytics: 200 OK\n- 광고 노출 수: 10,000\n- 클릭 수: 500
deactivate GenieAPI
else Timeout (10초 초과)
Analytics -> Analytics: **Timeout 처리**\n기본값 반환 (0)
note right of Analytics
Timeout 발생
- 리소스 점유 방지
- Fallback으로 기본값 설정
end note
end
else
Analytics -> SNSAPI: GET /posts/{eventId}/insights\n+ Access Token\n[Circuit Breaker]
activate SNSAPI
SNSAPI --> Analytics: 200 OK\n- Instagram: 좋아요 300, 댓글 50\n- Naver: 조회 수 2,000\n- Kakao: 공유 수 100
deactivate SNSAPI
end
|||
== 2.3. 데이터 통합 및 ROI 계산 ==

View File

@ -11,7 +11,6 @@ participant "AI Service" as AI
participant "Content Service" as Content
participant "Distribution Service" as Dist
participant "Kafka" as Kafka
participant "Redis Cache" as Cache
database "Event DB" as EventDB
participant "외부 AI API" as AIApi
participant "이미지 생성 API" as ImageApi
@ -21,14 +20,8 @@ participant "배포 채널 APIs" as ChannelApis
User -> FE: 이벤트 목적 선택
FE -> Gateway: POST /events/purposes\n{목적, 매장정보}
Gateway -> Event: 이벤트 목적 저장 요청
Event -> Cache: 캐시 조회\nkey: purpose:{userId}
alt 캐시 히트
Cache --> Event: 캐시된 데이터
else 캐시 미스
Event -> EventDB: 이벤트 목적 저장
EventDB --> Event: 저장 완료
Event -> Cache: 캐시 저장\nTTL: 30분
end
Event --> Gateway: 저장 완료\n{eventDraftId}
Gateway --> FE: 200 OK
FE --> User: AI 추천 화면으로 이동
@ -42,38 +35,29 @@ Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
Gateway --> FE: 202 Accepted\n{jobId}
FE --> User: "AI가 분석 중입니다..." (로딩)
note over AI: Kafka Consumer\nai-job-topic 구독
note over AI: Kafka Consumer\nai 이벤트 생성 topic 구독
Kafka --> AI: Consume Job Message\n{jobId, eventDraftId, ...}
AI -> Cache: 트렌드 분석 캐시 조회\nkey: trend:{업종}:{지역}
alt 캐시 히트
Cache --> AI: 캐시된 트렌드 데이터
else 캐시 미스
AI -> EventDB: 과거 이벤트 데이터 조회
EventDB --> AI: 이벤트 통계 데이터
AI -> AIApi: 트렌드 분석 요청\n{업종, 지역, 과거데이터}
AIApi --> AI: 트렌드 분석 결과
AI -> Cache: 트렌드 캐시 저장\nTTL: 1시간
end
AI -> AIApi: 이벤트 추천 요청\n{목적, 트렌드, 매장정보}
AIApi --> AI: 3가지 추천안 생성
AI -> EventDB: 추천 결과 저장
AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 과거데이터, 매장정보}
AIApi --> AI: 3가지 추천안 + 트렌드 요약\n(예: "여름철 시원한 음료 선호도 증가")
AI -> EventDB: 추천 결과 및 트렌드 요약 저장
EventDB --> AI: 저장 완료
AI -> Cache: Job 상태 업데이트\nkey: job:{jobId}\nstatus: COMPLETED
AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations}
AI -> EventDB: Job 상태 업데이트\nstatus: COMPLETED
AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations, trendSummary}
group Polling으로 상태 확인
loop 상태 확인 (최대 30초)
FE -> Gateway: GET /jobs/{jobId}/status
Gateway -> Event: Job 상태 조회
Event -> Cache: 캐시에서 Job 상태 확인
Cache --> Event: {status, result}
Event -> EventDB: Job 상태 및 결과 조회
EventDB --> Event: {status, result}
alt Job 완료
Event --> Gateway: 200 OK\n{status: COMPLETED, recommendations}
Gateway --> FE: 추천 결과 반환
FE --> User: 3가지 추천안 표시\n(제목/경품 수정 가능)
Event --> Gateway: 200 OK\n{status: COMPLETED, recommendations, trendSummary}
Gateway --> FE: 추천 결과 및 트렌드 요약 반환
FE --> User: 트렌드 요약 표시\n3가지 추천안 표시\n(제목/경품 수정 가능)
else Job 진행중
Event --> Gateway: 200 OK\n{status: PENDING/PROCESSING}
Gateway --> FE: 진행중 상태
@ -100,7 +84,7 @@ Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
Gateway --> FE: 202 Accepted\n{jobId}
FE --> User: "이미지 생성 중..." (로딩)
note over Content: Kafka Consumer\nimage-job-topic 구독
note over Content: Kafka Consumer\n이미지 생성 topic 구독
Kafka --> Content: Consume Job Message\n{jobId, eventDraftId, ...}
par 심플 스타일
@ -116,15 +100,15 @@ end
Content -> EventDB: 이미지 URL 저장
EventDB --> Content: 저장 완료
Content -> Cache: Job 상태 업데이트\nkey: job:{jobId}\nstatus: COMPLETED
Content -> EventDB: Job 상태 업데이트\nstatus: COMPLETED
Content -> Kafka: Publish to event-topic\nContentCreated\n{jobId, eventDraftId, imageUrls}
group Polling으로 상태 확인
loop 상태 확인 (최대 30초)
FE -> Gateway: GET /jobs/{jobId}/status
Gateway -> Event: Job 상태 조회
Event -> Cache: 캐시에서 Job 상태 확인
Cache --> Event: {status, imageUrls}
Event -> EventDB: Job 상태 및 결과 조회
EventDB --> Event: {status, imageUrls}
alt Job 완료
Event --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}