변경 사항: - 이벤트생성플로우 outer: FE → Gateway → User Service 호출 패턴 추가 - user-로그인 inner: 전화번호 → 이메일 기반 인증으로 변경 - user-회원가입 inner: 국세청 API 제거, 이메일 중복검사 추가 - event-목적선택 inner: Gateway 경유, 요청/응답 한글화 - ai-트렌드분석및추천 inner: 과거 이벤트 데이터 제거, Timeout 5분으로 변경 - analytics-대시보드조회 inner: Redis TTL 5분 → 1시간으로 변경 모든 파일에 Repository CRUD 작업 한글 설명 적용 (SQL 제거) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
307 lines
9.1 KiB
Plaintext
307 lines
9.1 KiB
Plaintext
@startuml analytics-대시보드조회
|
||
!theme mono
|
||
|
||
title Analytics Service - 대시보드 조회 내부 시퀀스\n(UFR-ANAL-010: 실시간 성과분석 대시보드 조회)
|
||
|
||
participant "AnalyticsController" as Controller
|
||
participant "AnalyticsService" as Service
|
||
participant "CacheService" as Cache
|
||
participant "AnalyticsRepository" as Repository
|
||
participant "ExternalChannelService" as ChannelService
|
||
participant "ROICalculator" as Calculator
|
||
participant "CircuitBreaker" as CB
|
||
participant "Redis<<E>>" as Redis
|
||
database "Analytics DB<<E>>" as DB
|
||
|
||
-> Controller: GET /api/events/{id}/analytics\n+ Authorization: Bearer {token}
|
||
activate Controller
|
||
|
||
Controller -> Service: getDashboardData(eventId, userId)
|
||
activate Service
|
||
|
||
note right of Service
|
||
**입력 검증**
|
||
- eventId: UUID 형식 검증
|
||
- userId: JWT에서 추출
|
||
- 권한 확인: 매장 소유자 여부
|
||
end note
|
||
|
||
Service -> Cache: get("analytics:dashboard:{eventId}")
|
||
activate Cache
|
||
|
||
note right of Cache
|
||
**Cache-Aside 패턴**
|
||
- Redis GET 호출
|
||
- Cache Key 구조:
|
||
analytics:dashboard:{eventId}
|
||
- TTL: 3600초 (1시간)
|
||
end note
|
||
|
||
Cache -> Redis: GET analytics:dashboard:{eventId}
|
||
activate Redis
|
||
|
||
alt Cache HIT
|
||
|
||
Redis --> Cache: **Cache HIT**\n캐시된 데이터 반환\n{\n totalParticipants: 1234,\n totalViews: 17200,\n roi: 250,\n channelStats: [...],\n lastUpdated: "2025-10-22T10:30:00Z"\n}
|
||
deactivate Redis
|
||
|
||
Cache --> Service: Dashboard 데이터 (JSON)
|
||
deactivate Cache
|
||
|
||
note right of Service
|
||
**응답 데이터 구조**
|
||
- 4개 요약 카드
|
||
* 총 참여자 수, 달성률
|
||
* 총 노출 수, 증감률
|
||
* 예상 ROI, 업종 평균 대비
|
||
* 매출 증가율
|
||
- 채널별 성과
|
||
- 시간대별 참여 추이
|
||
- 참여자 프로필 분석
|
||
- 비교 분석 (업종 평균, 이전 이벤트)
|
||
end note
|
||
|
||
Service --> Controller: DashboardResponse\n(200 OK)
|
||
deactivate Service
|
||
|
||
Controller --> : 200 OK\nDashboard Data (JSON)
|
||
deactivate Controller
|
||
|
||
note over Controller, Redis
|
||
**Cache HIT 시나리오 성능**
|
||
- 응답 시간: 약 0.5초
|
||
- Redis 조회 시간: 0.01초
|
||
- 직렬화/역직렬화: 0.05초
|
||
- HTTP 오버헤드: 0.44초
|
||
- 예상 히트율: 95%
|
||
end note
|
||
|
||
else Cache MISS
|
||
|
||
Redis --> Cache: **Cache MISS** (null)
|
||
deactivate Redis
|
||
|
||
Cache --> Service: null (캐시 미스)
|
||
deactivate Cache
|
||
|
||
note right of Service
|
||
**Cache MISS 처리**
|
||
- 데이터 통합 작업 시작
|
||
- 로컬 DB 조회 + 외부 API 병렬 호출
|
||
end note
|
||
|
||
|||
|
||
== 1. Analytics DB 조회 (로컬 데이터) ==
|
||
|
||
Service -> Repository: getEventStats(eventId)
|
||
activate Repository
|
||
|
||
Repository -> DB: 이벤트 통계 조회\n(이벤트ID로 통계 데이터 조회)
|
||
activate DB
|
||
|
||
DB --> Repository: EventStatsEntity\n- totalParticipants\n- estimatedROI\n- salesGrowthRate
|
||
deactivate DB
|
||
|
||
Repository --> Service: EventStats
|
||
deactivate Repository
|
||
|
||
note right of Service
|
||
**로컬 데이터 확보**
|
||
- 총 참여자 수
|
||
- 예상 ROI (DB 캐시)
|
||
- 매출 증가율 (POS 연동)
|
||
end note
|
||
|
||
|||
|
||
== 2. 외부 채널 API 병렬 호출 (Circuit Breaker 적용) ==
|
||
|
||
note right of Service
|
||
**병렬 처리 시작**
|
||
- CompletableFuture 3개 생성
|
||
- 우리동네TV, 지니TV, SNS APIs 동시 호출
|
||
- Circuit Breaker 적용 (채널별 독립)
|
||
end note
|
||
|
||
par 외부 API 병렬 호출
|
||
|
||
Service -> ChannelService: getWooriTVStats(eventId)
|
||
activate ChannelService
|
||
|
||
ChannelService -> CB: execute("wooriTV", () -> callAPI())
|
||
activate CB
|
||
|
||
note right of CB
|
||
**Circuit Breaker**
|
||
- State: CLOSED (정상)
|
||
- Failure Rate: 50% 초과 시 OPEN
|
||
- Timeout: 10초
|
||
end note
|
||
|
||
CB -> CB: 외부 API 호출\nGET /stats/{eventId}
|
||
|
||
alt Circuit Breaker CLOSED (정상)
|
||
CB --> ChannelService: ChannelStats\n- views: 5000\n- clicks: 1200
|
||
deactivate CB
|
||
|
||
ChannelService --> Service: WooriTVStats
|
||
deactivate ChannelService
|
||
else Circuit Breaker OPEN (장애)
|
||
CB -> CB: **Fallback 실행**\n캐시된 이전 데이터 반환
|
||
note right of CB
|
||
Fallback 전략:
|
||
- Redis에서 이전 통계 조회
|
||
- 없으면 기본값 (0) 반환
|
||
- 알림: "일부 채널 데이터 로딩 실패"
|
||
end note
|
||
CB --> ChannelService: Fallback 데이터
|
||
deactivate CB
|
||
ChannelService --> Service: WooriTVStats (Fallback)
|
||
deactivate ChannelService
|
||
end
|
||
|
||
else
|
||
|
||
Service -> ChannelService: getGenieTVStats(eventId)
|
||
activate ChannelService
|
||
|
||
ChannelService -> CB: execute("genieTV", () -> callAPI())
|
||
activate CB
|
||
|
||
CB -> CB: 외부 API 호출\nGET /campaign/{id}/stats
|
||
|
||
alt 정상 응답
|
||
CB --> ChannelService: ChannelStats\n- adViews: 10000\n- clicks: 500
|
||
deactivate CB
|
||
ChannelService --> Service: GenieTVStats
|
||
deactivate ChannelService
|
||
else Timeout (10초 초과)
|
||
CB -> CB: **Timeout 처리**\n기본값 반환
|
||
note right of CB
|
||
Timeout 발생:
|
||
- 리소스 점유 방지
|
||
- Fallback으로 기본값 (0) 설정
|
||
- 알림: "지니TV 데이터 로딩 지연"
|
||
end note
|
||
CB --> ChannelService: 기본값 (0)
|
||
deactivate CB
|
||
ChannelService --> Service: GenieTVStats (기본값)
|
||
deactivate ChannelService
|
||
end
|
||
|
||
else
|
||
|
||
Service -> ChannelService: getSNSStats(eventId)
|
||
activate ChannelService
|
||
|
||
ChannelService -> CB: execute("SNS", () -> callAPIs())
|
||
activate CB
|
||
|
||
note right of CB
|
||
**SNS APIs 통합 호출**
|
||
- Instagram API
|
||
- Naver Blog API
|
||
- Kakao Channel API
|
||
- 3개 API 병렬 호출
|
||
end note
|
||
|
||
CB -> CB: 외부 APIs 호출\n(Instagram, Naver, Kakao)
|
||
|
||
alt 정상 응답
|
||
CB --> ChannelService: SNSStats\n- Instagram: likes 300, comments 50\n- Naver: views 2000\n- Kakao: shares 100
|
||
deactivate CB
|
||
ChannelService --> Service: SNSStats
|
||
deactivate ChannelService
|
||
else 장애 또는 Timeout
|
||
CB -> CB: **Fallback 실행**\n기본값 반환
|
||
note right of CB
|
||
SNS API 장애:
|
||
- 기본값 (0) 반환
|
||
- 알림: "SNS 데이터 로딩 실패"
|
||
end note
|
||
CB --> ChannelService: 기본값 (0)
|
||
deactivate CB
|
||
ChannelService --> Service: SNSStats (기본값)
|
||
deactivate ChannelService
|
||
end
|
||
|
||
end
|
||
|
||
|||
|
||
== 3. 데이터 통합 및 ROI 계산 ==
|
||
|
||
Service -> Service: mergeChannelStats(\n wooriTV, genieTV, sns\n)
|
||
|
||
note right of Service
|
||
**데이터 통합**
|
||
- 총 노출 수 = 외부 채널 노출 합계
|
||
- 총 참여자 수 = Analytics DB
|
||
- 채널별 전환율 = 참여자 수 / 노출 수
|
||
end note
|
||
|
||
Service -> Calculator: calculateROI(\n eventStats, channelStats\n)
|
||
activate Calculator
|
||
|
||
note right of Calculator
|
||
**ROI 계산 로직**
|
||
총 비용 = 경품 비용 + 플랫폼 비용
|
||
예상 수익 = 매출 증가액 + 신규 고객 LTV
|
||
ROI = (수익 - 비용) / 비용 × 100
|
||
end note
|
||
|
||
Calculator --> Service: ROIData\n- roi: 250%\n- totalCost: 100만원\n- totalRevenue: 350만원\n- breakEvenPoint: 달성
|
||
deactivate Calculator
|
||
|
||
Service -> Service: buildDashboardData(\n eventStats, channelStats, roiData\n)
|
||
|
||
note right of Service
|
||
**대시보드 데이터 구조 생성**
|
||
- 4개 요약 카드
|
||
- 채널별 성과 차트 데이터
|
||
- 시간대별 참여 추이
|
||
- 참여자 프로필 분석
|
||
- 비교 분석 (업종 평균, 이전 이벤트)
|
||
end note
|
||
|
||
|||
|
||
== 4. Redis 캐싱 및 응답 ==
|
||
|
||
Service -> Cache: set(\n "analytics:dashboard:{eventId}",\n dashboardData,\n TTL=3600\n)
|
||
activate Cache
|
||
|
||
Cache -> Redis: 캐시 저장\nSET analytics:dashboard:{eventId}\nvalue={통합 데이터}\nEX 3600 (1시간)
|
||
activate Redis
|
||
|
||
Redis --> Cache: OK (저장 완료)
|
||
deactivate Redis
|
||
|
||
Cache --> Service: OK (캐싱 완료)
|
||
deactivate Cache
|
||
|
||
note right of Service
|
||
**캐싱 완료**
|
||
- TTL: 3600초 (1시간)
|
||
- 다음 조회 시 Cache HIT
|
||
- 예상 크기: 5KB
|
||
- 갱신 주기: 1시간마다 새 데이터 조회
|
||
end note
|
||
|
||
Service --> Controller: DashboardResponse\n(200 OK)
|
||
deactivate Service
|
||
|
||
Controller --> : 200 OK\nDashboard Data (JSON)
|
||
deactivate Controller
|
||
|
||
note over Controller, DB
|
||
**Cache MISS 시나리오 성능**
|
||
- 응답 시간: 약 3초
|
||
- Analytics DB 조회: 0.1초
|
||
- 외부 API 병렬 호출: 2초 (병렬 처리)
|
||
- ROI 계산: 0.05초
|
||
- Redis 캐싱: 0.01초
|
||
- 직렬화/HTTP: 0.84초
|
||
end note
|
||
|
||
end
|
||
|
||
@enduml
|