@startuml !theme mono title Content Service - ERD (Entity Relationship Diagram) ' ============================================ ' PostgreSQL 테이블 ' ============================================ entity "content" as content { * id : BIGSERIAL <> -- * event_id : VARCHAR(100) <> * event_title : VARCHAR(200) event_description : TEXT * created_at : TIMESTAMP * updated_at : TIMESTAMP } entity "generated_image" as generated_image { * id : BIGSERIAL <> -- * event_id : VARCHAR(100) <> * style : VARCHAR(20) <> * platform : VARCHAR(30) <> * cdn_url : VARCHAR(500) * prompt : TEXT * selected : BOOLEAN * width : INT * height : INT file_size : BIGINT * content_type : VARCHAR(50) * created_at : TIMESTAMP * updated_at : TIMESTAMP -- <> (event_id) <> (event_id, style, platform) <> (created_at) } entity "job" as job { * id : VARCHAR(100) <> -- * event_id : VARCHAR(100) * job_type : VARCHAR(50) <> * status : VARCHAR(20) <> * progress : INT result_message : TEXT error_message : TEXT * created_at : TIMESTAMP * updated_at : TIMESTAMP completed_at : TIMESTAMP -- <> (event_id) <> (status, created_at) } ' ============================================ ' Redis 캐시 구조 (개념적 표현) ' ============================================ entity "RedisJobData\n(Cache)" as redis_job { * key : job:{jobId} -- id : STRING eventId : STRING jobType : STRING status : STRING progress : INT resultMessage : STRING errorMessage : STRING createdAt : TIMESTAMP updatedAt : TIMESTAMP -- <> 1 hour } entity "RedisImageData\n(Cache)" as redis_image { * key : image:{eventId}:{style}:{platform} -- eventId : STRING style : STRING platform : STRING imageUrl : STRING prompt : STRING createdAt : TIMESTAMP -- <> 7 days } entity "RedisAIEventData\n(Cache)" as redis_ai { * key : ai:event:{eventId} -- eventId : STRING recommendedStyles : LIST recommendedKeywords : LIST cachedAt : TIMESTAMP -- <> 1 hour } ' ============================================ ' 관계 정의 ' ============================================ content ||--o{ generated_image : "has many" content ||--o{ job : "tracks" ' ============================================ ' 캐시 관계 (점선: 논리적 연관) ' ============================================ job ..> redis_job : "cached in" generated_image ..> redis_image : "cached in" ' ============================================ ' 노트 및 설명 ' ============================================ note right of content **콘텐츠 집합** • 이벤트당 하나의 콘텐츠 집합 • event_id로 이미지 그룹핑 • 생성/수정 시각 추적 end note note right of generated_image **생성된 이미지 메타데이터** • CDN URL만 저장 (Azure Blob) • 스타일: FANCY, SIMPLE, TRENDY • 플랫폼: INSTAGRAM, FACEBOOK, KAKAO, BLOG • 플랫폼별 해상도: - INSTAGRAM: 1080x1080 - FACEBOOK: 1200x628 - KAKAO: 800x800 - BLOG: 800x600 • selected = true: 최종 선택 이미지 end note note right of job **비동기 작업 추적** • Job ID: "job-img-{uuid}" • 상태: PENDING → PROCESSING → COMPLETED/FAILED • progress: 0-100 • Kafka 기반 비동기 처리 end note note bottom of redis_job **Job 상태 캐싱** • 폴링 조회 성능 최적화 • TTL 1시간 후 자동 삭제 • PostgreSQL과 동기화 end note note bottom of redis_image **이미지 캐싱** • 동일 이벤트 재요청 시 즉시 반환 • TTL 7일 후 자동 삭제 • Key: event_id + style + platform end note note bottom of redis_ai **AI 추천 데이터 캐싱** • AI Service 이벤트 분석 결과 • 추천 스타일 및 키워드 • TTL 1시간 후 자동 삭제 end note ' ============================================ ' 제약 조건 표시 ' ============================================ note top of content **제약 조건** • PK: id (BIGSERIAL) • UK: event_id (이벤트당 하나) • INDEX: created_at end note note top of generated_image **제약 조건** • PK: id (BIGSERIAL) • INDEX: (event_id, style, platform) • INDEX: event_id • INDEX: created_at • CHECK: style IN ('FANCY', 'SIMPLE', 'TRENDY') • CHECK: platform IN ('INSTAGRAM', 'FACEBOOK', 'KAKAO', 'BLOG') • CHECK: width > 0 AND height > 0 end note note top of job **제약 조건** • PK: id (VARCHAR) • INDEX: event_id • INDEX: (status, created_at) • CHECK: status IN ('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED') • CHECK: job_type IN ('IMAGE_GENERATION', 'IMAGE_REGENERATION') • CHECK: progress >= 0 AND progress <= 100 end note ' ============================================ ' 데이터 흐름 및 외부 연동 설명 ' ============================================ note as external_integration **외부 시스템 연동** • Azure Blob Storage (CDN): 이미지 파일 저장 • Stable Diffusion API: 이미지 생성 • DALL-E API: Fallback 이미지 생성 • Kafka Topic (image-generation-job): Job 트리거 **데이터 흐름** 1. Kafka에서 이미지 생성 Job 수신 2. Job 상태 PENDING → PostgreSQL + Redis 저장 3. AI 추천 데이터 Redis에서 조회 4. 외부 API 호출 (Stable Diffusion) 5. 생성된 이미지 CDN 업로드 6. generated_image 테이블 저장 (CDN URL) 7. Job 상태 COMPLETED → Redis 업데이트 8. 클라이언트 폴링 조회 → Redis 캐시 반환 end note @enduml