@startuml event-AI추천요청 !theme mono title Event Service - AI 추천 요청 (Kafka Job 발행) (UFR-EVENT-030) actor Client participant "API Gateway" as Gateway participant "EventController" as Controller <> participant "EventService" as Service <> participant "JobService" as JobSvc <> participant "EventRepository" as Repo <> participant "Redis Cache" as Cache <> database "Event DB" as DB <> participant "Kafka Producer" as Kafka <> note over Controller, Kafka **UFR-EVENT-030: AI 이벤트 추천 요청** - Kafka 비동기 Job 발행 - AI Service가 Kafka 구독하여 처리 - 트렌드 분석 + 3가지 추천안 생성 - 처리 시간: 평균 2분 이내 end note Client -> Gateway: POST /api/events/{eventDraftId}/ai-recommendations\n{"objective": "신규 고객 유치",\n"industry": "음식점",\n"region": "서울 강남구"} activate Gateway Gateway -> Controller: POST /api/events/{eventDraftId}/ai-recommendations activate Controller Controller -> Controller: 요청 검증\n(필수 필드, 목적 유효성) Controller -> Service: requestAIRecommendation(eventDraftId, userId) activate Service == 1단계: 이벤트 초안 조회 및 검증 == Service -> Repo: findById(eventDraftId) activate Repo Repo -> DB: 이벤트 초안 조회\n(초안ID로 이벤트 목적,\n매장 정보 조회) activate DB DB --> Repo: EventDraft 엔티티\n{목적, 매장명, 업종, 주소} deactivate DB Repo --> Service: EventDraft entity deactivate Repo Service -> Service: 소유권 검증\nvalidateOwnership(userId, eventDraft) alt 소유권 없음 Service --> Controller: throw ForbiddenException\n("권한이 없습니다") Controller --> Gateway: 403 Forbidden\n{"code": "EVENT_003",\n"message": "권한이 없습니다"} deactivate Service deactivate Controller Gateway --> Client: 403 Forbidden deactivate Gateway else 소유권 확인 == 2단계: Kafka Job 생성 == Service -> JobSvc: createAIJob(eventDraft) activate JobSvc JobSvc -> JobSvc: Job ID 생성 (UUID) JobSvc -> Cache: Job 상태 저장\nKey: job:{jobId}\nValue: {status: PENDING,\neventDraftId, type: AI_RECOMMEND,\ncreatedAt}\nTTL: 1시간 activate Cache Cache --> JobSvc: 저장 완료 deactivate Cache == 3단계: Kafka 이벤트 발행 == JobSvc -> Kafka: 이벤트 발행\nTopic: ai-job-topic\nPayload: {jobId, eventDraftId,\nobjective, industry,\nregion, storeInfo} activate Kafka note right of Kafka **Kafka Topic** - Topic: ai-job-topic - Consumer: AI Service - Consumer Group: ai-service-group **Payload** { "jobId": "UUID", "eventDraftId": "UUID", "objective": "신규 고객 유치", "industry": "음식점", "region": "서울 강남구", "storeInfo": {...} } end note Kafka --> JobSvc: ACK (발행 확인) deactivate Kafka JobSvc --> Service: JobResponse\n{jobId, status: PENDING} deactivate JobSvc == 4단계: 응답 반환 == Service --> Controller: JobResponse\n{jobId, status: PENDING} deactivate Service Controller --> Gateway: 202 Accepted\n{"jobId": "job-uuid-123",\n"status": "PENDING",\n"message": "AI가 분석 중입니다"} deactivate Controller Gateway --> Client: 202 Accepted\nAI 분석 시작 deactivate Gateway note over Service, Kafka **AI Service 비동기 처리** - Kafka 구독: ai-job-topic - 트렌드 분석 (업종, 지역 기반) - 3가지 추천안 생성 (저/중/고 비용) - 결과: Redis에 저장 (TTL: 24시간) - 상세: ai-트렌드분석및추천.puml 참조 **처리 시간** - 평균: 2분 이내 - P95: 4분 이내 - Timeout: 5분 **결과 조회** - 폴링 방식: GET /api/jobs/{jobId}/status - 간격: 2초, 최대 30초 end note end @enduml