mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 06:06:24 +00:00
- 공통 OpenAPI 3.0.3 컨벤션 문서 작성 (design/backend/api/API_CONVENTION.md) - 7개 서비스 API 명세서 표준화 완료: * User Service (8081) * Event Service (8080) * Content Service (8082) * AI Service (8083) * Participation Service (8084) * Distribution Service (8085) * Analytics Service (8086) 주요 변경사항: - API 경로에서 /api prefix 제거 (/api/users → /users) - 서버 URL 패턴 통일 (Local → Dev → Prod) - 연락처 정보 표준화 (Digital Garage Team) - ErrorResponse 스키마 통일 (error → message, details 추가) - securitySchemes 이름 통일 (BearerAuth) - 포트 번호 명확히 할당 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
850 lines
26 KiB
YAML
850 lines
26 KiB
YAML
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
|