개발

React와 AI 통합: ChatGPT API · Hugging Face로 챗봇, 추천, 스마트 폼 만들기

stable_project 2025. 10. 31. 14:40
반응형

 

React와 AI 통합: ChatGPT API · Hugging Face로 챗봇, 추천, 스마트 폼 만들기

요약: 이 글에서는 React에서 OpenAI(ChatGPT API)Hugging Face 같은 AI API를 손쉽게 연결하는 법을 설명합니다.
챗봇 UI, AI 추천 시스템, 스마트 폼 등 실무 예제 중심으로 구성했습니다.


1. 기본 구조

  • 클라이언트(React): 입력 UI, 채팅 인터페이스
  • 서버 프록시(API Route): API 키 보호 및 검증
  • AI API: OpenAI, Hugging Face 등

TIP: 브라우저에서 직접 비공개 키를 쓰면 안 됩니다. 반드시 서버에서 호출하세요.


2. 환경 변수 설정

# .env (서버 전용)
OPENAI_API_KEY=your-openai-key
HF_API_TOKEN=your-huggingface-token

3. 서버 API 라우트 만들기

3.1 OpenAI Chat API (Next.js 14 기준)

// app/api/chat/route.ts
import { NextResponse } from "next/server";

export async function POST(req: Request) {
  const { messages } = await req.json();

  const res = await fetch("https://api.openai.com/v1/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      model: "gpt-4o-mini",
      messages,
      stream: true
    })
  });

  return new NextResponse(res.body, {
    headers: { "Content-Type": "text/event-stream" }
  });
}

3.2 Hugging Face API (텍스트 분류 등)

// app/api/hf/route.ts
import { NextResponse } from "next/server";

export async function POST(req: Request) {
  const { inputs, model = "sentence-transformers/all-MiniLM-L6-v2" } = await req.json();

  const res = await fetch(`https://api-inference.huggingface.co/models/${model}`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.HF_API_TOKEN}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ inputs })
  });

  const data = await res.json();
  return NextResponse.json(data);
}

4. React 챗봇 UI 예제

// app/chat/page.tsx
"use client";
import { useState, useEffect, useRef } from "react";

export default function ChatPage() {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState("");
  const viewRef = useRef(null);

  const send = async () => {
    const next = [...messages, { role: "user", content: input }];
    setMessages(next);
    setInput("");

    const res = await fetch("/api/chat", {
      method: "POST",
      body: JSON.stringify({ messages: next }),
      headers: { "Content-Type": "application/json" }
    });

    const reader = res.body?.getReader();
    const decoder = new TextDecoder();
    let text = "";

    while (true) {
      const { value, done } = await reader.read();
      if (done) break;
      text += decoder.decode(value);
      setMessages([...next, { role: "assistant", content: text }]);
    }
  };

  useEffect(() => {
    viewRef.current?.scrollTo({ top: viewRef.current.scrollHeight });
  }, [messages]);

  return (
    <main style={{ maxWidth: 600, margin: "0 auto" }}>
      <h2>AI 챗봇</h2>
      <div ref={viewRef} style={{ height: 300, overflowY: "auto", border: "1px solid #333", padding: 10 }}>
        {messages.map((m, i) => (
          <div key={i}><b>{m.role}:</b> {m.content}</div>
        ))}
      </div>
      <form onSubmit={(e) => { e.preventDefault(); send(); }} style={{ display: "flex", marginTop: 10 }}>
        <input value={input} onChange={(e) => setInput(e.target.value)} style={{ flex: 1, padding: "8px" }} />
        <button type="submit">보내기</button>
      </form>
    </main>
  );
}

5. AI 추천 시스템 (임베딩 기반)

// app/api/embed/route.ts
import { NextResponse } from "next/server";

export async function POST(req: Request) {
  const { texts } = await req.json();
  const res = await fetch("https://api.openai.com/v1/embeddings", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ model: "text-embedding-3-small", input: texts })
  });

  const data = await res.json();
  return NextResponse.json(data.data.map((d) => d.embedding));
}
// utils/similarity.ts
export function cosine(a, b) {
  let dot = 0, na = 0, nb = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    na  += a[i] * a[i];
    nb  += b[i] * b[i];
  }
  return dot / (Math.sqrt(na) * Math.sqrt(nb));
}

이 함수를 이용하면, 사용자의 쿼리와 임베딩 벡터 간 유사도를 계산해 AI 추천을 구현할 수 있습니다.


6. 스마트 폼 (AI 교정 / 요약)

// app/api/rewrite/route.ts
import { NextResponse } from "next/server";

export async function POST(req: Request) {
  const { text } = await req.json();
  const res = await fetch("https://api.openai.com/v1/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      model: "gpt-4o-mini",
      messages: [
        { role: "system", content: "You are a helpful Korean writing assistant." },
        { role: "user", content: `이 문장을 자연스럽게 교정해줘:\n${text}` }
      ]
    })
  });
  const data = await res.json();
  return NextResponse.json({ output: data.choices[0].message.content });
}
// app/form/page.tsx
"use client";
import { useState } from "react";

export default function SmartForm() {
  const [text, setText] = useState("");
  const [output, setOutput] = useState("");

  const handle = async () => {
    const res = await fetch("/api/rewrite", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ text })
    });
    const { output } = await res.json();
    setOutput(output);
  };

  return (
    <div style={{ maxWidth:600, margin:"0 auto" }}>
      <h3>AI 교정 폼</h3>
      <textarea value={text} onChange={(e) => setText(e.target.value)} rows={5} style={{ width:"100%", padding:"8px" }} />
      <button onClick={handle} style={{ marginTop:10 }}>AI 교정</button>
      <pre>{output}</pre>
    </div>
  );
}

7. OpenAI vs Hugging Face 비교

항목 OpenAI Hugging Face
강점 고품질 언어모델, 간단한 API 모델 다양성, 커스텀 가능
속도 빠름 (상용 인프라) 모델별 상이
사용예 Chatbot, Smart Form 추천, 감정분석, 요약
비용 API 기반, 토큰 단위 과금 무료/유료 모델 선택 가능

8. 결론

React + AI API는 복잡하지 않습니다. 핵심은 다음 세 가지입니다:

  • 서버 프록시를 통해 키를 숨긴다.
  • 스트리밍 응답으로 실시간 UX 구현.
  • RSC/클라이언트 컴포넌트로 역할 분리.

이 구조를 기반으로 챗봇, 추천 시스템, 스마트 입력 폼 등 다양한 AI 기능을 React에서 구현할 수 있습니다.

반응형