mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 21:26:24 +00:00
변경 사항: - 이벤트생성플로우 outer: FE → Gateway → User Service 호출 패턴 추가 - user-로그인 inner: 전화번호 → 이메일 기반 인증으로 변경 - user-회원가입 inner: 국세청 API 제거, 이메일 중복검사 추가 - event-목적선택 inner: Gateway 경유, 요청/응답 한글화 - ai-트렌드분석및추천 inner: 과거 이벤트 데이터 제거, Timeout 5분으로 변경 - analytics-대시보드조회 inner: Redis TTL 5분 → 1시간으로 변경 모든 파일에 Repository CRUD 작업 한글 설명 적용 (SQL 제거) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
251 lines
11 KiB
Plaintext
251 lines
11 KiB
Plaintext
@startuml 이벤트생성플로우
|
|
!theme mono
|
|
|
|
title 이벤트 생성 플로우 - 외부 시퀀스 다이어그램
|
|
|
|
actor "소상공인" as User
|
|
participant "Frontend" as FE
|
|
participant "API Gateway" as Gateway
|
|
participant "Event Service" as Event
|
|
participant "User Service" as UserSvc
|
|
participant "AI Service" as AI
|
|
participant "Content Service" as Content
|
|
participant "Distribution Service" as Dist
|
|
participant "Kafka" as Kafka
|
|
database "Event DB" as EventDB
|
|
database "User DB" as UserDB
|
|
database "Redis" as Redis
|
|
participant "외부 AI API" as AIApi
|
|
participant "이미지 생성 API" as ImageApi
|
|
participant "배포 채널 APIs" as ChannelApis
|
|
|
|
== 1. 이벤트 목적 선택 (UFR-EVENT-020) ==
|
|
User -> FE: 이벤트 목적 선택
|
|
FE -> Gateway: GET /api/users/{userId}/store\n회원 및 매장정보 조회
|
|
activate Gateway
|
|
Gateway -> UserSvc: GET /api/users/{userId}/store\n회원 및 매장정보 조회
|
|
activate UserSvc
|
|
UserSvc -> UserDB: 사용자 및 매장 정보 조회
|
|
activate UserDB
|
|
UserDB --> UserSvc: 사용자, 매장 정보 반환
|
|
deactivate UserDB
|
|
UserSvc --> Gateway: 200 OK\n{userId, storeName, industry, address}
|
|
deactivate UserSvc
|
|
Gateway --> FE: 200 OK\n{userId, storeName, industry, address}
|
|
deactivate Gateway
|
|
FE -> Gateway: POST /events/purposes\n{목적, userId, storeName, industry, address}
|
|
Gateway -> Event: 이벤트 목적 저장 요청
|
|
Event -> Redis: 이벤트 목적 정보 저장\nKey: draft:event:{eventDraftId}\n(목적, 매장정보 저장)\nTTL: 24시간
|
|
activate Redis
|
|
Redis --> Event: 저장 완료
|
|
deactivate Redis
|
|
Event --> Gateway: 저장 완료\n{eventDraftId}
|
|
Gateway --> FE: 200 OK
|
|
FE --> User: AI 추천 화면으로 이동
|
|
|
|
== 2. AI 이벤트 추천 - 비동기 처리 (UFR-EVENT-030) ==
|
|
User -> FE: AI 추천 요청
|
|
FE -> Gateway: POST /api/events/{eventDraftId}/ai-recommendations\n{목적, 업종, 지역}
|
|
Gateway -> Event: AI 추천 요청 전달
|
|
Event -> Kafka: Publish to ai-job-topic\n{jobId, eventDraftId, 목적, 업종, 지역}
|
|
Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
|
Gateway --> FE: 202 Accepted\n{jobId}
|
|
FE --> User: "AI가 분석 중입니다..." (로딩)
|
|
|
|
note over AI: Kafka Consumer\nai 이벤트 생성 topic 구독
|
|
Kafka --> AI: Consume Job Message\n{jobId, eventDraftId, ...}
|
|
|
|
AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 매장정보}\n[Circuit Breaker, Timeout: 5분]
|
|
AIApi --> AI: 3가지 추천안 + 트렌드 요약\n(예: "여름철 시원한 음료 선호도 증가")
|
|
AI -> Redis: AI 추천 결과 저장\nKey: ai:event:{eventDraftId}\n(3가지 추천안, 트렌드 요약)\nTTL: 24시간
|
|
Redis --> AI: 저장 완료
|
|
AI -> Redis: Job 상태 업데이트\n(상태를 COMPLETED로 변경)
|
|
note over AI, Redis: AI 추천 정보는 Redis에 저장\n- Content Service가 읽기 위함\n- 최종 승인 시 Event DB에 영구 저장
|
|
|
|
group Polling으로 상태 확인
|
|
loop 상태 확인 (최대 30초)
|
|
FE -> Gateway: GET /jobs/{jobId}/status
|
|
Gateway -> Event: Job 상태 조회
|
|
Event -> Redis: Job 상태 조회\n(jobId로 상태 및 결과 조회)
|
|
Redis --> Event: {status, result}
|
|
|
|
alt Job 완료
|
|
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: 진행중 상태
|
|
note over FE: 2초 후 재요청
|
|
end
|
|
end
|
|
end
|
|
|
|
User -> FE: 추천안 선택\n(제목/경품 커스텀)
|
|
FE -> Gateway: PUT /events/drafts/{eventDraftId}\n{선택한 추천안, 커스텀 정보}
|
|
Gateway -> Event: 선택 저장
|
|
Event -> Redis: 선택한 추천안 저장\nKey: draft:event:{eventDraftId}\n(이벤트 초안 업데이트)\nTTL: 24시간
|
|
activate Redis
|
|
Redis --> Event: 업데이트 완료
|
|
deactivate Redis
|
|
Event --> Gateway: 200 OK
|
|
Gateway --> FE: 저장 완료
|
|
FE --> User: 콘텐츠 생성 화면으로 이동
|
|
|
|
== 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) ==
|
|
User -> FE: 이미지 생성 요청
|
|
FE -> Gateway: POST /api/content/images/{eventDraftId}/generate
|
|
Gateway -> Content: 이미지 생성 요청
|
|
Content -> Content: Job 생성\n{jobId, eventDraftId, status: PENDING}
|
|
Content --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
|
Gateway --> FE: 202 Accepted\n{jobId}
|
|
FE --> User: "이미지 생성 중..." (로딩)
|
|
|
|
note over Content: 백그라운드 워커\nRedis 폴링 또는 스케줄러
|
|
|
|
Content -> Redis: AI 이벤트 데이터 읽기\nKey: ai:event:{eventDraftId}
|
|
activate Redis
|
|
Redis --> Content: AI 추천 결과\n{선택된 추천안, 이벤트 정보}
|
|
deactivate Redis
|
|
|
|
note over Content: inner sequence 참조:\ncontent-이미지생성.puml
|
|
|
|
par 심플 스타일
|
|
Content -> ImageApi: 심플 스타일 생성 요청\n[Circuit Breaker, Timeout: 5분]
|
|
ImageApi --> Content: 심플 이미지 URL
|
|
else 화려한 스타일
|
|
Content -> ImageApi: 화려한 스타일 생성 요청\n[Circuit Breaker, Timeout: 5분]
|
|
ImageApi --> Content: 화려한 이미지 URL
|
|
else 트렌디 스타일
|
|
Content -> ImageApi: 트렌디 스타일 생성 요청\n[Circuit Breaker, Timeout: 5분]
|
|
ImageApi --> Content: 트렌디 이미지 URL
|
|
end
|
|
|
|
Content -> Redis: 이미지 URL 저장\nKey: content:image:{eventDraftId}\n{심플, 화려, 트렌디 URL}\nTTL: 7일
|
|
activate Redis
|
|
Redis --> Content: 저장 완료
|
|
deactivate Redis
|
|
Content -> Redis: Job 상태 업데이트\n(상태를 COMPLETED로 변경)
|
|
note over Content, Redis: 이미지 URL은 Redis에 저장\n- 최종 승인 시 Event DB에 영구 저장
|
|
|
|
group Polling으로 상태 확인
|
|
loop 상태 확인 (최대 30초)
|
|
FE -> Gateway: GET /api/content/jobs/{jobId}/status
|
|
Gateway -> Content: Job 상태 조회
|
|
Content -> Redis: Job 상태 조회\n(jobId로 상태 및 이미지 URL 조회)
|
|
Redis --> Content: {status, imageUrls}
|
|
|
|
alt Job 완료
|
|
Content --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
|
|
Gateway --> FE: 이미지 URL 반환
|
|
FE --> User: 3가지 스타일 카드 표시
|
|
else Job 진행중
|
|
Content --> Gateway: 200 OK\n{status: PENDING/PROCESSING}
|
|
Gateway --> FE: 진행중 상태
|
|
note over FE: 2초 후 재요청
|
|
end
|
|
end
|
|
end
|
|
|
|
User -> FE: 스타일 선택 및 편집
|
|
FE -> Gateway: PUT /events/drafts/{eventDraftId}/content\n{선택한 이미지, 편집내용}
|
|
Gateway -> Event: 콘텐츠 선택 저장
|
|
Event -> Redis: 선택한 콘텐츠 저장\nKey: draft:event:{eventDraftId}\n(이벤트 초안 업데이트)\nTTL: 24시간
|
|
activate Redis
|
|
Redis --> Event: 업데이트 완료
|
|
deactivate Redis
|
|
Event --> Gateway: 200 OK
|
|
Gateway --> FE: 저장 완료
|
|
FE --> User: 배포 채널 선택 화면으로 이동
|
|
|
|
== 4. 최종 승인 및 다중 채널 배포 - 동기 처리 (UFR-EVENT-050) ==
|
|
User -> FE: 배포 채널 선택\n최종 승인 요청
|
|
FE -> Gateway: POST /api/events/{eventDraftId}/publish\n{선택 채널 목록}
|
|
Gateway -> Event: 최종 승인 및 배포 처리
|
|
|
|
note over Event: Redis 데이터를 Event DB에 영구 저장
|
|
|
|
Event -> Redis: 이벤트 초안 조회\nKey: draft:event:{eventDraftId}
|
|
activate Redis
|
|
Redis --> Event: 이벤트 초안 데이터\n(목적, 매장정보, 추천안, 콘텐츠)
|
|
deactivate Redis
|
|
|
|
Event -> Redis: AI 추천 결과 조회\nKey: ai:event:{eventDraftId}
|
|
activate Redis
|
|
Redis --> Event: AI 추천 결과
|
|
deactivate Redis
|
|
|
|
Event -> Redis: 이미지 URL 조회\nKey: content:image:{eventDraftId}
|
|
activate Redis
|
|
Redis --> Event: 이미지 URL 목록
|
|
deactivate Redis
|
|
|
|
Event -> EventDB: 이벤트 정보 영구 저장\n(목적, 매장정보, AI 추천, 이미지 URL, 배포 채널 포함)
|
|
EventDB --> Event: 저장 완료
|
|
|
|
Event -> EventDB: 이벤트 상태 변경\n(DRAFT → APPROVED로 업데이트)
|
|
EventDB --> Event: 상태 변경 완료
|
|
Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보}
|
|
|
|
note over Event: 동기 호출로 배포 진행\ninner sequence 참조:\ndistribution-다중채널배포.puml
|
|
Event -> Dist: REST API - 배포 요청\nPOST /api/distribution/distribute\n{eventId, channels[], contentUrls}
|
|
|
|
note over Dist: Sprint 2: Mock 처리\n- 외부 API 호출 없음\n- 모든 배포 즉시 성공 처리\n- 배포 로그만 DB 기록
|
|
|
|
Dist -> EventDB: 배포 이력 초기화\n(이벤트ID, 상태: PENDING)
|
|
EventDB --> Dist: 배포 이력 ID
|
|
Dist -> EventDB: 배포 이력 상태 업데이트\n(상태: IN_PROGRESS)
|
|
|
|
note over Dist: 다중 채널 Mock 배포\n(내부 처리 상세는 inner sequence 참조)
|
|
|
|
par 우리동네TV
|
|
alt 우리동네TV 선택
|
|
Dist -> Dist: Mock 처리\n(즉시 성공)
|
|
Dist -> EventDB: 채널 로그 저장\n(우리동네TV, 성공,\n배포ID, 예상노출수)
|
|
end
|
|
else 링고비즈
|
|
alt 링고비즈 선택
|
|
Dist -> Dist: Mock 처리\n(즉시 성공)
|
|
Dist -> EventDB: 채널 로그 저장\n(링고비즈, 성공,\n업데이트 시각)
|
|
end
|
|
else 지니TV
|
|
alt 지니TV 선택
|
|
Dist -> Dist: Mock 처리\n(즉시 성공)
|
|
Dist -> EventDB: 채널 로그 저장\n(지니TV, 성공,\n광고ID, 스케줄)
|
|
end
|
|
else Instagram
|
|
alt Instagram 선택
|
|
Dist -> Dist: Mock 처리\n(즉시 성공)
|
|
Dist -> EventDB: 채널 로그 저장\n(Instagram, 성공,\npostUrl, postId)
|
|
end
|
|
else Naver Blog
|
|
alt Naver Blog 선택
|
|
Dist -> Dist: Mock 처리\n(즉시 성공)
|
|
Dist -> EventDB: 채널 로그 저장\n(NaverBlog, 성공,\npostUrl)
|
|
end
|
|
else Kakao Channel
|
|
alt Kakao Channel 선택
|
|
Dist -> Dist: Mock 처리\n(즉시 성공)
|
|
Dist -> EventDB: 채널 로그 저장\n(KakaoChannel, 성공,\nmessageId)
|
|
end
|
|
end
|
|
|
|
note over Dist: 모든 채널 배포 완료 (즉시 처리)
|
|
|
|
Dist -> EventDB: 배포 이력 상태 업데이트\n(상태: COMPLETED, 완료일시)
|
|
|
|
Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, channels[], results[], completedAt}
|
|
|
|
Dist --> Event: REST API 동기 응답\n200 OK\n{distributionId, status: COMPLETED, results[]}
|
|
|
|
Event -> EventDB: 이벤트 상태 업데이트\n(APPROVED → ACTIVE로 변경)
|
|
EventDB --> Event: 업데이트 완료
|
|
|
|
Event --> Gateway: 200 OK\n{eventId, 배포결과}
|
|
Gateway --> FE: 배포 완료
|
|
FE --> User: "이벤트가 배포되었습니다"\n대시보드로 이동
|
|
|
|
note over Event, Dist: Sprint 2 제약사항\n- 외부 API 호출 없음 (Mock)\n- 모든 배포 즉시 성공 처리\n- Circuit Breaker 미구현\n- Retry 로직 미구현\n\nSprint 3 이후 구현 예정\n- 실제 외부 채널 API 연동\n- Circuit Breaker 패턴\n- Retry 및 실패 처리
|
|
|
|
@enduml
|