@startuml !theme mono title Event Service ERD (Entity Relationship Diagram) ' ============================== ' 엔티티 정의 ' ============================== entity "events" as events { * event_id : UUID <> -- * user_id : UUID <> * store_id : UUID <> event_name : VARCHAR(200) description : TEXT * objective : VARCHAR(100) start_date : DATE end_date : DATE * status : VARCHAR(20) <> selected_image_id : UUID selected_image_url : VARCHAR(500) channels : TEXT * created_at : TIMESTAMP * updated_at : TIMESTAMP } entity "ai_recommendations" as ai_recommendations { * recommendation_id : UUID <> -- * event_id : UUID <> * event_name : VARCHAR(200) * description : TEXT * promotion_type : VARCHAR(50) * target_audience : VARCHAR(100) * is_selected : BOOLEAN <> * created_at : TIMESTAMP * updated_at : TIMESTAMP } entity "generated_images" as generated_images { * image_id : UUID <> -- * event_id : UUID <> * image_url : VARCHAR(500) * style : VARCHAR(50) * platform : VARCHAR(50) * is_selected : BOOLEAN <> * created_at : TIMESTAMP * updated_at : TIMESTAMP } entity "jobs" as jobs { * job_id : UUID <> -- * event_id : UUID * job_type : VARCHAR(50) * status : VARCHAR(20) <> * progress : INT <> result_key : VARCHAR(200) error_message : TEXT completed_at : TIMESTAMP * created_at : TIMESTAMP * updated_at : TIMESTAMP } ' ============================== ' 관계 정의 ' ============================== events ||--o{ ai_recommendations : "has many" events ||--o{ generated_images : "has many" events ||--o{ jobs : "tracks" ' ============================== ' 제약조건 노트 ' ============================== note right of events **핵심 도메인 엔티티** - 상태 머신: DRAFT → PUBLISHED → ENDED - DRAFT에서만 수정 가능 - PUBLISHED에서 END만 가능 - channels: JSON 배열 (["SMS", "EMAIL"]) **인덱스**: - IDX_events_user_id (user_id) - IDX_events_store_id (store_id) - IDX_events_status (status) - IDX_events_user_status (user_id, status) **체크 제약조건**: - status IN ('DRAFT', 'PUBLISHED', 'ENDED') - start_date <= end_date end note note right of ai_recommendations **AI 추천 결과** - 이벤트당 최대 3개 생성 - is_selected=true는 이벤트당 1개만 **인덱스**: - IDX_recommendations_event_id (event_id) - IDX_recommendations_selected (event_id, is_selected) **외래 키**: - FK_recommendations_event (event_id) → events(event_id) ON DELETE CASCADE end note note right of generated_images **생성 이미지 정보** - 여러 스타일/플랫폼 조합 가능 - is_selected=true는 이벤트당 1개만 **인덱스**: - IDX_images_event_id (event_id) - IDX_images_selected (event_id, is_selected) **외래 키**: - FK_images_event (event_id) → events(event_id) ON DELETE CASCADE end note note right of jobs **비동기 작업 추적** - job_type: AI_RECOMMENDATION, IMAGE_GENERATION - status: PENDING → PROCESSING → COMPLETED/FAILED - progress: 0-100 **인덱스**: - IDX_jobs_event_id (event_id) - IDX_jobs_type_status (job_type, status) - IDX_jobs_status (status) **체크 제약조건**: - status IN ('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED') - job_type IN ('AI_RECOMMENDATION', 'IMAGE_GENERATION') - progress BETWEEN 0 AND 100 **외래 키 없음**: 이벤트 삭제 후에도 작업 이력 보존 end note ' ============================== ' Redis 캐시 노트 ' ============================== note top of events **Redis 캐시 전략** 1. event:session:{userId} (TTL: 3600s) - 이벤트 생성 세션 정보 - Hash: eventId, objective, storeId, createdAt 2. event:draft:{eventId} (TTL: 1800s) - DRAFT 상태 이벤트 캐시 - Hash: eventName, description, objective, status, userId, storeId 3. job:status:{jobId} (TTL: 600s) - 작업 상태 실시간 조회 - Hash: jobType, status, progress, eventId end note @enduml