mirror of
https://github.com/ktds-dg0501/kt-event-marketing-fe.git
synced 2026-06-13 14:19:10 +00:00
초기 프로젝트 설정 및 설계 문서 추가
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,849 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: AI Service API
|
||||
description: |
|
||||
KT AI 기반 소상공인 이벤트 자동 생성 서비스 - AI Service
|
||||
|
||||
## 서비스 개요
|
||||
- Kafka를 통한 비동기 AI 추천 처리
|
||||
- Claude API / GPT-4 API 연동
|
||||
- Redis 기반 결과 캐싱 (TTL 24시간)
|
||||
|
||||
## 처리 흐름
|
||||
1. Event Service가 Kafka Topic에 Job 메시지 발행
|
||||
2. AI Service가 메시지 구독 및 처리
|
||||
3. 트렌드 분석 수행 (Claude/GPT-4 API)
|
||||
4. 3가지 이벤트 추천안 생성
|
||||
5. 결과를 Redis에 저장 (TTL 24시간)
|
||||
6. Job 상태를 Redis에 업데이트
|
||||
|
||||
## 외부 API 통합
|
||||
- **Claude API / GPT-4 API**: 트렌드 분석 및 이벤트 추천
|
||||
- **Circuit Breaker**: 5분 타임아웃, Fallback to 캐시
|
||||
- **Retry**: 최대 3회, Exponential Backoff
|
||||
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: Digital Garage Team
|
||||
email: support@kt-event-marketing.com
|
||||
|
||||
servers:
|
||||
- url: http://localhost:8083
|
||||
description: Local Development Server
|
||||
- url: https://dev-api.kt-event-marketing.com/ai/v1
|
||||
description: Development Server
|
||||
- url: https://api.kt-event-marketing.com/ai/v1
|
||||
description: Production Server
|
||||
|
||||
tags:
|
||||
- name: Health Check
|
||||
description: 서비스 상태 확인
|
||||
- name: Internal API
|
||||
description: 내부 서비스 간 통신용 API
|
||||
- name: Kafka Consumer
|
||||
description: 비동기 작업 처리 (문서화만)
|
||||
|
||||
paths:
|
||||
/health:
|
||||
get:
|
||||
tags:
|
||||
- Health Check
|
||||
summary: 서비스 헬스체크
|
||||
description: AI Service 상태 및 외부 연동 확인
|
||||
operationId: healthCheck
|
||||
x-user-story: System
|
||||
x-controller: HealthController
|
||||
responses:
|
||||
'200':
|
||||
description: 서비스 정상
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/HealthCheckResponse'
|
||||
example:
|
||||
status: UP
|
||||
timestamp: "2025-10-23T10:30:00Z"
|
||||
services:
|
||||
kafka: UP
|
||||
redis: UP
|
||||
claude_api: UP
|
||||
gpt4_api: UP
|
||||
circuit_breaker: CLOSED
|
||||
|
||||
/internal/jobs/{jobId}/status:
|
||||
get:
|
||||
tags:
|
||||
- Internal API
|
||||
summary: 작업 상태 조회
|
||||
description: Redis에 저장된 AI 추천 작업 상태 조회 (Event Service에서 호출)
|
||||
operationId: getJobStatus
|
||||
x-user-story: UFR-AI-010
|
||||
x-controller: InternalJobController
|
||||
parameters:
|
||||
- name: jobId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Job ID
|
||||
example: "job-ai-evt001-20251023103000"
|
||||
responses:
|
||||
'200':
|
||||
description: 작업 상태 조회 성공
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/JobStatusResponse'
|
||||
examples:
|
||||
processing:
|
||||
summary: 처리 중
|
||||
value:
|
||||
jobId: "job-ai-evt001-20251023103000"
|
||||
status: "PROCESSING"
|
||||
progress: 50
|
||||
message: "AI 추천 생성 중"
|
||||
createdAt: "2025-10-23T10:30:00Z"
|
||||
startedAt: "2025-10-23T10:30:05Z"
|
||||
completed:
|
||||
summary: 완료
|
||||
value:
|
||||
jobId: "job-ai-evt001-20251023103000"
|
||||
status: "COMPLETED"
|
||||
progress: 100
|
||||
message: "AI 추천 완료"
|
||||
createdAt: "2025-10-23T10:30:00Z"
|
||||
startedAt: "2025-10-23T10:30:05Z"
|
||||
completedAt: "2025-10-23T10:35:00Z"
|
||||
processingTimeMs: 295000
|
||||
failed:
|
||||
summary: 실패
|
||||
value:
|
||||
jobId: "job-ai-evt001-20251023103000"
|
||||
status: "FAILED"
|
||||
progress: 0
|
||||
message: "Claude API timeout"
|
||||
errorMessage: "Claude API timeout after 5 minutes"
|
||||
createdAt: "2025-10-23T10:30:00Z"
|
||||
startedAt: "2025-10-23T10:30:05Z"
|
||||
failedAt: "2025-10-23T10:35:05Z"
|
||||
retryCount: 3
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
'500':
|
||||
$ref: '#/components/responses/InternalServerError'
|
||||
|
||||
/internal/recommendations/{eventId}:
|
||||
get:
|
||||
tags:
|
||||
- Internal API
|
||||
summary: AI 추천 결과 조회
|
||||
description: Redis에 캐시된 AI 추천 결과 조회 (Event Service에서 호출)
|
||||
operationId: getRecommendation
|
||||
x-user-story: UFR-AI-010
|
||||
x-controller: InternalRecommendationController
|
||||
parameters:
|
||||
- name: eventId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: 이벤트 ID
|
||||
example: "evt-001"
|
||||
responses:
|
||||
'200':
|
||||
description: 추천 결과 조회 성공
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AIRecommendationResult'
|
||||
example:
|
||||
eventId: "evt-001"
|
||||
trendAnalysis:
|
||||
industryTrends:
|
||||
- keyword: "프리미엄 디저트"
|
||||
relevance: 0.85
|
||||
description: "고급 디저트 카페 트렌드 증가"
|
||||
regionalTrends:
|
||||
- keyword: "핫플레이스"
|
||||
relevance: 0.78
|
||||
description: "강남 신논현역 주변 유동인구 증가"
|
||||
seasonalTrends:
|
||||
- keyword: "가을 시즌"
|
||||
relevance: 0.92
|
||||
description: "가을 시즌 한정 메뉴 선호도 증가"
|
||||
recommendations:
|
||||
- optionNumber: 1
|
||||
concept: "프리미엄 경험형"
|
||||
title: "가을 한정 시그니처 디저트 페어링 이벤트"
|
||||
description: "가을 제철 재료를 활용한 시그니처 디저트와 음료 페어링 체험"
|
||||
targetAudience: "20-30대 여성, SNS 활동적인 고객"
|
||||
duration:
|
||||
recommendedDays: 14
|
||||
recommendedPeriod: "10월 중순 ~ 11월 초"
|
||||
mechanics:
|
||||
type: "EXPERIENCE"
|
||||
details: "디저트+음료 페어링 세트 주문 시 인스타그램 업로드 고객에게 다음 방문 시 사용 가능한 10% 할인권 제공"
|
||||
promotionChannels:
|
||||
- "Instagram"
|
||||
- "카카오톡 채널"
|
||||
- "네이버 플레이스"
|
||||
estimatedCost:
|
||||
min: 300000
|
||||
max: 500000
|
||||
breakdown:
|
||||
material: 200000
|
||||
promotion: 150000
|
||||
discount: 150000
|
||||
expectedMetrics:
|
||||
newCustomers:
|
||||
min: 50
|
||||
max: 80
|
||||
repeatVisits:
|
||||
min: 30
|
||||
max: 50
|
||||
revenueIncrease:
|
||||
min: 15.0
|
||||
max: 25.0
|
||||
roi:
|
||||
min: 120.0
|
||||
max: 180.0
|
||||
socialEngagement:
|
||||
estimatedPosts: 100
|
||||
estimatedReach: 5000
|
||||
differentiator: "프리미엄 경험 제공으로 고객 만족도와 SNS 바이럴 효과 극대화"
|
||||
generatedAt: "2025-10-23T10:35:00Z"
|
||||
expiresAt: "2025-10-24T10:35:00Z"
|
||||
aiProvider: "CLAUDE"
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
'500':
|
||||
$ref: '#/components/responses/InternalServerError'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
# ==================== Health Check ====================
|
||||
HealthCheckResponse:
|
||||
type: object
|
||||
description: 서비스 헬스체크 응답
|
||||
required:
|
||||
- status
|
||||
- timestamp
|
||||
- services
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [UP, DOWN, DEGRADED]
|
||||
description: 전체 서비스 상태
|
||||
example: UP
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 체크 시각
|
||||
example: "2025-10-23T10:30:00Z"
|
||||
services:
|
||||
type: object
|
||||
description: 개별 서비스 상태
|
||||
required:
|
||||
- kafka
|
||||
- redis
|
||||
- claude_api
|
||||
- circuit_breaker
|
||||
properties:
|
||||
kafka:
|
||||
type: string
|
||||
enum: [UP, DOWN]
|
||||
description: Kafka 연결 상태
|
||||
example: UP
|
||||
redis:
|
||||
type: string
|
||||
enum: [UP, DOWN]
|
||||
description: Redis 연결 상태
|
||||
example: UP
|
||||
claude_api:
|
||||
type: string
|
||||
enum: [UP, DOWN, CIRCUIT_OPEN]
|
||||
description: Claude API 상태
|
||||
example: UP
|
||||
gpt4_api:
|
||||
type: string
|
||||
enum: [UP, DOWN, CIRCUIT_OPEN]
|
||||
description: GPT-4 API 상태 (선택)
|
||||
example: UP
|
||||
circuit_breaker:
|
||||
type: string
|
||||
enum: [CLOSED, OPEN, HALF_OPEN]
|
||||
description: Circuit Breaker 상태
|
||||
example: CLOSED
|
||||
|
||||
# ==================== Kafka Job Message (문서화만) ====================
|
||||
KafkaAIJobMessage:
|
||||
type: object
|
||||
description: |
|
||||
**Kafka Topic**: `ai-event-generation-job`
|
||||
**Consumer Group**: `ai-service-consumers`
|
||||
**처리 방식**: 비동기
|
||||
**최대 처리 시간**: 5분
|
||||
|
||||
AI 이벤트 생성 요청 메시지
|
||||
required:
|
||||
- jobId
|
||||
- eventId
|
||||
- objective
|
||||
- industry
|
||||
- region
|
||||
properties:
|
||||
jobId:
|
||||
type: string
|
||||
description: Job 고유 ID
|
||||
example: "job-ai-evt001-20251023103000"
|
||||
eventId:
|
||||
type: string
|
||||
description: 이벤트 ID (Event Service에서 생성)
|
||||
example: "evt-001"
|
||||
objective:
|
||||
type: string
|
||||
description: 이벤트 목적
|
||||
enum:
|
||||
- "신규 고객 유치"
|
||||
- "재방문 유도"
|
||||
- "매출 증대"
|
||||
- "브랜드 인지도 향상"
|
||||
example: "신규 고객 유치"
|
||||
industry:
|
||||
type: string
|
||||
description: 업종
|
||||
example: "음식점"
|
||||
region:
|
||||
type: string
|
||||
description: 지역 (시/구/동)
|
||||
example: "서울 강남구"
|
||||
storeName:
|
||||
type: string
|
||||
description: 매장명 (선택)
|
||||
example: "맛있는 고깃집"
|
||||
targetAudience:
|
||||
type: string
|
||||
description: 목표 고객층 (선택)
|
||||
example: "20-30대 여성"
|
||||
budget:
|
||||
type: integer
|
||||
description: 예산 (원) (선택)
|
||||
example: 500000
|
||||
requestedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 요청 시각
|
||||
example: "2025-10-23T10:30:00Z"
|
||||
|
||||
# ==================== AI Recommendation Result ====================
|
||||
AIRecommendationResult:
|
||||
type: object
|
||||
description: |
|
||||
**Redis Key**: `ai:recommendation:{eventId}`
|
||||
**TTL**: 86400초 (24시간)
|
||||
|
||||
AI 이벤트 추천 결과
|
||||
required:
|
||||
- eventId
|
||||
- trendAnalysis
|
||||
- recommendations
|
||||
- generatedAt
|
||||
- aiProvider
|
||||
properties:
|
||||
eventId:
|
||||
type: string
|
||||
description: 이벤트 ID
|
||||
example: "evt-001"
|
||||
trendAnalysis:
|
||||
$ref: '#/components/schemas/TrendAnalysis'
|
||||
recommendations:
|
||||
type: array
|
||||
description: 추천 이벤트 기획안 (3개)
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
items:
|
||||
$ref: '#/components/schemas/EventRecommendation'
|
||||
generatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 생성 시각
|
||||
example: "2025-10-23T10:35:00Z"
|
||||
expiresAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 캐시 만료 시각 (생성 시각 + 24시간)
|
||||
example: "2025-10-24T10:35:00Z"
|
||||
aiProvider:
|
||||
type: string
|
||||
enum: [CLAUDE, GPT4]
|
||||
description: 사용된 AI 제공자
|
||||
example: "CLAUDE"
|
||||
|
||||
TrendAnalysis:
|
||||
type: object
|
||||
description: 트렌드 분석 결과 (업종/지역/시즌)
|
||||
required:
|
||||
- industryTrends
|
||||
- regionalTrends
|
||||
- seasonalTrends
|
||||
properties:
|
||||
industryTrends:
|
||||
type: array
|
||||
description: 업종 트렌드 키워드 (최대 5개)
|
||||
maxItems: 5
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- keyword
|
||||
- relevance
|
||||
- description
|
||||
properties:
|
||||
keyword:
|
||||
type: string
|
||||
description: 트렌드 키워드
|
||||
example: "프리미엄 디저트"
|
||||
relevance:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
description: 연관도 (0-1)
|
||||
example: 0.85
|
||||
description:
|
||||
type: string
|
||||
description: 트렌드 설명
|
||||
example: "고급 디저트 카페 트렌드 증가"
|
||||
regionalTrends:
|
||||
type: array
|
||||
description: 지역 트렌드 키워드 (최대 5개)
|
||||
maxItems: 5
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- keyword
|
||||
- relevance
|
||||
- description
|
||||
properties:
|
||||
keyword:
|
||||
type: string
|
||||
example: "핫플레이스"
|
||||
relevance:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
example: 0.78
|
||||
description:
|
||||
type: string
|
||||
example: "강남 신논현역 주변 유동인구 증가"
|
||||
seasonalTrends:
|
||||
type: array
|
||||
description: 시즌 트렌드 키워드 (최대 5개)
|
||||
maxItems: 5
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- keyword
|
||||
- relevance
|
||||
- description
|
||||
properties:
|
||||
keyword:
|
||||
type: string
|
||||
example: "가을 시즌"
|
||||
relevance:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
example: 0.92
|
||||
description:
|
||||
type: string
|
||||
example: "가을 시즌 한정 메뉴 선호도 증가"
|
||||
|
||||
EventRecommendation:
|
||||
type: object
|
||||
description: 이벤트 추천안 (차별화된 3가지 옵션)
|
||||
required:
|
||||
- optionNumber
|
||||
- concept
|
||||
- title
|
||||
- description
|
||||
- targetAudience
|
||||
- duration
|
||||
- mechanics
|
||||
- promotionChannels
|
||||
- estimatedCost
|
||||
- expectedMetrics
|
||||
- differentiator
|
||||
properties:
|
||||
optionNumber:
|
||||
type: integer
|
||||
description: 옵션 번호 (1-3)
|
||||
minimum: 1
|
||||
maximum: 3
|
||||
example: 1
|
||||
concept:
|
||||
type: string
|
||||
description: 이벤트 컨셉
|
||||
example: "프리미엄 경험형"
|
||||
title:
|
||||
type: string
|
||||
description: 이벤트 제목
|
||||
maxLength: 100
|
||||
example: "가을 한정 시그니처 디저트 페어링 이벤트"
|
||||
description:
|
||||
type: string
|
||||
description: 이벤트 설명
|
||||
maxLength: 500
|
||||
example: "가을 제철 재료를 활용한 시그니처 디저트와 음료 페어링 체험"
|
||||
targetAudience:
|
||||
type: string
|
||||
description: 목표 고객층
|
||||
example: "20-30대 여성, SNS 활동적인 고객"
|
||||
duration:
|
||||
type: object
|
||||
description: 이벤트 기간
|
||||
required:
|
||||
- recommendedDays
|
||||
properties:
|
||||
recommendedDays:
|
||||
type: integer
|
||||
description: 권장 진행 일수
|
||||
minimum: 1
|
||||
example: 14
|
||||
recommendedPeriod:
|
||||
type: string
|
||||
description: 권장 진행 시기
|
||||
example: "10월 중순 ~ 11월 초"
|
||||
mechanics:
|
||||
type: object
|
||||
description: 이벤트 메커니즘
|
||||
required:
|
||||
- type
|
||||
- details
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [DISCOUNT, GIFT, STAMP, EXPERIENCE, LOTTERY, COMBO]
|
||||
description: 이벤트 유형
|
||||
example: "EXPERIENCE"
|
||||
details:
|
||||
type: string
|
||||
description: 상세 메커니즘
|
||||
maxLength: 500
|
||||
example: "디저트+음료 페어링 세트 주문 시 인스타그램 업로드 고객에게 다음 방문 시 사용 가능한 10% 할인권 제공"
|
||||
promotionChannels:
|
||||
type: array
|
||||
description: 추천 홍보 채널 (최대 5개)
|
||||
maxItems: 5
|
||||
items:
|
||||
type: string
|
||||
example:
|
||||
- "Instagram"
|
||||
- "카카오톡 채널"
|
||||
- "네이버 플레이스"
|
||||
estimatedCost:
|
||||
type: object
|
||||
description: 예상 비용
|
||||
required:
|
||||
- min
|
||||
- max
|
||||
properties:
|
||||
min:
|
||||
type: integer
|
||||
description: 최소 비용 (원)
|
||||
minimum: 0
|
||||
example: 300000
|
||||
max:
|
||||
type: integer
|
||||
description: 최대 비용 (원)
|
||||
minimum: 0
|
||||
example: 500000
|
||||
breakdown:
|
||||
type: object
|
||||
description: 비용 구성
|
||||
properties:
|
||||
material:
|
||||
type: integer
|
||||
description: 재료비 (원)
|
||||
example: 200000
|
||||
promotion:
|
||||
type: integer
|
||||
description: 홍보비 (원)
|
||||
example: 150000
|
||||
discount:
|
||||
type: integer
|
||||
description: 할인 비용 (원)
|
||||
example: 150000
|
||||
expectedMetrics:
|
||||
$ref: '#/components/schemas/ExpectedMetrics'
|
||||
differentiator:
|
||||
type: string
|
||||
description: 다른 옵션과의 차별점
|
||||
maxLength: 500
|
||||
example: "프리미엄 경험 제공으로 고객 만족도와 SNS 바이럴 효과 극대화, 브랜드 이미지 향상에 집중"
|
||||
|
||||
ExpectedMetrics:
|
||||
type: object
|
||||
description: 예상 성과 지표
|
||||
required:
|
||||
- newCustomers
|
||||
- revenueIncrease
|
||||
- roi
|
||||
properties:
|
||||
newCustomers:
|
||||
type: object
|
||||
description: 신규 고객 수
|
||||
required:
|
||||
- min
|
||||
- max
|
||||
properties:
|
||||
min:
|
||||
type: integer
|
||||
minimum: 0
|
||||
example: 50
|
||||
max:
|
||||
type: integer
|
||||
minimum: 0
|
||||
example: 80
|
||||
repeatVisits:
|
||||
type: object
|
||||
description: 재방문 고객 수 (선택)
|
||||
properties:
|
||||
min:
|
||||
type: integer
|
||||
minimum: 0
|
||||
example: 30
|
||||
max:
|
||||
type: integer
|
||||
minimum: 0
|
||||
example: 50
|
||||
revenueIncrease:
|
||||
type: object
|
||||
description: 매출 증가율 (%)
|
||||
required:
|
||||
- min
|
||||
- max
|
||||
properties:
|
||||
min:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0
|
||||
example: 15.0
|
||||
max:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0
|
||||
example: 25.0
|
||||
roi:
|
||||
type: object
|
||||
description: ROI - 투자 대비 수익률 (%)
|
||||
required:
|
||||
- min
|
||||
- max
|
||||
properties:
|
||||
min:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0
|
||||
example: 120.0
|
||||
max:
|
||||
type: number
|
||||
format: float
|
||||
minimum: 0
|
||||
example: 180.0
|
||||
socialEngagement:
|
||||
type: object
|
||||
description: SNS 참여도 (선택)
|
||||
properties:
|
||||
estimatedPosts:
|
||||
type: integer
|
||||
description: 예상 게시물 수
|
||||
minimum: 0
|
||||
example: 100
|
||||
estimatedReach:
|
||||
type: integer
|
||||
description: 예상 도달 수
|
||||
minimum: 0
|
||||
example: 5000
|
||||
|
||||
# ==================== Job Status ====================
|
||||
JobStatusResponse:
|
||||
type: object
|
||||
description: |
|
||||
**Redis Key**: `ai:job:status:{jobId}`
|
||||
**TTL**: 86400초 (24시간)
|
||||
|
||||
작업 상태 응답
|
||||
required:
|
||||
- jobId
|
||||
- status
|
||||
- progress
|
||||
- message
|
||||
- createdAt
|
||||
properties:
|
||||
jobId:
|
||||
type: string
|
||||
description: Job ID
|
||||
example: "job-ai-evt001-20251023103000"
|
||||
status:
|
||||
type: string
|
||||
enum: [PENDING, PROCESSING, COMPLETED, FAILED]
|
||||
description: 작업 상태
|
||||
example: "COMPLETED"
|
||||
progress:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
description: 진행률 (%)
|
||||
example: 100
|
||||
message:
|
||||
type: string
|
||||
description: 상태 메시지
|
||||
example: "AI 추천 완료"
|
||||
eventId:
|
||||
type: string
|
||||
description: 이벤트 ID
|
||||
example: "evt-001"
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 작업 생성 시각
|
||||
example: "2025-10-23T10:30:00Z"
|
||||
startedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 작업 시작 시각
|
||||
example: "2025-10-23T10:30:05Z"
|
||||
completedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 작업 완료 시각 (완료 시)
|
||||
example: "2025-10-23T10:35:00Z"
|
||||
failedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 작업 실패 시각 (실패 시)
|
||||
example: "2025-10-23T10:35:05Z"
|
||||
errorMessage:
|
||||
type: string
|
||||
description: 에러 메시지 (실패 시)
|
||||
example: "Claude API timeout after 5 minutes"
|
||||
retryCount:
|
||||
type: integer
|
||||
description: 재시도 횟수
|
||||
minimum: 0
|
||||
example: 0
|
||||
processingTimeMs:
|
||||
type: integer
|
||||
description: 처리 시간 (밀리초)
|
||||
minimum: 0
|
||||
example: 295000
|
||||
|
||||
# ==================== Error Response ====================
|
||||
ErrorResponse:
|
||||
type: object
|
||||
description: 에러 응답
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
- timestamp
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
description: 에러 코드
|
||||
enum:
|
||||
- AI_SERVICE_ERROR
|
||||
- JOB_NOT_FOUND
|
||||
- RECOMMENDATION_NOT_FOUND
|
||||
- REDIS_ERROR
|
||||
- KAFKA_ERROR
|
||||
- CIRCUIT_BREAKER_OPEN
|
||||
- INTERNAL_ERROR
|
||||
example: "JOB_NOT_FOUND"
|
||||
message:
|
||||
type: string
|
||||
description: 에러 메시지
|
||||
example: "작업을 찾을 수 없습니다"
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
description: 에러 발생 시각
|
||||
example: "2025-10-23T10:30:00Z"
|
||||
details:
|
||||
type: object
|
||||
description: 추가 에러 상세
|
||||
additionalProperties: true
|
||||
example:
|
||||
jobId: "job-ai-evt001-20251023103000"
|
||||
|
||||
responses:
|
||||
NotFound:
|
||||
description: 리소스를 찾을 수 없음
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
example:
|
||||
code: "JOB_NOT_FOUND"
|
||||
message: "작업을 찾을 수 없습니다"
|
||||
timestamp: "2025-10-23T10:30:00Z"
|
||||
|
||||
InternalServerError:
|
||||
description: 서버 내부 오류
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
example:
|
||||
code: "INTERNAL_ERROR"
|
||||
message: "서버 내부 오류가 발생했습니다"
|
||||
timestamp: "2025-10-23T10:30:00Z"
|
||||
|
||||
# ==================== 기술 구성 문서화 ====================
|
||||
x-technical-specifications:
|
||||
circuit-breaker:
|
||||
claude-api:
|
||||
failureThreshold: 5
|
||||
successThreshold: 2
|
||||
timeout: 300000
|
||||
resetTimeout: 60000
|
||||
fallbackStrategy: CACHED_RECOMMENDATION
|
||||
gpt4-api:
|
||||
failureThreshold: 5
|
||||
successThreshold: 2
|
||||
timeout: 300000
|
||||
resetTimeout: 60000
|
||||
fallbackStrategy: CACHED_RECOMMENDATION
|
||||
|
||||
redis-cache:
|
||||
patterns:
|
||||
recommendation: "ai:recommendation:{eventId}"
|
||||
jobStatus: "ai:job:status:{jobId}"
|
||||
fallback: "ai:fallback:{industry}:{region}"
|
||||
ttl:
|
||||
recommendation: 86400
|
||||
jobStatus: 86400
|
||||
fallback: 604800
|
||||
|
||||
kafka:
|
||||
topics:
|
||||
input: "ai-event-generation-job"
|
||||
consumer:
|
||||
groupId: "ai-service-consumers"
|
||||
maxRetries: 3
|
||||
retryBackoffMs: 5000
|
||||
maxPollRecords: 10
|
||||
sessionTimeoutMs: 30000
|
||||
|
||||
external-apis:
|
||||
claude:
|
||||
endpoint: "https://api.anthropic.com/v1/messages"
|
||||
model: "claude-3-5-sonnet-20241022"
|
||||
maxTokens: 4096
|
||||
timeout: 300000
|
||||
gpt4:
|
||||
endpoint: "https://api.openai.com/v1/chat/completions"
|
||||
model: "gpt-4-turbo-preview"
|
||||
maxTokens: 4096
|
||||
timeout: 300000
|
||||
Reference in New Issue
Block a user