이 교안은 아래의 기술을 사용하여 AI 챗봇을 만드는 방법을 단계별로 설명한다.
| 역할 | 기술 | 설명 |
|---|---|---|
| 프론트엔드(front-end) | React(리액트) + Vanilla CSS | 사용자 화면 |
| 백엔드(back-end) | Python(파이썬) + FastAPI(패스트에이피아이) | 서버 로직 |
| AI 모델 | HuggingFace(허깅페이스) | 무료 AI API |
| 배포 | Render(렌더) | 무료 호스팅 |
Info: HuggingFace(허깅페이스) 란? AI 모델을 누구나 무료로 사용할 수 있도록 제공하는 플랫폼이다. 회원가입만 하면 API(에이피아이) 키를 무료로 받을 수 있다.
my-chatbot/
├── backend/ ← 파이썬 서버
│ ├── main.py
│ └── requirements.txt
└── frontend/ ← 리액트 화면
├── src/
│ ├── App.jsx
│ └── App.css
└── package.json
backend/ : 파이썬 코드가 들어가는 폴더이다.frontend/ : 리액트 코드가 들어가는 폴더이다.mkdir my-chatbot
cd my-chatbot
mkdir backend
mkdir frontend
mkdir (메이크 디렉토리): 폴더를 만드는 명령어이다.cd (체인지 디렉토리): 폴더 안으로 이동하는 명령어이다.Tip: API(에이피아이) 키란? 내 신분증처럼, 허깅페이스 서버에 "나는 회원이에요"라고 증명하는 비밀 문자열이다.
hf_xxxxxxxxxxxxxxxx)를 복사하여 안전한 곳에 저장한다.Warning: API(에이피아이) 키는 절대로 GitHub(깃허브)에 올리면 안 된다. 타인이 내 키를 무단으로 사용할 수 있다.
cd backend
python -m venv .venv
.venv\Scripts\activate
python -m venv .venv : 가상환경 폴더를 만든다..venv\Scripts\activate : 가상환경을 실행(활성화)한다.(.venv) 표시가 나타난다.cd backend
python3 -m venv .venv
source .venv/bin/activate
source .venv/bin/activate : Mac/Linux에서 가상환경을 활성화하는 명령어이다.pip install fastapi uvicorn requests python-dotenv
| 라이브러리 | 발음 | 역할 |
|---|---|---|
| fastapi | 패스트에이피아이 | 파이썬 웹 서버 프레임워크 |
| uvicorn | 유비콘 | 서버 실행기 |
| requests | 리퀘스츠 | 외부 API 호출 도구 |
| python-dotenv | 파이썬 닷엔브 | 환경변수 관리 |
backend/ 폴더 안에 .env 파일을 만들고 아래 내용을 입력한다.
HF_TOKEN=hf_여기에_내_키를_붙여넣기
Note:
.env(닷엔브) 파일이란? 비밀 정보를 코드 밖에 보관하는 파일이다. 코드에 직접 키를 쓰지 않아도 되므로 안전하다.
backend/main.py 파일을 만들고 아래 코드를 작성한다.
from fastapi import FastAPI # 01
from fastapi.middleware.cors import CORSMiddleware # 02
from pydantic import BaseModel # 03
import requests, os # 04
from dotenv import load_dotenv # 05
load_dotenv() # 06
app = FastAPI() # 07
app.add_middleware( # 08
CORSMiddleware, # 09
allow_origins=["*"], # 10
allow_methods=["*"], # 11
allow_headers=["*"], # 12
) # 13
class Msg(BaseModel): # 14
text: str # 15
HF_URL = "https://router.huggingface.co/v1/chat/completions" # 16
HF_MODEL = "Qwen/Qwen2.5-72B-Instruct" # 17
def ask_ai(q: str) -> str: # 18
token = os.getenv("HF_TOKEN") # 19
headers = {"Authorization": f"Bearer {token}"} # 20
payload = { # 21
"model": HF_MODEL, # 22
"messages": [{"role": "user", "content": q}], # 23
"max_tokens": 300 # 24
} # 25
res = requests.post(HF_URL, headers=headers, json=payload) # 26
data = res.json() # 27
return data["choices"][0]["message"]["content"] # 28
@app.post("/chat") # 27
def chat(msg: Msg): # 28
reply = ask_ai(msg.text) # 29
return {"reply": reply} # 30
uvicorn main:app --reload
uvicorn (유비콘): 파이썬 서버 실행 도구이다.main:app : main.py 파일의 app 객체를 실행한다는 뜻이다.--reload : 코드 수정 시 자동으로 서버를 재시작한다.브라우저에서 http://localhost:8000/docs 에 접속하면 자동 생성된 API(에이피아이) 문서를 확인할 수 있다.
Tip:
/docs(닥스) 페이지에서/chat엔드포인트를 직접 테스트해볼 수 있다. Try it out(트라이 잇 아웃) 버튼을 클릭하여{"text": "안녕?"}을 입력해 보자.
배포 시 필요한 파일이다. backend/requirements.txt 를 만들고 아래 내용을 입력한다.
fastapi
uvicorn
requests
python-dotenv
cd ../frontend
npm create vite@latest . -- --template react
npm install
cd ../frontend : 백엔드 폴더에서 나와 프론트엔드 폴더로 이동한다.npm create vite@latest . : 현재 폴더에 Vite(비트) 프로젝트를 생성한다.-- --template react : 리액트 템플릿(template)으로 생성한다.npm install : 필요한 패키지(package)들을 설치한다.frontend/src/App.jsx 파일을 아래 코드로 교체한다.
import { useState } from "react"; // 01
import "./App.css"; // 02
const API = "http://localhost:8000/chat"; // 03
export default function App() { // 04
const [msgs, setMsgs] = useState([]); // 05
const [input, setInput] = useState(""); // 06
const [loading, setLoading] = useState(false); // 07
const send = async () => { // 08
if (!input.trim()) return; // 09
const userMsg = { role: "user", text: input }; // 10
setMsgs(prev => [...prev, userMsg]); // 11
setInput(""); // 12
setLoading(true); // 13
const res = await fetch(API, { // 14
method: "POST", // 15
headers: { "Content-Type": "application/json" }, // 16
body: JSON.stringify({ text: input }) // 17
}); // 18
const data = await res.json(); // 19
const botMsg = { role: "bot", text: data.reply }; // 20
setMsgs(prev => [...prev, botMsg]); // 21
setLoading(false); // 22
}; // 23
const onKey = (e) => { // 24
if (e.key === "Enter") send(); // 25
}; // 26
return ( // 27
<div className="wrap"> // 28
<h1>🤖 AI 챗봇</h1> // 29
<div className="box"> // 30
{msgs.map((m, i) => ( // 31
<div key={i} className={m.role}> // 32
<span>{m.role === "user" ? "🧑" : "🤖"}</span> // 33
<p>{m.text}</p> // 34
</div> // 35
))} // 36
{loading && <p className="loading">생각 중...</p>} // 37
</div> // 38
<div className="input-row"> // 39
<input // 40
value={input} // 41
onChange={e => setInput(e.target.value)} // 42
onKeyDown={onKey} // 43
placeholder="메시지를 입력하세요" // 44
/> // 45
<button onClick={send}>전송</button> // 46
</div> // 47
</div> // 48
); // 49
} // 50
frontend/src/App.css 파일을 아래 코드로 교체한다.
.wrap { max-width: 600px; margin: 40px auto; font-family: sans-serif; }
.box { border: 1px solid #ccc; height: 400px; overflow-y: auto; padding: 16px; }
.user { text-align: right; margin: 8px 0; }
.bot { text-align: left; margin: 8px 0; }
.user p, .bot p { display: inline-block; padding: 8px 12px; border-radius: 8px; }
.user p { background: #d1e7ff; }
.bot p { background: #f0f0f0; }
.loading { color: #888; font-style: italic; }
.input-row { display: flex; gap: 8px; margin-top: 8px; }
.input-row input { flex: 1; padding: 8px; }
.input-row button { padding: 8px 16px; cursor: pointer; }
.user와 .bot으로 사용자와 봇 메시지를 좌우로 구분한다.npm run dev
브라우저에서 http://localhost:5173 에 접속하여 챗봇이 동작하는지 확인한다.
Tip: 파이썬 서버(
uvicorn)와 리액트 개발 서버(npm run dev)를 동시에 실행해야 한다. 터미널 창을 두 개 열어서 각각 실행한다.
Note: GitHub(깃허브)란? 코드를 온라인에 저장하고 공유하는 서비스이다. Render(렌더)는 깃허브 저장소를 연결하여 자동으로 배포한다.
my-chatbot/)에 .gitignore 파일을 만들고 아래 내용을 입력한다.backend/.env
backend/.venv/
frontend/node_modules/
git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/내아이디/my-chatbot.git
git push -u origin main
| 항목 | 입력값 |
|---|---|
| Root Directory(루트 디렉토리) | backend |
| Runtime(런타임) | Python 3 |
| Build Command(빌드 커맨드) | pip install -r requirements.txt |
| Start Command(스타트 커맨드) | uvicorn main:app --host 0.0.0.0 --port 10000 |
| Key(키) | Value(값) |
|---|---|
HF_TOKEN | 허깅페이스에서 발급받은 API(에이피아이) 키 |
https://my-chatbot-xxxx.onrender.com 형태의 주소가 생성된다.frontend/src/App.jsx 의 API 상수를 Render(렌더) 주소로 변경한다.
const API = "https://my-chatbot-xxxx.onrender.com/chat";
localhost:8000 을 배포된 파이썬 서버 주소로 바꾼다.push(푸시)한다.| 항목 | 입력값 |
|---|---|
| Root Directory(루트 디렉토리) | frontend |
| Build Command(빌드 커맨드) | npm install && npm run build |
| Publish Directory(퍼블리시 디렉토리) | dist |
Tip: Render(렌더) 무료 플랜은 15분간 요청이 없으면 서버가 절전 모드로 전환된다. 처음 요청 시 30초~1분 정도 응답이 느릴 수 있다. 이는 정상 동작이다.

npm error ..., Conflicting peer dependency 가 포함되어 있을 경우 의존성 버전이 안맞아 실패한 것이다..npmrc 파일을 생성하고 아래의 코드를 추가한다. legacy-peer-deps=true
4. 깃허브에 푸쉬한다.
5. 렌더에 재배포 한다.

main.py의 HF_URL 을 변경하면 다른 AI 모델을 사용할 수 있다.
| 모델명 | 특징 |
|---|---|
Qwen/Qwen2.5-72B-Instruct | ✅ 기본 추천, 한국어 응답 우수 |
meta-llama/Llama-3.1-8B-Instruct | 가볍고 빠른 응답 |
mistralai/Mistral-Nemo-Instruct-2407 | 균형 잡힌 성능 |
Warning: 2025년 기준
api-inference.huggingface.co엔드포인트는 폐지되었다. 반드시router.huggingface.co/v1을 사용해야 한다.
# HF_MODEL 변수의 모델명만 교체한다
HF_MODEL = "meta-llama/Llama-3.1-8B-Instruct"
HF_MODEL 변수의 값만 바꾸면 된다.AI에게 역할을 부여하면 특정 캐릭터처럼 대화할 수 있다. ask_ai 함수의 messages 부분을 수정한다.
def ask_ai(q: str) -> str:
token = os.getenv("HF_TOKEN")
headers = {"Authorization": f"Bearer {token}"}
# 캐릭터 역할 설정 (system 메시지로 전달)
system = "You are a helpful Korean cooking teacher. Answer only about Korean food."
payload = {
"model": HF_MODEL,
"messages": [
{"role": "system", "content": system}, # 역할 설정
{"role": "user", "content": q} # 사용자 질문
],
"max_tokens": 300
}
res = requests.post(HF_URL, headers=headers, json=payload)
data = res.json()
return data["choices"][0]["message"]["content"]
system 역할의 메시지를 messages 배열 맨 앞에 추가하면 AI가 해당 캐릭터처럼 행동한다.system 내용을 바꾸면 요리 선생님, 영어 튜터, 게임 캐릭터 등 다양한 챗봇을 만들 수 있다.Note:
system역할 메시지는 영어로 작성할 때 더 정확하게 동작한다. 한국어 지시도 가능하지만 영어를 권장한다.
사용자 입력
↓
리액트 (fetch POST /chat)
↓
파이썬 FastAPI (/chat 엔드포인트)
↓
허깅페이스 API (AI 모델 호출)
↓
AI 응답 반환
↓
리액트 화면에 메시지 출력
Tip: 막히는 부분이 있으면 각 단계의
console.log(리액트) 또는