mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 16:46:23 +00:00
✨ 주요 기능 - Azure 기반 물리아키텍처 설계 (개발환경/운영환경) - 7개 마이크로서비스 물리 구조 설계 - 네트워크 아키텍처 다이어그램 작성 (Mermaid) - 환경별 비교 분석 및 마스터 인덱스 문서 📁 생성 파일 - design/backend/physical/physical-architecture.md (마스터) - design/backend/physical/physical-architecture-dev.md (개발환경) - design/backend/physical/physical-architecture-prod.md (운영환경) - design/backend/physical/*.mmd (4개 Mermaid 다이어그램) 🎯 핵심 성과 - 비용 최적화: 개발환경 월 $143, 운영환경 월 $2,860 - 확장성: 개발환경 100명 → 운영환경 10,000명 (100배) - 가용성: 개발환경 95% → 운영환경 99.9% - 보안: 다층 보안 아키텍처 (L1~L4) 🛠️ 기술 스택 - Azure Kubernetes Service (AKS) - Azure Database for PostgreSQL Flexible - Azure Cache for Redis Premium - Azure Service Bus Premium - Application Gateway + WAF 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
739 lines
26 KiB
Plaintext
739 lines
26 KiB
Plaintext
@startuml
|
|
!theme mono
|
|
|
|
title Analytics Service 클래스 다이어그램 (상세)
|
|
|
|
' ============================================================
|
|
' Presentation Layer - Controller
|
|
' ============================================================
|
|
package "com.kt.event.analytics.controller" <<Rectangle>> #F0F8FF {
|
|
|
|
class AnalyticsDashboardController {
|
|
- analyticsService: AnalyticsService
|
|
+ getEventAnalytics(eventId: String, startDate: LocalDateTime, endDate: LocalDateTime, refresh: Boolean): ResponseEntity<ApiResponse<AnalyticsDashboardResponse>>
|
|
}
|
|
|
|
class ChannelAnalyticsController {
|
|
- channelAnalyticsService: ChannelAnalyticsService
|
|
+ getChannelAnalytics(eventId: String, channels: String, sortBy: String, sortOrder: String): ResponseEntity<ApiResponse<ChannelAnalyticsResponse>>
|
|
}
|
|
|
|
class RoiAnalyticsController {
|
|
- roiAnalyticsService: RoiAnalyticsService
|
|
+ getRoiAnalytics(eventId: String): ResponseEntity<ApiResponse<RoiAnalyticsResponse>>
|
|
}
|
|
|
|
class TimelineAnalyticsController {
|
|
- timelineAnalyticsService: TimelineAnalyticsService
|
|
+ getTimelineAnalytics(eventId: String, granularity: String, startDate: LocalDateTime, endDate: LocalDateTime): ResponseEntity<ApiResponse<TimelineAnalyticsResponse>>
|
|
}
|
|
|
|
class UserAnalyticsDashboardController {
|
|
- userAnalyticsService: UserAnalyticsService
|
|
+ getUserEventAnalytics(userId: String, startDate: LocalDateTime, endDate: LocalDateTime): ResponseEntity<ApiResponse<UserAnalyticsDashboardResponse>>
|
|
}
|
|
|
|
class UserChannelAnalyticsController {
|
|
- userChannelAnalyticsService: UserChannelAnalyticsService
|
|
+ getUserChannelAnalytics(userId: String, channels: String): ResponseEntity<ApiResponse<UserChannelAnalyticsResponse>>
|
|
}
|
|
|
|
class UserRoiAnalyticsController {
|
|
- userRoiAnalyticsService: UserRoiAnalyticsService
|
|
+ getUserRoiAnalytics(userId: String): ResponseEntity<ApiResponse<UserRoiAnalyticsResponse>>
|
|
}
|
|
|
|
class UserTimelineAnalyticsController {
|
|
- userTimelineAnalyticsService: UserTimelineAnalyticsService
|
|
+ getUserTimelineAnalytics(userId: String, granularity: String, startDate: LocalDateTime, endDate: LocalDateTime): ResponseEntity<ApiResponse<UserTimelineAnalyticsResponse>>
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' Business Layer - Service
|
|
' ============================================================
|
|
package "com.kt.event.analytics.service" <<Rectangle>> #E6F7E6 {
|
|
|
|
class AnalyticsService {
|
|
- eventStatsRepository: EventStatsRepository
|
|
- channelStatsRepository: ChannelStatsRepository
|
|
- externalChannelService: ExternalChannelService
|
|
- roiCalculator: ROICalculator
|
|
- redisTemplate: RedisTemplate<String, String>
|
|
- objectMapper: ObjectMapper
|
|
+ getDashboardData(eventId: String, startDate: LocalDateTime, endDate: LocalDateTime, refresh: boolean): AnalyticsDashboardResponse
|
|
- buildDashboardData(eventStats: EventStats, channelStatsList: List<ChannelStats>, startDate: LocalDateTime, endDate: LocalDateTime): AnalyticsDashboardResponse
|
|
- buildPeriodInfo(startDate: LocalDateTime, endDate: LocalDateTime): PeriodInfo
|
|
- buildAnalyticsSummary(eventStats: EventStats, channelStatsList: List<ChannelStats>): AnalyticsSummary
|
|
- buildChannelPerformance(channelStatsList: List<ChannelStats>, totalInvestment: BigDecimal): List<ChannelSummary>
|
|
}
|
|
|
|
class ChannelAnalyticsService {
|
|
- channelStatsRepository: ChannelStatsRepository
|
|
- externalChannelService: ExternalChannelService
|
|
- redisTemplate: RedisTemplate<String, String>
|
|
- objectMapper: ObjectMapper
|
|
+ getChannelAnalytics(eventId: String, channels: List<String>, sortBy: String, sortOrder: String): ChannelAnalyticsResponse
|
|
- buildChannelMetrics(channelStats: ChannelStats): ChannelMetrics
|
|
- buildChannelPerformance(channelStats: ChannelStats): ChannelPerformance
|
|
- buildChannelComparison(channelStatsList: List<ChannelStats>): ChannelComparison
|
|
}
|
|
|
|
class RoiAnalyticsService {
|
|
- eventStatsRepository: EventStatsRepository
|
|
- channelStatsRepository: ChannelStatsRepository
|
|
- roiCalculator: ROICalculator
|
|
- redisTemplate: RedisTemplate<String, String>
|
|
- objectMapper: ObjectMapper
|
|
+ getRoiAnalytics(eventId: String): RoiAnalyticsResponse
|
|
- buildRoiCalculation(eventStats: EventStats, channelStatsList: List<ChannelStats>): RoiCalculation
|
|
- buildInvestmentDetails(channelStatsList: List<ChannelStats>): InvestmentDetails
|
|
- buildRevenueDetails(eventStats: EventStats): RevenueDetails
|
|
}
|
|
|
|
class TimelineAnalyticsService {
|
|
- timelineDataRepository: TimelineDataRepository
|
|
- eventStatsRepository: EventStatsRepository
|
|
- redisTemplate: RedisTemplate<String, String>
|
|
- objectMapper: ObjectMapper
|
|
+ getTimelineAnalytics(eventId: String, granularity: String, startDate: LocalDateTime, endDate: LocalDateTime): TimelineAnalyticsResponse
|
|
- buildTimelineDataPoints(timelineDataList: List<TimelineData>): List<TimelineDataPoint>
|
|
- buildTrendAnalysis(timelineDataList: List<TimelineData>): TrendAnalysis
|
|
- buildPeakTimeInfo(timelineDataList: List<TimelineData>): PeakTimeInfo
|
|
}
|
|
|
|
class UserAnalyticsService {
|
|
- eventStatsRepository: EventStatsRepository
|
|
- channelStatsRepository: ChannelStatsRepository
|
|
- roiCalculator: ROICalculator
|
|
+ getUserEventAnalytics(userId: String, startDate: LocalDateTime, endDate: LocalDateTime): UserAnalyticsDashboardResponse
|
|
- buildUserAnalyticsSummary(eventStatsList: List<EventStats>, channelStatsList: List<ChannelStats>): AnalyticsSummary
|
|
}
|
|
|
|
class UserChannelAnalyticsService {
|
|
- channelStatsRepository: ChannelStatsRepository
|
|
- eventStatsRepository: EventStatsRepository
|
|
+ getUserChannelAnalytics(userId: String, channels: List<String>): UserChannelAnalyticsResponse
|
|
}
|
|
|
|
class UserRoiAnalyticsService {
|
|
- eventStatsRepository: EventStatsRepository
|
|
- channelStatsRepository: ChannelStatsRepository
|
|
- roiCalculator: ROICalculator
|
|
+ getUserRoiAnalytics(userId: String): UserRoiAnalyticsResponse
|
|
}
|
|
|
|
class UserTimelineAnalyticsService {
|
|
- timelineDataRepository: TimelineDataRepository
|
|
- eventStatsRepository: EventStatsRepository
|
|
+ getUserTimelineAnalytics(userId: String, granularity: String, startDate: LocalDateTime, endDate: LocalDateTime): UserTimelineAnalyticsResponse
|
|
}
|
|
|
|
class ExternalChannelService {
|
|
+ updateChannelStatsFromExternalAPIs(eventId: String, channelStatsList: List<ChannelStats>): void
|
|
- updateChannelStatsFromAPI(eventId: String, channelStats: ChannelStats): void
|
|
- updateWooriTVStats(eventId: String, channelStats: ChannelStats): void
|
|
- wooriTVFallback(eventId: String, channelStats: ChannelStats, e: Exception): void
|
|
- updateGenieTVStats(eventId: String, channelStats: ChannelStats): void
|
|
- genieTVFallback(eventId: String, channelStats: ChannelStats, e: Exception): void
|
|
- updateRingoBizStats(eventId: String, channelStats: ChannelStats): void
|
|
- ringoBizFallback(eventId: String, channelStats: ChannelStats, e: Exception): void
|
|
- updateSNSStats(eventId: String, channelStats: ChannelStats): void
|
|
- snsFallback(eventId: String, channelStats: ChannelStats, e: Exception): void
|
|
}
|
|
|
|
class ROICalculator {
|
|
+ calculateRoiSummary(eventStats: EventStats): RoiSummary
|
|
+ calculateRoi(investment: BigDecimal, revenue: BigDecimal): BigDecimal
|
|
+ calculateCostPerParticipant(totalInvestment: BigDecimal, participants: int): BigDecimal
|
|
+ calculateRevenueProjection(currentRevenue: BigDecimal, targetRoi: BigDecimal): RevenueProjection
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' Data Access Layer - Repository
|
|
' ============================================================
|
|
package "com.kt.event.analytics.repository" <<Rectangle>> #FFF8DC {
|
|
|
|
interface EventStatsRepository {
|
|
+ findByEventId(eventId: String): Optional<EventStats>
|
|
+ findByUserId(userId: String): List<EventStats>
|
|
+ save(eventStats: EventStats): EventStats
|
|
+ findAll(): List<EventStats>
|
|
}
|
|
|
|
interface ChannelStatsRepository {
|
|
+ findByEventId(eventId: String): List<ChannelStats>
|
|
+ findByEventIdAndChannelName(eventId: String, channelName: String): Optional<ChannelStats>
|
|
+ findByEventIdIn(eventIds: List<String>): List<ChannelStats>
|
|
+ save(channelStats: ChannelStats): ChannelStats
|
|
}
|
|
|
|
interface TimelineDataRepository {
|
|
+ findByEventIdOrderByTimestampAsc(eventId: String): List<TimelineData>
|
|
+ findByEventIdAndTimestampBetween(eventId: String, startDate: LocalDateTime, endDate: LocalDateTime): List<TimelineData>
|
|
+ findByEventIdIn(eventIds: List<String>): List<TimelineData>
|
|
+ save(timelineData: TimelineData): TimelineData
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' Domain Layer - Entity
|
|
' ============================================================
|
|
package "com.kt.event.analytics.entity" <<Rectangle>> #FFFACD {
|
|
|
|
class EventStats {
|
|
- id: Long
|
|
- eventId: String
|
|
- eventTitle: String
|
|
- userId: String
|
|
- totalParticipants: Integer
|
|
- totalViews: Integer
|
|
- estimatedRoi: BigDecimal
|
|
- targetRoi: BigDecimal
|
|
- salesGrowthRate: BigDecimal
|
|
- totalInvestment: BigDecimal
|
|
- expectedRevenue: BigDecimal
|
|
- status: String
|
|
+ incrementParticipants(): void
|
|
+ incrementParticipants(count: int): void
|
|
}
|
|
|
|
class ChannelStats {
|
|
- id: Long
|
|
- eventId: String
|
|
- channelName: String
|
|
- channelType: String
|
|
- impressions: Integer
|
|
- views: Integer
|
|
- clicks: Integer
|
|
- participants: Integer
|
|
- conversions: Integer
|
|
- distributionCost: BigDecimal
|
|
- likes: Integer
|
|
- comments: Integer
|
|
- shares: Integer
|
|
- totalCalls: Integer
|
|
- completedCalls: Integer
|
|
- averageDuration: Integer
|
|
}
|
|
|
|
class TimelineData {
|
|
- id: Long
|
|
- eventId: String
|
|
- timestamp: LocalDateTime
|
|
- participants: Integer
|
|
- views: Integer
|
|
- engagement: Integer
|
|
- conversions: Integer
|
|
- cumulativeParticipants: Integer
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' DTO Layer
|
|
' ============================================================
|
|
package "com.kt.event.analytics.dto.response" <<Rectangle>> #E6E6FA {
|
|
|
|
class AnalyticsDashboardResponse {
|
|
- eventId: String
|
|
- eventTitle: String
|
|
- period: PeriodInfo
|
|
- summary: AnalyticsSummary
|
|
- channelPerformance: List<ChannelSummary>
|
|
- roi: RoiSummary
|
|
- lastUpdatedAt: LocalDateTime
|
|
- dataSource: String
|
|
}
|
|
|
|
class AnalyticsSummary {
|
|
- participants: Integer
|
|
- participantsDelta: Integer
|
|
- totalViews: Integer
|
|
- totalReach: Integer
|
|
- engagementRate: Double
|
|
- conversionRate: Double
|
|
- averageEngagementTime: Integer
|
|
- targetRoi: Double
|
|
- socialInteractions: SocialInteractionStats
|
|
}
|
|
|
|
class ChannelSummary {
|
|
- channel: String
|
|
- views: Integer
|
|
- participants: Integer
|
|
- engagementRate: Double
|
|
- conversionRate: Double
|
|
- roi: Double
|
|
}
|
|
|
|
class PeriodInfo {
|
|
- startDate: LocalDateTime
|
|
- endDate: LocalDateTime
|
|
- durationDays: Integer
|
|
}
|
|
|
|
class SocialInteractionStats {
|
|
- likes: Integer
|
|
- comments: Integer
|
|
- shares: Integer
|
|
}
|
|
|
|
class RoiSummary {
|
|
- currentRoi: Double
|
|
- targetRoi: Double
|
|
- achievementRate: Double
|
|
- expectedReturn: BigDecimal
|
|
- totalInvestment: BigDecimal
|
|
}
|
|
|
|
class ChannelAnalyticsResponse {
|
|
- eventId: String
|
|
- eventTitle: String
|
|
- totalChannels: Integer
|
|
- channels: List<ChannelAnalytics>
|
|
- comparison: ChannelComparison
|
|
- lastUpdatedAt: LocalDateTime
|
|
}
|
|
|
|
class ChannelAnalytics {
|
|
- channelName: String
|
|
- channelType: String
|
|
- metrics: ChannelMetrics
|
|
- performance: ChannelPerformance
|
|
- costs: ChannelCosts
|
|
- voiceCallStats: VoiceCallStats
|
|
- socialStats: SocialInteractionStats
|
|
}
|
|
|
|
class ChannelMetrics {
|
|
- impressions: Integer
|
|
- views: Integer
|
|
- clicks: Integer
|
|
- participants: Integer
|
|
- conversions: Integer
|
|
}
|
|
|
|
class ChannelPerformance {
|
|
- engagementRate: Double
|
|
- clickThroughRate: Double
|
|
- conversionRate: Double
|
|
- participationRate: Double
|
|
}
|
|
|
|
class ChannelCosts {
|
|
- distributionCost: BigDecimal
|
|
- costPerImpression: BigDecimal
|
|
- costPerClick: BigDecimal
|
|
- costPerParticipant: BigDecimal
|
|
}
|
|
|
|
class ChannelComparison {
|
|
- bestPerformingChannel: String
|
|
- mostCostEffectiveChannel: String
|
|
- highestEngagementChannel: String
|
|
}
|
|
|
|
class VoiceCallStats {
|
|
- totalCalls: Integer
|
|
- completedCalls: Integer
|
|
- completionRate: Double
|
|
- averageDuration: Integer
|
|
}
|
|
|
|
class RoiAnalyticsResponse {
|
|
- eventId: String
|
|
- eventTitle: String
|
|
- roiCalculation: RoiCalculation
|
|
- investment: InvestmentDetails
|
|
- revenue: RevenueDetails
|
|
- costEfficiency: CostEfficiency
|
|
- projection: RevenueProjection
|
|
- lastUpdatedAt: LocalDateTime
|
|
}
|
|
|
|
class RoiCalculation {
|
|
- currentRoi: Double
|
|
- targetRoi: Double
|
|
- achievementRate: Double
|
|
- breakEvenPoint: BigDecimal
|
|
}
|
|
|
|
class InvestmentDetails {
|
|
- totalInvestment: BigDecimal
|
|
- channelDistribution: Map<String, BigDecimal>
|
|
- costPerChannel: Map<String, BigDecimal>
|
|
}
|
|
|
|
class RevenueDetails {
|
|
- expectedRevenue: BigDecimal
|
|
- currentRevenue: BigDecimal
|
|
- salesGrowthRate: Double
|
|
}
|
|
|
|
class CostEfficiency {
|
|
- costPerParticipant: BigDecimal
|
|
- costPerConversion: BigDecimal
|
|
- costPerView: BigDecimal
|
|
}
|
|
|
|
class RevenueProjection {
|
|
- projectedRevenue: BigDecimal
|
|
- projectedRoi: Double
|
|
- estimatedGrowth: Double
|
|
}
|
|
|
|
class TimelineAnalyticsResponse {
|
|
- eventId: String
|
|
- eventTitle: String
|
|
- granularity: String
|
|
- period: PeriodInfo
|
|
- dataPoints: List<TimelineDataPoint>
|
|
- trend: TrendAnalysis
|
|
- peakTime: PeakTimeInfo
|
|
- lastUpdatedAt: LocalDateTime
|
|
}
|
|
|
|
class TimelineDataPoint {
|
|
- timestamp: LocalDateTime
|
|
- participants: Integer
|
|
- views: Integer
|
|
- engagement: Integer
|
|
- conversions: Integer
|
|
- cumulativeParticipants: Integer
|
|
}
|
|
|
|
class TrendAnalysis {
|
|
- growthRate: Double
|
|
- averageParticipantsPerHour: Double
|
|
- totalEngagement: Integer
|
|
- conversionTrend: String
|
|
}
|
|
|
|
class PeakTimeInfo {
|
|
- peakTimestamp: LocalDateTime
|
|
- peakParticipants: Integer
|
|
- peakHour: Integer
|
|
}
|
|
|
|
class UserAnalyticsDashboardResponse {
|
|
- userId: String
|
|
- totalEvents: Integer
|
|
- period: PeriodInfo
|
|
- summary: AnalyticsSummary
|
|
- events: List<AnalyticsDashboardResponse>
|
|
- lastUpdatedAt: LocalDateTime
|
|
}
|
|
|
|
class UserChannelAnalyticsResponse {
|
|
- userId: String
|
|
- totalEvents: Integer
|
|
- channels: List<ChannelAnalytics>
|
|
- comparison: ChannelComparison
|
|
- lastUpdatedAt: LocalDateTime
|
|
}
|
|
|
|
class UserRoiAnalyticsResponse {
|
|
- userId: String
|
|
- totalEvents: Integer
|
|
- roiCalculation: RoiCalculation
|
|
- investment: InvestmentDetails
|
|
- revenue: RevenueDetails
|
|
- lastUpdatedAt: LocalDateTime
|
|
}
|
|
|
|
class UserTimelineAnalyticsResponse {
|
|
- userId: String
|
|
- totalEvents: Integer
|
|
- granularity: String
|
|
- period: PeriodInfo
|
|
- dataPoints: List<TimelineDataPoint>
|
|
- lastUpdatedAt: LocalDateTime
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' Messaging Layer - Kafka Consumer
|
|
' ============================================================
|
|
package "com.kt.event.analytics.messaging.consumer" <<Rectangle>> #FFE4E1 {
|
|
|
|
class EventCreatedConsumer {
|
|
- eventStatsRepository: EventStatsRepository
|
|
- objectMapper: ObjectMapper
|
|
- redisTemplate: RedisTemplate<String, String>
|
|
+ handleEventCreated(message: String): void
|
|
}
|
|
|
|
class ParticipantRegisteredConsumer {
|
|
- eventStatsRepository: EventStatsRepository
|
|
- timelineDataRepository: TimelineDataRepository
|
|
- objectMapper: ObjectMapper
|
|
- redisTemplate: RedisTemplate<String, String>
|
|
+ handleParticipantRegistered(message: String): void
|
|
- updateTimelineData(eventId: String): void
|
|
}
|
|
|
|
class DistributionCompletedConsumer {
|
|
- channelStatsRepository: ChannelStatsRepository
|
|
- objectMapper: ObjectMapper
|
|
- redisTemplate: RedisTemplate<String, String>
|
|
+ handleDistributionCompleted(message: String): void
|
|
}
|
|
}
|
|
|
|
package "com.kt.event.analytics.messaging.event" <<Rectangle>> #FFE4E1 {
|
|
|
|
class EventCreatedEvent {
|
|
- eventId: String
|
|
- eventTitle: String
|
|
- storeId: String
|
|
- totalInvestment: BigDecimal
|
|
- status: String
|
|
}
|
|
|
|
class ParticipantRegisteredEvent {
|
|
- eventId: String
|
|
- participantId: String
|
|
- channelName: String
|
|
- registeredAt: LocalDateTime
|
|
}
|
|
|
|
class DistributionCompletedEvent {
|
|
- eventId: String
|
|
- channelName: String
|
|
- distributionCost: BigDecimal
|
|
- estimatedReach: Integer
|
|
- completedAt: LocalDateTime
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' Batch Layer
|
|
' ============================================================
|
|
package "com.kt.event.analytics.batch" <<Rectangle>> #FFF5EE {
|
|
|
|
class AnalyticsBatchScheduler {
|
|
- analyticsService: AnalyticsService
|
|
- eventStatsRepository: EventStatsRepository
|
|
- redisTemplate: RedisTemplate<String, String>
|
|
+ refreshAnalyticsDashboard(): void
|
|
+ initialDataLoad(): void
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' Configuration Layer
|
|
' ============================================================
|
|
package "com.kt.event.analytics.config" <<Rectangle>> #F5F5F5 {
|
|
|
|
class RedisConfig {
|
|
+ redisConnectionFactory(): RedisConnectionFactory
|
|
+ redisTemplate(): RedisTemplate<String, String>
|
|
}
|
|
|
|
class KafkaConsumerConfig {
|
|
+ consumerFactory(): ConsumerFactory<String, String>
|
|
+ kafkaListenerContainerFactory(): ConcurrentKafkaListenerContainerFactory<String, String>
|
|
}
|
|
|
|
class KafkaTopicConfig {
|
|
+ sampleEventCreatedTopic(): NewTopic
|
|
+ sampleParticipantRegisteredTopic(): NewTopic
|
|
+ sampleDistributionCompletedTopic(): NewTopic
|
|
}
|
|
|
|
class Resilience4jConfig {
|
|
+ customize(factory: Resilience4JCircuitBreakerFactory): Customizer<Resilience4JCircuitBreakerFactory>
|
|
}
|
|
|
|
class SecurityConfig {
|
|
+ securityFilterChain(http: HttpSecurity): SecurityFilterChain
|
|
}
|
|
|
|
class SwaggerConfig {
|
|
+ openAPI(): OpenAPI
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' Common Components (from common-base)
|
|
' ============================================================
|
|
package "com.kt.event.common" <<Rectangle>> #DCDCDC {
|
|
|
|
abstract class BaseTimeEntity {
|
|
- createdAt: LocalDateTime
|
|
- updatedAt: LocalDateTime
|
|
}
|
|
|
|
class "ApiResponse<T>" {
|
|
- success: boolean
|
|
- data: T
|
|
- errorCode: String
|
|
- message: String
|
|
- timestamp: LocalDateTime
|
|
+ success(data: T): ApiResponse<T>
|
|
+ success(): ApiResponse<T>
|
|
+ error(errorCode: String, message: String): ApiResponse<T>
|
|
}
|
|
|
|
interface ErrorCode {
|
|
+ getCode(): String
|
|
+ getMessage(): String
|
|
}
|
|
|
|
class BusinessException {
|
|
- errorCode: ErrorCode
|
|
- details: String
|
|
}
|
|
}
|
|
|
|
' ============================================================
|
|
' Relationships
|
|
' ============================================================
|
|
|
|
' Controller -> Service
|
|
AnalyticsDashboardController --> AnalyticsService : uses
|
|
ChannelAnalyticsController --> ChannelAnalyticsService : uses
|
|
RoiAnalyticsController --> RoiAnalyticsService : uses
|
|
TimelineAnalyticsController --> TimelineAnalyticsService : uses
|
|
UserAnalyticsDashboardController --> UserAnalyticsService : uses
|
|
UserChannelAnalyticsController --> UserChannelAnalyticsService : uses
|
|
UserRoiAnalyticsController --> UserRoiAnalyticsService : uses
|
|
UserTimelineAnalyticsController --> UserTimelineAnalyticsService : uses
|
|
|
|
' Service -> Repository
|
|
AnalyticsService --> EventStatsRepository : uses
|
|
AnalyticsService --> ChannelStatsRepository : uses
|
|
ChannelAnalyticsService --> ChannelStatsRepository : uses
|
|
RoiAnalyticsService --> EventStatsRepository : uses
|
|
RoiAnalyticsService --> ChannelStatsRepository : uses
|
|
TimelineAnalyticsService --> TimelineDataRepository : uses
|
|
TimelineAnalyticsService --> EventStatsRepository : uses
|
|
UserAnalyticsService --> EventStatsRepository : uses
|
|
UserAnalyticsService --> ChannelStatsRepository : uses
|
|
UserChannelAnalyticsService --> ChannelStatsRepository : uses
|
|
UserChannelAnalyticsService --> EventStatsRepository : uses
|
|
UserRoiAnalyticsService --> EventStatsRepository : uses
|
|
UserRoiAnalyticsService --> ChannelStatsRepository : uses
|
|
UserTimelineAnalyticsService --> TimelineDataRepository : uses
|
|
UserTimelineAnalyticsService --> EventStatsRepository : uses
|
|
|
|
' Service -> Service
|
|
AnalyticsService --> ExternalChannelService : uses
|
|
AnalyticsService --> ROICalculator : uses
|
|
ChannelAnalyticsService --> ExternalChannelService : uses
|
|
RoiAnalyticsService --> ROICalculator : uses
|
|
UserAnalyticsService --> ROICalculator : uses
|
|
UserRoiAnalyticsService --> ROICalculator : uses
|
|
|
|
' Service -> External Components
|
|
ExternalChannelService --> ChannelStats : modifies
|
|
|
|
' Consumer -> Repository
|
|
EventCreatedConsumer --> EventStatsRepository : uses
|
|
ParticipantRegisteredConsumer --> EventStatsRepository : uses
|
|
ParticipantRegisteredConsumer --> TimelineDataRepository : uses
|
|
DistributionCompletedConsumer --> ChannelStatsRepository : uses
|
|
|
|
' Consumer -> Event
|
|
EventCreatedConsumer --> EventCreatedEvent : consumes
|
|
ParticipantRegisteredConsumer --> ParticipantRegisteredEvent : consumes
|
|
DistributionCompletedConsumer --> DistributionCompletedEvent : consumes
|
|
|
|
' Batch -> Service/Repository
|
|
AnalyticsBatchScheduler --> AnalyticsService : uses
|
|
AnalyticsBatchScheduler --> EventStatsRepository : uses
|
|
|
|
' Repository -> Entity
|
|
EventStatsRepository --> EventStats : manages
|
|
ChannelStatsRepository --> ChannelStats : manages
|
|
TimelineDataRepository --> TimelineData : manages
|
|
|
|
' Entity -> BaseTimeEntity
|
|
EventStats --|> BaseTimeEntity : extends
|
|
ChannelStats --|> BaseTimeEntity : extends
|
|
TimelineData --|> BaseTimeEntity : extends
|
|
|
|
' Controller -> DTO
|
|
AnalyticsDashboardController --> AnalyticsDashboardResponse : returns
|
|
ChannelAnalyticsController --> ChannelAnalyticsResponse : returns
|
|
RoiAnalyticsController --> RoiAnalyticsResponse : returns
|
|
TimelineAnalyticsController --> TimelineAnalyticsResponse : returns
|
|
UserAnalyticsDashboardController --> UserAnalyticsDashboardResponse : returns
|
|
UserChannelAnalyticsController --> UserChannelAnalyticsResponse : returns
|
|
UserRoiAnalyticsController --> UserRoiAnalyticsResponse : returns
|
|
UserTimelineAnalyticsController --> UserTimelineAnalyticsResponse : returns
|
|
|
|
' Service -> DTO
|
|
AnalyticsService --> AnalyticsDashboardResponse : creates
|
|
ChannelAnalyticsService --> ChannelAnalyticsResponse : creates
|
|
RoiAnalyticsService --> RoiAnalyticsResponse : creates
|
|
TimelineAnalyticsService --> TimelineAnalyticsResponse : creates
|
|
UserAnalyticsService --> UserAnalyticsDashboardResponse : creates
|
|
UserChannelAnalyticsService --> UserChannelAnalyticsResponse : creates
|
|
UserRoiAnalyticsService --> UserRoiAnalyticsResponse : creates
|
|
UserTimelineAnalyticsService --> UserTimelineAnalyticsResponse : creates
|
|
|
|
' DTO Composition
|
|
AnalyticsDashboardResponse *-- PeriodInfo : contains
|
|
AnalyticsDashboardResponse *-- AnalyticsSummary : contains
|
|
AnalyticsDashboardResponse *-- RoiSummary : contains
|
|
AnalyticsSummary *-- SocialInteractionStats : contains
|
|
ChannelAnalyticsResponse *-- ChannelAnalytics : contains
|
|
ChannelAnalyticsResponse *-- ChannelComparison : contains
|
|
ChannelAnalytics *-- ChannelMetrics : contains
|
|
ChannelAnalytics *-- ChannelPerformance : contains
|
|
ChannelAnalytics *-- ChannelCosts : contains
|
|
ChannelAnalytics *-- VoiceCallStats : contains
|
|
RoiAnalyticsResponse *-- RoiCalculation : contains
|
|
RoiAnalyticsResponse *-- InvestmentDetails : contains
|
|
RoiAnalyticsResponse *-- RevenueDetails : contains
|
|
RoiAnalyticsResponse *-- CostEfficiency : contains
|
|
RoiAnalyticsResponse *-- RevenueProjection : contains
|
|
TimelineAnalyticsResponse *-- PeriodInfo : contains
|
|
TimelineAnalyticsResponse *-- TimelineDataPoint : contains
|
|
TimelineAnalyticsResponse *-- TrendAnalysis : contains
|
|
TimelineAnalyticsResponse *-- PeakTimeInfo : contains
|
|
UserAnalyticsDashboardResponse *-- PeriodInfo : contains
|
|
UserAnalyticsDashboardResponse *-- AnalyticsSummary : contains
|
|
|
|
' Common Dependencies
|
|
BusinessException --> ErrorCode : uses
|
|
AnalyticsDashboardController --> "ApiResponse<T>" : uses
|
|
ChannelAnalyticsController --> "ApiResponse<T>" : uses
|
|
RoiAnalyticsController --> "ApiResponse<T>" : uses
|
|
TimelineAnalyticsController --> "ApiResponse<T>" : uses
|
|
|
|
note top of AnalyticsService
|
|
**핵심 서비스**
|
|
- Redis 캐싱 (1시간 TTL)
|
|
- 외부 API 병렬 호출
|
|
- Circuit Breaker 패턴
|
|
- Cache-Aside 패턴
|
|
end note
|
|
|
|
note top of ExternalChannelService
|
|
**외부 채널 통합**
|
|
- 우리동네TV API
|
|
- 지니TV API
|
|
- 링고비즈 API
|
|
- SNS APIs
|
|
- Resilience4j Circuit Breaker
|
|
end note
|
|
|
|
note top of EventCreatedConsumer
|
|
**Kafka Event Consumer**
|
|
- EventCreated 이벤트 구독
|
|
- 멱등성 처리 (Redis Set)
|
|
- 캐시 무효화
|
|
end note
|
|
|
|
note top of AnalyticsBatchScheduler
|
|
**배치 스케줄러**
|
|
- 5분 단위 캐시 갱신
|
|
- 초기 데이터 로딩
|
|
- 캐시 워밍업
|
|
end note
|
|
|
|
@enduml
|