delete outer backup
This commit is contained in:
parent
9fd060b275
commit
d876763477
66
claude/check-plantuml.ps1
Normal file
66
claude/check-plantuml.ps1
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$false)]
|
||||||
|
[string]$FilePath = "C:\home\workspace\tripgen\design\backend\system\azure-physical-architecture.txt"
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host "=== PlantUML Syntax Checker ===" -ForegroundColor Cyan
|
||||||
|
Write-Host "Target file: $FilePath" -ForegroundColor Yellow
|
||||||
|
|
||||||
|
# Check if file exists
|
||||||
|
if (-not (Test-Path $FilePath)) {
|
||||||
|
Write-Host "❌ File not found: $FilePath" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute directly in PowerShell
|
||||||
|
$timestamp = Get-Date -Format 'yyyyMMddHHmmss'
|
||||||
|
$tempFile = "/tmp/puml_$timestamp.puml"
|
||||||
|
|
||||||
|
# Copy file
|
||||||
|
Write-Host "`n1. Copying file..." -ForegroundColor Gray
|
||||||
|
Write-Host " Temporary file: $tempFile"
|
||||||
|
docker cp $FilePath "plantuml:$tempFile"
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host "❌ File copy failed" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host " ✅ Copy completed" -ForegroundColor Green
|
||||||
|
|
||||||
|
# Find JAR file path
|
||||||
|
Write-Host "`n2. Looking for PlantUML JAR file..." -ForegroundColor Gray
|
||||||
|
$JAR_PATH = docker exec plantuml sh -c "find / -name 'plantuml*.jar' 2>/dev/null | head -1"
|
||||||
|
Write-Host " JAR path: $JAR_PATH"
|
||||||
|
Write-Host " ✅ JAR file confirmed" -ForegroundColor Green
|
||||||
|
|
||||||
|
# Syntax check
|
||||||
|
Write-Host "`n3. Running syntax check..." -ForegroundColor Gray
|
||||||
|
$syntaxOutput = docker exec plantuml sh -c "java -jar $JAR_PATH -checkonly $tempFile 2>&1"
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
Write-Host "`n✅ Syntax check passed!" -ForegroundColor Green
|
||||||
|
Write-Host " No syntax errors found in the diagram." -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "`n❌ Syntax errors detected!" -ForegroundColor Red
|
||||||
|
Write-Host "Error details:" -ForegroundColor Red
|
||||||
|
Write-Host $syntaxOutput -ForegroundColor Yellow
|
||||||
|
|
||||||
|
# Detailed error check
|
||||||
|
Write-Host "`nAnalyzing detailed errors..." -ForegroundColor Yellow
|
||||||
|
$detailError = docker exec plantuml sh -c "java -jar $JAR_PATH -failfast -v $tempFile 2>&1"
|
||||||
|
$errorLines = $detailError | Select-String "Error line"
|
||||||
|
|
||||||
|
if ($errorLines) {
|
||||||
|
Write-Host "`n📍 Error locations:" -ForegroundColor Magenta
|
||||||
|
$errorLines | ForEach-Object {
|
||||||
|
Write-Host " $($_.Line)" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean up temporary file
|
||||||
|
Write-Host "`n4. Cleaning up temporary files..." -ForegroundColor Gray
|
||||||
|
docker exec plantuml sh -c "rm -f $tempFile" 2>$null
|
||||||
|
Write-Host " ✅ Cleanup completed" -ForegroundColor Green
|
||||||
|
|
||||||
|
Write-Host "`n=== Check completed ===" -ForegroundColor Cyan
|
||||||
@ -1,210 +0,0 @@
|
|||||||
@startuml 이벤트생성플로우
|
|
||||||
!theme mono
|
|
||||||
|
|
||||||
title 이벤트 생성 플로우 - 외부 시퀀스 다이어그램
|
|
||||||
|
|
||||||
actor "소상공인" as User
|
|
||||||
participant "Frontend" as FE
|
|
||||||
participant "API Gateway" as Gateway
|
|
||||||
participant "Event Service" as Event
|
|
||||||
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
|
|
||||||
participant "배포 채널 APIs" as ChannelApis
|
|
||||||
|
|
||||||
== 1. 이벤트 목적 선택 (UFR-EVENT-020) ==
|
|
||||||
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 추천 화면으로 이동
|
|
||||||
|
|
||||||
== 2. AI 이벤트 추천 - 비동기 처리 (UFR-EVENT-030) ==
|
|
||||||
User -> FE: AI 추천 요청
|
|
||||||
FE -> Gateway: POST /events/recommendations\n{eventDraftId, 목적, 업종, 지역}
|
|
||||||
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-job-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: 추천 결과 저장
|
|
||||||
EventDB --> AI: 저장 완료
|
|
||||||
AI -> Cache: Job 상태 업데이트\nkey: job:{jobId}\nstatus: COMPLETED
|
|
||||||
AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations}
|
|
||||||
|
|
||||||
group Polling으로 상태 확인
|
|
||||||
loop 상태 확인 (최대 30초)
|
|
||||||
FE -> Gateway: GET /jobs/{jobId}/status
|
|
||||||
Gateway -> Event: Job 상태 조회
|
|
||||||
Event -> Cache: 캐시에서 Job 상태 확인
|
|
||||||
Cache --> Event: {status, result}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, recommendations}
|
|
||||||
Gateway --> FE: 추천 결과 반환
|
|
||||||
FE --> User: 3가지 추천안 표시\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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 콘텐츠 생성 화면으로 이동
|
|
||||||
|
|
||||||
== 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) ==
|
|
||||||
User -> FE: 이미지 생성 요청
|
|
||||||
FE -> Gateway: POST /contents/images\n{eventDraftId, 이벤트정보}
|
|
||||||
Gateway -> Event: 이미지 생성 요청
|
|
||||||
Event -> Kafka: Publish to image-job-topic\n{jobId, eventDraftId, 이벤트정보}
|
|
||||||
Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
|
||||||
Gateway --> FE: 202 Accepted\n{jobId}
|
|
||||||
FE --> User: "이미지 생성 중..." (로딩)
|
|
||||||
|
|
||||||
note over Content: Kafka Consumer\nimage-job-topic 구독
|
|
||||||
Kafka --> Content: Consume Job Message\n{jobId, eventDraftId, ...}
|
|
||||||
|
|
||||||
par 3가지 스타일 병렬 생성
|
|
||||||
Content -> ImageApi: 심플 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 심플 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 화려한 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 화려한 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 트렌디 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 트렌디 이미지 URL
|
|
||||||
end
|
|
||||||
|
|
||||||
Content -> EventDB: 이미지 URL 저장
|
|
||||||
EventDB --> Content: 저장 완료
|
|
||||||
Content -> Cache: Job 상태 업데이트\nkey: job:{jobId}\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}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
|
|
||||||
Gateway --> FE: 이미지 URL 반환
|
|
||||||
FE --> User: 3가지 스타일 카드 표시
|
|
||||||
else Job 진행중
|
|
||||||
Event --> 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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 배포 채널 선택 화면으로 이동
|
|
||||||
|
|
||||||
== 4. 최종 승인 및 다중 채널 배포 - 동기 처리 (UFR-EVENT-050) ==
|
|
||||||
User -> FE: 배포 채널 선택\n최종 승인 요청
|
|
||||||
FE -> Gateway: POST /events/{eventDraftId}/approve\n{선택 채널 목록, 승인}
|
|
||||||
Gateway -> Event: 최종 승인 처리
|
|
||||||
Event -> EventDB: 이벤트 상태 변경\nDRAFT → APPROVED
|
|
||||||
EventDB --> Event: 상태 변경 완료
|
|
||||||
Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보}
|
|
||||||
|
|
||||||
note over Event: 동기 호출로 배포 진행
|
|
||||||
Event -> Dist: REST API - 배포 요청\nPOST /distributions\n{eventId, channels, content}
|
|
||||||
|
|
||||||
note over Dist: Circuit Breaker 적용
|
|
||||||
|
|
||||||
par 다중 채널 병렬 배포
|
|
||||||
alt 우리동네TV 선택
|
|
||||||
Dist -> ChannelApis: 우리동네TV API\n15초 영상 업로드
|
|
||||||
ChannelApis --> Dist: 배포 완료\n{배포ID, 예상노출수}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 링고비즈 선택
|
|
||||||
Dist -> ChannelApis: 링고비즈 API\n연결음 업데이트
|
|
||||||
ChannelApis --> Dist: 업데이트 완료\n{완료시각}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 지니TV 선택
|
|
||||||
Dist -> ChannelApis: 지니TV API\n광고 등록
|
|
||||||
ChannelApis --> Dist: 광고 등록 완료\n{광고ID, 스케줄}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Instagram 선택
|
|
||||||
Dist -> ChannelApis: Instagram API\n포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Naver Blog 선택
|
|
||||||
Dist -> ChannelApis: Naver API\n블로그 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Kakao Channel 선택
|
|
||||||
Dist -> ChannelApis: Kakao API\n채널 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Dist -> EventDB: 배포 이력 저장
|
|
||||||
EventDB --> Dist: 저장 완료
|
|
||||||
|
|
||||||
Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, 배포결과}
|
|
||||||
|
|
||||||
Dist --> Event: REST API 응답\n200 OK\n{배포결과, 채널별 상태}
|
|
||||||
Event -> EventDB: 이벤트 상태 업데이트\nAPPROVED → ACTIVE
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
|
|
||||||
Event --> Gateway: 200 OK\n{eventId, 배포결과}
|
|
||||||
Gateway --> FE: 배포 완료
|
|
||||||
FE --> User: "이벤트가 배포되었습니다"\n대시보드로 이동
|
|
||||||
|
|
||||||
note over Event, Dist: 배포 실패 시\n- 채널별 독립 처리\n- 자동 재시도 (최대 3회)\n- Circuit Breaker로 장애 전파 방지\n- 실패한 채널만 재시도 가능
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
@ -1,211 +0,0 @@
|
|||||||
@startuml 이벤트생성플로우
|
|
||||||
!theme mono
|
|
||||||
|
|
||||||
title 이벤트 생성 플로우 - 외부 시퀀스 다이어그램
|
|
||||||
|
|
||||||
actor Client
|
|
||||||
actor "소상공인" as User
|
|
||||||
participant "Frontend" as FE
|
|
||||||
participant "API Gateway" as Gateway
|
|
||||||
participant "Event Service" as Event
|
|
||||||
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
|
|
||||||
participant "배포 채널 APIs" as ChannelApis
|
|
||||||
|
|
||||||
== 1. 이벤트 목적 선택 (UFR-EVENT-020) ==
|
|
||||||
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 추천 화면으로 이동
|
|
||||||
|
|
||||||
== 2. AI 이벤트 추천 - 비동기 처리 (UFR-EVENT-030) ==
|
|
||||||
User -> FE: AI 추천 요청
|
|
||||||
FE -> Gateway: POST /events/recommendations\n{eventDraftId, 목적, 업종, 지역}
|
|
||||||
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-job-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: 추천 결과 저장
|
|
||||||
EventDB --> AI: 저장 완료
|
|
||||||
AI -> Cache: Job 상태 업데이트\nkey: job:{jobId}\nstatus: COMPLETED
|
|
||||||
AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations}
|
|
||||||
|
|
||||||
group Polling으로 상태 확인
|
|
||||||
loop 상태 확인 (최대 30초)
|
|
||||||
FE -> Gateway: GET /jobs/{jobId}/status
|
|
||||||
Gateway -> Event: Job 상태 조회
|
|
||||||
Event -> Cache: 캐시에서 Job 상태 확인
|
|
||||||
Cache --> Event: {status, result}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, recommendations}
|
|
||||||
Gateway --> FE: 추천 결과 반환
|
|
||||||
FE --> User: 3가지 추천안 표시\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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 콘텐츠 생성 화면으로 이동
|
|
||||||
|
|
||||||
== 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) ==
|
|
||||||
User -> FE: 이미지 생성 요청
|
|
||||||
FE -> Gateway: POST /contents/images\n{eventDraftId, 이벤트정보}
|
|
||||||
Gateway -> Event: 이미지 생성 요청
|
|
||||||
Event -> Kafka: Publish to image-job-topic\n{jobId, eventDraftId, 이벤트정보}
|
|
||||||
Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
|
||||||
Gateway --> FE: 202 Accepted\n{jobId}
|
|
||||||
FE --> User: "이미지 생성 중..." (로딩)
|
|
||||||
|
|
||||||
note over Content: Kafka Consumer\nimage-job-topic 구독
|
|
||||||
Kafka --> Content: Consume Job Message\n{jobId, eventDraftId, ...}
|
|
||||||
|
|
||||||
par 3가지 스타일 병렬 생성
|
|
||||||
Content -> ImageApi: 심플 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 심플 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 화려한 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 화려한 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 트렌디 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 트렌디 이미지 URL
|
|
||||||
end
|
|
||||||
|
|
||||||
Content -> EventDB: 이미지 URL 저장
|
|
||||||
EventDB --> Content: 저장 완료
|
|
||||||
Content -> Cache: Job 상태 업데이트\nkey: job:{jobId}\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}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
|
|
||||||
Gateway --> FE: 이미지 URL 반환
|
|
||||||
FE --> User: 3가지 스타일 카드 표시
|
|
||||||
else Job 진행중
|
|
||||||
Event --> 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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 배포 채널 선택 화면으로 이동
|
|
||||||
|
|
||||||
== 4. 최종 승인 및 다중 채널 배포 - 동기 처리 (UFR-EVENT-050) ==
|
|
||||||
User -> FE: 배포 채널 선택\n최종 승인 요청
|
|
||||||
FE -> Gateway: POST /events/{eventDraftId}/approve\n{선택 채널 목록, 승인}
|
|
||||||
Gateway -> Event: 최종 승인 처리
|
|
||||||
Event -> EventDB: 이벤트 상태 변경\nDRAFT → APPROVED
|
|
||||||
EventDB --> Event: 상태 변경 완료
|
|
||||||
Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보}
|
|
||||||
|
|
||||||
note over Event: 동기 호출로 배포 진행
|
|
||||||
Event -> Dist: REST API - 배포 요청\nPOST /distributions\n{eventId, channels, content}
|
|
||||||
|
|
||||||
note over Dist: Circuit Breaker 적용
|
|
||||||
|
|
||||||
par 다중 채널 병렬 배포
|
|
||||||
alt 우리동네TV 선택
|
|
||||||
Dist -> ChannelApis: 우리동네TV API\n15초 영상 업로드
|
|
||||||
ChannelApis --> Dist: 배포 완료\n{배포ID, 예상노출수}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 링고비즈 선택
|
|
||||||
Dist -> ChannelApis: 링고비즈 API\n연결음 업데이트
|
|
||||||
ChannelApis --> Dist: 업데이트 완료\n{완료시각}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 지니TV 선택
|
|
||||||
Dist -> ChannelApis: 지니TV API\n광고 등록
|
|
||||||
ChannelApis --> Dist: 광고 등록 완료\n{광고ID, 스케줄}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Instagram 선택
|
|
||||||
Dist -> ChannelApis: Instagram API\n포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Naver Blog 선택
|
|
||||||
Dist -> ChannelApis: Naver API\n블로그 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Kakao Channel 선택
|
|
||||||
Dist -> ChannelApis: Kakao API\n채널 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Dist -> EventDB: 배포 이력 저장
|
|
||||||
EventDB --> Dist: 저장 완료
|
|
||||||
|
|
||||||
Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, 배포결과}
|
|
||||||
|
|
||||||
Dist --> Event: REST API 응답\n200 OK\n{배포결과, 채널별 상태}
|
|
||||||
Event -> EventDB: 이벤트 상태 업데이트\nAPPROVED → ACTIVE
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
|
|
||||||
Event --> Gateway: 200 OK\n{eventId, 배포결과}
|
|
||||||
Gateway --> FE: 배포 완료
|
|
||||||
FE --> User: "이벤트가 배포되었습니다"\n대시보드로 이동
|
|
||||||
|
|
||||||
note over Event, Dist: 배포 실패 시\n- 채널별 독립 처리\n- 자동 재시도 (최대 3회)\n- Circuit Breaker로 장애 전파 방지\n- 실패한 채널만 재시도 가능
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
@ -1,213 +0,0 @@
|
|||||||
@startuml 이벤트생성플로우
|
|
||||||
!theme mono
|
|
||||||
|
|
||||||
title 이벤트 생성 플로우 - 외부 시퀀스 다이어그램
|
|
||||||
|
|
||||||
actor Client
|
|
||||||
actor "소상공인" as User
|
|
||||||
participant "Frontend" as FE
|
|
||||||
participant "API Gateway" as Gateway
|
|
||||||
participant "Event Service" as Event
|
|
||||||
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
|
|
||||||
participant "배포 채널 APIs" as ChannelApis
|
|
||||||
|
|
||||||
== 1. 이벤트 목적 선택 (UFR-EVENT-020) ==
|
|
||||||
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 추천 화면으로 이동
|
|
||||||
|
|
||||||
== 2. AI 이벤트 추천 - 비동기 처리 (UFR-EVENT-030) ==
|
|
||||||
User -> FE: AI 추천 요청
|
|
||||||
FE -> Gateway: POST /events/recommendations\n{eventDraftId, 목적, 업종, 지역}
|
|
||||||
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-job-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: 추천 결과 저장
|
|
||||||
EventDB --> AI: 저장 완료
|
|
||||||
AI -> Cache: Job 상태 업데이트\nkey: job:{jobId}\nstatus: COMPLETED
|
|
||||||
AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations}
|
|
||||||
|
|
||||||
group Polling으로 상태 확인
|
|
||||||
loop 상태 확인 (최대 30초)
|
|
||||||
FE -> Gateway: GET /jobs/{jobId}/status
|
|
||||||
Gateway -> Event: Job 상태 조회
|
|
||||||
Event -> Cache: 캐시에서 Job 상태 확인
|
|
||||||
Cache --> Event: {status, result}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, recommendations}
|
|
||||||
Gateway --> FE: 추천 결과 반환
|
|
||||||
FE --> User: 3가지 추천안 표시\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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 콘텐츠 생성 화면으로 이동
|
|
||||||
|
|
||||||
== 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) ==
|
|
||||||
User -> FE: 이미지 생성 요청
|
|
||||||
FE -> Gateway: POST /contents/images\n{eventDraftId, 이벤트정보}
|
|
||||||
Gateway -> Event: 이미지 생성 요청
|
|
||||||
Event -> Kafka: Publish to image-job-topic\n{jobId, eventDraftId, 이벤트정보}
|
|
||||||
Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
|
||||||
Gateway --> FE: 202 Accepted\n{jobId}
|
|
||||||
FE --> User: "이미지 생성 중..." (로딩)
|
|
||||||
|
|
||||||
note over Content: Kafka Consumer\nimage-job-topic 구독
|
|
||||||
Kafka --> Content: Consume Job Message\n{jobId, eventDraftId, ...}
|
|
||||||
|
|
||||||
par
|
|
||||||
note over : 3가지 스타일 병렬 생성
|
|
||||||
Content -> ImageApi: 심플 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 심플 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 화려한 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 화려한 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 트렌디 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 트렌디 이미지 URL
|
|
||||||
end
|
|
||||||
|
|
||||||
Content -> EventDB: 이미지 URL 저장
|
|
||||||
EventDB --> Content: 저장 완료
|
|
||||||
Content -> Cache: Job 상태 업데이트\nkey: job:{jobId}\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}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
|
|
||||||
Gateway --> FE: 이미지 URL 반환
|
|
||||||
FE --> User: 3가지 스타일 카드 표시
|
|
||||||
else Job 진행중
|
|
||||||
Event --> 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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 배포 채널 선택 화면으로 이동
|
|
||||||
|
|
||||||
== 4. 최종 승인 및 다중 채널 배포 - 동기 처리 (UFR-EVENT-050) ==
|
|
||||||
User -> FE: 배포 채널 선택\n최종 승인 요청
|
|
||||||
FE -> Gateway: POST /events/{eventDraftId}/approve\n{선택 채널 목록, 승인}
|
|
||||||
Gateway -> Event: 최종 승인 처리
|
|
||||||
Event -> EventDB: 이벤트 상태 변경\nDRAFT → APPROVED
|
|
||||||
EventDB --> Event: 상태 변경 완료
|
|
||||||
Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보}
|
|
||||||
|
|
||||||
note over Event: 동기 호출로 배포 진행
|
|
||||||
Event -> Dist: REST API - 배포 요청\nPOST /distributions\n{eventId, channels, content}
|
|
||||||
|
|
||||||
note over Dist: Circuit Breaker 적용
|
|
||||||
|
|
||||||
par
|
|
||||||
note over : 다중 채널 병렬 배포
|
|
||||||
alt 우리동네TV 선택
|
|
||||||
Dist -> ChannelApis: 우리동네TV API\n15초 영상 업로드
|
|
||||||
ChannelApis --> Dist: 배포 완료\n{배포ID, 예상노출수}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 링고비즈 선택
|
|
||||||
Dist -> ChannelApis: 링고비즈 API\n연결음 업데이트
|
|
||||||
ChannelApis --> Dist: 업데이트 완료\n{완료시각}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 지니TV 선택
|
|
||||||
Dist -> ChannelApis: 지니TV API\n광고 등록
|
|
||||||
ChannelApis --> Dist: 광고 등록 완료\n{광고ID, 스케줄}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Instagram 선택
|
|
||||||
Dist -> ChannelApis: Instagram API\n포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Naver Blog 선택
|
|
||||||
Dist -> ChannelApis: Naver API\n블로그 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Kakao Channel 선택
|
|
||||||
Dist -> ChannelApis: Kakao API\n채널 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Dist -> EventDB: 배포 이력 저장
|
|
||||||
EventDB --> Dist: 저장 완료
|
|
||||||
|
|
||||||
Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, 배포결과}
|
|
||||||
|
|
||||||
Dist --> Event: REST API 응답\n200 OK\n{배포결과, 채널별 상태}
|
|
||||||
Event -> EventDB: 이벤트 상태 업데이트\nAPPROVED → ACTIVE
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
|
|
||||||
Event --> Gateway: 200 OK\n{eventId, 배포결과}
|
|
||||||
Gateway --> FE: 배포 완료
|
|
||||||
FE --> User: "이벤트가 배포되었습니다"\n대시보드로 이동
|
|
||||||
|
|
||||||
note over Event, Dist: 배포 실패 시\n- 채널별 독립 처리\n- 자동 재시도 (최대 3회)\n- Circuit Breaker로 장애 전파 방지\n- 실패한 채널만 재시도 가능
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
@ -1,211 +0,0 @@
|
|||||||
@startuml 이벤트생성플로우
|
|
||||||
!theme mono
|
|
||||||
|
|
||||||
title 이벤트 생성 플로우 - 외부 시퀀스 다이어그램
|
|
||||||
|
|
||||||
actor Client
|
|
||||||
actor "소상공인" as User
|
|
||||||
participant "Frontend" as FE
|
|
||||||
participant "API Gateway" as Gateway
|
|
||||||
participant "Event Service" as Event
|
|
||||||
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
|
|
||||||
participant "배포 채널 APIs" as ChannelApis
|
|
||||||
|
|
||||||
== 1. 이벤트 목적 선택 (UFR-EVENT-020) ==
|
|
||||||
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 추천 화면으로 이동
|
|
||||||
|
|
||||||
== 2. AI 이벤트 추천 - 비동기 처리 (UFR-EVENT-030) ==
|
|
||||||
User -> FE: AI 추천 요청
|
|
||||||
FE -> Gateway: POST /events/recommendations\n{eventDraftId, 목적, 업종, 지역}
|
|
||||||
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-job-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: 추천 결과 저장
|
|
||||||
EventDB --> AI: 저장 완료
|
|
||||||
AI -> Cache: Job 상태 업데이트\nkey: job:{jobId}\nstatus: COMPLETED
|
|
||||||
AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations}
|
|
||||||
|
|
||||||
group Polling으로 상태 확인
|
|
||||||
loop 상태 확인 (최대 30초)
|
|
||||||
FE -> Gateway: GET /jobs/{jobId}/status
|
|
||||||
Gateway -> Event: Job 상태 조회
|
|
||||||
Event -> Cache: 캐시에서 Job 상태 확인
|
|
||||||
Cache --> Event: {status, result}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, recommendations}
|
|
||||||
Gateway --> FE: 추천 결과 반환
|
|
||||||
FE --> User: 3가지 추천안 표시\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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 콘텐츠 생성 화면으로 이동
|
|
||||||
|
|
||||||
== 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) ==
|
|
||||||
User -> FE: 이미지 생성 요청
|
|
||||||
FE -> Gateway: POST /contents/images\n{eventDraftId, 이벤트정보}
|
|
||||||
Gateway -> Event: 이미지 생성 요청
|
|
||||||
Event -> Kafka: Publish to image-job-topic\n{jobId, eventDraftId, 이벤트정보}
|
|
||||||
Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
|
||||||
Gateway --> FE: 202 Accepted\n{jobId}
|
|
||||||
FE --> User: "이미지 생성 중..." (로딩)
|
|
||||||
|
|
||||||
note over Content: Kafka Consumer\nimage-job-topic 구독
|
|
||||||
Kafka --> Content: Consume Job Message\n{jobId, eventDraftId, ...}
|
|
||||||
|
|
||||||
par
|
|
||||||
Content -> ImageApi: 심플 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 심플 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 화려한 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 화려한 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 트렌디 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 트렌디 이미지 URL
|
|
||||||
end
|
|
||||||
|
|
||||||
Content -> EventDB: 이미지 URL 저장
|
|
||||||
EventDB --> Content: 저장 완료
|
|
||||||
Content -> Cache: Job 상태 업데이트\nkey: job:{jobId}\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}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
|
|
||||||
Gateway --> FE: 이미지 URL 반환
|
|
||||||
FE --> User: 3가지 스타일 카드 표시
|
|
||||||
else Job 진행중
|
|
||||||
Event --> 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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 배포 채널 선택 화면으로 이동
|
|
||||||
|
|
||||||
== 4. 최종 승인 및 다중 채널 배포 - 동기 처리 (UFR-EVENT-050) ==
|
|
||||||
User -> FE: 배포 채널 선택\n최종 승인 요청
|
|
||||||
FE -> Gateway: POST /events/{eventDraftId}/approve\n{선택 채널 목록, 승인}
|
|
||||||
Gateway -> Event: 최종 승인 처리
|
|
||||||
Event -> EventDB: 이벤트 상태 변경\nDRAFT → APPROVED
|
|
||||||
EventDB --> Event: 상태 변경 완료
|
|
||||||
Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보}
|
|
||||||
|
|
||||||
note over Event: 동기 호출로 배포 진행
|
|
||||||
Event -> Dist: REST API - 배포 요청\nPOST /distributions\n{eventId, channels, content}
|
|
||||||
|
|
||||||
note over Dist: Circuit Breaker 적용
|
|
||||||
|
|
||||||
par
|
|
||||||
alt 우리동네TV 선택
|
|
||||||
Dist -> ChannelApis: 우리동네TV API\n15초 영상 업로드
|
|
||||||
ChannelApis --> Dist: 배포 완료\n{배포ID, 예상노출수}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 링고비즈 선택
|
|
||||||
Dist -> ChannelApis: 링고비즈 API\n연결음 업데이트
|
|
||||||
ChannelApis --> Dist: 업데이트 완료\n{완료시각}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 지니TV 선택
|
|
||||||
Dist -> ChannelApis: 지니TV API\n광고 등록
|
|
||||||
ChannelApis --> Dist: 광고 등록 완료\n{광고ID, 스케줄}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Instagram 선택
|
|
||||||
Dist -> ChannelApis: Instagram API\n포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Naver Blog 선택
|
|
||||||
Dist -> ChannelApis: Naver API\n블로그 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Kakao Channel 선택
|
|
||||||
Dist -> ChannelApis: Kakao API\n채널 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Dist -> EventDB: 배포 이력 저장
|
|
||||||
EventDB --> Dist: 저장 완료
|
|
||||||
|
|
||||||
Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, 배포결과}
|
|
||||||
|
|
||||||
Dist --> Event: REST API 응답\n200 OK\n{배포결과, 채널별 상태}
|
|
||||||
Event -> EventDB: 이벤트 상태 업데이트\nAPPROVED → ACTIVE
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
|
|
||||||
Event --> Gateway: 200 OK\n{eventId, 배포결과}
|
|
||||||
Gateway --> FE: 배포 완료
|
|
||||||
FE --> User: "이벤트가 배포되었습니다"\n대시보드로 이동
|
|
||||||
|
|
||||||
note over Event, Dist: 배포 실패 시\n- 채널별 독립 처리\n- 자동 재시도 (최대 3회)\n- Circuit Breaker로 장애 전파 방지\n- 실패한 채널만 재시도 가능
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
@ -1,211 +0,0 @@
|
|||||||
@startuml 이벤트생성플로우
|
|
||||||
!theme mono
|
|
||||||
|
|
||||||
title 이벤트 생성 플로우 - 외부 시퀀스 다이어그램
|
|
||||||
|
|
||||||
actor Client
|
|
||||||
actor "소상공인" as User
|
|
||||||
participant "Frontend" as FE
|
|
||||||
participant "API Gateway" as Gateway
|
|
||||||
participant "Event Service" as Event
|
|
||||||
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
|
|
||||||
participant "배포 채널 APIs" as ChannelApis
|
|
||||||
|
|
||||||
== 1. 이벤트 목적 선택 (UFR-EVENT-020) ==
|
|
||||||
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 추천 화면으로 이동
|
|
||||||
|
|
||||||
== 2. AI 이벤트 추천 - 비동기 처리 (UFR-EVENT-030) ==
|
|
||||||
User -> FE: AI 추천 요청
|
|
||||||
FE -> Gateway: POST /events/recommendations\n{eventDraftId, 목적, 업종, 지역}
|
|
||||||
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-job-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: 추천 결과 저장
|
|
||||||
EventDB --> AI: 저장 완료
|
|
||||||
AI -> Cache: Job 상태 업데이트\nkey: job:{jobId}\nstatus: COMPLETED
|
|
||||||
AI -> Kafka: Publish to event-topic\nEventRecommended\n{jobId, eventDraftId, recommendations}
|
|
||||||
|
|
||||||
group Polling으로 상태 확인
|
|
||||||
loop 상태 확인 (최대 30초)
|
|
||||||
FE -> Gateway: GET /jobs/{jobId}/status
|
|
||||||
Gateway -> Event: Job 상태 조회
|
|
||||||
Event -> Cache: 캐시에서 Job 상태 확인
|
|
||||||
Cache --> Event: {status, result}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, recommendations}
|
|
||||||
Gateway --> FE: 추천 결과 반환
|
|
||||||
FE --> User: 3가지 추천안 표시\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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 콘텐츠 생성 화면으로 이동
|
|
||||||
|
|
||||||
== 3. SNS 이미지 생성 - 비동기 처리 (UFR-CONT-010) ==
|
|
||||||
User -> FE: 이미지 생성 요청
|
|
||||||
FE -> Gateway: POST /contents/images\n{eventDraftId, 이벤트정보}
|
|
||||||
Gateway -> Event: 이미지 생성 요청
|
|
||||||
Event -> Kafka: Publish to image-job-topic\n{jobId, eventDraftId, 이벤트정보}
|
|
||||||
Event --> Gateway: Job 생성 완료\n{jobId, status: PENDING}
|
|
||||||
Gateway --> FE: 202 Accepted\n{jobId}
|
|
||||||
FE --> User: "이미지 생성 중..." (로딩)
|
|
||||||
|
|
||||||
note over Content: Kafka Consumer\nimage-job-topic 구독
|
|
||||||
Kafka --> Content: Consume Job Message\n{jobId, eventDraftId, ...}
|
|
||||||
|
|
||||||
group parallel
|
|
||||||
Content -> ImageApi: 심플 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 심플 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 화려한 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 화려한 이미지 URL
|
|
||||||
and
|
|
||||||
Content -> ImageApi: 트렌디 스타일 생성 요청
|
|
||||||
ImageApi --> Content: 트렌디 이미지 URL
|
|
||||||
end
|
|
||||||
|
|
||||||
Content -> EventDB: 이미지 URL 저장
|
|
||||||
EventDB --> Content: 저장 완료
|
|
||||||
Content -> Cache: Job 상태 업데이트\nkey: job:{jobId}\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}
|
|
||||||
|
|
||||||
alt Job 완료
|
|
||||||
Event --> Gateway: 200 OK\n{status: COMPLETED, imageUrls}
|
|
||||||
Gateway --> FE: 이미지 URL 반환
|
|
||||||
FE --> User: 3가지 스타일 카드 표시
|
|
||||||
else Job 진행중
|
|
||||||
Event --> 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 -> EventDB: 이벤트 초안 업데이트
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
Event --> Gateway: 200 OK
|
|
||||||
Gateway --> FE: 저장 완료
|
|
||||||
FE --> User: 배포 채널 선택 화면으로 이동
|
|
||||||
|
|
||||||
== 4. 최종 승인 및 다중 채널 배포 - 동기 처리 (UFR-EVENT-050) ==
|
|
||||||
User -> FE: 배포 채널 선택\n최종 승인 요청
|
|
||||||
FE -> Gateway: POST /events/{eventDraftId}/approve\n{선택 채널 목록, 승인}
|
|
||||||
Gateway -> Event: 최종 승인 처리
|
|
||||||
Event -> EventDB: 이벤트 상태 변경\nDRAFT → APPROVED
|
|
||||||
EventDB --> Event: 상태 변경 완료
|
|
||||||
Event -> Kafka: Publish to event-topic\nEventCreated\n{eventId, 이벤트정보}
|
|
||||||
|
|
||||||
note over Event: 동기 호출로 배포 진행
|
|
||||||
Event -> Dist: REST API - 배포 요청\nPOST /distributions\n{eventId, channels, content}
|
|
||||||
|
|
||||||
note over Dist: Circuit Breaker 적용
|
|
||||||
|
|
||||||
group parallel
|
|
||||||
alt 우리동네TV 선택
|
|
||||||
Dist -> ChannelApis: 우리동네TV API\n15초 영상 업로드
|
|
||||||
ChannelApis --> Dist: 배포 완료\n{배포ID, 예상노출수}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 링고비즈 선택
|
|
||||||
Dist -> ChannelApis: 링고비즈 API\n연결음 업데이트
|
|
||||||
ChannelApis --> Dist: 업데이트 완료\n{완료시각}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt 지니TV 선택
|
|
||||||
Dist -> ChannelApis: 지니TV API\n광고 등록
|
|
||||||
ChannelApis --> Dist: 광고 등록 완료\n{광고ID, 스케줄}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Instagram 선택
|
|
||||||
Dist -> ChannelApis: Instagram API\n포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Naver Blog 선택
|
|
||||||
Dist -> ChannelApis: Naver API\n블로그 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
and
|
|
||||||
alt Kakao Channel 선택
|
|
||||||
Dist -> ChannelApis: Kakao API\n채널 포스팅
|
|
||||||
ChannelApis --> Dist: 포스팅 완료\n{postUrl}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Dist -> EventDB: 배포 이력 저장
|
|
||||||
EventDB --> Dist: 저장 완료
|
|
||||||
|
|
||||||
Dist -> Kafka: Publish to event-topic\nDistributionCompleted\n{eventId, 배포결과}
|
|
||||||
|
|
||||||
Dist --> Event: REST API 응답\n200 OK\n{배포결과, 채널별 상태}
|
|
||||||
Event -> EventDB: 이벤트 상태 업데이트\nAPPROVED → ACTIVE
|
|
||||||
EventDB --> Event: 업데이트 완료
|
|
||||||
|
|
||||||
Event --> Gateway: 200 OK\n{eventId, 배포결과}
|
|
||||||
Gateway --> FE: 배포 완료
|
|
||||||
FE --> User: "이벤트가 배포되었습니다"\n대시보드로 이동
|
|
||||||
|
|
||||||
note over Event, Dist: 배포 실패 시\n- 채널별 독립 처리\n- 자동 재시도 (최대 3회)\n- Circuit Breaker로 장애 전파 방지\n- 실패한 채널만 재시도 가능
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
Loading…
x
Reference in New Issue
Block a user