From 232021020eec37ffa0df51d42cfa2393167e48c4 Mon Sep 17 00:00:00 2001 From: sunmingLee <25thbam@gmail.com> Date: Tue, 21 Oct 2025 15:48:04 +0900 Subject: [PATCH 1/2] =?UTF-8?q?AI=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EC=B2=9C=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EB=B0=A9=EC=95=88=20=EB=AC=B8=EC=84=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/구현방안-AI이벤트설계.md | 1612 +++++++++++++++++++++++++++++++ 1 file changed, 1612 insertions(+) create mode 100644 design/구현방안-AI이벤트설계.md diff --git a/design/구현방안-AI이벤트설계.md b/design/구현방안-AI이벤트설계.md new file mode 100644 index 0000000..44f394d --- /dev/null +++ b/design/구현방안-AI이벤트설계.md @@ -0,0 +1,1612 @@ +# AI 기반 이벤트 추천 시스템 구현방안 + +**작성일**: 2025-10-21 +**버전**: 1.0 +**작성자**: 프로젝트 팀 전체 + +--- + +## 목차 +1. [개요](#개요) +2. [데이터 확보 및 처리 방안](#데이터-확보-및-처리-방안) +3. [Claude API 연동 구조](#claude-api-연동-구조) +4. [시스템 아키텍처](#시스템-아키텍처) +5. [성능 최적화 전략](#성능-최적화-전략) +6. [구현 로드맵](#구현-로드맵) + +--- + +## 개요 + +### 목적 +소상공인이 이벤트 목적을 선택하면, AI가 업종/지역/시즌 트렌드를 분석하고 3가지 예산별 이벤트 기획안(각 온라인/오프라인 2개씩 총 6개)을 추천하는 시스템 구현 + +### 핵심 요구사항 +- **응답 시간**: 10초 이내 +- **추천 개수**: 6개 (저/중/고 예산 × 온라인/오프라인) +- **포함 정보**: 트렌드 분석, 이벤트 제목, 경품, 참여방법, 예상 참여자, 비용, 투자대비수익률 + +### 기술 스택 결정 +- **AI 모델**: Claude 3.5 Sonnet API +- **벡터 DB**: Pinecone (관리형 서비스) +- **임베딩**: OpenAI text-embedding-3-large +- **캐싱**: Redis Cluster +- **백엔드**: Node.js (또는 Spring Boot) +- **메시지 큐**: RabbitMQ (비동기 처리) + +--- + +## 데이터 확보 및 처리 방안 + +### 1. 데이터 소스 + +#### 1.1 외부 데이터 (초기 학습용) + +**공공데이터** +- 소상공인진흥공단 API + - 업종별 사업체 수 + - 지역별 매출 통계 + - 시즌별 소비 트렌드 +- 통계청 데이터 + - 업종별 월별 매출액 + - 지역별 소비자 특성 + - 연령대별 소비 패턴 + +**SNS 및 블로그 데이터** +- 네이버 블로그 검색 API + - 키워드: "소상공인 이벤트", "매장 프로모션" + - 수집 항목: 이벤트명, 경품, 참여방법, 후기 +- Instagram Graph API + - 해시태그: #소상공인이벤트, #가게이벤트 + - 수집 항목: 이미지, 캡션, 좋아요/댓글 수 + +**경쟁사/벤치마크 데이터** +- 유사 서비스 공개 사례 분석 +- 성공 사례 DB 구축 (100~500건) + +#### 1.2 자사 데이터 (운영 데이터) + +**사용자 프로필** +- 매장명, 업종, 주소, 영업시간 +- 사업자번호 (업종 분류 용) + +**이벤트 생성 데이터** +- 사용자가 생성한 이벤트 정보 +- AI 추천 중 선택한 옵션 +- 커스텀 수정 내용 (제목, 경품 변경) + +**이벤트 성과 데이터** +- 참여자 수 +- 실제 비용 +- 실제 투자대비수익률 +- 배포 채널별 성과 + +**사용자 피드백** +- "다시 추천받기" 클릭 (부정적 피드백) +- 이벤트 선택 (긍정적 피드백) +- 추천과 실제 성과 차이 + +### 2. 데이터 수집 프로세스 + +#### 2.1 초기 데이터 수집 (프로젝트 시작 시) + +```python +# ETL 파이프라인 (Apache Airflow DAG) + +# 일일 배치 작업 +@dag(schedule_interval='0 2 * * *') # 매일 새벽 2시 +def collect_external_data(): + + # Task 1: 공공데이터 수집 + @task + def fetch_public_data(): + # 소상공인진흥공단 API 호출 + # 통계청 데이터 수집 + return data + + # Task 2: SNS 크롤링 + @task + def crawl_sns_data(): + # 네이버 블로그 검색 + # Instagram 해시태그 검색 + return data + + # Task 3: 데이터 정제 + @task + def clean_data(raw_data): + # 중복 제거 + # 이상치 탐지 및 제거 + # 업종/지역/시즌 태깅 + # 텍스트 정규화 + return cleaned_data + + # Task 4: 데이터베이스 저장 + @task + def save_to_db(cleaned_data): + # PostgreSQL에 저장 + # events 테이블에 insert + pass + + # Task 5: 벡터 임베딩 생성 + @task + def generate_embeddings(cleaned_data): + # OpenAI Embeddings API 호출 + # Pinecone에 저장 + pass +``` + +#### 2.2 실시간 데이터 수집 + +```javascript +// 이벤트 생성 시 +async function onEventCreated(eventData) { + // 1. 데이터베이스 저장 + await db.events.create(eventData); + + // 2. 벡터 임베딩 생성 (비동기) + await queue.publish('embedding', { + eventId: eventData.id, + text: `${eventData.title} ${eventData.prize} ${eventData.participation}` + }); +} + +// 이벤트 성과 수집 +async function onEventCompleted(eventId, performanceData) { + // 성과 데이터 저장 + await db.eventPerformance.create({ + eventId, + actualParticipants: performanceData.participants, + actualCost: performanceData.cost, + actualRoi: performanceData.roi + }); + + // 추천 정확도 계산 + const prediction = await db.eventRecommendations.findOne({ eventId }); + const accuracy = calculateAccuracy(prediction, performanceData); + + // 모델 성능 모니터링 + await logAccuracy(accuracy); +} +``` + +### 3. 데이터 정제 프로세스 + +#### 3.1 데이터 정제 규칙 + +**텍스트 정규화** +```python +def normalize_event_data(raw_event): + return { + 'title': clean_text(raw_event['title']), # 특수문자 제거, 소문자 변환 + 'prize': normalize_prize_name(raw_event['prize']), # 경품명 표준화 + 'participation': normalize_participation(raw_event['participation']), + 'industry': classify_industry(raw_event['industry']), # 업종 분류 + 'location': parse_location(raw_event['location']), # 지역 파싱 + 'season': extract_season(raw_event['date']), # 시즌 추출 + 'cost': parse_cost(raw_event['cost']), # 비용 숫자 변환 + 'roi': parse_roi(raw_event['roi']) # 투자대비수익률 숫자 변환 + } +``` + +**업종 분류 표준화** +```python +INDUSTRY_MAPPING = { + '음식점': ['한식', '중식', '일식', '양식', '카페', '베이커리', '치킨', '피자'], + '소매점': ['편의점', '슈퍼마켓', '화장품', '의류', '잡화'], + '서비스': ['미용실', '네일샵', 'PC방', '노래방', '헬스장'], + '숙박': ['모텔', '호텔', '게스트하우스', '펜션'] +} + +def classify_industry(raw_industry): + for category, subcategories in INDUSTRY_MAPPING.items(): + if raw_industry in subcategories: + return category + return '기타' +``` + +**지역 파싱** +```python +def parse_location(address): + # "서울특별시 강남구 역삼동" -> {"city": "서울", "district": "강남구"} + import re + + city_pattern = r'(서울|부산|대구|인천|광주|대전|울산|세종|경기|강원|충북|충남|전북|전남|경북|경남|제주)' + district_pattern = r'([가-힣]+구)' + + city = re.search(city_pattern, address) + district = re.search(district_pattern, address) + + return { + 'city': city.group(1) if city else None, + 'district': district.group(1) if district else None + } +``` + +**시즌 추출** +```python +def extract_season(date): + month = date.month + if month in [12, 1, 2]: + return '겨울' + elif month in [3, 4, 5]: + return '봄' + elif month in [6, 7, 8]: + return '여름' + else: + return '가을' +``` + +#### 3.2 이상치 탐지 + +```python +def detect_outliers(events_df): + # IQR 방식으로 이상치 탐지 + Q1 = events_df['roi'].quantile(0.25) + Q3 = events_df['roi'].quantile(0.75) + IQR = Q3 - Q1 + + lower_bound = Q1 - 1.5 * IQR + upper_bound = Q3 + 1.5 * IQR + + # 이상치 제거 + filtered_df = events_df[ + (events_df['roi'] >= lower_bound) & + (events_df['roi'] <= upper_bound) + ] + + return filtered_df +``` + +### 4. 벡터라이징 전략 + +#### 4.1 임베딩 생성 + +```python +import openai +import pinecone + +# OpenAI 임베딩 생성 +def generate_embedding(text): + response = openai.embeddings.create( + model="text-embedding-3-large", # 3072 차원 + input=text + ) + return response.data[0].embedding + +# 이벤트 데이터를 텍스트로 변환 +def event_to_text(event): + return f""" +이벤트명: {event['title']} +업종: {event['industry']} +경품: {event['prize']} +참여방법: {event['participation']} +지역: {event['location']['city']} {event['location']['district']} +시즌: {event['season']} +예산: {event['cost']}원 +투자대비수익률: {event['roi']}% +""" + +# Pinecone에 저장 +def save_to_pinecone(event): + text = event_to_text(event) + embedding = generate_embedding(text) + + pinecone_index.upsert(vectors=[{ + 'id': event['id'], + 'values': embedding, + 'metadata': { + 'title': event['title'], + 'industry': event['industry'], + 'location': event['location']['district'], + 'season': event['season'], + 'budget': event['cost'], + 'roi': event['roi'], + 'prize': event['prize'], + 'participation': event['participation'] + } + }]) +``` + +#### 4.2 벡터 검색 + +```python +# 유사 이벤트 검색 +def search_similar_events(query_event, top_k=5): + # 쿼리 텍스트 생성 + query_text = event_to_text(query_event) + + # 쿼리 임베딩 생성 + query_embedding = generate_embedding(query_text) + + # 필터 조건 구성 + filters = { + 'industry': query_event['industry'], + 'budget': {'$gte': query_event['cost'] * 0.5, '$lte': query_event['cost'] * 1.5} + } + + # Pinecone 검색 + results = pinecone_index.query( + vector=query_embedding, + filter=filters, + top_k=top_k, + include_metadata=True + ) + + return results['matches'] +``` + +#### 4.3 Pinecone 인덱스 설정 + +```python +import pinecone + +# Pinecone 초기화 +pinecone.init( + api_key="YOUR_API_KEY", + environment="us-west1-gcp" +) + +# 인덱스 생성 +index_name = "kt-event-recommendations" + +if index_name not in pinecone.list_indexes(): + pinecone.create_index( + name=index_name, + dimension=3072, # text-embedding-3-large 차원 + metric='cosine', + pods=1, + pod_type='p1.x1' # 성능 요구사항에 따라 조정 + ) + +# 인덱스 연결 +pinecone_index = pinecone.Index(index_name) +``` + +### 5. 데이터 통계 및 분포 분석 + +#### 5.1 초기 목표 데이터셋 규모 + +| 카테고리 | 목표 건수 | 수집 방법 | +|---------|----------|----------| +| 외부 데이터 (공공/SNS) | 300건 | 크롤링 + API | +| 벤치마크 사례 | 100건 | 수동 수집 | +| 자사 데이터 (초기) | 0건 | - | +| **총계** | **400건** | - | + +#### 5.2 데이터 분포 목표 + +**업종별 분포** +- 음식점: 40% +- 소매점: 25% +- 서비스: 20% +- 숙박: 10% +- 기타: 5% + +**예산별 분포** +- 저비용 (50만원 이하): 40% +- 중비용 (50~200만원): 35% +- 고비용 (200만원 이상): 25% + +**지역별 분포** +- 서울: 30% +- 경기: 25% +- 부산/대구/인천: 20% +- 기타 지역: 25% + +--- + +## Claude API 연동 구조 + +### 1. API 호출 전략 + +#### 1.1 단일 호출 + Structured Output 방식 (최종 선택) + +**선택 이유** +- 응답 시간 단축 (10초 내 보장) +- API 비용 절감 +- 트렌드와 추천의 일관성 유지 +- Structured Output으로 JSON 파싱 안정성 향상 + +**호출 플로우** +``` +1. 사용자 요청 → AI 서비스 +2. 유사 이벤트 벡터 검색 (Pinecone) +3. 캐시 확인 (Redis) +4. Claude API 단일 호출 (트렌드 + 6개 추천) +5. 응답 파싱 및 검증 +6. 캐시 저장 +7. 프론트엔드 응답 +``` + +### 2. JSON 요청/응답 구조 + +#### 2.1 Claude API 요청 구조 + +```json +{ + "model": "claude-3-5-sonnet-20241022", + "max_tokens": 4096, + "temperature": 0.7, + "system": "당신은 소상공인을 위한 이벤트 마케팅 전문가입니다. 주어진 매장 정보와 이벤트 목적을 바탕으로 효과적인 이벤트 기획안을 제안합니다.", + "messages": [ + { + "role": "user", + "content": "다음 정보를 바탕으로 이벤트를 추천해주세요:\n\n[매장 정보]\n- 업종: 음식점 (고깃집)\n- 지역: 서울 강남구\n- 이벤트 목적: 신규 고객 유치\n- 현재 시즌: 2025년 1월 (겨울)\n\n[참고 데이터]\n과거 유사한 매장에서 성공한 이벤트:\n1. SNS 팔로우 이벤트 - 참여자 200명, 비용 30만원, ROI 450%\n2. 리뷰 작성 이벤트 - 참여자 180명, 비용 120만원, ROI 380%\n...\n\n다음 형식으로 응답해주세요:\n1. 업종/지역/시즌 트렌드 분석\n2. 3가지 예산별 이벤트 추천 (각 온라인/오프라인 1개씩)" + } + ], + "response_format": { + "type": "json_schema", + "json_schema": { + "name": "event_recommendations", + "strict": true, + "schema": { + "type": "object", + "properties": { + "trends": { + "type": "object", + "properties": { + "industry": {"type": "string"}, + "location": {"type": "string"}, + "season": {"type": "string"} + }, + "required": ["industry", "location", "season"] + }, + "recommendations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "budget": {"type": "string", "enum": ["low", "medium", "high"]}, + "type": {"type": "string", "enum": ["online", "offline"]}, + "title": {"type": "string"}, + "prize": {"type": "string"}, + "participation": {"type": "string"}, + "expectedParticipants": {"type": "integer"}, + "cost": {"type": "integer"}, + "roi": {"type": "integer"} + }, + "required": ["budget", "type", "title", "prize", "participation", "expectedParticipants", "cost", "roi"] + }, + "minItems": 6, + "maxItems": 6 + } + }, + "required": ["trends", "recommendations"] + } + } + } +} +``` + +#### 2.2 Claude API 응답 구조 + +```json +{ + "id": "msg_01...", + "type": "message", + "role": "assistant", + "content": [ + { + "type": "text", + "text": "{\"trends\":{\"industry\":\"음식점업 신년 프로모션 트렌드: 1월은 새해 신규 고객 유치를 위한 할인 이벤트와 SNS 바이럴 마케팅이 효과적입니다. 특히 고깃집은 단체 할인 및 재방문 쿠폰 제공이 인기입니다.\",\"location\":\"강남구는 직장인 및 MZ세대 고객이 많아 SNS 기반 이벤트와 점심 특가 이벤트가 효과적입니다. 특히 Instagram과 네이버 블로그를 활용한 바이럴 마케팅이 유리합니다.\",\"season\":\"겨울 시즌에는 따뜻한 실내 이벤트와 재방문 유도 프로모션이 효과적입니다. 설 연휴 대비 가족 단위 고객 타겟팅이 중요합니다.\"},\"recommendations\":[{\"budget\":\"low\",\"type\":\"online\",\"title\":\"SNS 팔로우 이벤트\",\"prize\":\"커피 쿠폰\",\"participation\":\"Instagram 팔로우 + 게시물 공유\",\"expectedParticipants\":180,\"cost\":250000,\"roi\":520},{\"budget\":\"low\",\"type\":\"offline\",\"title\":\"전화번호 등록 이벤트\",\"prize\":\"커피 쿠폰\",\"participation\":\"매장 방문 시 전화번호 등록\",\"expectedParticipants\":150,\"cost\":300000,\"roi\":450},{\"budget\":\"medium\",\"type\":\"online\",\"title\":\"리뷰 작성 이벤트\",\"prize\":\"5천원 상품권\",\"participation\":\"네이버 블로그 리뷰 작성\",\"expectedParticipants\":250,\"cost\":1500000,\"roi\":380},{\"budget\":\"medium\",\"type\":\"offline\",\"title\":\"방문 도장 적립 이벤트\",\"prize\":\"무료 식사권\",\"participation\":\"5회 방문 시 도장 적립\",\"expectedParticipants\":200,\"cost\":1800000,\"roi\":320},{\"budget\":\"high\",\"type\":\"online\",\"title\":\"인플루언서 협업 이벤트\",\"prize\":\"1만원 할인권\",\"participation\":\"인플루언서 게시물 좋아요 + 팔로우\",\"expectedParticipants\":400,\"cost\":5000000,\"roi\":280},{\"budget\":\"high\",\"type\":\"offline\",\"title\":\"VIP 고객 초대 이벤트\",\"prize\":\"특별 메뉴 제공\",\"participation\":\"VIP 초대장 발송\",\"expectedParticipants\":300,\"cost\":6000000,\"roi\":240}]}" + } + ], + "model": "claude-3-5-sonnet-20241022", + "usage": { + "input_tokens": 1205, + "output_tokens": 856 + } +} +``` + +#### 2.3 서비스 레이어 응답 구조 (프론트엔드로 전달) + +```json +{ + "success": true, + "data": { + "trends": { + "industry": "음식점업 신년 프로모션 트렌드: 1월은 새해 신규 고객 유치를 위한 할인 이벤트와 SNS 바이럴 마케팅이 효과적입니다...", + "location": "강남구는 직장인 및 MZ세대 고객이 많아 SNS 기반 이벤트와 점심 특가 이벤트가 효과적입니다...", + "season": "겨울 시즌에는 따뜻한 실내 이벤트와 재방문 유도 프로모션이 효과적입니다..." + }, + "recommendations": [ + { + "id": "low-online", + "budget": "low", + "type": "online", + "title": "SNS 팔로우 이벤트", + "prize": "커피 쿠폰", + "participation": "Instagram 팔로우 + 게시물 공유", + "expectedParticipants": 180, + "cost": 250000, + "roi": 520 + }, + { + "id": "low-offline", + "budget": "low", + "type": "offline", + "title": "전화번호 등록 이벤트", + "prize": "커피 쿠폰", + "participation": "매장 방문 시 전화번호 등록", + "expectedParticipants": 150, + "cost": 300000, + "roi": 450 + }, + { + "id": "medium-online", + "budget": "medium", + "type": "online", + "title": "리뷰 작성 이벤트", + "prize": "5천원 상품권", + "participation": "네이버 블로그 리뷰 작성", + "expectedParticipants": 250, + "cost": 1500000, + "roi": 380 + }, + { + "id": "medium-offline", + "budget": "medium", + "type": "offline", + "title": "방문 도장 적립 이벤트", + "prize": "무료 식사권", + "participation": "5회 방문 시 도장 적립", + "expectedParticipants": 200, + "cost": 1800000, + "roi": 320 + }, + { + "id": "high-online", + "budget": "high", + "type": "online", + "title": "인플루언서 협업 이벤트", + "prize": "1만원 할인권", + "participation": "인플루언서 게시물 좋아요 + 팔로우", + "expectedParticipants": 400, + "cost": 5000000, + "roi": 280 + }, + { + "id": "high-offline", + "budget": "high", + "type": "offline", + "title": "VIP 고객 초대 이벤트", + "prize": "특별 메뉴 제공", + "participation": "VIP 초대장 발송", + "expectedParticipants": 300, + "cost": 6000000, + "roi": 240 + } + ] + }, + "metadata": { + "cacheHit": false, + "processingTime": 8.5, + "modelUsage": { + "inputTokens": 1205, + "outputTokens": 856 + } + } +} +``` + +### 3. 프롬프트 엔지니어링 + +#### 3.1 System Prompt + +``` +당신은 소상공인을 위한 이벤트 마케팅 전문가입니다. + +[역할] +- 매장 정보와 이벤트 목적을 바탕으로 효과적인 이벤트 기획안 제안 +- 업종별, 지역별, 시즌별 트렌드 분석 +- 예산별 차별화된 이벤트 추천 + +[제약사항] +- 추천은 반드시 6개 (저/중/고 예산 × 온라인/오프라인) +- 모든 추천은 실현 가능하고 구체적이어야 함 +- 예상 참여자, 비용, 투자대비수익률은 과거 데이터 기반 현실적 수치 +- 경품은 예산 범위 내에서 실현 가능한 것 + +[응답 형식] +- JSON 형식으로 응답 +- trends: 업종/지역/시즌 트렌드 분석 (각 100자 내외) +- recommendations: 6개 이벤트 기획안 배열 +``` + +#### 3.2 User Prompt 템플릿 + +```python +def build_user_prompt(store_info, event_purpose, similar_events): + return f""" +다음 정보를 바탕으로 이벤트를 추천해주세요: + +[매장 정보] +- 업종: {store_info['industry']} ({store_info['businessType']}) +- 지역: {store_info['location']['city']} {store_info['location']['district']} +- 이벤트 목적: {event_purpose} +- 현재 시즌: {get_current_season()} + +[참고 데이터] +과거 유사한 매장에서 성공한 이벤트: +{format_similar_events(similar_events)} + +[요구사항] +1. 업종/지역/시즌 트렌드 분석 (각 100자 내외) +2. 3가지 예산별 이벤트 추천: + - 저비용 (25~30만원): 온라인 1개, 오프라인 1개 + - 중비용 (150~180만원): 온라인 1개, 오프라인 1개 + - 고비용 (500~600만원): 온라인 1개, 오프라인 1개 + +각 추천에는 다음 정보를 포함: +- 이벤트 제목 +- 경품명 +- 참여 방법 +- 예상 참여자 수 +- 예상 비용 (원 단위) +- 예상 투자대비수익률 (%) +""" + +def format_similar_events(events): + formatted = [] + for i, event in enumerate(events, 1): + formatted.append(f"{i}. {event['title']} - 참여자 {event['participants']}명, 비용 {event['cost']:,}원, ROI {event['roi']}%") + return "\n".join(formatted) +``` + +#### 3.3 Few-shot 예제 (필요 시) + +```python +FEW_SHOT_EXAMPLES = [ + { + "input": { + "industry": "음식점", + "location": "서울 강남구", + "purpose": "신규 고객 유치", + "season": "겨울" + }, + "output": { + "trends": { + "industry": "음식점업 신년 프로모션 트렌드...", + "location": "강남구는 직장인 및 MZ세대 고객이 많아...", + "season": "겨울 시즌에는 따뜻한 실내 이벤트..." + }, + "recommendations": [...] + } + } +] +``` + +### 4. 백엔드 구현 (Node.js) + +#### 4.1 AI 서비스 컨트롤러 + +```javascript +// controllers/aiController.js +const aiService = require('../services/aiService'); +const cacheService = require('../services/cacheService'); + +exports.getEventRecommendations = async (req, res) => { + try { + const { eventPurpose, storeInfo } = req.body; + const userId = req.user.id; + + // 1. 캐시 키 생성 + const cacheKey = `recommendations:${storeInfo.industry}:${storeInfo.location.district}:${eventPurpose}`; + + // 2. 캐시 확인 + const cached = await cacheService.get(cacheKey); + if (cached) { + return res.json({ + success: true, + data: cached, + metadata: { cacheHit: true } + }); + } + + // 3. AI 추천 생성 + const startTime = Date.now(); + const recommendations = await aiService.generateRecommendations({ + eventPurpose, + storeInfo, + season: getCurrentSeason() + }); + const processingTime = (Date.now() - startTime) / 1000; + + // 4. 캐시 저장 (15분 TTL) + await cacheService.set(cacheKey, recommendations, 900); + + // 5. 응답 + res.json({ + success: true, + data: recommendations, + metadata: { + cacheHit: false, + processingTime, + modelUsage: recommendations.usage + } + }); + + } catch (error) { + console.error('AI recommendation error:', error); + res.status(500).json({ + success: false, + error: 'AI 추천 생성 중 오류가 발생했습니다.' + }); + } +}; + +function getCurrentSeason() { + const month = new Date().getMonth() + 1; + if ([12, 1, 2].includes(month)) return '겨울'; + if ([3, 4, 5].includes(month)) return '봄'; + if ([6, 7, 8].includes(month)) return '여름'; + return '가을'; +} +``` + +#### 4.2 AI 서비스 레이어 + +```javascript +// services/aiService.js +const Anthropic = require('@anthropic-ai/sdk'); +const pineconeService = require('./pineconeService'); + +const anthropic = new Anthropic({ + apiKey: process.env.CLAUDE_API_KEY +}); + +exports.generateRecommendations = async ({ eventPurpose, storeInfo, season }) => { + try { + // 1. 유사 이벤트 검색 + const similarEvents = await pineconeService.searchSimilarEvents({ + industry: storeInfo.industry, + location: storeInfo.location.district, + season + }); + + // 2. 프롬프트 생성 + const userPrompt = buildUserPrompt(storeInfo, eventPurpose, season, similarEvents); + + // 3. Claude API 호출 + const message = await anthropic.messages.create({ + model: 'claude-3-5-sonnet-20241022', + max_tokens: 4096, + temperature: 0.7, + system: getSystemPrompt(), + messages: [{ role: 'user', content: userPrompt }], + response_format: { + type: 'json_schema', + json_schema: getResponseSchema() + } + }); + + // 4. 응답 파싱 + const content = message.content[0].text; + const result = JSON.parse(content); + + // 5. ID 추가 및 검증 + result.recommendations = result.recommendations.map((rec, idx) => ({ + id: `${rec.budget}-${rec.type}`, + ...rec + })); + + // 6. 검증 + validateRecommendations(result); + + return { + ...result, + usage: message.usage + }; + + } catch (error) { + console.error('Claude API error:', error); + + // Fallback: 기본 추천 반환 + return getFallbackRecommendations(storeInfo); + } +}; + +function buildUserPrompt(storeInfo, eventPurpose, season, similarEvents) { + const purposeMap = { + '신규고객유치': '신규 고객 유치', + '재방문유도': '재방문 유도', + '매출증대': '매출 증대', + '인지도향상': '인지도 향상' + }; + + return ` +다음 정보를 바탕으로 이벤트를 추천해주세요: + +[매장 정보] +- 업종: ${storeInfo.industry} (${storeInfo.businessType}) +- 지역: ${storeInfo.location.city} ${storeInfo.location.district} +- 이벤트 목적: ${purposeMap[eventPurpose]} +- 현재 시즌: ${season} + +[참고 데이터] +과거 유사한 매장에서 성공한 이벤트: +${formatSimilarEvents(similarEvents)} + +[요구사항] +1. 업종/지역/시즌 트렌드 분석 (각 100자 내외) +2. 3가지 예산별 이벤트 추천: + - 저비용 (25~30만원): 온라인 1개, 오프라인 1개 + - 중비용 (150~180만원): 온라인 1개, 오프라인 1개 + - 고비용 (500~600만원): 온라인 1개, 오프라인 1개 + +각 추천에는 다음 정보를 포함: +- 이벤트 제목 (30자 이내) +- 경품명 (20자 이내) +- 참여 방법 (간결하게) +- 예상 참여자 수 (정수) +- 예상 비용 (원 단위, 정수) +- 예상 투자대비수익률 (%, 정수) +`.trim(); +} + +function formatSimilarEvents(events) { + return events.map((e, i) => + `${i + 1}. ${e.metadata.title} - 참여자 ${e.metadata.participants}명, 비용 ${e.metadata.cost.toLocaleString()}원, ROI ${e.metadata.roi}%` + ).join('\n'); +} + +function getSystemPrompt() { + return `당신은 소상공인을 위한 이벤트 마케팅 전문가입니다. + +[역할] +- 매장 정보와 이벤트 목적을 바탕으로 효과적인 이벤트 기획안 제안 +- 업종별, 지역별, 시즌별 트렌드 분석 +- 예산별 차별화된 이벤트 추천 + +[제약사항] +- 추천은 반드시 6개 (저/중/고 예산 × 온라인/오프라인) +- 모든 추천은 실현 가능하고 구체적이어야 함 +- 예상 참여자, 비용, 투자대비수익률은 과거 데이터 기반 현실적 수치 +- 경품은 예산 범위 내에서 실현 가능한 것 +- 투자대비수익률은 저예산일수록 높고, 고예산일수록 낮게 설정`; +} + +function getResponseSchema() { + return { + name: 'event_recommendations', + strict: true, + schema: { + type: 'object', + properties: { + trends: { + type: 'object', + properties: { + industry: { type: 'string' }, + location: { type: 'string' }, + season: { type: 'string' } + }, + required: ['industry', 'location', 'season'] + }, + recommendations: { + type: 'array', + items: { + type: 'object', + properties: { + budget: { type: 'string', enum: ['low', 'medium', 'high'] }, + type: { type: 'string', enum: ['online', 'offline'] }, + title: { type: 'string' }, + prize: { type: 'string' }, + participation: { type: 'string' }, + expectedParticipants: { type: 'integer' }, + cost: { type: 'integer' }, + roi: { type: 'integer' } + }, + required: ['budget', 'type', 'title', 'prize', 'participation', 'expectedParticipants', 'cost', 'roi'] + }, + minItems: 6, + maxItems: 6 + } + }, + required: ['trends', 'recommendations'] + } + }; +} + +function validateRecommendations(result) { + // 6개 추천 검증 + if (result.recommendations.length !== 6) { + throw new Error('추천 개수가 6개가 아닙니다'); + } + + // 예산별, 타입별 개수 검증 + const counts = {}; + result.recommendations.forEach(rec => { + const key = `${rec.budget}-${rec.type}`; + counts[key] = (counts[key] || 0) + 1; + }); + + const expected = { + 'low-online': 1, + 'low-offline': 1, + 'medium-online': 1, + 'medium-offline': 1, + 'high-online': 1, + 'high-offline': 1 + }; + + for (const [key, count] of Object.entries(expected)) { + if (counts[key] !== count) { + throw new Error(`${key} 추천 개수가 올바르지 않습니다`); + } + } +} + +function getFallbackRecommendations(storeInfo) { + // API 실패 시 기본 추천 반환 + return { + trends: { + industry: `${storeInfo.industry} 업종의 일반적인 트렌드입니다.`, + location: `${storeInfo.location.district} 지역의 일반적인 특성입니다.`, + season: '계절별 일반적인 이벤트 특성입니다.' + }, + recommendations: [ + { + id: 'low-online', + budget: 'low', + type: 'online', + title: 'SNS 팔로우 이벤트', + prize: '커피 쿠폰', + participation: 'SNS 팔로우', + expectedParticipants: 150, + cost: 250000, + roi: 500 + }, + // ... 나머지 5개 + ] + }; +} +``` + +#### 4.3 Pinecone 서비스 + +```javascript +// services/pineconeService.js +const { PineconeClient } = require('@pinecone-database/pinecone'); +const openai = require('openai'); + +const pinecone = new PineconeClient(); +await pinecone.init({ + apiKey: process.env.PINECONE_API_KEY, + environment: process.env.PINECONE_ENV +}); + +const index = pinecone.Index('kt-event-recommendations'); + +exports.searchSimilarEvents = async ({ industry, location, season }) => { + try { + // 1. 쿼리 텍스트 생성 + const queryText = `업종: ${industry}, 지역: ${location}, 시즌: ${season}`; + + // 2. 임베딩 생성 + const embedding = await generateEmbedding(queryText); + + // 3. 필터 조건 + const filter = { + industry: { $eq: industry } + }; + + // 4. 벡터 검색 + const results = await index.query({ + vector: embedding, + filter, + topK: 5, + includeMetadata: true + }); + + return results.matches; + + } catch (error) { + console.error('Pinecone search error:', error); + return []; + } +}; + +async function generateEmbedding(text) { + const response = await openai.embeddings.create({ + model: 'text-embedding-3-large', + input: text + }); + return response.data[0].embedding; +} +``` + +### 5. 타임아웃 및 에러 처리 + +```javascript +// utils/timeout.js +exports.withTimeout = (promise, timeoutMs) => { + return Promise.race([ + promise, + new Promise((_, reject) => + setTimeout(() => reject(new Error('Timeout')), timeoutMs) + ) + ]); +}; + +// 사용 예시 +const recommendations = await withTimeout( + aiService.generateRecommendations(params), + 10000 // 10초 +); +``` + +--- + +## 시스템 아키텍처 + +### 1. 전체 아키텍처 다이어그램 + +``` +┌─────────────────┐ +│ Frontend │ +│ (React) │ +└────────┬────────┘ + │ HTTP/REST + ▼ +┌─────────────────────────────────────────────────────┐ +│ API Gateway (Express) │ +└────────┬────────────────────────────────────────────┘ + │ + ├─────────────────┬──────────────────┬─────────────┐ + ▼ ▼ ▼ ▼ +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ +│User Service │ │Event Service │ │AI Service │ │Analytics │ +└──────────────┘ └──────────────┘ └──────┬───────┘ └──────────┘ + │ + ┌─────────────────────────┼────────────────┐ + ▼ ▼ ▼ + ┌────────────────┐ ┌──────────────────┐ ┌──────────┐ + │Redis Cache │ │Pinecone │ │Claude API│ + │- Trends (1h) │ │Vector DB │ └──────────┘ + │- Similar (30m) │ │- Event Embeddings│ + │- Results (15m) │ └──────────────────┘ + └────────────────┘ + │ + ▼ + ┌────────────────┐ + │PostgreSQL │ + │- Users │ + │- Events │ + │- Performance │ + └────────────────┘ +``` + +### 2. AI 서비스 상세 플로우 + +``` +사용자 요청 + │ + ▼ +[1] 요청 수신 + │ + ▼ +[2] 캐시 확인 (Redis) + │ + ├─ Hit → 즉시 응답 (< 100ms) + │ + └─ Miss + │ + ▼ + [3] 유사 이벤트 검색 (Pinecone) + │ - 쿼리 임베딩 생성 (OpenAI API) + │ - 벡터 검색 (코사인 유사도) + │ - Top 5 반환 + ▼ + [4] 프롬프트 생성 + │ - 매장 정보 + 이벤트 목적 + │ - 유사 이벤트 컨텍스트 + │ - Few-shot 예제 + ▼ + [5] Claude API 호출 + │ - Structured Output + │ - 타임아웃: 8초 + ▼ + [6] 응답 파싱 및 검증 + │ - JSON 파싱 + │ - 6개 추천 검증 + │ - 예산/타입 검증 + ▼ + [7] 캐시 저장 (Redis) + │ - TTL: 15분 + ▼ + [8] 프론트엔드 응답 + │ - 총 소요시간: < 10초 +``` + +### 3. 데이터 파이프라인 + +``` +[일일 배치 작업] (Airflow) + │ + ├─ [외부 데이터 수집] + │ ├─ 공공데이터 API + │ ├─ SNS 크롤링 + │ └─ 벤치마크 사례 + │ + ▼ +[데이터 정제] + │ - 중복 제거 + │ - 이상치 탐지 + │ - 태깅 + ▼ +[PostgreSQL 저장] + │ + ▼ +[벡터 임베딩 생성] + │ - OpenAI API + │ - 배치 처리 + ▼ +[Pinecone 저장] + + +[실시간 이벤트 생성] + │ + ▼ +[PostgreSQL 저장] + │ + ▼ +[비동기 큐 (RabbitMQ)] + │ + ▼ +[벡터 임베딩 생성] + │ + ▼ +[Pinecone 업데이트] +``` + +--- + +## 성능 최적화 전략 + +### 1. Redis 캐싱 전략 + +#### 1.1 3단계 캐싱 + +```javascript +// services/cacheService.js +const redis = require('redis'); +const client = redis.createClient({ + host: process.env.REDIS_HOST, + port: process.env.REDIS_PORT, + password: process.env.REDIS_PASSWORD +}); + +// 레벨 1: 트렌드 분석 캐싱 (1시간 TTL) +exports.getTrendCache = async (industry, location, season) => { + const key = `trend:${industry}:${location}:${season}`; + const cached = await client.get(key); + return cached ? JSON.parse(cached) : null; +}; + +exports.setTrendCache = async (industry, location, season, data) => { + const key = `trend:${industry}:${location}:${season}`; + await client.setex(key, 3600, JSON.stringify(data)); +}; + +// 레벨 2: 유사 이벤트 검색 캐싱 (30분 TTL) +exports.getSimilarEventsCache = async (industry, location, season) => { + const key = `similar:${industry}:${location}:${season}`; + const cached = await client.get(key); + return cached ? JSON.parse(cached) : null; +}; + +exports.setSimilarEventsCache = async (industry, location, season, data) => { + const key = `similar:${industry}:${location}:${season}`; + await client.setex(key, 1800, JSON.stringify(data)); +}; + +// 레벨 3: 전체 추천 결과 캐싱 (15분 TTL) +exports.getRecommendationCache = async (industry, location, purpose) => { + const key = `recommendations:${industry}:${location}:${purpose}`; + const cached = await client.get(key); + return cached ? JSON.parse(cached) : null; +}; + +exports.setRecommendationCache = async (industry, location, purpose, data) => { + const key = `recommendations:${industry}:${location}:${purpose}`; + await client.setex(key, 900, JSON.stringify(data)); +}; +``` + +#### 1.2 캐시 무효화 전략 + +```javascript +// 새로운 이벤트 성과 데이터 수집 시 관련 캐시 무효화 +exports.invalidateRelatedCache = async (eventData) => { + const patterns = [ + `trend:${eventData.industry}:*`, + `similar:${eventData.industry}:*`, + `recommendations:${eventData.industry}:*` + ]; + + for (const pattern of patterns) { + const keys = await client.keys(pattern); + if (keys.length > 0) { + await client.del(...keys); + } + } +}; +``` + +### 2. 병렬 처리 최적화 + +```javascript +// services/aiService.js +exports.generateRecommendations = async ({ eventPurpose, storeInfo, season }) => { + // 병렬 실행 + const [similarEvents, trendCache] = await Promise.all([ + // 유사 이벤트 검색 + pineconeService.searchSimilarEvents({ + industry: storeInfo.industry, + location: storeInfo.location.district, + season + }), + + // 트렌드 캐시 확인 + cacheService.getTrendCache( + storeInfo.industry, + storeInfo.location.district, + season + ) + ]); + + // ... 나머지 로직 +}; +``` + +### 3. Rate Limiting 대응 + +```javascript +// utils/rateLimiter.js +const rateLimit = require('express-rate-limit'); + +// Claude API Rate Limit 대응 +const apiLimiter = rateLimit({ + windowMs: 60 * 1000, // 1분 + max: 50, // 분당 최대 50건 (Claude API 제한에 맞춤) + message: '요청이 너무 많습니다. 잠시 후 다시 시도해주세요.', + handler: async (req, res) => { + // Rate limit 초과 시 캐시된 기본 추천 반환 + const fallback = await getFallbackRecommendations(req.body.storeInfo); + res.status(200).json({ + success: true, + data: fallback, + metadata: { + rateLimited: true, + message: '일시적으로 기본 추천을 제공합니다' + } + }); + } +}); + +module.exports = apiLimiter; +``` + +### 4. 벡터 검색 최적화 + +```python +# Pinecone 인덱스 파티셔닝 +# 업종별로 네임스페이스 분리하여 검색 성능 향상 + +def save_to_pinecone_with_namespace(event): + industry_namespace = event['industry'] + + pinecone_index.upsert( + vectors=[{ + 'id': event['id'], + 'values': embedding, + 'metadata': {...} + }], + namespace=industry_namespace # 업종별 네임스페이스 + ) + +def search_with_namespace(query_event): + industry_namespace = query_event['industry'] + + results = pinecone_index.query( + vector=query_embedding, + namespace=industry_namespace, # 동일 업종 내에서만 검색 + top_k=5 + ) + return results +``` + +### 5. 응답 시간 모니터링 + +```javascript +// middleware/performanceMonitor.js +exports.trackPerformance = async (req, res, next) => { + const start = Date.now(); + + res.on('finish', () => { + const duration = Date.now() - start; + + // 10초 초과 시 경고 + if (duration > 10000) { + console.warn(`Slow request: ${req.path} took ${duration}ms`); + + // 모니터링 시스템에 전송 (예: Datadog, New Relic) + sendMetric('ai.recommendation.slow', { + path: req.path, + duration, + industry: req.body.storeInfo?.industry + }); + } + + // 평균 응답 시간 추적 + sendMetric('ai.recommendation.duration', duration); + }); + + next(); +}; +``` + +--- + +## 구현 로드맵 + +### Phase 1: 기본 인프라 구축 (2주) + +**Week 1** +- [ ] Pinecone 계정 생성 및 인덱스 설정 +- [ ] Redis 클러스터 구축 +- [ ] PostgreSQL 스키마 설계 +- [ ] Claude API 키 발급 및 테스트 + +**Week 2** +- [ ] 외부 데이터 수집 스크립트 개발 +- [ ] ETL 파이프라인 (Airflow DAG) 구축 +- [ ] 데이터 정제 로직 구현 +- [ ] 초기 데이터셋 구축 (300건) + +### Phase 2: AI 서비스 개발 (3주) + +**Week 3** +- [ ] Claude API 연동 기본 구조 +- [ ] 프롬프트 템플릿 개발 +- [ ] Structured Output 스키마 설계 +- [ ] 응답 파싱 및 검증 로직 + +**Week 4** +- [ ] 벡터 임베딩 생성 로직 +- [ ] Pinecone 연동 (저장/검색) +- [ ] 유사 이벤트 검색 알고리즘 +- [ ] 캐싱 레이어 구현 + +**Week 5** +- [ ] AI 서비스 통합 테스트 +- [ ] 성능 최적화 (병렬 처리) +- [ ] 에러 처리 및 Fallback 구현 +- [ ] 응답 시간 모니터링 + +### Phase 3: 프론트엔드 연동 (1주) + +**Week 6** +- [ ] API 엔드포인트 연동 +- [ ] 로딩 상태 UI 구현 +- [ ] 에러 핸들링 UI +- [ ] E2E 테스트 + +### Phase 4: 운영 및 개선 (지속적) + +**Week 7+** +- [ ] 실사용 데이터 수집 시작 +- [ ] 추천 정확도 모니터링 +- [ ] 프롬프트 최적화 +- [ ] A/B 테스트 진행 +- [ ] 사용자 피드백 반영 + +--- + +## 비용 예측 + +### 1. Claude API 비용 + +**가정** +- 월 사용자 수: 1,000명 +- 사용자당 월 평균 이벤트 생성: 3회 +- 월 총 API 호출: 3,000회 + +**토큰 사용량 (예상)** +- Input: 1,200 tokens/호출 +- Output: 800 tokens/호출 + +**비용 계산** (Claude 3.5 Sonnet 기준) +- Input: $3 / 1M tokens = $0.003 / 1K tokens +- Output: $15 / 1M tokens = $0.015 / 1K tokens + +``` +월 비용 = (1,200 * 0.003 + 800 * 0.015) * 3,000 + = (3.6 + 12) * 3,000 + = 15.6 * 3,000 + = $46,800 / 월 +``` + +### 2. OpenAI Embeddings API 비용 + +**가정** +- 일일 외부 데이터 수집: 10건 +- 월 수집: 300건 +- 사용자 이벤트 생성: 3,000건/월 + +**비용 계산** (text-embedding-3-large 기준) +- $0.13 / 1M tokens + +``` +월 비용 = (300 + 3,000) * 100 tokens * 0.13 / 1,000,000 + = 3,300 * 100 * 0.00000013 + = $0.04 / 월 +``` + +### 3. Pinecone 비용 + +**가정** +- 벡터 차원: 3,072 +- 저장 벡터 수: 10,000건 +- 월 쿼리 수: 3,000회 + +**비용 계산** (Starter Plan) +- $70 / 월 (100,000 벡터 포함) + +### 4. Redis 비용 + +**가정** +- AWS ElastiCache (cache.t3.micro) + +**비용 계산** +- $0.017 / 시간 = $12.24 / 월 + +### 5. 총 비용 + +| 항목 | 월 비용 | +|------|--------| +| Claude API | $46,800 | +| OpenAI Embeddings | $0.04 | +| Pinecone | $70 | +| Redis | $12.24 | +| **총계** | **$46,882** | + +**비용 절감 방안** +1. 캐싱 활용률 향상 (목표: 50% 캐시 히트율) + - Claude API 비용 50% 절감 → $23,400 +2. 배치 처리 최적화 +3. 사용량 기반 동적 스케일링 + +--- + +## 모니터링 및 개선 + +### 1. 핵심 지표 + +**성능 지표** +- 평균 응답 시간: < 10초 +- 캐시 히트율: > 50% +- API 성공률: > 99% + +**품질 지표** +- 추천 선택률: > 70% (사용자가 6개 중 1개 이상 선택) +- "다시 추천받기" 비율: < 30% +- 예측 정확도: 실제 ROI와 예측 ROI 차이 < 20% + +### 2. 개선 사이클 + +``` +[데이터 수집] + │ + ▼ +[정확도 분석] + │ - 예측 vs 실제 비교 + │ - 업종별/지역별 분석 + ▼ +[프롬프트 최적화] + │ - Few-shot 예제 개선 + │ - 시스템 프롬프트 조정 + ▼ +[A/B 테스트] + │ - 새 버전 vs 기존 버전 + │ - 승자 선택 + ▼ +[배포 및 모니터링] +``` + +--- + +## 부록 + +### A. 데이터 스키마 + +#### PostgreSQL 테이블 구조 + +```sql +-- 이벤트 테이블 +CREATE TABLE events ( + id SERIAL PRIMARY KEY, + user_id INTEGER REFERENCES users(id), + title VARCHAR(100), + prize VARCHAR(50), + participation VARCHAR(200), + industry VARCHAR(50), + location_city VARCHAR(50), + location_district VARCHAR(50), + season VARCHAR(10), + cost INTEGER, + expected_roi INTEGER, + created_at TIMESTAMP DEFAULT NOW() +); + +-- 이벤트 성과 테이블 +CREATE TABLE event_performance ( + id SERIAL PRIMARY KEY, + event_id INTEGER REFERENCES events(id), + actual_participants INTEGER, + actual_cost INTEGER, + actual_roi INTEGER, + completed_at TIMESTAMP DEFAULT NOW() +); + +-- AI 추천 이력 테이블 +CREATE TABLE ai_recommendations ( + id SERIAL PRIMARY KEY, + event_id INTEGER REFERENCES events(id), + recommendation_data JSONB, -- Claude API 응답 전체 + selected_option VARCHAR(20), -- 예: "low-online" + created_at TIMESTAMP DEFAULT NOW() +); + +-- 인덱스 +CREATE INDEX idx_events_industry ON events(industry); +CREATE INDEX idx_events_location ON events(location_district); +CREATE INDEX idx_events_season ON events(season); +CREATE INDEX idx_performance_event ON event_performance(event_id); +``` + +### B. 환경 변수 설정 + +```bash +# .env +# Claude API +CLAUDE_API_KEY=sk-ant-xxx + +# OpenAI +OPENAI_API_KEY=sk-xxx + +# Pinecone +PINECONE_API_KEY=xxx +PINECONE_ENV=us-west1-gcp +PINECONE_INDEX=kt-event-recommendations + +# Redis +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_PASSWORD=xxx + +# PostgreSQL +DB_HOST=localhost +DB_PORT=5432 +DB_NAME=kt_events +DB_USER=postgres +DB_PASSWORD=xxx +``` + +### C. 참고 자료 + +**Claude API** +- [Anthropic Documentation](https://docs.anthropic.com/) +- [Structured Outputs Guide](https://docs.anthropic.com/en/docs/build-with-claude/structured-outputs) + +**Pinecone** +- [Pinecone Documentation](https://docs.pinecone.io/) +- [Vector Search Best Practices](https://www.pinecone.io/learn/vector-search/) + +**OpenAI Embeddings** +- [OpenAI Embeddings Guide](https://platform.openai.com/docs/guides/embeddings) + +--- + +**문서 끝** From d5ada31f62587a9b34797bf262fe6510d1581cdc Mon Sep 17 00:00:00 2001 From: cherry2250 Date: Tue, 21 Oct 2025 15:50:17 +0900 Subject: [PATCH 2/2] push prototype --- design/uiux/prototype/03-프로필.html | 214 ++++++++ design/uiux/prototype/04-로그아웃확인.html | 54 ++ design/uiux/prototype/06-이벤트목록.html | 323 +++++++++++ design/uiux/prototype/09-콘텐츠미리보기.html | 296 ++++++++++ design/uiux/prototype/10-콘텐츠편집.html | 329 ++++++++++++ design/uiux/prototype/11-배포채널선택.html | 336 ++++++++++++ design/uiux/prototype/14-참여자목록.html | 350 ++++++++++++ design/uiux/prototype/15-이벤트참여.html | 309 +++++++++++ design/uiux/prototype/16-당첨자추첨.html | 536 +++++++++++++++++++ design/uiux/prototype/17-성과분석.html | 430 +++++++++++++++ 10 files changed, 3177 insertions(+) create mode 100644 design/uiux/prototype/03-프로필.html create mode 100644 design/uiux/prototype/04-로그아웃확인.html create mode 100644 design/uiux/prototype/06-이벤트목록.html create mode 100644 design/uiux/prototype/09-콘텐츠미리보기.html create mode 100644 design/uiux/prototype/10-콘텐츠편집.html create mode 100644 design/uiux/prototype/11-배포채널선택.html create mode 100644 design/uiux/prototype/14-참여자목록.html create mode 100644 design/uiux/prototype/15-이벤트참여.html create mode 100644 design/uiux/prototype/16-당첨자추첨.html create mode 100644 design/uiux/prototype/17-성과분석.html diff --git a/design/uiux/prototype/03-프로필.html b/design/uiux/prototype/03-프로필.html new file mode 100644 index 0000000..0026659 --- /dev/null +++ b/design/uiux/prototype/03-프로필.html @@ -0,0 +1,214 @@ + + + + + + 프로필 - KT AI 이벤트 마케팅 + + + + + +
+ + + +
+ +
+
+ person +
+

홍길동

+

hong@example.com

+
+ + +
+

기본 정보

+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+

매장 정보

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+

비밀번호 변경

+ +
+ + +
+ +
+ + + 8자 이상, 영문과 숫자를 포함해주세요 +
+ +
+ + +
+
+ + +
+ + +
+
+ + +
+
+ + + + + diff --git a/design/uiux/prototype/04-로그아웃확인.html b/design/uiux/prototype/04-로그아웃확인.html new file mode 100644 index 0000000..b6c1acd --- /dev/null +++ b/design/uiux/prototype/04-로그아웃확인.html @@ -0,0 +1,54 @@ + + + + + + 로그아웃 확인 - KT AI 이벤트 마케팅 + + + + + + + + + + + + diff --git a/design/uiux/prototype/06-이벤트목록.html b/design/uiux/prototype/06-이벤트목록.html new file mode 100644 index 0000000..dd2b91e --- /dev/null +++ b/design/uiux/prototype/06-이벤트목록.html @@ -0,0 +1,323 @@ + + + + + + 이벤트 목록 - KT AI 이벤트 마케팅 + + + + + +
+ + + +
+ +
+
+
+ search + +
+
+
+ + +
+
+ filter_list + + +
+
+ + +
+
+

정렬:

+ +
+
+ + +
+ +
+ + +
+ +
+
+ + +
+
+ + + + + diff --git a/design/uiux/prototype/09-콘텐츠미리보기.html b/design/uiux/prototype/09-콘텐츠미리보기.html new file mode 100644 index 0000000..684ef1d --- /dev/null +++ b/design/uiux/prototype/09-콘텐츠미리보기.html @@ -0,0 +1,296 @@ + + + + + + SNS 이미지 생성 - KT AI 이벤트 마케팅 + + + + + + +
+ + + +
+ +
+ psychology +

AI 이미지 생성 중

+

+ 딥러닝 모델이 이벤트에 어울리는
+ 이미지를 생성하고 있어요... +

+
+

예상 시간: 5초

+
+ + + +
+ + +
+
+ + +
+ + 이벤트 이미지 미리보기 +
+ + + + + diff --git a/design/uiux/prototype/10-콘텐츠편집.html b/design/uiux/prototype/10-콘텐츠편집.html new file mode 100644 index 0000000..8263c51 --- /dev/null +++ b/design/uiux/prototype/10-콘텐츠편집.html @@ -0,0 +1,329 @@ + + + + + + 콘텐츠 편집 - KT AI 이벤트 마케팅 + + + + + + +
+ + + +
+ +
+ +
+

미리보기

+
+
+ celebration +

신규고객 유치 이벤트

+

커피 쿠폰 100매

+

전화번호를 입력하고 참여하세요

+
+
+
+ + +
+

편집

+ + +
+

+ edit + 텍스트 편집 +

+ +
+ + + 11/50자 +
+ +
+ + + 9/30자 +
+ +
+ + + 17/100자 +
+
+ + +
+

+ palette + 색상 조정 +

+ +
+ +
+
+ + 클릭하여 선택 +
+
+ +
+ +
+
+ + 클릭하여 선택 +
+
+ +
+ +
+
+ + 클릭하여 선택 +
+
+
+ + +
+

+ business + 로고 위치 +

+ +
+ +
+ + 좌/우 이동 + +
+
+ +
+ +
+ + 중간 + +
+
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + + + + diff --git a/design/uiux/prototype/11-배포채널선택.html b/design/uiux/prototype/11-배포채널선택.html new file mode 100644 index 0000000..f0bb5c8 --- /dev/null +++ b/design/uiux/prototype/11-배포채널선택.html @@ -0,0 +1,336 @@ + + + + + + 배포 채널 선택 - KT AI 이벤트 마케팅 + + + + + + +
+ + + +
+ +
+

배포 채널을 선택해주세요

+

(최소 1개 이상)

+
+ + +
+
+
+
+ + +
+
+ +
+
+ + +
+ +
+ + +
+ +
+

예상 노출: 5만명

+

비용: 8만원

+
+
+
+
+ + +
+
+
+
+ + +
+
+ +
+
+ + +
+ +
+

연결음 자동 업데이트

+

예상 노출: 3만명

+

비용: 무료

+
+
+
+
+ + +
+
+
+
+ + +
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+

예상 노출: 계산중...

+
+
+
+
+ + +
+
+
+
+ + +
+
+ +
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+

예상 노출: -

+

비용: 무료

+
+
+
+
+ + +
+
+
+ 총 예상 비용 + 0원 +
+
+ 총 예상 노출 + 0명 +
+
+
+ + +
+ +
+
+ + +
+
+ + + + + diff --git a/design/uiux/prototype/14-참여자목록.html b/design/uiux/prototype/14-참여자목록.html new file mode 100644 index 0000000..5a019dc --- /dev/null +++ b/design/uiux/prototype/14-참여자목록.html @@ -0,0 +1,350 @@ + + + + + + 참여자 목록 - KT AI 이벤트 마케팅 + + + + + +
+ + + +
+ +
+
+
+ search + +
+
+
+ + +
+
+ filter_list + + +
+
+ + +
+

128명 참여

+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+
+ + + + + diff --git a/design/uiux/prototype/15-이벤트참여.html b/design/uiux/prototype/15-이벤트참여.html new file mode 100644 index 0000000..603a92f --- /dev/null +++ b/design/uiux/prototype/15-이벤트참여.html @@ -0,0 +1,309 @@ + + + + + + 이벤트 참여 - KT AI 이벤트 마케팅 + + + + + + +
+ +
+ celebration +

신규고객 유치 이벤트

+
+ + +
+
+ card_giftcard +
+

경품

+

커피 쿠폰

+
+
+ +
+ calendar_today +
+

기간

+

2025-11-01 ~ 2025-11-15

+
+
+
+ + +
+ + +
+

참여하기

+ +
+ + + +
+ +
+ + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+

+ 참여자: 128명 +

+
+
+ + +
+
+ check +
+

참여가 완료되었습니다!

+

+ 홍길동님의 행운을 기원합니다! +

+ +
+

당첨자 발표

+

2025-11-16 (월)

+
+ + +
+ + + + + diff --git a/design/uiux/prototype/16-당첨자추첨.html b/design/uiux/prototype/16-당첨자추첨.html new file mode 100644 index 0000000..00749c1 --- /dev/null +++ b/design/uiux/prototype/16-당첨자추첨.html @@ -0,0 +1,536 @@ + + + + + + 당첨자 추첨 - KT AI 이벤트 마케팅 + + + + + + +
+ +
+ +
+
+
+ event_note +

이벤트 정보

+
+
+

이벤트명

+

신규고객 유치 이벤트

+
+
+

총 참여자

+

127명

+
+
+

추첨 상태

+

추첨 전

+
+
+
+ + +
+
+
+ tune +

추첨 설정

+
+ +
+ +
+ +
5
+ +
+
+ +
+ + +
+ +
+

+ info + 추첨 방식 +

+

• 난수 기반 무작위 추첨

+

• 모든 추첨 과정은 자동 기록됩니다

+
+
+
+ + +
+ +
+ + +
+

📜 추첨 이력 (최근 3건)

+
+ +
+
+
+ + +
+ +
+

🎉 추첨 완료!

+

127명 중 5명 당첨

+
+ + +
+

🏆 당첨자 목록

+
+ +
+
+

🌟 매장 방문 고객 가산점 적용

+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+
+
+ + +
+
🎰
+

추첨 중...

+

난수 생성 중

+
+ + + + + diff --git a/design/uiux/prototype/17-성과분석.html b/design/uiux/prototype/17-성과분석.html new file mode 100644 index 0000000..334b6f2 --- /dev/null +++ b/design/uiux/prototype/17-성과분석.html @@ -0,0 +1,430 @@ + + + + + + 실시간 대시보드 - KT AI 이벤트 마케팅 + + + + + + +
+ + + +
+ +
+

📊 요약 (실시간)

+
+
+ 방금 전 +
+
+ + +
+
+
+

참여자 수

+
128명
+

↑ 12명 (오늘)

+
+
+

총 비용

+
30만원
+

경품 25만 + 채널 5만

+
+
+

예상 수익

+
135만원
+

매출증가 100만 + LTV 35만

+
+
+

투자대비수익률

+
450%
+

목표 300% 달성

+
+
+
+ + +
+ +
+
+
+ pie_chart +

채널별 성과

+
+
+ donut_large +

파이 차트

+
+
+
+
+ 우리동네TV + 45% (58명) +
+
+
+ 링고비즈 + 30% (38명) +
+
+
+ SNS + 25% (32명) +
+
+
+
+ + +
+
+
+ show_chart +

시간대별 참여 추이

+
+
+ trending_up +

라인 차트

+
+
+

피크 시간: 오후 2-4시 (35명)

+

평균 시간당: 8명

+
+
+
+
+ + +
+ +
+
+
+ payments +

투자대비수익률 상세

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
총 비용: 30만원
• 경품 비용25만원
• 채널 비용5만원
예상 수익: 135만원
• 매출 증가100만원
• 신규 고객 LTV35만원
투자대비수익률
+
+

(수익 - 비용) ÷ 비용 × 100

+

(135만 - 30만) ÷ 30만 × 100

+

= 450%

+
+
+
+
+ + +
+
+
+ people +

참여자 프로필

+
+ +
+

연령별

+
+
+ 20대 +
+
35%
+
+
+
+ 30대 +
+
40%
+
+
+
+ 40대 +
+
25%
+
+
+
+
+ +
+

성별

+
+
+ 여성 +
+
60%
+
+
+
+ 남성 +
+
40%
+
+
+
+
+
+
+
+
+ + +
+
+ + + + +