kt-event-marketing/design/backend/class/content-service-simple.puml
jhbkjh 3075a5d49f 물리아키텍처 설계 완료
 주요 기능
- 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>
2025-10-29 15:13:01 +09:00

228 lines
7.7 KiB
Plaintext

@startuml
!theme mono
title Content Service - 클래스 다이어그램 요약 (Clean Architecture)
' ============================================
' 레이어 구조 표시
' ============================================
package "Domain Layer" <<Rectangle>> {
class Content {
- id: Long
- eventId: String
- images: List<GeneratedImage>
+ addImage(image: GeneratedImage): void
+ getSelectedImages(): List<GeneratedImage>
}
class GeneratedImage {
- id: Long
- eventId: String
- style: ImageStyle
- platform: Platform
- cdnUrl: String
+ select(): void
+ deselect(): void
}
class Job {
- id: String
- eventId: String
- status: Status
- progress: int
+ start(): void
+ updateProgress(progress: int): void
+ complete(resultMessage: String): void
+ fail(errorMessage: String): void
}
enum ImageStyle {
FANCY
SIMPLE
TRENDY
}
enum Platform {
INSTAGRAM
FACEBOOK
KAKAO
BLOG
}
}
package "Application Layer" <<Rectangle>> {
package "Use Cases (Input Port)" {
interface GenerateImagesUseCase {
+ execute(command: ContentCommand.GenerateImages): JobInfo
}
interface GetJobStatusUseCase {
+ execute(jobId: String): JobInfo
}
interface GetEventContentUseCase {
+ execute(eventId: String): ContentInfo
}
interface GetImageListUseCase {
+ execute(eventId: String, style: ImageStyle, platform: Platform): List<ImageInfo>
}
interface DeleteImageUseCase {
+ execute(imageId: Long): void
}
interface RegenerateImageUseCase {
+ execute(command: ContentCommand.RegenerateImage): JobInfo
}
}
package "Ports (Output Port)" {
interface ContentReader {
+ findByEventDraftIdWithImages(eventId: String): Optional<Content>
}
interface ContentWriter {
+ save(content: Content): Content
+ saveImage(image: GeneratedImage): GeneratedImage
}
interface JobReader {
+ getJob(jobId: String): Optional<RedisJobData>
}
interface JobWriter {
+ saveJob(jobData: RedisJobData, ttlSeconds: long): void
+ updateJobStatus(jobId: String, status: String, progress: Integer): void
}
interface CDNUploader {
+ upload(imageData: byte[], fileName: String): String
}
}
package "Service Implementation" {
class StableDiffusionImageGenerator implements GenerateImagesUseCase {
- replicateClient: ReplicateApiClient
- cdnUploader: CDNUploader
- jobWriter: JobWriter
- contentWriter: ContentWriter
+ execute(command: ContentCommand.GenerateImages): JobInfo
}
class JobManagementService implements GetJobStatusUseCase {
- jobReader: JobReader
+ execute(jobId: String): JobInfo
}
class GetEventContentService implements GetEventContentUseCase {
- contentReader: ContentReader
+ execute(eventId: String): ContentInfo
}
class GetImageListService implements GetImageListUseCase {
- imageReader: ImageReader
+ execute(eventId: String, style: ImageStyle, platform: Platform): List<ImageInfo>
}
class DeleteImageService implements DeleteImageUseCase {
- imageWriter: ImageWriter
+ execute(imageId: Long): void
}
class RegenerateImageService implements RegenerateImageUseCase {
- imageReader: ImageReader
- imageWriter: ImageWriter
- jobWriter: JobWriter
+ execute(command: ContentCommand.RegenerateImage): JobInfo
}
}
}
package "Infrastructure Layer" <<Rectangle>> {
class RedisGateway implements ContentReader, ContentWriter, JobReader, JobWriter {
- redisTemplate: RedisTemplate<String, Object>
- objectMapper: ObjectMapper
+ getAIRecommendation(eventId: String): Optional<Map<String, Object>>
+ saveJob(jobData: RedisJobData, ttlSeconds: long): void
+ getJob(jobId: String): Optional<RedisJobData>
+ save(content: Content): Content
+ saveImage(image: GeneratedImage): GeneratedImage
}
class ReplicateApiClient {
- apiToken: String
- baseUrl: String
+ createPrediction(request: ReplicateRequest): ReplicateResponse
+ getPrediction(predictionId: String): ReplicateResponse
}
class AzureBlobStorageUploader implements CDNUploader {
- connectionString: String
- containerName: String
- circuitBreaker: CircuitBreaker
+ upload(imageData: byte[], fileName: String): String
}
}
package "Presentation Layer" <<Rectangle>> {
class ContentController {
- generateImagesUseCase: GenerateImagesUseCase
- getJobStatusUseCase: GetJobStatusUseCase
- getEventContentUseCase: GetEventContentUseCase
- getImageListUseCase: GetImageListUseCase
- deleteImageUseCase: DeleteImageUseCase
- regenerateImageUseCase: RegenerateImageUseCase
+ generateImages(command: ContentCommand.GenerateImages): ResponseEntity<JobInfo>
+ getJobStatus(jobId: String): ResponseEntity<JobInfo>
+ getContentByEventId(eventId: String): ResponseEntity<ContentInfo>
+ deleteImage(imageId: Long): ResponseEntity<Void>
}
}
' ============================================
' 관계 정의
' ============================================
Content "1" o-- "0..*" GeneratedImage : contains
GeneratedImage --> ImageStyle
GeneratedImage --> Platform
ContentController ..> GenerateImagesUseCase
ContentController ..> GetJobStatusUseCase
ContentController ..> GetEventContentUseCase
ContentController ..> GetImageListUseCase
ContentController ..> DeleteImageUseCase
ContentController ..> RegenerateImageUseCase
StableDiffusionImageGenerator ..> CDNUploader
StableDiffusionImageGenerator ..> JobWriter
StableDiffusionImageGenerator ..> ContentWriter
StableDiffusionImageGenerator --> ReplicateApiClient
JobManagementService ..> JobReader
GetEventContentService ..> ContentReader
GetImageListService ..> "ImageReader\n(extends ContentReader)"
DeleteImageService ..> "ImageWriter\n(extends ContentWriter)"
RegenerateImageService ..> "ImageReader\n(extends ContentReader)"
RegenerateImageService ..> "ImageWriter\n(extends ContentWriter)"
RegenerateImageService ..> JobWriter
RedisGateway ..|> ContentReader
RedisGateway ..|> ContentWriter
RedisGateway ..|> JobReader
RedisGateway ..|> JobWriter
AzureBlobStorageUploader ..|> CDNUploader
' ============================================
' 레이어 의존성 방향
' ============================================
note top of Content : **Domain Layer**\n순수 비즈니스 로직\n외부 의존성 없음
note top of "Use Cases (Input Port)" : **Application Layer**\nUse Case 인터페이스 (Input Port)\n비즈니스 흐름 정의
note top of "Ports (Output Port)" : **Application Layer**\n외부 시스템 추상화 (Output Port)\n의존성 역전 원칙
note top of RedisGateway : **Infrastructure Layer**\nOutput Port 구현체\nRedis 저장소 연동
note top of ContentController : **Presentation Layer**\nREST API 컨트롤러\nHTTP 요청 처리
note bottom of ContentController : **의존성 방향**\nPresentation → Application → Domain\nInfrastructure → Application\n\n**핵심 원칙**\n• Domain은 다른 레이어에 의존하지 않음\n• Application은 Domain에만 의존\n• Infrastructure는 Application Port 구현\n• Presentation은 Application Use Case 호출
@enduml