13.1 OpenAI API와의 클라이언트 통신
Chapter 13. 프론트엔드 통합 (React, Streamlit, Gradio 등) 13.1 OpenAI API와의 클라이언트 통신
OpenAI API는 기본적으로 RESTful API로, HTTP 기반 통신을 통해 임의의 클라이언트(frontend 혹은 backend)로부터 요청을 받아 응답을 반환합니다. 이 장에서는 React 또는 기타 프론트엔드 환경에서 OpenAI API와 통신하는 데 필요한 구조, 보안 고려 사항, 그리고 효율적인 요청 처리 방법을 소개합니다. 사용자는 이를 통해 사용자가 입력한 프롬프트를 API로 전송하고, 생성된 응답을 실시간 또는 비동기 방식으로 UI에 반영하는 인터페이스를 구현할 수 있습니다.
🔹 13.1.1 프런트엔드에서 직접 OpenAI API를 호출할 수 있을까?
기술적으로는 가능합니다. Axios 또는 Fetch API를 사용하여 OpenAI의 엔드포인트(예: https://api.openai.com/v1/chat/completions)에 직접 요청을 보낼 수 있습니다. 하지만 이는 보안상 매우 위험한 방식입니다. 프론트엔드 코드에 OpenAI의 API 키를 직접 포함시키면 사용자 누구나 네트워크 탭(Developer Tools)을 통해 해당 키를 확인할 수 있으며, 이는 심각한 오용 및 과금 문제로 이어질 수 있습니다.
따라서 일반적으로는 프론트엔드 자체가 OpenAI API와 직접 통신하지 않고, 중간에 백엔드 서버(FastAPI, Flask 등)를 두고 프론트가 해당 백엔드에 요청을 보내며, 백엔드는 실제로 OpenAI API에 접근하는 방식을 권장합니다.
다음 그림은 안전한 통신 구조의 예시입니다.
사용자 → React UI → (HTTPS 요청) → Backend (API Key 보관) → OpenAI API
🔹 13.1.2 백엔드를 통한 API 프록시 구조
React 같은 SPA(Single Page Application)는 보통 다음과 같은 워크플로우를 가집니다:
사용자가 입력창에 프롬프트를 작성
"보내기" 버튼 클릭
내부적으로 Fetch, Axios 등을 사용해 백엔드 서버로 요청 전송 (POST /chat)
백엔드에서는 OpenAI API에 요청하고 결과 응답을 받아 프론트엔드로 전달
응답 텍스트를 화면에 출력
간단한 예시는 다음과 같습니다.
백엔드 (예: Flask):
from flask import Flask, request, jsonify
import openai
import os
app = Flask(__name__)
openai.api_key = os.getenv("OPENAI_API_KEY")
@app.route("/chat", methods=["POST"])
def chat():
data = request.json
prompt = data.get("prompt")
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt}
]
)
return jsonify({"response": response['choices'][0]['message']['content']})
프론트엔드 (React):
import React, { useState } from "react";
import axios from "axios";
function ChatApp() {
const [prompt, setPrompt] = useState("");
const [response, setResponse] = useState("");
const handleSend = async () => {
try {
const res = await axios.post("/chat", { prompt });
setResponse(res.data.response);
} catch (e) {
setResponse("오류 발생: " + e.message);
}
};
return (
<div>
<h1>OpenAI 챗봇 인터페이스</h1>
<textarea value={prompt} onChange={(e) => setPrompt(e.target.value)} />
<button onClick={handleSend}>보내기</button>
<div>
<h3>응답</h3>
<p>{response}</p>
</div>
</div>
);
}
export default ChatApp;
이 구조의 장점:
API Key가 유출되지 않음
백엔드에서 요청 로그 및 분석 가능
응답 구조를 프론트에 맞춰 가공 가능
🔹 13.1.3 프론트엔드에서 OpenAI API 호출 구조
만약 개발 초기 테스트 단계에서 백엔드가 없고, 직접 OpenAI API에 연결하는 것이 필요할 경우에는 다음과 같은 방법으로 요청은 가능하지만, 이 방식은 절대 배포 환경에 사용해서는 안됩니다.
주요 요소 정리:
엔드포인트: https://api.openai.com/v1/chat/completions
요청 방식: POST
헤더:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
바디: messages, model, temperature 등 설정 포함
예: 직접 Fetch 요청
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer <YOUR_OPENAI_API_KEY>",
},
body: JSON.stringify({
model: "gpt-4",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "대한민국의 수도는 어디인가요?" }
],
temperature: 0.7,
}),
})
.then((res) => res.json())
.then((data) => {
console.log("응답:", data.choices[0].message.content);
})
.catch((err) => {
console.error("에러 발생:", err);
});
주의 사항:
브라우저 콘솔에서 API 키 노출됨
CORS 정책이 적용되어 사전에 서버에서 인증되지 않으면 실패
토큰 과금/사용량 추적이 어려움
🔹 13.1.4 실시간 스트리밍 방식 지원 (event-based / SSE)
OpenAI의 Chat Completions API는 응답을 스트림으로 받아오는 기능(stream: true)을 제공합니다. 이는 UI 상에서 점진적으로 답변이 출력되는 방식으로 사용자 경험을 크게 향상시킬 수 있습니다. 다만, 클라이언트에서 직접 이 기능을 구현하기에는 HTTP streaming에 대한 이해가 필요하며, 대부분은 서버 측에서 chunked 응답을 SSE(Server Sent Events)나 WebSocket으로 프록시한 후 프론트엔드에서 수신하는 구조로 만듭니다.
Advanced Node.js 예시 (Express + SSE):
백엔드에서 stream: true로 요청
응답을 받아 각 chunk 데이터 마다 event emit
프론트에서는 EventSource를 통해 수신 후 렌더링
🔹 13.1.5 에러 처리 전략
OpenAI API는 다양한 이유로 에러를 반환할 수 있습니다. 대표적인 예는 다음과 같습니다.
401 Unauthorized: API 키 오류 또는 누락
429 Rate Limit 초과
500/503 Server error
따라서 프론트엔드에서 다음과 같은 대응을 적용해야 합니다:
사용자에게 명확한 에러 메시지 표시
재시도 전략(backoff 정책 기반)
요청 중 isLoading 상태 관리로 중복 클릭 방지
불완전 응답 시 롤백 처리
🔹 13.1.6 요약
프론트에서 직접 OpenAI 호출
❌
API Key 노출, 보안 위험
백엔드 프록시 통한 호출
✅
API Key 보호, 요청 관리 용이
Streaming 응답
조건부 권장
UX 향상에도 성능 및 구현 복잡성 고려
React와 통신 방식
Axios / Fetch
REST 기반 요청 처리에 적합
에러 처리
필수
사용자 경험과 안정성 확보
이 절의 핵심은 “API 키는 절대 공개되지 않는 환경에서만 사용하라”는 점입니다. 프런트엔드에서의 OpenAI API 호출은 반드시 백엔드를 통한 안전한 중계 구조를 갖추어야 하며, 비동기 처리 방식과 사용자 인터랙션 관리(로딩 상태, 입력 차단, 에러 알림 등)를 적절히 구성하는 것이 중요합니다.
다음 절에서는 실제 Streamlit과 Gradio를 활용해 데모 인터페이스를 구현하는 방법을 실습 중심으로 설명하겠습니다.
Last updated