mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2026-06-13 14:59:13 +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>
This commit is contained in:
@@ -0,0 +1,738 @@
|
||||
@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
|
||||
Reference in New Issue
Block a user