Skip to content

홍보물 이미지 합성 기능 구현 #90

@yunrry

Description

@yunrry

📝 Issue Description

기존 OpenAI LLM 기반 홍보물 콘텐츠 생성(SpringAIPromotionProvider)에 HTML 폰트-이미지 합성 기능을 추가하여, 텍스트가 오버레이된 완성형 홍보물 이미지를 자동 생성하는 기능을 구현합니다.

🎯 Goals

  • LLM 생성 콘텐츠를 기반으로 HTML 템플릿 생성
  • 투명 배경 텍스트 이미지 생성 (Playwright 사용)
  • 배경 이미지 다운로드 및 전처리
  • 텍스트 오버레이 합성으로 최종 썸네일 PNG 생성
  • 성능 최적화 (브라우저 인스턴스 재사용, 비동기 처리)

🔧 Technical Requirements

Environment

  • Java 21
  • Gradle
  • Spring Boot 3.x
  • Spring AI (OpenAI integration)

Dependencies to Add

dependencies {
    // Playwright for HTML to PNG conversion
    implementation 'com.microsoft.playwright:playwright:1.40.0'
    
    // WebFlux for async image download
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    
    // Image processing utilities
    implementation 'org.apache.commons:commons-imaging:1.0.0-alpha5'
    
    // Async processing
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

📋 Implementation Tasks

Phase 1: Core Infrastructure

  • Task 1.1: PromotionImageService 구현

    • 메인 홍보물 생성 메서드
    • HTML 템플릿 → PNG 변환
    • 이미지 합성 로직
  • Task 1.2: ImageDownloadService 구현

    • URL에서 이미지 다운로드 (WebClient 사용)
    • 이미지 크기 조정 및 최적화
    • 캐싱 메커니즘
  • Task 1.3: HtmlTemplateService 구현

    • PromotionResult → HTML 템플릿 변환
    • 반응형 CSS 스타일링
    • 한글 폰트 지원 (Noto Sans KR)

Phase 2: Browser Management

  • Task 2.1: PlaywrightBrowserPool 구현

    • 브라우저 인스턴스 풀링
    • 동시 접근 제어 (Semaphore)
    • 리소스 정리 및 관리
  • Task 2.2: 투명 배경 텍스트 이미지 생성

    • Headless 브라우저 설정
    • setOmitBackground(true) 적용
    • 폰트 로딩 최적화

Phase 3: Integration & Enhancement

  • Task 3.1: SpringAIPromotionProvider 확장

    • 기존 LLM 호출 후 이미지 생성 추가
    • PromotionImageResult 응답 구조 정의
    • 에러 처리 및 폴백 전략
  • Task 3.2: 비동기 처리 구현

    • @Async 기반 백그라운드 처리
    • 진행 상태 추적 (taskId 기반)
    • CompletableFuture 활용

Phase 4: Performance & Monitoring

  • Task 4.1: 성능 최적화

    • 브라우저 인스턴스 재사용
    • 이미지 다운로드 캐싱
    • 메모리 효율적 처리
  • Task 4.2: 모니터링 및 로깅

    • 생성 시간 측정 (Micrometer)
    • 메모리 사용량 추적
    • 실패율 모니터링

📐 HTML Template Design

Layout Types

public enum PromotionLayoutType {
    OVERLAY_CENTER,    // 중앙 텍스트 오버레이
    OVERLAY_BOTTOM,    // 하단 정보 배치  
    SPLIT_LAYOUT,      // 좌우 분할 레이아웃
    CARD_STYLE         // 카드형 디자인
}

Template Structure

<div class="promotion-container">
    <div class="spot-name">{{ spotName }}</div>
    <div class="title">{{ suggestedTitle }}</div>
    <div class="tags">
        <span class="tag">{{ recommendedTag }}</span>
    </div>
    <div class="emotions">{{ emotions }}</div>
</div>

⚙️ Configuration

application.yml

thumbnail:
  image:
    default-width: 1200
    default-height: 630  # SNS 최적 비율 (1.91:1)
    max-file-size: 5MB
    quality: 85
    timeout: 30s
  
  template:
    font-family: "Noto Sans KR"
    primary-color: "#FFFFFF"
    shadow-color: "rgba(0,0,0,0.8)"
  
  browser:
    pool-size: 3
    headless: true
    timeout: 10s

🔄 Data Flow

PromotionRequest 
  ↓
OpenAI LLM → PromotionResult
  ↓
mainImageUrl → Download Background Image
  ↓  
PromotionResult → HTML Template
  ↓
HTML → Playwright → Transparent Text PNG
  ↓
Background + Text → BufferedImage Composite
  ↓
Final Thumbnail PNG

📊 Expected Performance

Target Metrics

  • 전체 프로세스: 3-6초 (최적화 후)
  • LLM 응답: 2-5초 (기존)
  • 이미지 다운로드: 0.5-2초
  • HTML → PNG 변환: 1-2초
  • 이미지 합성: 0.2-0.5초

Performance Optimizations

  • 브라우저 인스턴스 재사용으로 초기화 시간 단축
  • 이미지 다운로드 캐싱
  • 비동기 처리로 사용자 응답성 향상

🧪 Testing Strategy

Unit Tests

  • HTML 템플릿 생성 검증
  • 이미지 다운로드 테스트
  • 합성 결과 이미지 검증
  • 에러 상황 처리 테스트

Integration Tests

  • End-to-End 썸네일 생성 플로우
  • 다양한 PromotionResult 입력 시나리오
  • 성능 및 메모리 사용량 테스트

Test Data

// 테스트용 PromotionResult 샘플
PromotionResult testData = new PromotionResult(
    "맛있는 카페",
    "https://example.com/image.jpg", 
    List.of("커피", "디저트", "분위기"),
    List.of("따뜻함", "아늑함"),
    "감성 가득한 동네 카페에서의 특별한 시간",
    "직접 로스팅한 원두로 내린 커피가 일품입니다. 아늑한 인테리어와 친절한 사장님이 기억에 남아요. 디저트도 맛있어서 재방문 의사 100%입니다."
);

🚨 Error Handling & Fallback

Fallback Strategy

  1. LLM 실패: 기존 createFallbackPromotion() 사용
  2. 이미지 다운로드 실패: 기본 배경 이미지 적용
  3. HTML 렌더링 실패: 텍스트만으로 간단한 이미지 생성
  4. 합성 실패: 원본 배경 이미지 반환

Error Monitoring

  • 각 단계별 실패율 추적
  • 실패 원인별 분류 및 로깅
  • 알림 및 모니터링 대시보드 연동

🔍 Definition of Done

  • 모든 구현 태스크 완료
  • 단위 테스트 및 통합 테스트 통과 (커버리지 80% 이상)
  • 성능 목표 달성 (3-6초 이내)
  • 에러 처리 및 폴백 전략 구현
  • 코드 리뷰 완료
  • 문서화 완료 (API 문서, 설정 가이드)

📚 References


Estimated Timeline: 2-3 weeks
Priority: High
Labels: enhancement, feature, backend, image-processing

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions