@startuml !theme mono title Event Service 클래스 다이어그램 (요약) ' ============================== ' Domain Layer (핵심 비즈니스) ' ============================== package "Domain Layer" <> { class Event { - eventId: UUID - status: EventStatus - eventName, description: String - startDate, endDate: LocalDate - selectedImageId: UUID - channels: List -- + publish(): void + end(): void + updateEventPeriod(): void + selectImage(): void + isModifiable(): boolean } class Job { - jobId: UUID - jobType: JobType - status: JobStatus - progress: int -- + start(): void + complete(): void + fail(): void } enum EventStatus { DRAFT PUBLISHED ENDED } enum JobStatus { PENDING PROCESSING COMPLETED FAILED } interface EventRepository { + findByEventIdAndUserId(): Optional + findEventsByUser(): Page } interface JobRepository { + findByEventId(): List } } ' ============================== ' Application Layer (유스케이스) ' ============================== package "Application Layer" <> { class EventService { - eventRepository - jobRepository - contentServiceClient - aiJobKafkaProducer -- + createEvent(): EventCreatedResponse + getEvent(): EventDetailResponse + publishEvent(): void + requestAiRecommendations(): JobAcceptedResponse + selectRecommendation(): void + requestImageGeneration(): ImageGenerationResponse + selectImage(): void + selectChannels(): void } class JobService { - jobRepository -- + getJobStatus(): JobStatusResponse + completeJob(): void + failJob(): void } package "DTOs" { class "Request DTOs" { SelectObjectiveRequest AiRecommendationRequest SelectRecommendationRequest ImageGenerationRequest SelectImageRequest SelectChannelsRequest } class "Response DTOs" { EventCreatedResponse EventDetailResponse JobAcceptedResponse JobStatusResponse ImageGenerationResponse } } } ' ============================== ' Infrastructure Layer (기술 구현) ' ============================== package "Infrastructure Layer" <> { class AIJobKafkaProducer { + publishAIGenerationJob(): void + publishMessage(): void } class AIJobKafkaConsumer { + consumeAIEventGenerationJob(): void } interface ContentServiceClient { + generateImages(): ContentJobResponse } class RedisConfig { + redisTemplate(): RedisTemplate } } ' ============================== ' Presentation Layer (API) ' ============================== package "Presentation Layer" <> { class EventController { - eventService -- POST /objectives GET /events GET /events/{id} DELETE /events/{id} POST /events/{id}/publish POST /events/{id}/ai-recommendations PUT /events/{id}/recommendations POST /events/{id}/images PUT /events/{id}/images/{imageId}/select PUT /events/{id}/channels } class JobController { - jobService -- GET /jobs/{id} } } ' ============================== ' 관계 정의 (간소화) ' ============================== ' Domain Layer Event ..> EventStatus Job ..> JobStatus EventRepository ..> Event JobRepository ..> Job ' Application → Domain EventService --> EventRepository EventService --> JobRepository JobService --> JobRepository ' Application → Infrastructure EventService --> ContentServiceClient EventService --> AIJobKafkaProducer ' Presentation → Application EventController --> EventService JobController --> JobService ' Application DTOs EventService ..> "Request DTOs" EventService ..> "Response DTOs" ' Infrastructure Kafka AIJobKafkaProducer ..> AIJobKafkaConsumer : pub/sub ' Clean Architecture Flow EventController -[hidden]down-> EventService EventService -[hidden]down-> Event Event -[hidden]down-> EventRepository ' Notes note as N1 **Clean Architecture 계층 구조** 1. **Domain Layer (핵심)** - 비즈니스 로직과 규칙 - 외부 의존성 없음 2. **Application Layer (유스케이스)** - 도메인 로직 조율 - 트랜잭션 경계 3. **Infrastructure Layer (기술)** - Kafka, Feign, Redis - 외부 시스템 연동 4. **Presentation Layer (API)** - REST 엔드포인트 - 인증/검증 end note note as N2 **핵심 플로우** **이벤트 생성 플로우:** 1. 목적 선택 (DRAFT 생성) 2. AI 추천 요청 (Kafka) 3. 추천 선택 및 커스터마이징 4. 이미지 생성 요청 (Content Service) 5. 이미지 선택 6. 배포 채널 선택 7. 배포 (DRAFT → PUBLISHED) **상태 전이:** DRAFT → PUBLISHED → ENDED end note note as N3 **비동기 작업 처리** - AI 추천 생성: Kafka로 비동기 처리 - 이미지 생성: Content Service 호출 - Job 엔티티로 작업 상태 추적 - Redis 캐시로 결과 임시 저장 end note N1 -[hidden]- N2 N2 -[hidden]- N3 @enduml