# v7: ChatGPT API 연동 ## 개요 이번 단계에서는 OpenAI ChatGPT API를 프로젝트에 연동합니다. API 키를 설정하고, 클라이언트를 초기화하며, 기본 연결 테스트를 진행합니다. ## OpenAI API 키 발급 ### 1. OpenAI 계정 생성 1. https://platform.openai.com 방문 2. "Sign up" 클릭하여 계정 생성 3. 이메일 인증 완료 ### 2. API 키 발급 1. https://platform.openai.com/api-keys 접속 2. "Create new secret key" 클릭 3. 키 이름 입력 (예: "stripe-sales-analyzer") 4. 생성된 키 복사 (`sk-proj-...`로 시작) **중요**: API 키는 한 번만 표시되므로 안전한 곳에 저장하세요! ### 3. 사용량 및 과금 확인 - https://platform.openai.com/usage 에서 사용량 확인 - https://platform.openai.com/account/billing 에서 결제 정보 설정 - 무료 크레딧이 있는 경우 먼저 사용됨 ### 4. 모델별 비용 (2024년 기준) **GPT-4 Turbo**: - Input: $10.00 / 1M tokens - Output: $30.00 / 1M tokens **GPT-3.5 Turbo**: - Input: $0.50 / 1M tokens - Output: $1.50 / 1M tokens **이번 프로젝트에서는**: GPT-3.5 Turbo 사용 권장 (비용 효율적) ## 환경 변수 설정 ### .env 파일 업데이트 ```bash # Stripe API Keys STRIPE_SECRET_KEY=sk_test_your_key_here # OpenAI API Key OPENAI_API_KEY=sk-proj-your_openai_key_here # 환경 설정 NODE_ENV=development # OpenAI 설정 (선택사항) OPENAI_MODEL=gpt-3.5-turbo OPENAI_MAX_TOKENS=1000 OPENAI_TEMPERATURE=0.7 ``` ### src/config/env.ts 업데이트 ```typescript import 'dotenv/config'; export const env = { // Stripe stripeSecretKey: process.env.STRIPE_SECRET_KEY, // OpenAI openaiApiKey: process.env.OPENAI_API_KEY, openaiModel: process.env.OPENAI_MODEL || 'gpt-3.5-turbo', openaiMaxTokens: parseInt(process.env.OPENAI_MAX_TOKENS || '1000'), openaiTemperature: parseFloat(process.env.OPENAI_TEMPERATURE || '0.7'), // General nodeEnv: process.env.NODE_ENV || 'development', } as const; // 환경 변수 검증 function validateEnv() { const required = { STRIPE_SECRET_KEY: env.stripeSecretKey, OPENAI_API_KEY: env.openaiApiKey, }; const missing = Object.entries(required) .filter(([_, value]) => !value) .map(([key]) => key); if (missing.length > 0) { throw new Error( `필수 환경 변수가 설정되지 않았습니다: ${missing.join(', ')}\n` + '.env 파일을 확인해주세요.' ); } } validateEnv(); ``` ## ChatGPT 클라이언트 생성 ### src/chatgpt/client.ts ```typescript import OpenAI from 'openai'; import { env } from '../config/env.js'; /** * OpenAI 클라이언트 초기화 */ export const openai = new OpenAI({ apiKey: env.openaiApiKey, }); /** * ChatGPT 연결 테스트 */ export async function testChatGPTConnection(): Promise { try { console.log('🔄 ChatGPT API 연결 테스트 중...\n'); const response = await openai.chat.completions.create({ model: env.openaiModel, messages: [ { role: 'user', content: 'Hello! Please respond with "Connection successful".', }, ], max_tokens: 50, }); const message = response.choices[0].message.content; console.log('✅ ChatGPT 연결 성공!'); console.log(`Model: ${response.model}`); console.log(`Response: ${message}`); console.log(`Tokens used: ${response.usage?.total_tokens || 'N/A'}`); return true; } catch (error) { console.error('❌ ChatGPT 연결 실패:', error); if (error instanceof OpenAI.APIError) { console.error(`Status: ${error.status}`); console.error(`Message: ${error.message}`); if (error.status === 401) { console.error('\nAPI 키가 유효하지 않습니다. .env 파일을 확인해주세요.'); } else if (error.status === 429) { console.error('\nAPI 요청 한도를 초과했습니다. 잠시 후 다시 시도해주세요.'); } } return false; } } /** * 간단한 ChatGPT 요청 헬퍼 */ export async function askChatGPT( prompt: string, systemPrompt?: string ): Promise { const messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = []; if (systemPrompt) { messages.push({ role: 'system', content: systemPrompt, }); } messages.push({ role: 'user', content: prompt, }); const response = await openai.chat.completions.create({ model: env.openaiModel, messages, max_tokens: env.openaiMaxTokens, temperature: env.openaiTemperature, }); return response.choices[0].message.content || ''; } ``` ## 연결 테스트 스크립트 ### src/test-chatgpt.ts ```typescript import { testChatGPTConnection, askChatGPT } from './chatgpt/client.js'; async function main() { console.log('🤖 ChatGPT API 테스트\n'); // 1. 연결 테스트 const isConnected = await testChatGPTConnection(); if (!isConnected) { console.error('\n❌ ChatGPT 연결 실패. 프로그램을 종료합니다.'); process.exit(1); } // 2. 간단한 질문 테스트 console.log('\n📝 간단한 질문 테스트...\n'); const question = '오늘 매출이 100만원이고 10건의 거래가 있었습니다. 간단히 요약해주세요.'; const answer = await askChatGPT(question, '당신은 매출 분석 전문가입니다.'); console.log('질문:', question); console.log('\n답변:', answer); // 3. 복잡한 데이터 분석 테스트 console.log('\n\n📊 데이터 분석 테스트...\n'); const salesData = ` 날짜: 2025-11-28 총 매출: $5,432.00 결제 건수: 15건 평균 결제 금액: $362.13 카테고리별 매출: - electronics: $2,450.00 (6건) - books: $1,680.00 (4건) - clothing: $902.00 (3건) - home: $400.00 (2건) 결제가 많은 시간대: - 14시: 5건 - 16시: 4건 - 11시: 3건 `; const analysisPrompt = ` 다음은 오늘의 매출 데이터입니다: ${salesData} 이 데이터를 분석하여 다음을 제공해주세요: 1. 전체 매출 요약 (2-3문장) 2. 주요 인사이트 (3가지) 3. 개선 제안 (2가지) 간결하고 명확하게 작성해주세요. `; const analysis = await askChatGPT( analysisPrompt, '당신은 전문적인 매출 분석가입니다. 데이터를 기반으로 실용적인 인사이트를 제공합니다.' ); console.log('분석 결과:\n'); console.log(analysis); console.log('\n✨ 모든 테스트 완료!'); } main().catch((error) => { console.error('\n💥 예상치 못한 에러 발생:'); console.error(error); process.exit(1); }); ``` ### package.json에 스크립트 추가 ```json { "scripts": { "test:chatgpt": "tsx src/test-chatgpt.ts", "test:ai": "tsx src/test-chatgpt.ts" } } ``` ## 실행 및 테스트 ```bash npm run test:chatgpt ``` ### 예상 출력 ``` 🤖 ChatGPT API 테스트 🔄 ChatGPT API 연결 테스트 중... ✅ ChatGPT 연결 성공! Model: gpt-3.5-turbo-0125 Response: Connection successful Tokens used: 15 📝 간단한 질문 테스트... 질문: 오늘 매출이 100만원이고 10건의 거래가 있었습니다. 간단히 요약해주세요. 답변: 오늘 총 10건의 거래를 통해 100만원의 매출을 달성했습니다. 건당 평균 거래액은 10만원입니다. 꾸준한 거래 흐름을 보이고 있습니다. 📊 데이터 분석 테스트... 분석 결과: 1. 전체 매출 요약: 오늘 15건의 거래를 통해 총 $5,432의 매출을 기록했습니다. 건당 평균 $362.13으로 중간 가격대의 상품들이 고르게 판매되었습니다. 2. 주요 인사이트: • Electronics 카테고리가 전체 매출의 45%를 차지하며 가장 높은 비중 • 오후 시간대(14시, 16시)에 거래가 집중되는 패턴 발견 • 다양한 카테고리에 걸쳐 판매가 분산되어 있어 포트폴리오가 건강함 3. 개선 제안: • 오전 시간대 프로모션을 통해 거래를 더 고르게 분산시킬 수 있습니다 • Electronics 인기를 활용하여 관련 액세서리 교차 판매 전략 수립 권장 ✨ 모든 테스트 완료! ``` ## 모델 선택 가이드 ### GPT-3.5 Turbo (권장) **장점**: - 빠른 응답 속도 - 저렴한 비용 - 대부분의 분석 작업에 충분 **사용 케이스**: - 매출 요약 - 기본 인사이트 생성 - 간단한 데이터 해석 ### GPT-4 Turbo **장점**: - 더 정확한 분석 - 복잡한 패턴 인식 - 더 창의적인 제안 **사용 케이스**: - 심층 분석 - 복잡한 비즈니스 전략 제안 - 고급 트렌드 예측 ### 비용 비교 예시 ```typescript // 평균 요청당 토큰: ~500 (입력) + ~300 (출력) // GPT-3.5 Turbo // 입력: 500 * $0.50 / 1,000,000 = $0.00025 // 출력: 300 * $1.50 / 1,000,000 = $0.00045 // 총: $0.0007 (약 1원) // GPT-4 Turbo // 입력: 500 * $10.00 / 1,000,000 = $0.005 // 출력: 300 * $30.00 / 1,000,000 = $0.009 // 총: $0.014 (약 20원) ``` ## 에러 처리 ### src/utils/openai-error-handler.ts ```typescript import OpenAI from 'openai'; /** * OpenAI 에러를 사용자 친화적인 메시지로 변환 */ export function handleOpenAIError(error: unknown): string { if (error instanceof OpenAI.APIError) { switch (error.status) { case 401: return 'API 키가 유효하지 않습니다. 환경 변수를 확인해주세요.'; case 429: return 'API 요청 한도를 초과했습니다. 잠시 후 다시 시도해주세요.'; case 500: case 502: case 503: return 'OpenAI 서버에 일시적인 문제가 있습니다. 잠시 후 다시 시도해주세요.'; default: return `OpenAI API 에러: ${error.message}`; } } return '알 수 없는 에러가 발생했습니다.'; } /** * 에러 로깅 */ export function logOpenAIError(error: unknown, context?: string): void { console.error('\n❌ OpenAI 에러 발생'); if (context) { console.error(`Context: ${context}`); } if (error instanceof OpenAI.APIError) { console.error(`Status: ${error.status}`); console.error(`Message: ${error.message}`); console.error(`Type: ${error.type}`); if (error.code) { console.error(`Code: ${error.code}`); } } else { console.error(error); } } ``` ## 토큰 사용량 추적 ### src/utils/token-tracker.ts ```typescript import OpenAI from 'openai'; export class TokenTracker { private totalTokens = 0; private totalCost = 0; // 모델별 가격 (per 1M tokens) private readonly pricing: Record< string, { input: number; output: number } > = { 'gpt-3.5-turbo': { input: 0.5, output: 1.5 }, 'gpt-4-turbo': { input: 10.0, output: 30.0 }, 'gpt-4': { input: 30.0, output: 60.0 }, }; track(response: OpenAI.Chat.Completions.ChatCompletion) { const usage = response.usage; if (!usage) return; const model = response.model.includes('gpt-4') ? 'gpt-4-turbo' : 'gpt-3.5-turbo'; const prices = this.pricing[model]; const inputCost = (usage.prompt_tokens / 1_000_000) * prices.input; const outputCost = (usage.completion_tokens / 1_000_000) * prices.output; const requestCost = inputCost + outputCost; this.totalTokens += usage.total_tokens; this.totalCost += requestCost; console.log(`\n💰 사용량:`); console.log(` 토큰: ${usage.total_tokens} (입력: ${usage.prompt_tokens}, 출력: ${usage.completion_tokens})`); console.log(` 비용: $${requestCost.toFixed(6)} (약 ${(requestCost * 1400).toFixed(2)}원)`); } getSummary() { return { totalTokens: this.totalTokens, totalCost: this.totalCost, totalCostKRW: this.totalCost * 1400, // 대략적인 환율 }; } printSummary() { const summary = this.getSummary(); console.log('\n📊 전체 사용량:'); console.log(` 총 토큰: ${summary.totalTokens.toLocaleString()}`); console.log(` 총 비용: $${summary.totalCost.toFixed(4)} (약 ${summary.totalCostKRW.toFixed(0)}원)`); } } ``` ## 스트리밍 응답 (선택사항) 실시간으로 응답을 받고 싶다면: ```typescript export async function askChatGPTStream(prompt: string): Promise { const stream = await openai.chat.completions.create({ model: env.openaiModel, messages: [{ role: 'user', content: prompt }], stream: true, }); let fullResponse = ''; for await (const chunk of stream) { const content = chunk.choices[0]?.delta?.content || ''; process.stdout.write(content); // 실시간 출력 fullResponse += content; } console.log('\n'); // 줄바꿈 return fullResponse; } ``` ## 체크리스트 v7를 완료하기 전에 다음을 확인하세요: - [ ] OpenAI API 키 발급 - [ ] `.env` 파일에 `OPENAI_API_KEY` 추가 - [ ] `src/config/env.ts` 업데이트 - [ ] `src/chatgpt/client.ts` 작성 - [ ] `src/test-chatgpt.ts` 작성 - [ ] `src/utils/openai-error-handler.ts` 작성 - [ ] package.json 스크립트 추가 - [ ] `npm run test:chatgpt` 실행 성공 - [ ] 연결 테스트 통과 - [ ] 분석 테스트 결과 확인 ## 트러블슈팅 ### 1. "Invalid API Key" 에러 **원인**: API 키가 잘못되었거나 만료됨 **해결**: - `.env` 파일에서 `OPENAI_API_KEY` 확인 - `sk-proj-`로 시작하는지 확인 - 새로운 키 발급 ### 2. "Rate Limit Exceeded" 에러 **원인**: 요청 한도 초과 **해결**: - 무료 플랜의 경우 분당 3회 제한 - 유료 플랜으로 업그레이드 고려 - 요청 간 딜레이 추가 ### 3. "Model not found" 에러 **원인**: 잘못된 모델 이름 **해결**: - `gpt-3.5-turbo` 또는 `gpt-4-turbo` 사용 - 최신 모델 목록: https://platform.openai.com/docs/models ## 다음 단계 v8에서는 실제 Stripe 매출 데이터를 ChatGPT에 전달하여 분석을 요청합니다. 준비할 것: - ChatGPT 연결 테스트 성공 - 프롬프트 엔지니어링 기초 이해 --- **작성일**: 2025-11-28 **상태**: ✅ 완료 **다음**: v8 - 매출 분석 요청