mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2026-06-13 18:19:10 +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,223 @@
|
||||
@startuml
|
||||
!theme mono
|
||||
|
||||
title Content Service - ERD (Entity Relationship Diagram)
|
||||
|
||||
' ============================================
|
||||
' PostgreSQL 테이블
|
||||
' ============================================
|
||||
|
||||
entity "content" as content {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
* event_id : VARCHAR(100) <<UK>>
|
||||
* event_title : VARCHAR(200)
|
||||
event_description : TEXT
|
||||
* created_at : TIMESTAMP
|
||||
* updated_at : TIMESTAMP
|
||||
}
|
||||
|
||||
entity "generated_image" as generated_image {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
* event_id : VARCHAR(100) <<FK>>
|
||||
* style : VARCHAR(20) <<CHECK>>
|
||||
* platform : VARCHAR(30) <<CHECK>>
|
||||
* 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
|
||||
--
|
||||
<<INDEX>> (event_id)
|
||||
<<INDEX>> (event_id, style, platform)
|
||||
<<INDEX>> (created_at)
|
||||
}
|
||||
|
||||
entity "job" as job {
|
||||
* id : VARCHAR(100) <<PK>>
|
||||
--
|
||||
* event_id : VARCHAR(100)
|
||||
* job_type : VARCHAR(50) <<CHECK>>
|
||||
* status : VARCHAR(20) <<CHECK>>
|
||||
* progress : INT
|
||||
result_message : TEXT
|
||||
error_message : TEXT
|
||||
* created_at : TIMESTAMP
|
||||
* updated_at : TIMESTAMP
|
||||
completed_at : TIMESTAMP
|
||||
--
|
||||
<<INDEX>> (event_id)
|
||||
<<INDEX>> (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
|
||||
--
|
||||
<<TTL>> 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
|
||||
--
|
||||
<<TTL>> 7 days
|
||||
}
|
||||
|
||||
entity "RedisAIEventData\n(Cache)" as redis_ai {
|
||||
* key : ai:event:{eventId}
|
||||
--
|
||||
eventId : STRING
|
||||
recommendedStyles : LIST
|
||||
recommendedKeywords : LIST
|
||||
cachedAt : TIMESTAMP
|
||||
--
|
||||
<<TTL>> 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
|
||||
Reference in New Issue
Block a user