mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 16:06:24 +00:00
edit all sequence
This commit is contained in:
parent
a8c6397edf
commit
9192e1e453
@ -66,7 +66,7 @@ else 유효한 메시지
|
||||
end note
|
||||
|
||||
else 캐시 미스
|
||||
TrendEngine -> EventDB: 과거 이벤트 데이터 조회\nSELECT * FROM events\nWHERE industry = ?\nAND region LIKE ?\nAND created_at > NOW() - INTERVAL 3 MONTH\nORDER BY roi DESC
|
||||
TrendEngine -> EventDB: 과거 이벤트 데이터 조회\n(업종과 지역으로 필터링,\n최근 3개월 이벤트,\nROI 내림차순 정렬)
|
||||
EventDB --> TrendEngine: 이벤트 통계 데이터\n{성공 이벤트 리스트, ROI 정보}
|
||||
|
||||
TrendEngine -> TrendEngine: 트렌드 패턴 분석
|
||||
|
||||
@ -96,7 +96,7 @@ else Cache MISS
|
||||
Service -> Repository: getEventStats(eventId)
|
||||
activate Repository
|
||||
|
||||
Repository -> DB: SELECT event_stats\nWHERE event_id = ?
|
||||
Repository -> DB: 이벤트 통계 조회\n(이벤트ID로 통계 데이터 조회)
|
||||
activate DB
|
||||
|
||||
DB --> Repository: EventStatsEntity\n- totalParticipants\n- estimatedROI\n- salesGrowthRate
|
||||
|
||||
@ -62,7 +62,7 @@ alt 이벤트 미처리 (멱등성 보장)
|
||||
Service -> Repository: saveChannelStats(\n eventId, channel, stats\n)
|
||||
activate Repository
|
||||
|
||||
Repository -> DB: INSERT INTO channel_stats (\n event_id,\n channel_name,\n status,\n expected_views,\n distributed_at\n) VALUES (?, ?, ?, ?, ?)\nON CONFLICT (event_id, channel_name)\nDO UPDATE SET\n status = EXCLUDED.status,\n expected_views = EXCLUDED.expected_views,\n distributed_at = EXCLUDED.distributed_at
|
||||
Repository -> DB: 채널별 통계 저장\n(이벤트ID, 채널명, 상태,\n예상노출수, 배포일시 저장,\n중복 시 업데이트)
|
||||
activate DB
|
||||
|
||||
DB --> Repository: 1 row inserted/updated
|
||||
@ -82,7 +82,7 @@ alt 이벤트 미처리 (멱등성 보장)
|
||||
Service -> Repository: updateTotalViews(eventId, totalViews)
|
||||
activate Repository
|
||||
|
||||
Repository -> DB: UPDATE event_stats\nSET total_views = ?,\n updated_at = NOW()\nWHERE event_id = ?
|
||||
Repository -> DB: 총 노출 수 업데이트\n(총 예상 노출 수를 설정하고,\n수정일시를 현재 시각으로 업데이트)
|
||||
activate DB
|
||||
|
||||
DB --> Repository: 1 row updated
|
||||
|
||||
@ -54,7 +54,7 @@ alt 이벤트 미처리 (멱등성 보장)
|
||||
Service -> Repository: save(eventStatsEntity)
|
||||
activate Repository
|
||||
|
||||
Repository -> DB: INSERT INTO event_stats (\n event_id,\n store_id,\n title,\n objective,\n participant_count,\n total_views,\n estimated_roi,\n sales_growth_rate,\n created_at\n) VALUES (?, ?, ?, ?, 0, 0, 0, 0, ?)
|
||||
Repository -> DB: 이벤트 통계 초기화\n(이벤트ID, 매장ID, 제목, 목적,\n참여자수/노출수/ROI/매출증가율을\n0으로 초기화하여 저장)
|
||||
activate DB
|
||||
|
||||
DB --> Repository: 1 row inserted
|
||||
|
||||
@ -50,7 +50,7 @@ alt 이벤트 미처리 (멱등성 보장)
|
||||
Service -> Repository: incrementParticipantCount(eventId)
|
||||
activate Repository
|
||||
|
||||
Repository -> DB: UPDATE event_stats\nSET participant_count = participant_count + 1,\n updated_at = NOW()\nWHERE event_id = ?
|
||||
Repository -> DB: 참여자 수 증가\n(참여자 수를 1 증가시키고,\n수정일시를 현재 시각으로 업데이트)
|
||||
activate DB
|
||||
|
||||
DB --> Repository: 1 row updated
|
||||
|
||||
@ -21,11 +21,11 @@ activate Controller
|
||||
Controller -> Service: executeDistribution(distributionRequest)
|
||||
activate Service
|
||||
|
||||
Service -> DB: 배포 이력 초기화\nINSERT distribution_logs\n{eventId, status: PENDING}
|
||||
Service -> DB: 배포 이력 초기화\n(이벤트ID, 상태를 PENDING으로 저장)
|
||||
DB --> Service: 배포 이력 ID
|
||||
|
||||
note over Service: 배포 시작 상태로 변경
|
||||
Service -> DB: UPDATE distribution_logs\nSET status = 'IN_PROGRESS'
|
||||
Service -> DB: 배포 이력 상태 업데이트\n(상태를 IN_PROGRESS로 변경)
|
||||
|
||||
== 다중 채널 배포 로그 기록 (Sprint 2: Mock 처리) ==
|
||||
|
||||
@ -38,7 +38,7 @@ par 우리동네TV 배포
|
||||
|
||||
note over Service: 배포 요청 검증\n- eventId 유효성\n- contentUrls 존재 여부
|
||||
|
||||
Service -> DB: 배포 채널 로그 저장\nINSERT distribution_channel_logs\n{channel: WooridongneTV,\nstatus: SUCCESS,\ndistributionId: generated_uuid,\nestimatedViews: 1000}
|
||||
Service -> DB: 배포 채널 로그 저장\n(채널: 우리동네TV,\n상태: 성공, 배포ID,\n예상노출수 저장)
|
||||
|
||||
note over Service: Mock 결과:\n성공 (distributionId 생성)
|
||||
|
||||
@ -51,7 +51,7 @@ par 우리동네TV 배포
|
||||
|
||||
note over Service: 배포 요청 검증\n- phoneNumber 형식\n- audioUrl 존재 여부
|
||||
|
||||
Service -> DB: 배포 채널 로그 저장\nINSERT distribution_channel_logs\n{channel: RingoBiz,\nstatus: SUCCESS,\nupdateTimestamp: NOW()}
|
||||
Service -> DB: 배포 채널 로그 저장\n(채널: 링고비즈,\n상태: 성공,\n업데이트 시각 저장)
|
||||
|
||||
note over Service: Mock 결과:\n성공 (timestamp 기록)
|
||||
|
||||
@ -64,7 +64,7 @@ par 우리동네TV 배포
|
||||
|
||||
note over Service: 배포 요청 검증\n- region 유효성\n- schedule 형식\n- budget 범위
|
||||
|
||||
Service -> DB: 배포 채널 로그 저장\nINSERT distribution_channel_logs\n{channel: GenieTV,\nstatus: SUCCESS,\nadId: generated_uuid,\nimpressionSchedule: calculated}
|
||||
Service -> DB: 배포 채널 로그 저장\n(채널: 지니TV,\n상태: 성공, 광고ID,\n노출 스케줄 저장)
|
||||
|
||||
note over Service: Mock 결과:\n성공 (adId 생성)
|
||||
|
||||
@ -77,7 +77,7 @@ par 우리동네TV 배포
|
||||
|
||||
note over Service: 배포 요청 검증\n- imageUrl 형식\n- caption 길이\n- hashtags 유효성
|
||||
|
||||
Service -> DB: 배포 채널 로그 저장\nINSERT distribution_channel_logs\n{channel: Instagram,\nstatus: SUCCESS,\npostUrl: generated_url,\npostId: generated_uuid}
|
||||
Service -> DB: 배포 채널 로그 저장\n(채널: Instagram,\n상태: 성공,\n포스트 URL/ID 저장)
|
||||
|
||||
note over Service: Mock 결과:\n성공 (postUrl, postId 생성)
|
||||
|
||||
@ -90,7 +90,7 @@ par 우리동네TV 배포
|
||||
|
||||
note over Service: 배포 요청 검증\n- imageUrl 형식\n- content 길이
|
||||
|
||||
Service -> DB: 배포 채널 로그 저장\nINSERT distribution_channel_logs\n{channel: NaverBlog,\nstatus: SUCCESS,\npostUrl: generated_url}
|
||||
Service -> DB: 배포 채널 로그 저장\n(채널: NaverBlog,\n상태: 성공,\n포스트 URL 저장)
|
||||
|
||||
note over Service: Mock 결과:\n성공 (postUrl 생성)
|
||||
|
||||
@ -103,7 +103,7 @@ par 우리동네TV 배포
|
||||
|
||||
note over Service: 배포 요청 검증\n- imageUrl 형식\n- message 길이
|
||||
|
||||
Service -> DB: 배포 채널 로그 저장\nINSERT distribution_channel_logs\n{channel: KakaoChannel,\nstatus: SUCCESS,\nmessageId: generated_uuid}
|
||||
Service -> DB: 배포 채널 로그 저장\n(채널: KakaoChannel,\n상태: 성공,\n메시지 ID 저장)
|
||||
|
||||
note over Service: Mock 결과:\n성공 (messageId 생성)
|
||||
|
||||
@ -118,7 +118,7 @@ Service -> Service: 채널별 배포 결과 집계\n성공: [선택된 모든
|
||||
|
||||
note over Service: Sprint 2에서는\n모든 채널 배포가 성공으로 처리됨
|
||||
|
||||
Service -> DB: UPDATE distribution_logs\nSET status = 'COMPLETED',\ncompleted_at = NOW()
|
||||
Service -> DB: 배포 이력 상태 업데이트\n(상태를 COMPLETED로,\n완료일시를 현재 시각으로 설정)
|
||||
|
||||
== Kafka 이벤트 발행 ==
|
||||
Service -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, channels[], results[], completedAt}
|
||||
|
||||
@ -17,7 +17,7 @@ activate Service
|
||||
|
||||
Service -> Repo: findById(eventDraftId)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT * FROM event_drafts\nWHERE id = ? AND user_id = ?
|
||||
Repo -> DB: 이벤트 초안 조회\n(초안ID와 사용자ID로 조회)
|
||||
activate DB
|
||||
DB --> Repo: EventDraft
|
||||
deactivate DB
|
||||
|
||||
@ -28,7 +28,7 @@ else 캐시 미스
|
||||
group parallel
|
||||
Service -> Repo: findTopByStatusAndUserId(ACTIVE, userId, limit=5)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT e.*, COUNT(p.id) as participant_count\nFROM events e\nLEFT JOIN participants p ON e.id = p.event_id\nWHERE e.user_id = ?\nAND e.status = 'ACTIVE'\nGROUP BY e.id\nORDER BY e.created_at DESC\nLIMIT 5
|
||||
Repo -> DB: 진행중 이벤트 목록 조회\n(사용자ID로 ACTIVE 상태 이벤트 조회,\n참여자 수 함께 조회,\n생성일 내림차순, 최대 5개)
|
||||
activate DB
|
||||
DB --> Repo: Active events
|
||||
deactivate DB
|
||||
@ -37,7 +37,7 @@ else 캐시 미스
|
||||
|
||||
Service -> Repo: findTopByStatusAndUserId(APPROVED, userId, limit=5)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT e.*\nFROM events e\nWHERE e.user_id = ?\nAND e.status = 'APPROVED'\nORDER BY e.approved_at DESC\nLIMIT 5
|
||||
Repo -> DB: 예정 이벤트 목록 조회\n(사용자ID로 APPROVED 상태 이벤트 조회,\n승인일 내림차순, 최대 5개)
|
||||
activate DB
|
||||
DB --> Repo: Approved events
|
||||
deactivate DB
|
||||
@ -46,7 +46,7 @@ else 캐시 미스
|
||||
|
||||
Service -> Repo: findTopByStatusAndUserId(COMPLETED, userId, limit=5)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT e.*, COUNT(p.id) as participant_count\nFROM events e\nLEFT JOIN participants p ON e.id = p.event_id\nWHERE e.user_id = ?\nAND e.status = 'COMPLETED'\nGROUP BY e.id\nORDER BY e.completed_at DESC\nLIMIT 5
|
||||
Repo -> DB: 종료 이벤트 목록 조회\n(사용자ID로 COMPLETED 상태 이벤트 조회,\n참여자 수 함께 조회,\n종료일 내림차순, 최대 5개)
|
||||
activate DB
|
||||
DB --> Repo: Completed events
|
||||
deactivate DB
|
||||
|
||||
@ -9,56 +9,56 @@ participant "EventRepository" as Repo <<R>>
|
||||
participant "Redis Cache" as Cache <<E>>
|
||||
database "Event DB" as DB <<E>>
|
||||
|
||||
note over Controller: GET /api/events?status={status}&keyword={keyword}\n&page={page}&size={size}
|
||||
Controller -> Service: getEventList(userId, filters, pagination)
|
||||
note over Controller: GET /api/events?status={상태}&keyword={검색어}\n&page={페이지}&size={크기}
|
||||
Controller -> Service: 이벤트 목록 조회(사용자ID, 필터, 페이징)
|
||||
activate Service
|
||||
|
||||
Service -> Cache: get("events:" + userId + ":" + filters + ":" + page)
|
||||
Service -> Cache: 캐시 조회("events:" + 사용자ID + ":" + 필터 + ":" + 페이지)
|
||||
activate Cache
|
||||
|
||||
alt 캐시 히트
|
||||
Cache --> Service: Event list data
|
||||
Service --> Controller: EventListResponse
|
||||
Cache --> Service: 이벤트 목록 데이터
|
||||
Service --> Controller: 이벤트 목록 응답
|
||||
|
||||
else 캐시 미스
|
||||
Cache --> Service: null
|
||||
deactivate Cache
|
||||
|
||||
Service -> Repo: findByUserIdWithFilters(userId, filters, pagination)
|
||||
Service -> Repo: 사용자별 필터링 이벤트 조회(사용자ID, 필터, 페이징)
|
||||
activate Repo
|
||||
|
||||
alt 필터 있음 (상태별)
|
||||
Repo -> DB: SELECT e.*, COUNT(p.id) as participant_count\nFROM events e\nLEFT JOIN participants p ON e.id = p.event_id\nWHERE e.user_id = ?\nAND e.status = ?\nGROUP BY e.id\nORDER BY e.created_at DESC\nLIMIT ? OFFSET ?
|
||||
Repo -> DB: 사용자별 특정 상태 이벤트 조회\n(참여자 수 포함, 생성일 기준 내림차순,\n페이징 적용)
|
||||
else 검색 있음 (키워드)
|
||||
Repo -> DB: SELECT e.*, COUNT(p.id) as participant_count\nFROM events e\nLEFT JOIN participants p ON e.id = p.event_id\nWHERE e.user_id = ?\nAND (e.title LIKE ? OR e.description LIKE ?)\nGROUP BY e.id\nORDER BY e.created_at DESC\nLIMIT ? OFFSET ?
|
||||
Repo -> DB: 사용자별 이벤트 키워드 검색\n(제목/설명에서 검색, 참여자 수 포함,\n생성일 기준 내림차순, 페이징 적용)
|
||||
else 필터 없음 (전체)
|
||||
Repo -> DB: SELECT e.*, COUNT(p.id) as participant_count\nFROM events e\nLEFT JOIN participants p ON e.id = p.event_id\nWHERE e.user_id = ?\nGROUP BY e.id\nORDER BY e.created_at DESC\nLIMIT ? OFFSET ?
|
||||
Repo -> DB: 사용자별 전체 이벤트 목록 조회\n(참여자 수 포함, 생성일 기준 내림차순,\n페이징 적용)
|
||||
end
|
||||
|
||||
activate DB
|
||||
note right: 인덱스 활용:\n- user_id\n- status\n- created_at
|
||||
DB --> Repo: Event list with participant count
|
||||
note right: 인덱스 활용:\n- 사용자ID\n- 상태\n- 생성일시
|
||||
DB --> Repo: 이벤트 목록 및 참여자 수
|
||||
deactivate DB
|
||||
|
||||
Repo -> DB: SELECT COUNT(*) FROM events\nWHERE user_id = ? [AND filters]
|
||||
Repo -> DB: 전체 이벤트 개수 조회\n(필터 조건 포함, 페이징용)
|
||||
activate DB
|
||||
DB --> Repo: totalCount
|
||||
DB --> Repo: 전체 개수
|
||||
deactivate DB
|
||||
|
||||
Repo --> Service: PagedResult<Event>
|
||||
Repo --> Service: 페이징된 이벤트 결과
|
||||
deactivate Repo
|
||||
|
||||
Service -> Cache: set("events:" + userId + ":" + filters + ":" + page,\npagedResult, TTL=1분)
|
||||
Service -> Cache: 캐시 저장("events:" + 사용자ID + ":" + 필터 + ":" + 페이지,\n페이징결과, TTL=1분)
|
||||
activate Cache
|
||||
Cache --> Service: OK
|
||||
deactivate Cache
|
||||
end
|
||||
|
||||
Service --> Controller: EventListResponse\n{events: [...], totalCount,\ntotalPages, currentPage}
|
||||
Service --> Controller: 이벤트 목록 응답\n{이벤트목록: [...], 전체개수,\n전체페이지수, 현재페이지}
|
||||
deactivate Service
|
||||
|
||||
Controller --> Client: 200 OK\n{events: [\n {eventId, title, period, status,\n participantCount, roi, createdAt},\n ...\n],\ntotalCount, totalPages, currentPage}
|
||||
Controller --> Client: 200 OK\n{이벤트목록: [\n {이벤트ID, 제목, 기간, 상태,\n 참여자수, ROI, 생성일시},\n ...\n],\n전체개수, 전체페이지수, 현재페이지}
|
||||
|
||||
note over Controller, DB: 필터 옵션:\n- status: DRAFT, ACTIVE, COMPLETED\n- 기간: 최근 1개월/3개월/6개월/1년\n- 정렬: 최신순, 참여자 많은 순,\n ROI 높은 순\n\n페이지네이션:\n- 기본 20개/페이지\n- 페이지 번호 기반
|
||||
note over Controller, DB: 필터 옵션:\n- 상태: 임시저장, 진행중, 완료\n- 기간: 최근 1개월/3개월/6개월/1년\n- 정렬: 최신순, 참여자 많은 순,\n ROI 높은 순\n\n페이지네이션:\n- 기본 20개/페이지\n- 페이지 번호 기반
|
||||
|
||||
@enduml
|
||||
|
||||
@ -24,7 +24,7 @@ note right: 목적 유효성 검증\n- 신규 고객 유치\n- 재방문 유도\
|
||||
|
||||
Service -> Repo: save(eventDraft)
|
||||
activate Repo
|
||||
Repo -> DB: INSERT INTO event_drafts\n(user_id, objective, store_info, status)
|
||||
Repo -> DB: 이벤트 초안 저장\n(사용자ID, 목적, 매장정보,\n상태를 저장)
|
||||
activate DB
|
||||
DB --> Repo: eventDraftId
|
||||
deactivate DB
|
||||
|
||||
@ -28,7 +28,7 @@ else 캐시 미스
|
||||
|
||||
Service -> Repo: findById(eventId)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT e.*, p.*, d.*\nFROM events e\nLEFT JOIN event_prizes p ON e.id = p.event_id\nLEFT JOIN distribution_logs d ON e.id = d.event_id\nWHERE e.id = ?
|
||||
Repo -> DB: 이벤트 상세 정보 조회\n(이벤트ID로 이벤트 정보,\n경품 정보, 배포 이력을\nJOIN하여 함께 조회)
|
||||
activate DB
|
||||
note right: JOIN으로\n경품 정보 및\n배포 이력 조회
|
||||
DB --> Repo: Event with prizes and distributions
|
||||
|
||||
@ -17,7 +17,7 @@ activate Service
|
||||
|
||||
Service -> Repo: findById(eventDraftId)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT * FROM event_drafts\nWHERE id = ? AND user_id = ?
|
||||
Repo -> DB: 이벤트 초안 조회\n(초안ID와 사용자ID로 조회)
|
||||
activate DB
|
||||
DB --> Repo: EventDraft
|
||||
deactivate DB
|
||||
|
||||
@ -17,7 +17,7 @@ activate Service
|
||||
|
||||
Service -> Repo: findById(eventDraftId)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT * FROM event_drafts\nWHERE id = ? AND user_id = ?
|
||||
Repo -> DB: 이벤트 초안 조회\n(초안ID와 사용자ID로 조회)
|
||||
activate DB
|
||||
DB --> Repo: EventDraft
|
||||
deactivate DB
|
||||
@ -30,7 +30,7 @@ note right: 발행 준비 검증:\n- 목적 선택 완료\n- AI 추천 선택
|
||||
|
||||
Service -> Repo: updateStatus(eventDraftId, APPROVED)
|
||||
activate Repo
|
||||
Repo -> DB: UPDATE event_drafts SET\nstatus = 'APPROVED',\napproved_at = NOW()\nWHERE id = ?
|
||||
Repo -> DB: 이벤트 초안 상태 업데이트\n(상태를 APPROVED로,\n승인일시를 현재 시각으로 설정)
|
||||
activate DB
|
||||
DB --> Repo: OK
|
||||
deactivate DB
|
||||
@ -53,7 +53,7 @@ deactivate DistSvc
|
||||
|
||||
Service -> Repo: updateStatus(eventDraftId, ACTIVE)
|
||||
activate Repo
|
||||
Repo -> DB: UPDATE event_drafts SET\nstatus = 'ACTIVE',\npublished_at = NOW()\nWHERE id = ?
|
||||
Repo -> DB: 이벤트 상태 업데이트\n(상태를 ACTIVE로,\n배포일시를 현재 시각으로 설정)
|
||||
activate DB
|
||||
DB --> Repo: OK
|
||||
deactivate DB
|
||||
|
||||
@ -15,7 +15,7 @@ activate Service
|
||||
|
||||
Service -> Repo: findById(eventDraftId)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT * FROM event_drafts\nWHERE id = ? AND user_id = ?
|
||||
Repo -> DB: 이벤트 초안 조회\n(초안ID와 사용자ID로 조회)
|
||||
activate DB
|
||||
DB --> Repo: EventDraft
|
||||
deactivate DB
|
||||
@ -31,7 +31,7 @@ note right: 편집 내용 적용:\n- 텍스트 수정\n- 색상 변경
|
||||
|
||||
Service -> Repo: update(eventDraft)
|
||||
activate Repo
|
||||
Repo -> DB: UPDATE event_drafts SET\nselected_image_url = ?,\nedited_title = ?,\nedited_text = ?,\nbackground_color = ?,\ntext_color = ?,\nupdated_at = NOW()\nWHERE id = ?
|
||||
Repo -> DB: 이벤트 초안 업데이트\n(선택된 이미지 URL,\n편집된 제목/텍스트,\n배경색/텍스트색,\n수정일시를 업데이트)
|
||||
activate DB
|
||||
DB --> Repo: OK
|
||||
deactivate DB
|
||||
|
||||
@ -43,7 +43,7 @@ else JWT 검증 성공
|
||||
|
||||
Service -> LogRepo: findByEventId(eventId)
|
||||
activate LogRepo
|
||||
LogRepo -> DB: SELECT * FROM draw_logs\nWHERE event_id = ?
|
||||
LogRepo -> DB: 추첨 로그 조회\n(이벤트ID로 조회)
|
||||
activate DB
|
||||
DB --> LogRepo: 추첨 로그 조회
|
||||
deactivate DB
|
||||
@ -61,7 +61,7 @@ else JWT 검증 성공
|
||||
|
||||
Service -> Repo: findAllByEventIdAndIsWinner(eventId, false)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT * FROM participants\nWHERE event_id = ?\nAND is_winner = false\nORDER BY participated_at ASC
|
||||
Repo -> DB: 미당첨 참여자 목록 조회\n(이벤트ID로 당첨되지 않은\n참여자 전체 조회,\n참여일시 오름차순 정렬)
|
||||
activate DB
|
||||
DB --> Repo: 전체 참여자 목록
|
||||
deactivate DB
|
||||
@ -119,7 +119,7 @@ else JWT 검증 성공
|
||||
|
||||
Service -> Repo: updateWinners(winnerIds)
|
||||
activate Repo
|
||||
Repo -> DB: UPDATE participants\nSET is_winner = true,\nwon_at = NOW()\nWHERE participant_id IN (?)
|
||||
Repo -> DB: 당첨자 정보 업데이트\n(당첨 여부를 true로,\n당첨 일시를 현재 시각으로 설정,\n대상: 선정된 참여자ID 목록)
|
||||
activate DB
|
||||
DB --> Repo: 업데이트 완료
|
||||
deactivate DB
|
||||
@ -130,7 +130,7 @@ else JWT 검증 성공
|
||||
|
||||
Service -> LogRepo: save(drawLog)
|
||||
activate LogRepo
|
||||
LogRepo -> DB: INSERT INTO draw_logs\n(draw_log_id, event_id, draw_method,\nalgorithm, visit_bonus_applied,\nwinner_count, drawn_at)
|
||||
LogRepo -> DB: 추첨 로그 저장\n(추첨로그ID, 이벤트ID,\n추첨방법, 알고리즘,\n가산점적용여부, 당첨인원,\n추첨일시 저장)
|
||||
activate DB
|
||||
note right of DB
|
||||
추첨 로그 저장:
|
||||
|
||||
@ -53,7 +53,7 @@ else 유효성 검증 성공
|
||||
|
||||
Service -> Repo: findByEventIdAndPhoneNumber(eventId, phone)
|
||||
activate Repo
|
||||
Repo -> DB: SELECT * FROM participants\nWHERE event_id = ? AND phone_number = ?
|
||||
Repo -> DB: 참여자 중복 확인\n(이벤트ID, 전화번호로 조회)
|
||||
activate DB
|
||||
DB --> Repo: 조회 결과
|
||||
deactivate DB
|
||||
@ -80,7 +80,7 @@ else 유효성 검증 성공
|
||||
|
||||
Service -> Repo: save(participant)
|
||||
activate Repo
|
||||
Repo -> DB: INSERT INTO participants\n(participant_id, event_id, name, phone_number,\nentry_path, application_number, participated_at,\nconsent_marketing)
|
||||
Repo -> DB: 참여자 정보 저장\n(참여자ID, 이벤트ID, 이름, 전화번호,\n참여경로, 응모번호, 참여일시,\n마케팅동의여부)
|
||||
activate DB
|
||||
DB --> Repo: 저장 완료
|
||||
deactivate DB
|
||||
|
||||
@ -64,7 +64,7 @@ else JWT 검증 성공
|
||||
Service -> Repo: findParticipants(eventId, filters, pageable)
|
||||
activate Repo
|
||||
|
||||
Repo -> DB: SELECT p.participant_id, p.name,\np.phone_number, p.entry_path,\np.application_number, p.participated_at,\np.is_winner\nFROM participants p\nWHERE p.event_id = ?\n[AND p.entry_path = ?]\n[AND p.is_winner = ?]\n[AND (p.name LIKE ? OR p.phone_number LIKE ?)]\nORDER BY p.participated_at DESC\nLIMIT ? OFFSET ?
|
||||
Repo -> DB: 참여자 목록 조회\n(이벤트ID, 참여경로, 당첨여부,\n이름/전화번호 검색조건으로 필터링하여\n참여일시 내림차순으로 페이징 조회)
|
||||
activate DB
|
||||
|
||||
note right of DB
|
||||
@ -82,7 +82,7 @@ else JWT 검증 성공
|
||||
DB --> Repo: 참여자 목록 결과셋
|
||||
deactivate DB
|
||||
|
||||
Repo -> DB: SELECT COUNT(*)\nFROM participants\nWHERE event_id = ?\n[필터 조건 동일]
|
||||
Repo -> DB: 전체 참여자 수 조회\n(동일한 필터 조건 적용)
|
||||
activate DB
|
||||
DB --> Repo: 전체 건수
|
||||
deactivate DB
|
||||
|
||||
@ -44,7 +44,7 @@ else JWT 토큰 유효
|
||||
|
||||
== 2단계: Redis 세션 삭제 ==
|
||||
|
||||
AuthService -> Redis: DEL user:session:{token}
|
||||
AuthService -> Redis: 세션 삭제\n(캐시키: user:session:{token})
|
||||
activate Redis
|
||||
Redis --> AuthService: 삭제된 키 개수 (0 또는 1)
|
||||
deactivate Redis
|
||||
@ -87,7 +87,7 @@ else JWT 토큰 유효
|
||||
deactivate JwtProvider
|
||||
|
||||
alt 남은 만료 시간 > 0
|
||||
AuthService -> Redis: SET jwt:blacklist:{token}\n"revoked" (TTL: remainingSeconds)
|
||||
AuthService -> Redis: 블랙리스트에 토큰 추가\n(캐시키: jwt:blacklist:{token},\n값: "revoked", TTL: 남은초)
|
||||
activate Redis
|
||||
Redis --> AuthService: Blacklist 추가 완료
|
||||
deactivate Redis
|
||||
|
||||
@ -36,7 +36,7 @@ AuthService -> Service: findByPhoneNumber(phoneNumber)
|
||||
activate Service
|
||||
Service -> UserRepo: findByPhoneNumber(phoneNumber)
|
||||
activate UserRepo
|
||||
UserRepo -> UserDB: SELECT user_id, password_hash,\nrole, name, email\nFROM users\nWHERE phone_number = ?
|
||||
UserRepo -> UserDB: 전화번호로 사용자 조회\n(사용자ID, 비밀번호해시, 역할,\n이름, 이메일 조회)
|
||||
activate UserDB
|
||||
UserDB --> UserRepo: 사용자 정보 또는 NULL
|
||||
deactivate UserDB
|
||||
@ -96,7 +96,7 @@ else 사용자 존재
|
||||
end note
|
||||
Service ->> UserRepo: updateLastLoginAt(userId)
|
||||
activate UserRepo
|
||||
UserRepo ->> UserDB: UPDATE users\nSET last_login_at = NOW()\nWHERE user_id = ?
|
||||
UserRepo ->> UserDB: 최종 로그인 시각 업데이트\n(현재 시각으로 갱신)
|
||||
activate UserDB
|
||||
UserDB -->> UserRepo: 업데이트 완료
|
||||
deactivate UserDB
|
||||
|
||||
@ -34,7 +34,7 @@ activate Service
|
||||
|
||||
Service -> UserRepo: findById(userId)
|
||||
activate UserRepo
|
||||
UserRepo -> UserDB: SELECT * FROM users\nWHERE user_id = ?
|
||||
UserRepo -> UserDB: 사용자ID로 사용자 조회\n(사용자 정보 조회)
|
||||
activate UserDB
|
||||
UserDB --> UserRepo: 사용자 정보
|
||||
deactivate UserDB
|
||||
@ -109,7 +109,7 @@ else 사용자 존재
|
||||
|
||||
Service -> StoreRepo: findByUserId(userId)
|
||||
activate StoreRepo
|
||||
StoreRepo -> UserDB: SELECT * FROM stores\nWHERE user_id = ?
|
||||
StoreRepo -> UserDB: 사용자ID로 매장 조회\n(매장 정보 조회)
|
||||
activate UserDB
|
||||
UserDB --> StoreRepo: 매장 정보
|
||||
deactivate UserDB
|
||||
@ -134,7 +134,7 @@ else 사용자 존재
|
||||
|
||||
== 5단계: 데이터베이스 트랜잭션 ==
|
||||
|
||||
Service -> UserDB: BEGIN TRANSACTION
|
||||
Service -> UserDB: 트랜잭션 시작
|
||||
activate UserDB
|
||||
|
||||
note right of Service
|
||||
@ -146,7 +146,7 @@ else 사용자 존재
|
||||
|
||||
Service -> UserRepo: save(user)
|
||||
activate UserRepo
|
||||
UserRepo -> UserDB: UPDATE users\nSET name = ?, phone_number = ?,\nemail = ?, password_hash = ?,\nupdated_at = NOW(),\nversion = version + 1\nWHERE user_id = ? AND version = ?
|
||||
UserRepo -> UserDB: 사용자 정보 업데이트\n(이름, 전화번호, 이메일,\n비밀번호해시, 수정일시,\n버전 증가)\nOptimistic Lock 적용
|
||||
UserDB --> UserRepo: 업데이트 완료 (1 row affected)
|
||||
UserRepo --> Service: User 엔티티
|
||||
deactivate UserRepo
|
||||
@ -155,7 +155,7 @@ else 사용자 존재
|
||||
UserRepo --> Service: throw OptimisticLockException
|
||||
Service --> Controller: throw ConcurrentModificationException\n("다른 사용자가 수정 중입니다")
|
||||
Controller --> Client: 409 Conflict\n{"code": "USER_005",\n"error": "다른 세션에서 프로필을\n수정했습니다.\n새로고침 후 다시 시도하세요"}
|
||||
Service -> UserDB: ROLLBACK TRANSACTION
|
||||
Service -> UserDB: 트랜잭션 롤백
|
||||
deactivate UserDB
|
||||
deactivate Service
|
||||
deactivate Controller
|
||||
@ -163,12 +163,12 @@ else 사용자 존재
|
||||
|
||||
Service -> StoreRepo: save(store)
|
||||
activate StoreRepo
|
||||
StoreRepo -> UserDB: UPDATE stores\nSET store_name = ?, industry = ?,\naddress = ?, business_hours = ?,\nupdated_at = NOW(),\nversion = version + 1\nWHERE store_id = ? AND version = ?
|
||||
StoreRepo -> UserDB: 매장 정보 업데이트\n(매장명, 업종, 주소,\n영업시간, 수정일시,\n버전 증가)\nOptimistic Lock 적용
|
||||
UserDB --> StoreRepo: 업데이트 완료 (1 row affected)
|
||||
StoreRepo --> Service: Store 엔티티
|
||||
deactivate StoreRepo
|
||||
|
||||
Service -> UserDB: COMMIT TRANSACTION
|
||||
Service -> UserDB: 트랜잭션 커밋
|
||||
UserDB --> Service: 트랜잭션 커밋 완료
|
||||
deactivate UserDB
|
||||
end
|
||||
@ -182,7 +182,7 @@ else 사용자 존재
|
||||
end note
|
||||
|
||||
alt 프로필 캐시 사용 중
|
||||
Service -> Redis: DEL user:profile:{userId}
|
||||
Service -> Redis: 프로필 캐시 삭제\n(캐시키: user:profile:{userId})
|
||||
activate Redis
|
||||
Redis --> Service: 캐시 삭제 완료
|
||||
deactivate Redis
|
||||
|
||||
@ -36,7 +36,7 @@ activate Service
|
||||
|
||||
Service -> UserRepo: findByPhoneNumber(phoneNumber)
|
||||
activate UserRepo
|
||||
UserRepo -> UserDB: SELECT * FROM users\nWHERE phone_number = ?
|
||||
UserRepo -> UserDB: 전화번호로 사용자 조회\n(중복 가입 확인)
|
||||
activate UserDB
|
||||
UserDB --> UserRepo: 조회 결과
|
||||
deactivate UserDB
|
||||
@ -132,24 +132,24 @@ else 신규 사용자
|
||||
|
||||
== 5단계: 데이터베이스 트랜잭션 ==
|
||||
|
||||
Service -> UserDB: BEGIN TRANSACTION
|
||||
Service -> UserDB: 트랜잭션 시작
|
||||
activate UserDB
|
||||
|
||||
Service -> UserRepo: save(User)\n(name, phoneNumber, email,\npasswordHash, createdAt)
|
||||
activate UserRepo
|
||||
UserRepo -> UserDB: INSERT INTO users\n(name, phone_number, email,\npassword_hash, created_at)\nRETURNING user_id
|
||||
UserRepo -> UserDB: 사용자 정보 저장\n(이름, 전화번호, 이메일,\n비밀번호해시, 생성일시)\n사용자ID 반환
|
||||
UserDB --> UserRepo: user_id
|
||||
UserRepo --> Service: User 엔티티\n(userId 포함)
|
||||
deactivate UserRepo
|
||||
|
||||
Service -> StoreRepo: save(Store)\n(userId, storeName, industry,\naddress, businessNumberEncrypted,\nbusinessHours)
|
||||
activate StoreRepo
|
||||
StoreRepo -> UserDB: INSERT INTO stores\n(user_id, store_name, industry,\naddress, business_number_encrypted,\nbusiness_hours)\nRETURNING store_id
|
||||
StoreRepo -> UserDB: 매장 정보 저장\n(사용자ID, 매장명, 업종,\n주소, 암호화된사업자번호,\n영업시간)\n매장ID 반환
|
||||
UserDB --> StoreRepo: store_id
|
||||
StoreRepo --> Service: Store 엔티티\n(storeId 포함)
|
||||
deactivate StoreRepo
|
||||
|
||||
Service -> UserDB: COMMIT TRANSACTION
|
||||
Service -> UserDB: 트랜잭션 커밋
|
||||
UserDB --> Service: 트랜잭션 커밋 완료
|
||||
deactivate UserDB
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ activate Gateway
|
||||
Gateway -> PartService: POST /participations/register\n{이름, 전화번호, 참여경로, 개인정보동의}
|
||||
activate PartService
|
||||
|
||||
PartService -> PartDB: SELECT * FROM participants\nWHERE phone_number = ? AND event_id = ?
|
||||
PartService -> PartDB: 참여자 중복 확인\n(전화번호, 이벤트ID로 조회)
|
||||
activate PartDB
|
||||
PartDB --> PartService: 중복 참여 여부 반환
|
||||
deactivate PartDB
|
||||
@ -45,7 +45,7 @@ alt 중복 참여인 경우
|
||||
else 신규 참여인 경우
|
||||
PartService -> PartService: 응모 번호 생성\n(UUID 또는 시퀀스 기반)
|
||||
|
||||
PartService -> PartDB: INSERT INTO participants\n(name, phone_number, entry_path,\napplication_number, participated_at)
|
||||
PartService -> PartDB: 참여자 정보 저장\n(이름, 전화번호, 참여경로,\n응모번호, 참여일시)
|
||||
activate PartDB
|
||||
PartDB --> PartService: 저장 완료
|
||||
deactivate PartDB
|
||||
@ -94,19 +94,19 @@ activate Gateway
|
||||
Gateway -> PartService: POST /events/{eventId}/draw-winners\n{winnerCount, visitBonus}
|
||||
activate PartService
|
||||
|
||||
PartService -> PartDB: SELECT * FROM participants\nWHERE event_id = ? AND is_winner = false
|
||||
PartService -> PartDB: 미당첨 참여자 목록 조회\n(이벤트ID로 당첨되지 않은 참여자 조회)
|
||||
activate PartDB
|
||||
PartDB --> PartService: 전체 참여자 목록 반환
|
||||
deactivate PartDB
|
||||
|
||||
PartService -> PartService: 당첨자 추첨 알고리즘 실행\n1. 난수 생성 (Crypto.randomBytes)\n2. 매장방문 가산점 적용 (옵션)\n3. Fisher-Yates Shuffle\n4. 당첨인원만큼 선정
|
||||
|
||||
PartService -> PartDB: UPDATE participants\nSET is_winner = true, won_at = NOW()\nWHERE participant_id IN (당첨자IDs)
|
||||
PartService -> PartDB: 당첨자 정보 업데이트\n(당첨 여부를 true로 설정, 당첨 일시 기록)
|
||||
activate PartDB
|
||||
PartDB --> PartService: 업데이트 완료
|
||||
deactivate PartDB
|
||||
|
||||
PartService -> PartDB: INSERT INTO draw_logs\n(event_id, draw_method, winner_count,\nalgorithm, drawn_at)
|
||||
PartService -> PartDB: 추첨 로그 저장\n(이벤트ID, 추첨방법, 당첨인원,\n알고리즘, 추첨일시)
|
||||
activate PartDB
|
||||
note right of PartDB
|
||||
추첨 로그 저장:
|
||||
|
||||
@ -27,7 +27,7 @@ activate UserService
|
||||
|
||||
UserService -> UserService: 서버 측 유효성 검증\n(이름 2자 이상, 전화번호 형식 등)
|
||||
|
||||
UserService -> UserDB: SELECT users\nWHERE phone_number = ?
|
||||
UserService -> UserDB: 전화번호로 사용자 조회\n(중복 가입 확인)
|
||||
activate UserDB
|
||||
UserDB --> UserService: 기존 사용자 확인 결과
|
||||
deactivate UserDB
|
||||
@ -42,16 +42,16 @@ else 신규 사용자
|
||||
|
||||
UserService -> UserService: 사업자번호 암호화\n(AES-256)
|
||||
|
||||
UserService -> UserDB: BEGIN TRANSACTION
|
||||
UserService -> UserDB: 트랜잭션 시작
|
||||
activate UserDB
|
||||
|
||||
UserService -> UserDB: INSERT INTO users\n(name, phone_number, email,\npassword_hash, created_at)
|
||||
UserService -> UserDB: 사용자 정보 저장\n(이름, 전화번호, 이메일,\n비밀번호해시, 생성일시)
|
||||
UserDB --> UserService: user_id 반환
|
||||
|
||||
UserService -> UserDB: INSERT INTO stores\n(user_id, store_name, industry,\naddress, business_number_encrypted,\nbusiness_hours)
|
||||
UserService -> UserDB: 매장 정보 저장\n(사용자ID, 매장명, 업종,\n주소, 암호화된사업자번호,\n영업시간)
|
||||
UserDB --> UserService: store_id 반환
|
||||
|
||||
UserService -> UserDB: COMMIT TRANSACTION
|
||||
UserService -> UserDB: 트랜잭션 커밋
|
||||
deactivate UserDB
|
||||
|
||||
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)
|
||||
@ -87,7 +87,7 @@ Gateway -> Gateway: Request 검증
|
||||
Gateway -> UserService: POST /api/users/login\n(전화번호, 비밀번호)
|
||||
activate UserService
|
||||
|
||||
UserService -> UserDB: SELECT users\nWHERE phone_number = ?
|
||||
UserService -> UserDB: 전화번호로 사용자 조회\n(로그인 인증용)
|
||||
activate UserDB
|
||||
UserDB --> UserService: 사용자 정보\n(user_id, password_hash, role)
|
||||
deactivate UserDB
|
||||
@ -108,7 +108,7 @@ else 사용자 존재
|
||||
|
||||
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)
|
||||
|
||||
UserService -> UserDB: UPDATE users\nSET last_login_at = NOW()\nWHERE user_id = ?
|
||||
UserService -> UserDB: 최종 로그인 시각 업데이트\n(현재 시각으로 갱신)
|
||||
activate UserDB
|
||||
UserDB --> UserService: 업데이트 완료
|
||||
deactivate UserDB
|
||||
|
||||
@ -30,7 +30,7 @@ GW -> GW: JWT 토큰 검증
|
||||
GW -> Analytics: GET /api/events/{id}/analytics
|
||||
activate Analytics
|
||||
|
||||
Analytics -> Redis: GET analytics:dashboard:{eventId}
|
||||
Analytics -> Redis: 대시보드 캐시 조회\n(캐시키: analytics:dashboard:{eventId})
|
||||
activate Redis
|
||||
Redis --> Analytics: **Cache HIT**\n캐시된 대시보드 데이터 반환
|
||||
deactivate Redis
|
||||
@ -64,7 +64,7 @@ activate GW
|
||||
GW -> Analytics: GET /api/events/{id}/analytics
|
||||
activate Analytics
|
||||
|
||||
Analytics -> Redis: GET analytics:dashboard:{eventId}
|
||||
Analytics -> Redis: 대시보드 캐시 조회\n(캐시키: analytics:dashboard:{eventId})
|
||||
activate Redis
|
||||
Redis --> Analytics: **Cache MISS**\nnull 반환
|
||||
deactivate Redis
|
||||
@ -79,7 +79,7 @@ end note
|
||||
|||
|
||||
== 2.1. Analytics DB 조회 (로컬 데이터) ==
|
||||
|
||||
Analytics -> AnalyticsDB: SELECT event_stats\nWHERE event_id = {id}
|
||||
Analytics -> AnalyticsDB: 이벤트 통계 조회\n(이벤트ID로 통계 데이터 조회)
|
||||
activate AnalyticsDB
|
||||
AnalyticsDB --> Analytics: 이벤트 통계\n- 총 참여자 수\n- 예상 ROI\n- 매출 증가율
|
||||
deactivate AnalyticsDB
|
||||
@ -87,7 +87,7 @@ deactivate AnalyticsDB
|
||||
|||
|
||||
== 2.2. 배치 수집된 채널 통계 데이터 조회 ==
|
||||
|
||||
Analytics -> AnalyticsDB: SELECT channel_stats\nWHERE event_id = {id}
|
||||
Analytics -> AnalyticsDB: 채널별 통계 조회\n(배치로 수집된 채널 데이터 조회)
|
||||
activate AnalyticsDB
|
||||
|
||||
note right of Analytics
|
||||
@ -123,7 +123,7 @@ end note
|
||||
|||
|
||||
== 2.4. Redis 캐싱 및 응답 ==
|
||||
|
||||
Analytics -> Redis: SET analytics:dashboard:{eventId}\nvalue={통합 데이터}\nTTL=300초 (5분)
|
||||
Analytics -> Redis: 대시보드 데이터 캐시 저장\n(캐시키: analytics:dashboard:{eventId},\n값: 통합 데이터, TTL: 5분)
|
||||
activate Redis
|
||||
Redis --> Analytics: OK
|
||||
deactivate Redis
|
||||
@ -149,11 +149,11 @@ end note
|
||||
|
||||
Kafka -> Analytics: **EventCreated** 이벤트\n{eventId, storeId, title, objective}
|
||||
activate Analytics
|
||||
Analytics -> AnalyticsDB: INSERT INTO event_stats\n이벤트 기본 정보 초기화
|
||||
Analytics -> AnalyticsDB: 이벤트 통계 초기화\n(이벤트 기본 정보 저장)
|
||||
activate AnalyticsDB
|
||||
AnalyticsDB --> Analytics: OK
|
||||
deactivate AnalyticsDB
|
||||
Analytics -> Redis: DEL analytics:dashboard:{eventId}\n캐시 무효화
|
||||
Analytics -> Redis: 캐시 무효화\n(캐시키 삭제: analytics:dashboard:{eventId})
|
||||
activate Redis
|
||||
Redis --> Analytics: OK
|
||||
deactivate Redis
|
||||
@ -163,11 +163,11 @@ deactivate Analytics
|
||||
|
||||
Kafka -> Analytics: **ParticipantRegistered** 이벤트\n{participantId, eventId, phoneNumber}
|
||||
activate Analytics
|
||||
Analytics -> AnalyticsDB: UPDATE event_stats\nSET participant_count = participant_count + 1\nWHERE event_id = {eventId}
|
||||
Analytics -> AnalyticsDB: 참여자 수 업데이트\n(참여자 수 1 증가)
|
||||
activate AnalyticsDB
|
||||
AnalyticsDB --> Analytics: OK
|
||||
deactivate AnalyticsDB
|
||||
Analytics -> Redis: DEL analytics:dashboard:{eventId}\n캐시 무효화 (다음 조회 시 갱신)
|
||||
Analytics -> Redis: 캐시 무효화\n(캐시키 삭제: analytics:dashboard:{eventId})
|
||||
activate Redis
|
||||
Redis --> Analytics: OK
|
||||
deactivate Redis
|
||||
@ -177,11 +177,11 @@ deactivate Analytics
|
||||
|
||||
Kafka -> Analytics: **DistributionCompleted** 이벤트\n{eventId, distributedChannels, completedAt}
|
||||
activate Analytics
|
||||
Analytics -> AnalyticsDB: INSERT INTO channel_stats\n배포 채널 통계 저장
|
||||
Analytics -> AnalyticsDB: 채널 통계 저장\n(배포 완료된 채널 정보 저장)
|
||||
activate AnalyticsDB
|
||||
AnalyticsDB --> Analytics: OK
|
||||
deactivate AnalyticsDB
|
||||
Analytics -> Redis: DEL analytics:dashboard:{eventId}\n캐시 무효화
|
||||
Analytics -> Redis: 캐시 무효화\n(캐시키 삭제: analytics:dashboard:{eventId})
|
||||
activate Redis
|
||||
Redis --> Analytics: OK
|
||||
deactivate Redis
|
||||
|
||||
@ -20,7 +20,7 @@ participant "배포 채널 APIs" as ChannelApis
|
||||
User -> FE: 이벤트 목적 선택
|
||||
FE -> Gateway: POST /events/purposes\n{목적, 매장정보}
|
||||
Gateway -> Event: 이벤트 목적 저장 요청
|
||||
Event -> EventDB: 이벤트 목적 저장
|
||||
Event -> EventDB: 이벤트 목적 정보 저장\n(목적, 매장정보 저장)
|
||||
EventDB --> Event: 저장 완료
|
||||
Event --> Gateway: 저장 완료\n{eventDraftId}
|
||||
Gateway --> FE: 200 OK
|
||||
@ -38,20 +38,20 @@ FE --> User: "AI가 분석 중입니다..." (로딩)
|
||||
note over AI: Kafka Consumer\nai 이벤트 생성 topic 구독
|
||||
Kafka --> AI: Consume Job Message\n{jobId, eventDraftId, ...}
|
||||
|
||||
AI -> EventDB: 과거 이벤트 데이터 조회
|
||||
AI -> EventDB: 과거 이벤트 데이터 조회\n(업종, 지역 기반 통계 조회)
|
||||
EventDB --> AI: 이벤트 통계 데이터
|
||||
AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 과거데이터, 매장정보}
|
||||
AIApi --> AI: 3가지 추천안 + 트렌드 요약\n(예: "여름철 시원한 음료 선호도 증가")
|
||||
AI -> EventDB: 추천 결과 및 트렌드 요약 저장
|
||||
AI -> EventDB: 추천 결과 저장\n(3가지 추천안, 트렌드 요약 저장)
|
||||
EventDB --> AI: 저장 완료
|
||||
AI -> EventDB: Job 상태 업데이트\nstatus: COMPLETED
|
||||
AI -> EventDB: Job 상태 업데이트\n(상태를 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 -> EventDB: Job 상태 및 결과 조회
|
||||
Event -> EventDB: Job 상태 조회\n(jobId로 상태 및 결과 조회)
|
||||
EventDB --> Event: {status, result}
|
||||
|
||||
alt Job 완료
|
||||
@ -69,7 +69,7 @@ end
|
||||
User -> FE: 추천안 선택\n(제목/경품 커스텀)
|
||||
FE -> Gateway: PUT /events/drafts/{eventDraftId}\n{선택한 추천안, 커스텀 정보}
|
||||
Gateway -> Event: 선택 저장
|
||||
Event -> EventDB: 이벤트 초안 업데이트
|
||||
Event -> EventDB: 선택한 추천안 저장\n(이벤트 초안 업데이트)
|
||||
EventDB --> Event: 업데이트 완료
|
||||
Event --> Gateway: 200 OK
|
||||
Gateway --> FE: 저장 완료
|
||||
@ -98,16 +98,16 @@ else 트렌디 스타일
|
||||
ImageApi --> Content: 트렌디 이미지 URL
|
||||
end
|
||||
|
||||
Content -> EventDB: 이미지 URL 저장
|
||||
Content -> EventDB: 생성된 이미지 URL 저장\n(3가지 스타일 이미지 URL 저장)
|
||||
EventDB --> Content: 저장 완료
|
||||
Content -> EventDB: Job 상태 업데이트\nstatus: COMPLETED
|
||||
Content -> EventDB: Job 상태 업데이트\n(상태를 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 -> EventDB: Job 상태 및 결과 조회
|
||||
Event -> EventDB: Job 상태 조회\n(jobId로 상태 및 이미지 URL 조회)
|
||||
EventDB --> Event: {status, imageUrls}
|
||||
|
||||
alt Job 완료
|
||||
@ -125,7 +125,7 @@ end
|
||||
User -> FE: 스타일 선택 및 편집
|
||||
FE -> Gateway: PUT /events/drafts/{eventDraftId}/content\n{선택한 이미지, 편집내용}
|
||||
Gateway -> Event: 콘텐츠 선택 저장
|
||||
Event -> EventDB: 이벤트 초안 업데이트
|
||||
Event -> EventDB: 선택한 콘텐츠 저장\n(이벤트 초안 업데이트)
|
||||
EventDB --> Event: 업데이트 완료
|
||||
Event --> Gateway: 200 OK
|
||||
Gateway --> FE: 저장 완료
|
||||
@ -135,7 +135,7 @@ FE --> User: 배포 채널 선택 화면으로 이동
|
||||
User -> FE: 배포 채널 선택\n최종 승인 요청
|
||||
FE -> Gateway: POST /api/events/{eventDraftId}/publish\n{선택 채널 목록}
|
||||
Gateway -> Event: 최종 승인 및 배포 처리
|
||||
Event -> EventDB: 이벤트 상태 변경\nDRAFT → APPROVED
|
||||
Event -> EventDB: 이벤트 상태 변경\n(DRAFT → APPROVED로 업데이트)
|
||||
EventDB --> Event: 상태 변경 완료
|
||||
Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보}
|
||||
|
||||
@ -176,13 +176,13 @@ else Kakao Channel
|
||||
end
|
||||
end
|
||||
|
||||
Dist -> EventDB: 배포 이력 저장
|
||||
Dist -> EventDB: 배포 이력 저장\n(채널별 배포 결과 저장)
|
||||
EventDB --> Dist: 저장 완료
|
||||
|
||||
Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, 배포결과}
|
||||
|
||||
Dist --> Event: REST API 응답\n200 OK\n{배포결과, 채널별 상태}
|
||||
Event -> EventDB: 이벤트 상태 업데이트\nAPPROVED → ACTIVE
|
||||
Event -> EventDB: 이벤트 상태 업데이트\n(APPROVED → ACTIVE로 변경)
|
||||
EventDB --> Event: 업데이트 완료
|
||||
|
||||
Event --> Gateway: 200 OK\n{eventId, 배포결과}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user