edit all sequence

This commit is contained in:
cherry2250 2025-10-22 20:13:56 +09:00
parent a8c6397edf
commit 9192e1e453
25 changed files with 106 additions and 106 deletions

View File

@ -66,7 +66,7 @@ else 유효한 메시지
end note end note
else 캐시 미스 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 정보} EventDB --> TrendEngine: 이벤트 통계 데이터\n{성공 이벤트 리스트, ROI 정보}
TrendEngine -> TrendEngine: 트렌드 패턴 분석 TrendEngine -> TrendEngine: 트렌드 패턴 분석

View File

@ -96,7 +96,7 @@ else Cache MISS
Service -> Repository: getEventStats(eventId) Service -> Repository: getEventStats(eventId)
activate Repository activate Repository
Repository -> DB: SELECT event_stats\nWHERE event_id = ? Repository -> DB: 이벤트 통계 조회\n(이벤트ID로 통계 데이터 조회)
activate DB activate DB
DB --> Repository: EventStatsEntity\n- totalParticipants\n- estimatedROI\n- salesGrowthRate DB --> Repository: EventStatsEntity\n- totalParticipants\n- estimatedROI\n- salesGrowthRate

View File

@ -62,7 +62,7 @@ alt 이벤트 미처리 (멱등성 보장)
Service -> Repository: saveChannelStats(\n eventId, channel, stats\n) Service -> Repository: saveChannelStats(\n eventId, channel, stats\n)
activate Repository 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 activate DB
DB --> Repository: 1 row inserted/updated DB --> Repository: 1 row inserted/updated
@ -82,7 +82,7 @@ alt 이벤트 미처리 (멱등성 보장)
Service -> Repository: updateTotalViews(eventId, totalViews) Service -> Repository: updateTotalViews(eventId, totalViews)
activate Repository activate Repository
Repository -> DB: UPDATE event_stats\nSET total_views = ?,\n updated_at = NOW()\nWHERE event_id = ? Repository -> DB: 총 노출 수 업데이트\n(총 예상 노출 수를 설정하고,\n수정일시를 현재 시각으로 업데이트)
activate DB activate DB
DB --> Repository: 1 row updated DB --> Repository: 1 row updated

View File

@ -54,7 +54,7 @@ alt 이벤트 미처리 (멱등성 보장)
Service -> Repository: save(eventStatsEntity) Service -> Repository: save(eventStatsEntity)
activate Repository 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 activate DB
DB --> Repository: 1 row inserted DB --> Repository: 1 row inserted

View File

@ -50,7 +50,7 @@ alt 이벤트 미처리 (멱등성 보장)
Service -> Repository: incrementParticipantCount(eventId) Service -> Repository: incrementParticipantCount(eventId)
activate Repository 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 activate DB
DB --> Repository: 1 row updated DB --> Repository: 1 row updated

View File

@ -21,11 +21,11 @@ activate Controller
Controller -> Service: executeDistribution(distributionRequest) Controller -> Service: executeDistribution(distributionRequest)
activate Service activate Service
Service -> DB: 배포 이력 초기화\nINSERT distribution_logs\n{eventId, status: PENDING} Service -> DB: 배포 이력 초기화\n(이벤트ID, 상태를 PENDING으로 저장)
DB --> Service: 배포 이력 ID DB --> Service: 배포 이력 ID
note over Service: 배포 시작 상태로 변경 note over Service: 배포 시작 상태로 변경
Service -> DB: UPDATE distribution_logs\nSET status = 'IN_PROGRESS' Service -> DB: 배포 이력 상태 업데이트\n(상태를 IN_PROGRESS로 변경)
== 다중 채널 배포 로그 기록 (Sprint 2: Mock 처리) == == 다중 채널 배포 로그 기록 (Sprint 2: Mock 처리) ==
@ -38,7 +38,7 @@ par 우리동네TV 배포
note over Service: 배포 요청 검증\n- eventId 유효성\n- contentUrls 존재 여부 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 생성) note over Service: Mock 결과:\n성공 (distributionId 생성)
@ -51,7 +51,7 @@ par 우리동네TV 배포
note over Service: 배포 요청 검증\n- phoneNumber 형식\n- audioUrl 존재 여부 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 기록) note over Service: Mock 결과:\n성공 (timestamp 기록)
@ -64,7 +64,7 @@ par 우리동네TV 배포
note over Service: 배포 요청 검증\n- region 유효성\n- schedule 형식\n- budget 범위 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 생성) note over Service: Mock 결과:\n성공 (adId 생성)
@ -77,7 +77,7 @@ par 우리동네TV 배포
note over Service: 배포 요청 검증\n- imageUrl 형식\n- caption 길이\n- hashtags 유효성 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 생성) note over Service: Mock 결과:\n성공 (postUrl, postId 생성)
@ -90,7 +90,7 @@ par 우리동네TV 배포
note over Service: 배포 요청 검증\n- imageUrl 형식\n- content 길이 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 생성) note over Service: Mock 결과:\n성공 (postUrl 생성)
@ -103,7 +103,7 @@ par 우리동네TV 배포
note over Service: 배포 요청 검증\n- imageUrl 형식\n- message 길이 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 생성) note over Service: Mock 결과:\n성공 (messageId 생성)
@ -118,7 +118,7 @@ Service -> Service: 채널별 배포 결과 집계\n성공: [선택된 모든
note over Service: Sprint 2에서는\n모든 채널 배포가 성공으로 처리됨 note over Service: Sprint 2에서는\n모든 채널 배포가 성공으로 처리됨
Service -> DB: UPDATE distribution_logs\nSET status = 'COMPLETED',\ncompleted_at = NOW() Service -> DB: 배포 이력 상태 업데이트\n(상태를 COMPLETED로,\n완료일시를 현재 시각으로 설정)
== Kafka 이벤트 발행 == == Kafka 이벤트 발행 ==
Service -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, channels[], results[], completedAt} Service -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, channels[], results[], completedAt}

View File

@ -17,7 +17,7 @@ activate Service
Service -> Repo: findById(eventDraftId) Service -> Repo: findById(eventDraftId)
activate Repo activate Repo
Repo -> DB: SELECT * FROM event_drafts\nWHERE id = ? AND user_id = ? Repo -> DB: 이벤트 초안 조회\n(초안ID와 사용자ID로 조회)
activate DB activate DB
DB --> Repo: EventDraft DB --> Repo: EventDraft
deactivate DB deactivate DB

View File

@ -28,7 +28,7 @@ else 캐시 미스
group parallel group parallel
Service -> Repo: findTopByStatusAndUserId(ACTIVE, userId, limit=5) Service -> Repo: findTopByStatusAndUserId(ACTIVE, userId, limit=5)
activate Repo 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 activate DB
DB --> Repo: Active events DB --> Repo: Active events
deactivate DB deactivate DB
@ -37,7 +37,7 @@ else 캐시 미스
Service -> Repo: findTopByStatusAndUserId(APPROVED, userId, limit=5) Service -> Repo: findTopByStatusAndUserId(APPROVED, userId, limit=5)
activate Repo 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 activate DB
DB --> Repo: Approved events DB --> Repo: Approved events
deactivate DB deactivate DB
@ -46,7 +46,7 @@ else 캐시 미스
Service -> Repo: findTopByStatusAndUserId(COMPLETED, userId, limit=5) Service -> Repo: findTopByStatusAndUserId(COMPLETED, userId, limit=5)
activate Repo 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 activate DB
DB --> Repo: Completed events DB --> Repo: Completed events
deactivate DB deactivate DB

View File

@ -9,56 +9,56 @@ participant "EventRepository" as Repo <<R>>
participant "Redis Cache" as Cache <<E>> participant "Redis Cache" as Cache <<E>>
database "Event DB" as DB <<E>> database "Event DB" as DB <<E>>
note over Controller: GET /api/events?status={status}&keyword={keyword}\n&page={page}&size={size} note over Controller: GET /api/events?status={상태}&keyword={검색어}\n&page={페이지}&size={크기}
Controller -> Service: getEventList(userId, filters, pagination) Controller -> Service: 이벤트 목록 조회(사용자ID, 필터, 페이징)
activate Service activate Service
Service -> Cache: get("events:" + userId + ":" + filters + ":" + page) Service -> Cache: 캐시 조회("events:" + 사용자ID + ":" + 필터 + ":" + 페이지)
activate Cache activate Cache
alt 캐시 히트 alt 캐시 히트
Cache --> Service: Event list data Cache --> Service: 이벤트 목록 데이터
Service --> Controller: EventListResponse Service --> Controller: 이벤트 목록 응답
else 캐시 미스 else 캐시 미스
Cache --> Service: null Cache --> Service: null
deactivate Cache deactivate Cache
Service -> Repo: findByUserIdWithFilters(userId, filters, pagination) Service -> Repo: 사용자별 필터링 이벤트 조회(사용자ID, 필터, 페이징)
activate Repo activate Repo
alt 필터 있음 (상태별) 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 검색 있음 (키워드) 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 필터 없음 (전체) 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 end
activate DB activate DB
note right: 인덱스 활용:\n- user_id\n- status\n- created_at note right: 인덱스 활용:\n- 사용자ID\n- 상태\n- 생성일시
DB --> Repo: Event list with participant count DB --> Repo: 이벤트 목록 및 참여자 수
deactivate DB deactivate DB
Repo -> DB: SELECT COUNT(*) FROM events\nWHERE user_id = ? [AND filters] Repo -> DB: 전체 이벤트 개수 조회\n(필터 조건 포함, 페이징용)
activate DB activate DB
DB --> Repo: totalCount DB --> Repo: 전체 개수
deactivate DB deactivate DB
Repo --> Service: PagedResult<Event> Repo --> Service: 페이징된 이벤트 결과
deactivate Repo deactivate Repo
Service -> Cache: set("events:" + userId + ":" + filters + ":" + page,\npagedResult, TTL=1분) Service -> Cache: 캐시 저장("events:" + 사용자ID + ":" + 필터 + ":" + 페이지,\n페이징결과, TTL=1분)
activate Cache activate Cache
Cache --> Service: OK Cache --> Service: OK
deactivate Cache deactivate Cache
end end
Service --> Controller: EventListResponse\n{events: [...], totalCount,\ntotalPages, currentPage} Service --> Controller: 이벤트 목록 응답\n{이벤트목록: [...], 전체개수,\n전체페이지수, 현재페이지}
deactivate Service 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 @enduml

View File

@ -24,7 +24,7 @@ note right: 목적 유효성 검증\n- 신규 고객 유치\n- 재방문 유도\
Service -> Repo: save(eventDraft) Service -> Repo: save(eventDraft)
activate Repo activate Repo
Repo -> DB: INSERT INTO event_drafts\n(user_id, objective, store_info, status) Repo -> DB: 이벤트 초안 저장\n(사용자ID, 목적, 매장정보,\n상태를 저장)
activate DB activate DB
DB --> Repo: eventDraftId DB --> Repo: eventDraftId
deactivate DB deactivate DB

View File

@ -28,7 +28,7 @@ else 캐시 미스
Service -> Repo: findById(eventId) Service -> Repo: findById(eventId)
activate Repo 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 activate DB
note right: JOIN으로\n경품 정보 및\n배포 이력 조회 note right: JOIN으로\n경품 정보 및\n배포 이력 조회
DB --> Repo: Event with prizes and distributions DB --> Repo: Event with prizes and distributions

View File

@ -17,7 +17,7 @@ activate Service
Service -> Repo: findById(eventDraftId) Service -> Repo: findById(eventDraftId)
activate Repo activate Repo
Repo -> DB: SELECT * FROM event_drafts\nWHERE id = ? AND user_id = ? Repo -> DB: 이벤트 초안 조회\n(초안ID와 사용자ID로 조회)
activate DB activate DB
DB --> Repo: EventDraft DB --> Repo: EventDraft
deactivate DB deactivate DB

View File

@ -17,7 +17,7 @@ activate Service
Service -> Repo: findById(eventDraftId) Service -> Repo: findById(eventDraftId)
activate Repo activate Repo
Repo -> DB: SELECT * FROM event_drafts\nWHERE id = ? AND user_id = ? Repo -> DB: 이벤트 초안 조회\n(초안ID와 사용자ID로 조회)
activate DB activate DB
DB --> Repo: EventDraft DB --> Repo: EventDraft
deactivate DB deactivate DB
@ -30,7 +30,7 @@ note right: 발행 준비 검증:\n- 목적 선택 완료\n- AI 추천 선택
Service -> Repo: updateStatus(eventDraftId, APPROVED) Service -> Repo: updateStatus(eventDraftId, APPROVED)
activate Repo activate Repo
Repo -> DB: UPDATE event_drafts SET\nstatus = 'APPROVED',\napproved_at = NOW()\nWHERE id = ? Repo -> DB: 이벤트 초안 상태 업데이트\n(상태를 APPROVED로,\n승인일시를 현재 시각으로 설정)
activate DB activate DB
DB --> Repo: OK DB --> Repo: OK
deactivate DB deactivate DB
@ -53,7 +53,7 @@ deactivate DistSvc
Service -> Repo: updateStatus(eventDraftId, ACTIVE) Service -> Repo: updateStatus(eventDraftId, ACTIVE)
activate Repo activate Repo
Repo -> DB: UPDATE event_drafts SET\nstatus = 'ACTIVE',\npublished_at = NOW()\nWHERE id = ? Repo -> DB: 이벤트 상태 업데이트\n(상태를 ACTIVE로,\n배포일시를 현재 시각으로 설정)
activate DB activate DB
DB --> Repo: OK DB --> Repo: OK
deactivate DB deactivate DB

View File

@ -15,7 +15,7 @@ activate Service
Service -> Repo: findById(eventDraftId) Service -> Repo: findById(eventDraftId)
activate Repo activate Repo
Repo -> DB: SELECT * FROM event_drafts\nWHERE id = ? AND user_id = ? Repo -> DB: 이벤트 초안 조회\n(초안ID와 사용자ID로 조회)
activate DB activate DB
DB --> Repo: EventDraft DB --> Repo: EventDraft
deactivate DB deactivate DB
@ -31,7 +31,7 @@ note right: 편집 내용 적용:\n- 텍스트 수정\n- 색상 변경
Service -> Repo: update(eventDraft) Service -> Repo: update(eventDraft)
activate Repo 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 activate DB
DB --> Repo: OK DB --> Repo: OK
deactivate DB deactivate DB

View File

@ -43,7 +43,7 @@ else JWT 검증 성공
Service -> LogRepo: findByEventId(eventId) Service -> LogRepo: findByEventId(eventId)
activate LogRepo activate LogRepo
LogRepo -> DB: SELECT * FROM draw_logs\nWHERE event_id = ? LogRepo -> DB: 추첨 로그 조회\n(이벤트ID로 조회)
activate DB activate DB
DB --> LogRepo: 추첨 로그 조회 DB --> LogRepo: 추첨 로그 조회
deactivate DB deactivate DB
@ -61,7 +61,7 @@ else JWT 검증 성공
Service -> Repo: findAllByEventIdAndIsWinner(eventId, false) Service -> Repo: findAllByEventIdAndIsWinner(eventId, false)
activate Repo 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 activate DB
DB --> Repo: 전체 참여자 목록 DB --> Repo: 전체 참여자 목록
deactivate DB deactivate DB
@ -119,7 +119,7 @@ else JWT 검증 성공
Service -> Repo: updateWinners(winnerIds) Service -> Repo: updateWinners(winnerIds)
activate Repo 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 activate DB
DB --> Repo: 업데이트 완료 DB --> Repo: 업데이트 완료
deactivate DB deactivate DB
@ -130,7 +130,7 @@ else JWT 검증 성공
Service -> LogRepo: save(drawLog) Service -> LogRepo: save(drawLog)
activate LogRepo 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 activate DB
note right of DB note right of DB
추첨 로그 저장: 추첨 로그 저장:

View File

@ -53,7 +53,7 @@ else 유효성 검증 성공
Service -> Repo: findByEventIdAndPhoneNumber(eventId, phone) Service -> Repo: findByEventIdAndPhoneNumber(eventId, phone)
activate Repo activate Repo
Repo -> DB: SELECT * FROM participants\nWHERE event_id = ? AND phone_number = ? Repo -> DB: 참여자 중복 확인\n(이벤트ID, 전화번호로 조회)
activate DB activate DB
DB --> Repo: 조회 결과 DB --> Repo: 조회 결과
deactivate DB deactivate DB
@ -80,7 +80,7 @@ else 유효성 검증 성공
Service -> Repo: save(participant) Service -> Repo: save(participant)
activate Repo 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 activate DB
DB --> Repo: 저장 완료 DB --> Repo: 저장 완료
deactivate DB deactivate DB

View File

@ -64,7 +64,7 @@ else JWT 검증 성공
Service -> Repo: findParticipants(eventId, filters, pageable) Service -> Repo: findParticipants(eventId, filters, pageable)
activate Repo 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 activate DB
note right of DB note right of DB
@ -82,7 +82,7 @@ else JWT 검증 성공
DB --> Repo: 참여자 목록 결과셋 DB --> Repo: 참여자 목록 결과셋
deactivate DB deactivate DB
Repo -> DB: SELECT COUNT(*)\nFROM participants\nWHERE event_id = ?\n[필터 조건 동일] Repo -> DB: 전체 참여자 수 조회\n(동일한 필터 조건 적용)
activate DB activate DB
DB --> Repo: 전체 건수 DB --> Repo: 전체 건수
deactivate DB deactivate DB

View File

@ -44,7 +44,7 @@ else JWT 토큰 유효
== 2단계: Redis 세션 삭제 == == 2단계: Redis 세션 삭제 ==
AuthService -> Redis: DEL user:session:{token} AuthService -> Redis: 세션 삭제\n(캐시키: user:session:{token})
activate Redis activate Redis
Redis --> AuthService: 삭제된 키 개수 (0 또는 1) Redis --> AuthService: 삭제된 키 개수 (0 또는 1)
deactivate Redis deactivate Redis
@ -87,7 +87,7 @@ else JWT 토큰 유효
deactivate JwtProvider deactivate JwtProvider
alt 남은 만료 시간 > 0 alt 남은 만료 시간 > 0
AuthService -> Redis: SET jwt:blacklist:{token}\n"revoked" (TTL: remainingSeconds) AuthService -> Redis: 블랙리스트에 토큰 추가\n(캐시키: jwt:blacklist:{token},\n값: "revoked", TTL: 남은초)
activate Redis activate Redis
Redis --> AuthService: Blacklist 추가 완료 Redis --> AuthService: Blacklist 추가 완료
deactivate Redis deactivate Redis

View File

@ -36,7 +36,7 @@ AuthService -> Service: findByPhoneNumber(phoneNumber)
activate Service activate Service
Service -> UserRepo: findByPhoneNumber(phoneNumber) Service -> UserRepo: findByPhoneNumber(phoneNumber)
activate UserRepo activate UserRepo
UserRepo -> UserDB: SELECT user_id, password_hash,\nrole, name, email\nFROM users\nWHERE phone_number = ? UserRepo -> UserDB: 전화번호로 사용자 조회\n(사용자ID, 비밀번호해시, 역할,\n이름, 이메일 조회)
activate UserDB activate UserDB
UserDB --> UserRepo: 사용자 정보 또는 NULL UserDB --> UserRepo: 사용자 정보 또는 NULL
deactivate UserDB deactivate UserDB
@ -96,7 +96,7 @@ else 사용자 존재
end note end note
Service ->> UserRepo: updateLastLoginAt(userId) Service ->> UserRepo: updateLastLoginAt(userId)
activate UserRepo activate UserRepo
UserRepo ->> UserDB: UPDATE users\nSET last_login_at = NOW()\nWHERE user_id = ? UserRepo ->> UserDB: 최종 로그인 시각 업데이트\n(현재 시각으로 갱신)
activate UserDB activate UserDB
UserDB -->> UserRepo: 업데이트 완료 UserDB -->> UserRepo: 업데이트 완료
deactivate UserDB deactivate UserDB

View File

@ -34,7 +34,7 @@ activate Service
Service -> UserRepo: findById(userId) Service -> UserRepo: findById(userId)
activate UserRepo activate UserRepo
UserRepo -> UserDB: SELECT * FROM users\nWHERE user_id = ? UserRepo -> UserDB: 사용자ID로 사용자 조회\n(사용자 정보 조회)
activate UserDB activate UserDB
UserDB --> UserRepo: 사용자 정보 UserDB --> UserRepo: 사용자 정보
deactivate UserDB deactivate UserDB
@ -109,7 +109,7 @@ else 사용자 존재
Service -> StoreRepo: findByUserId(userId) Service -> StoreRepo: findByUserId(userId)
activate StoreRepo activate StoreRepo
StoreRepo -> UserDB: SELECT * FROM stores\nWHERE user_id = ? StoreRepo -> UserDB: 사용자ID로 매장 조회\n(매장 정보 조회)
activate UserDB activate UserDB
UserDB --> StoreRepo: 매장 정보 UserDB --> StoreRepo: 매장 정보
deactivate UserDB deactivate UserDB
@ -134,7 +134,7 @@ else 사용자 존재
== 5단계: 데이터베이스 트랜잭션 == == 5단계: 데이터베이스 트랜잭션 ==
Service -> UserDB: BEGIN TRANSACTION Service -> UserDB: 트랜잭션 시작
activate UserDB activate UserDB
note right of Service note right of Service
@ -146,7 +146,7 @@ else 사용자 존재
Service -> UserRepo: save(user) Service -> UserRepo: save(user)
activate UserRepo 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) UserDB --> UserRepo: 업데이트 완료 (1 row affected)
UserRepo --> Service: User 엔티티 UserRepo --> Service: User 엔티티
deactivate UserRepo deactivate UserRepo
@ -155,7 +155,7 @@ else 사용자 존재
UserRepo --> Service: throw OptimisticLockException UserRepo --> Service: throw OptimisticLockException
Service --> Controller: throw ConcurrentModificationException\n("다른 사용자가 수정 중입니다") Service --> Controller: throw ConcurrentModificationException\n("다른 사용자가 수정 중입니다")
Controller --> Client: 409 Conflict\n{"code": "USER_005",\n"error": "다른 세션에서 프로필을\n수정했습니다.\n새로고침 후 다시 시도하세요"} Controller --> Client: 409 Conflict\n{"code": "USER_005",\n"error": "다른 세션에서 프로필을\n수정했습니다.\n새로고침 후 다시 시도하세요"}
Service -> UserDB: ROLLBACK TRANSACTION Service -> UserDB: 트랜잭션 롤백
deactivate UserDB deactivate UserDB
deactivate Service deactivate Service
deactivate Controller deactivate Controller
@ -163,12 +163,12 @@ else 사용자 존재
Service -> StoreRepo: save(store) Service -> StoreRepo: save(store)
activate StoreRepo 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) UserDB --> StoreRepo: 업데이트 완료 (1 row affected)
StoreRepo --> Service: Store 엔티티 StoreRepo --> Service: Store 엔티티
deactivate StoreRepo deactivate StoreRepo
Service -> UserDB: COMMIT TRANSACTION Service -> UserDB: 트랜잭션 커밋
UserDB --> Service: 트랜잭션 커밋 완료 UserDB --> Service: 트랜잭션 커밋 완료
deactivate UserDB deactivate UserDB
end end
@ -182,7 +182,7 @@ else 사용자 존재
end note end note
alt 프로필 캐시 사용 중 alt 프로필 캐시 사용 중
Service -> Redis: DEL user:profile:{userId} Service -> Redis: 프로필 캐시 삭제\n(캐시키: user:profile:{userId})
activate Redis activate Redis
Redis --> Service: 캐시 삭제 완료 Redis --> Service: 캐시 삭제 완료
deactivate Redis deactivate Redis

View File

@ -36,7 +36,7 @@ activate Service
Service -> UserRepo: findByPhoneNumber(phoneNumber) Service -> UserRepo: findByPhoneNumber(phoneNumber)
activate UserRepo activate UserRepo
UserRepo -> UserDB: SELECT * FROM users\nWHERE phone_number = ? UserRepo -> UserDB: 전화번호로 사용자 조회\n(중복 가입 확인)
activate UserDB activate UserDB
UserDB --> UserRepo: 조회 결과 UserDB --> UserRepo: 조회 결과
deactivate UserDB deactivate UserDB
@ -132,24 +132,24 @@ else 신규 사용자
== 5단계: 데이터베이스 트랜잭션 == == 5단계: 데이터베이스 트랜잭션 ==
Service -> UserDB: BEGIN TRANSACTION Service -> UserDB: 트랜잭션 시작
activate UserDB activate UserDB
Service -> UserRepo: save(User)\n(name, phoneNumber, email,\npasswordHash, createdAt) Service -> UserRepo: save(User)\n(name, phoneNumber, email,\npasswordHash, createdAt)
activate UserRepo 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 UserDB --> UserRepo: user_id
UserRepo --> Service: User 엔티티\n(userId 포함) UserRepo --> Service: User 엔티티\n(userId 포함)
deactivate UserRepo deactivate UserRepo
Service -> StoreRepo: save(Store)\n(userId, storeName, industry,\naddress, businessNumberEncrypted,\nbusinessHours) Service -> StoreRepo: save(Store)\n(userId, storeName, industry,\naddress, businessNumberEncrypted,\nbusinessHours)
activate StoreRepo 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 UserDB --> StoreRepo: store_id
StoreRepo --> Service: Store 엔티티\n(storeId 포함) StoreRepo --> Service: Store 엔티티\n(storeId 포함)
deactivate StoreRepo deactivate StoreRepo
Service -> UserDB: COMMIT TRANSACTION Service -> UserDB: 트랜잭션 커밋
UserDB --> Service: 트랜잭션 커밋 완료 UserDB --> Service: 트랜잭션 커밋 완료
deactivate UserDB deactivate UserDB

View File

@ -30,7 +30,7 @@ activate Gateway
Gateway -> PartService: POST /participations/register\n{이름, 전화번호, 참여경로, 개인정보동의} Gateway -> PartService: POST /participations/register\n{이름, 전화번호, 참여경로, 개인정보동의}
activate PartService activate PartService
PartService -> PartDB: SELECT * FROM participants\nWHERE phone_number = ? AND event_id = ? PartService -> PartDB: 참여자 중복 확인\n(전화번호, 이벤트ID로 조회)
activate PartDB activate PartDB
PartDB --> PartService: 중복 참여 여부 반환 PartDB --> PartService: 중복 참여 여부 반환
deactivate PartDB deactivate PartDB
@ -45,7 +45,7 @@ alt 중복 참여인 경우
else 신규 참여인 경우 else 신규 참여인 경우
PartService -> PartService: 응모 번호 생성\n(UUID 또는 시퀀스 기반) 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 activate PartDB
PartDB --> PartService: 저장 완료 PartDB --> PartService: 저장 완료
deactivate PartDB deactivate PartDB
@ -94,19 +94,19 @@ activate Gateway
Gateway -> PartService: POST /events/{eventId}/draw-winners\n{winnerCount, visitBonus} Gateway -> PartService: POST /events/{eventId}/draw-winners\n{winnerCount, visitBonus}
activate PartService activate PartService
PartService -> PartDB: SELECT * FROM participants\nWHERE event_id = ? AND is_winner = false PartService -> PartDB: 미당첨 참여자 목록 조회\n(이벤트ID로 당첨되지 않은 참여자 조회)
activate PartDB activate PartDB
PartDB --> PartService: 전체 참여자 목록 반환 PartDB --> PartService: 전체 참여자 목록 반환
deactivate PartDB deactivate PartDB
PartService -> PartService: 당첨자 추첨 알고리즘 실행\n1. 난수 생성 (Crypto.randomBytes)\n2. 매장방문 가산점 적용 (옵션)\n3. Fisher-Yates Shuffle\n4. 당첨인원만큼 선정 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 activate PartDB
PartDB --> PartService: 업데이트 완료 PartDB --> PartService: 업데이트 완료
deactivate PartDB 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 activate PartDB
note right of PartDB note right of PartDB
추첨 로그 저장: 추첨 로그 저장:

View File

@ -27,7 +27,7 @@ activate UserService
UserService -> UserService: 서버 측 유효성 검증\n(이름 2자 이상, 전화번호 형식 등) UserService -> UserService: 서버 측 유효성 검증\n(이름 2자 이상, 전화번호 형식 등)
UserService -> UserDB: SELECT users\nWHERE phone_number = ? UserService -> UserDB: 전화번호로 사용자 조회\n(중복 가입 확인)
activate UserDB activate UserDB
UserDB --> UserService: 기존 사용자 확인 결과 UserDB --> UserService: 기존 사용자 확인 결과
deactivate UserDB deactivate UserDB
@ -42,16 +42,16 @@ else 신규 사용자
UserService -> UserService: 사업자번호 암호화\n(AES-256) UserService -> UserService: 사업자번호 암호화\n(AES-256)
UserService -> UserDB: BEGIN TRANSACTION UserService -> UserDB: 트랜잭션 시작
activate 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 반환 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 반환 UserDB --> UserService: store_id 반환
UserService -> UserDB: COMMIT TRANSACTION UserService -> UserDB: 트랜잭션 커밋
deactivate UserDB deactivate UserDB
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일) UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일)
@ -87,7 +87,7 @@ Gateway -> Gateway: Request 검증
Gateway -> UserService: POST /api/users/login\n(전화번호, 비밀번호) Gateway -> UserService: POST /api/users/login\n(전화번호, 비밀번호)
activate UserService activate UserService
UserService -> UserDB: SELECT users\nWHERE phone_number = ? UserService -> UserDB: 전화번호로 사용자 조회\n(로그인 인증용)
activate UserDB activate UserDB
UserDB --> UserService: 사용자 정보\n(user_id, password_hash, role) UserDB --> UserService: 사용자 정보\n(user_id, password_hash, role)
deactivate UserDB deactivate UserDB
@ -108,7 +108,7 @@ else 사용자 존재
UserService -> UserService: JWT 토큰 생성\n(user_id, role=OWNER,\nexp=7일) 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 activate UserDB
UserDB --> UserService: 업데이트 완료 UserDB --> UserService: 업데이트 완료
deactivate UserDB deactivate UserDB

View File

@ -30,7 +30,7 @@ GW -> GW: JWT 토큰 검증
GW -> Analytics: GET /api/events/{id}/analytics GW -> Analytics: GET /api/events/{id}/analytics
activate Analytics activate Analytics
Analytics -> Redis: GET analytics:dashboard:{eventId} Analytics -> Redis: 대시보드 캐시 조회\n(캐시키: analytics:dashboard:{eventId})
activate Redis activate Redis
Redis --> Analytics: **Cache HIT**\n캐시된 대시보드 데이터 반환 Redis --> Analytics: **Cache HIT**\n캐시된 대시보드 데이터 반환
deactivate Redis deactivate Redis
@ -64,7 +64,7 @@ activate GW
GW -> Analytics: GET /api/events/{id}/analytics GW -> Analytics: GET /api/events/{id}/analytics
activate Analytics activate Analytics
Analytics -> Redis: GET analytics:dashboard:{eventId} Analytics -> Redis: 대시보드 캐시 조회\n(캐시키: analytics:dashboard:{eventId})
activate Redis activate Redis
Redis --> Analytics: **Cache MISS**\nnull 반환 Redis --> Analytics: **Cache MISS**\nnull 반환
deactivate Redis deactivate Redis
@ -79,7 +79,7 @@ end note
||| |||
== 2.1. Analytics DB 조회 (로컬 데이터) == == 2.1. Analytics DB 조회 (로컬 데이터) ==
Analytics -> AnalyticsDB: SELECT event_stats\nWHERE event_id = {id} Analytics -> AnalyticsDB: 이벤트 통계 조회\n(이벤트ID로 통계 데이터 조회)
activate AnalyticsDB activate AnalyticsDB
AnalyticsDB --> Analytics: 이벤트 통계\n- 총 참여자 수\n- 예상 ROI\n- 매출 증가율 AnalyticsDB --> Analytics: 이벤트 통계\n- 총 참여자 수\n- 예상 ROI\n- 매출 증가율
deactivate AnalyticsDB deactivate AnalyticsDB
@ -87,7 +87,7 @@ deactivate AnalyticsDB
||| |||
== 2.2. 배치 수집된 채널 통계 데이터 조회 == == 2.2. 배치 수집된 채널 통계 데이터 조회 ==
Analytics -> AnalyticsDB: SELECT channel_stats\nWHERE event_id = {id} Analytics -> AnalyticsDB: 채널별 통계 조회\n(배치로 수집된 채널 데이터 조회)
activate AnalyticsDB activate AnalyticsDB
note right of Analytics note right of Analytics
@ -123,7 +123,7 @@ end note
||| |||
== 2.4. Redis 캐싱 및 응답 == == 2.4. Redis 캐싱 및 응답 ==
Analytics -> Redis: SET analytics:dashboard:{eventId}\nvalue={통합 데이터}\nTTL=300초 (5분) Analytics -> Redis: 대시보드 데이터 캐시 저장\n(캐시키: analytics:dashboard:{eventId},\n값: 통합 데이터, TTL: 5분)
activate Redis activate Redis
Redis --> Analytics: OK Redis --> Analytics: OK
deactivate Redis deactivate Redis
@ -149,11 +149,11 @@ end note
Kafka -> Analytics: **EventCreated** 이벤트\n{eventId, storeId, title, objective} Kafka -> Analytics: **EventCreated** 이벤트\n{eventId, storeId, title, objective}
activate Analytics activate Analytics
Analytics -> AnalyticsDB: INSERT INTO event_stats\n이벤트 기본 정보 초기화 Analytics -> AnalyticsDB: 이벤트 통계 초기화\n(이벤트 기본 정보 저장)
activate AnalyticsDB activate AnalyticsDB
AnalyticsDB --> Analytics: OK AnalyticsDB --> Analytics: OK
deactivate AnalyticsDB deactivate AnalyticsDB
Analytics -> Redis: DEL analytics:dashboard:{eventId}\n캐시 무효화 Analytics -> Redis: 캐시 무효화\n(캐시키 삭제: analytics:dashboard:{eventId})
activate Redis activate Redis
Redis --> Analytics: OK Redis --> Analytics: OK
deactivate Redis deactivate Redis
@ -163,11 +163,11 @@ deactivate Analytics
Kafka -> Analytics: **ParticipantRegistered** 이벤트\n{participantId, eventId, phoneNumber} Kafka -> Analytics: **ParticipantRegistered** 이벤트\n{participantId, eventId, phoneNumber}
activate Analytics activate Analytics
Analytics -> AnalyticsDB: UPDATE event_stats\nSET participant_count = participant_count + 1\nWHERE event_id = {eventId} Analytics -> AnalyticsDB: 참여자 수 업데이트\n(참여자 수 1 증가)
activate AnalyticsDB activate AnalyticsDB
AnalyticsDB --> Analytics: OK AnalyticsDB --> Analytics: OK
deactivate AnalyticsDB deactivate AnalyticsDB
Analytics -> Redis: DEL analytics:dashboard:{eventId}\n캐시 무효화 (다음 조회 시 갱신) Analytics -> Redis: 캐시 무효화\n(캐시키 삭제: analytics:dashboard:{eventId})
activate Redis activate Redis
Redis --> Analytics: OK Redis --> Analytics: OK
deactivate Redis deactivate Redis
@ -177,11 +177,11 @@ deactivate Analytics
Kafka -> Analytics: **DistributionCompleted** 이벤트\n{eventId, distributedChannels, completedAt} Kafka -> Analytics: **DistributionCompleted** 이벤트\n{eventId, distributedChannels, completedAt}
activate Analytics activate Analytics
Analytics -> AnalyticsDB: INSERT INTO channel_stats\n배포 채널 통계 저장 Analytics -> AnalyticsDB: 채널 통계 저장\n(배포 완료된 채널 정보 저장)
activate AnalyticsDB activate AnalyticsDB
AnalyticsDB --> Analytics: OK AnalyticsDB --> Analytics: OK
deactivate AnalyticsDB deactivate AnalyticsDB
Analytics -> Redis: DEL analytics:dashboard:{eventId}\n캐시 무효화 Analytics -> Redis: 캐시 무효화\n(캐시키 삭제: analytics:dashboard:{eventId})
activate Redis activate Redis
Redis --> Analytics: OK Redis --> Analytics: OK
deactivate Redis deactivate Redis

View File

@ -20,7 +20,7 @@ participant "배포 채널 APIs" as ChannelApis
User -> FE: 이벤트 목적 선택 User -> FE: 이벤트 목적 선택
FE -> Gateway: POST /events/purposes\n{목적, 매장정보} FE -> Gateway: POST /events/purposes\n{목적, 매장정보}
Gateway -> Event: 이벤트 목적 저장 요청 Gateway -> Event: 이벤트 목적 저장 요청
Event -> EventDB: 이벤트 목적 저장 Event -> EventDB: 이벤트 목적 정보 저장\n(목적, 매장정보 저장)
EventDB --> Event: 저장 완료 EventDB --> Event: 저장 완료
Event --> Gateway: 저장 완료\n{eventDraftId} Event --> Gateway: 저장 완료\n{eventDraftId}
Gateway --> FE: 200 OK Gateway --> FE: 200 OK
@ -38,20 +38,20 @@ FE --> User: "AI가 분석 중입니다..." (로딩)
note over AI: Kafka Consumer\nai 이벤트 생성 topic 구독 note over AI: Kafka Consumer\nai 이벤트 생성 topic 구독
Kafka --> AI: Consume Job Message\n{jobId, eventDraftId, ...} Kafka --> AI: Consume Job Message\n{jobId, eventDraftId, ...}
AI -> EventDB: 과거 이벤트 데이터 조회 AI -> EventDB: 과거 이벤트 데이터 조회\n(업종, 지역 기반 통계 조회)
EventDB --> AI: 이벤트 통계 데이터 EventDB --> AI: 이벤트 통계 데이터
AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 과거데이터, 매장정보} AI -> AIApi: 트렌드 분석 및 이벤트 추천 요청\n{목적, 업종, 지역, 과거데이터, 매장정보}
AIApi --> AI: 3가지 추천안 + 트렌드 요약\n(예: "여름철 시원한 음료 선호도 증가") AIApi --> AI: 3가지 추천안 + 트렌드 요약\n(예: "여름철 시원한 음료 선호도 증가")
AI -> EventDB: 추천 결과 및 트렌드 요약 저장 AI -> EventDB: 추천 결과 저장\n(3가지 추천안, 트렌드 요약 저장)
EventDB --> AI: 저장 완료 EventDB --> AI: 저장 완료
AI -> EventDB: Job 상태 업데이트\nstatus: COMPLETED AI -> EventDB: Job 상태 업데이트\n(상태를 COMPLETED로 변경)
AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations, trendSummary} AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations, trendSummary}
group Polling으로 상태 확인 group Polling으로 상태 확인
loop 상태 확인 (최대 30초) loop 상태 확인 (최대 30초)
FE -> Gateway: GET /jobs/{jobId}/status FE -> Gateway: GET /jobs/{jobId}/status
Gateway -> Event: Job 상태 조회 Gateway -> Event: Job 상태 조회
Event -> EventDB: Job 상태 및 결과 조회 Event -> EventDB: Job 상태 조회\n(jobId로 상태 및 결과 조회)
EventDB --> Event: {status, result} EventDB --> Event: {status, result}
alt Job 완료 alt Job 완료
@ -69,7 +69,7 @@ end
User -> FE: 추천안 선택\n(제목/경품 커스텀) User -> FE: 추천안 선택\n(제목/경품 커스텀)
FE -> Gateway: PUT /events/drafts/{eventDraftId}\n{선택한 추천안, 커스텀 정보} FE -> Gateway: PUT /events/drafts/{eventDraftId}\n{선택한 추천안, 커스텀 정보}
Gateway -> Event: 선택 저장 Gateway -> Event: 선택 저장
Event -> EventDB: 이벤트 초안 업데이트 Event -> EventDB: 선택한 추천안 저장\n(이벤트 초안 업데이트)
EventDB --> Event: 업데이트 완료 EventDB --> Event: 업데이트 완료
Event --> Gateway: 200 OK Event --> Gateway: 200 OK
Gateway --> FE: 저장 완료 Gateway --> FE: 저장 완료
@ -98,16 +98,16 @@ else 트렌디 스타일
ImageApi --> Content: 트렌디 이미지 URL ImageApi --> Content: 트렌디 이미지 URL
end end
Content -> EventDB: 이미지 URL 저장 Content -> EventDB: 생성된 이미지 URL 저장\n(3가지 스타일 이미지 URL 저장)
EventDB --> Content: 저장 완료 EventDB --> Content: 저장 완료
Content -> EventDB: Job 상태 업데이트\nstatus: COMPLETED Content -> EventDB: Job 상태 업데이트\n(상태를 COMPLETED로 변경)
Content -> Kafka: Publish to event-topic\nContentCreated\n{jobId, eventDraftId, imageUrls} Content -> Kafka: Publish to event-topic\nContentCreated\n{jobId, eventDraftId, imageUrls}
group Polling으로 상태 확인 group Polling으로 상태 확인
loop 상태 확인 (최대 30초) loop 상태 확인 (최대 30초)
FE -> Gateway: GET /jobs/{jobId}/status FE -> Gateway: GET /jobs/{jobId}/status
Gateway -> Event: Job 상태 조회 Gateway -> Event: Job 상태 조회
Event -> EventDB: Job 상태 및 결과 조회 Event -> EventDB: Job 상태 조회\n(jobId로 상태 및 이미지 URL 조회)
EventDB --> Event: {status, imageUrls} EventDB --> Event: {status, imageUrls}
alt Job 완료 alt Job 완료
@ -125,7 +125,7 @@ end
User -> FE: 스타일 선택 및 편집 User -> FE: 스타일 선택 및 편집
FE -> Gateway: PUT /events/drafts/{eventDraftId}/content\n{선택한 이미지, 편집내용} FE -> Gateway: PUT /events/drafts/{eventDraftId}/content\n{선택한 이미지, 편집내용}
Gateway -> Event: 콘텐츠 선택 저장 Gateway -> Event: 콘텐츠 선택 저장
Event -> EventDB: 이벤트 초안 업데이트 Event -> EventDB: 선택한 콘텐츠 저장\n(이벤트 초안 업데이트)
EventDB --> Event: 업데이트 완료 EventDB --> Event: 업데이트 완료
Event --> Gateway: 200 OK Event --> Gateway: 200 OK
Gateway --> FE: 저장 완료 Gateway --> FE: 저장 완료
@ -135,7 +135,7 @@ FE --> User: 배포 채널 선택 화면으로 이동
User -> FE: 배포 채널 선택\n최종 승인 요청 User -> FE: 배포 채널 선택\n최종 승인 요청
FE -> Gateway: POST /api/events/{eventDraftId}/publish\n{선택 채널 목록} FE -> Gateway: POST /api/events/{eventDraftId}/publish\n{선택 채널 목록}
Gateway -> Event: 최종 승인 및 배포 처리 Gateway -> Event: 최종 승인 및 배포 처리
Event -> EventDB: 이벤트 상태 변경\nDRAFT → APPROVED Event -> EventDB: 이벤트 상태 변경\n(DRAFT → APPROVED로 업데이트)
EventDB --> Event: 상태 변경 완료 EventDB --> Event: 상태 변경 완료
Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보} Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보}
@ -176,13 +176,13 @@ else Kakao Channel
end end
end end
Dist -> EventDB: 배포 이력 저장 Dist -> EventDB: 배포 이력 저장\n(채널별 배포 결과 저장)
EventDB --> Dist: 저장 완료 EventDB --> Dist: 저장 완료
Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, 배포결과} Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, 배포결과}
Dist --> Event: REST API 응답\n200 OK\n{배포결과, 채널별 상태} Dist --> Event: REST API 응답\n200 OK\n{배포결과, 채널별 상태}
Event -> EventDB: 이벤트 상태 업데이트\nAPPROVED → ACTIVE Event -> EventDB: 이벤트 상태 업데이트\n(APPROVED → ACTIVE로 변경)
EventDB --> Event: 업데이트 완료 EventDB --> Event: 업데이트 완료
Event --> Gateway: 200 OK\n{eventId, 배포결과} Event --> Gateway: 200 OK\n{eventId, 배포결과}