Type something to search...

05 파이썬 챗봇 만들기

구현화면 랜더호스팅

전체 구조 이해하기

이 교안은 아래의 기술을 사용하여 AI 챗봇을 만드는 방법을 단계별로 설명한다.

역할기술설명
프론트엔드(front-end)React(리액트) + Vanilla CSS사용자 화면
백엔드(back-end)Python(파이썬) + FastAPI(패스트에이피아이)서버 로직
AI 모델HuggingFace(허깅페이스)무료 AI API
배포Render(렌더)무료 호스팅

정보

HuggingFace(허깅페이스) 란? AI 모델을 누구나 무료로 사용할 수 있도록 제공하는 플랫폼이다. 회원가입만 하면 API(에이피아이) 키를 무료로 받을 수 있다.


1단계. 개발 환경 준비

1.1. 프로젝트 폴더 만들기


1.2. HuggingFace(허깅페이스) API(에이피아이) 키 발급

요약

API(에이피아이) 키란? 내 신분증처럼, 허깅페이스 서버에 “나는 회원이에요”라고 증명하는 비밀 문자열이다.

  1. https://huggingface.co 에 접속하여 회원가입을 한다.
  2. 우측 상단 프로필 → Settings(설팅스)Access Tokens(액세스 토큰스) 를 클릭한다.
  3. New token(뉴 토큰) 버튼을 클릭하고 이름을 입력한 뒤 Read 권한으로 생성한다.
  4. 생성된 키(예: hf_xxxxxxxxxxxxxxxx)를 복사하여 안전한 곳에 저장한다.

주의

API(에이피아이) 키는 절대로 GitHub(깃허브)에 올리면 안 된다. 타인이 내 키를 무단으로 사용할 수 있다.


2단계. 파이썬 백엔드(back-end) 만들기

2.1. 가상환경 설정


2.2. 라이브러리(library) 설치

Terminal window
1
pip install fastapi uvicorn requests python-dotenv
라이브러리발음역할
fastapi패스트에이피아이파이썬 웹 서버 프레임워크
uvicorn유비콘서버 실행기
requests리퀘스츠외부 API 호출 도구
python-dotenv파이썬 닷엔브환경변수 관리

2.3. 환경변수(environment variable) 파일 만들기

backend/ 폴더 안에 .env 파일을 만들고 아래 내용을 입력한다.

1
HF_TOKEN=hf_여기에_내_키를_붙여넣기

참고

.env (닷엔브) 파일이란? 비밀 정보를 코드 밖에 보관하는 파일이다. 코드에 직접 키를 쓰지 않아도 되므로 안전하다.


2.4. 메인 서버 파일 작성

backend/main.py 파일을 만들고 아래 코드를 작성한다.

1
from fastapi import FastAPI # 01
2
from fastapi.middleware.cors import CORSMiddleware # 02
3
from pydantic import BaseModel # 03
4
import requests, os # 04
5
from dotenv import load_dotenv # 05
6
7
load_dotenv() # 06
8
app = FastAPI() # 07
9
10
app.add_middleware( # 08
11
CORSMiddleware, # 09
12
allow_origins=["*"], # 10
13
allow_methods=["*"], # 11
14
allow_headers=["*"], # 12
15
) # 13
16
17
class Msg(BaseModel): # 14
18
text: str # 15
19
20
HF_URL = "https://router.huggingface.co/v1/chat/completions" # 16
21
HF_MODEL = "Qwen/Qwen2.5-72B-Instruct" # 17
22
23
def ask_ai(q: str) -> str: # 18
24
token = os.getenv("HF_TOKEN") # 19
25
headers = {"Authorization": f"Bearer {token}"} # 20
26
payload = { # 21
27
"model": HF_MODEL, # 22
28
"messages": [{"role": "user", "content": q}], # 23
29
"max_tokens": 300 # 24
30
} # 25
31
res = requests.post(HF_URL, headers=headers, json=payload) # 26
32
data = res.json() # 27
33
return data["choices"][0]["message"]["content"] # 28
34
35
@app.post("/chat") # 29
36
def chat(msg: Msg): # 30
37
reply = ask_ai(msg.text) # 31
38
return {"reply": reply} # 32
설명
01FastAPI(패스트에이피아이) 라이브러리에서 FastAPI 클래스를 불러온다.
02CORS(코어스) 미들웨어를 불러온다. 리액트와 파이썬이 서로 통신할 수 있게 해준다.
03데이터 형태를 검사해 주는 BaseModel(베이스모델)을 불러온다.
04requests(리퀘스츠)는 외부 서버에 요청을 보내는 도구, os(오에스)는 환경변수를 읽는 도구이다.
05.env 파일을 읽어오는 load_dotenv(로드 닷엔브)를 불러온다.
06.env 파일을 실제로 불러온다.
07FastAPI 앱 객체를 만든다. 이 app이 우리 서버의 중심이다.
08~13CORS(코어스) 설정이다. 리액트(포트 5173)에서 파이썬(포트 8000)으로 요청을 허용한다. "*"는 모든 주소를 허용한다는 뜻이다.
14~15요청으로 받을 데이터 형태를 정의한다. text라는 문자열 필드 하나를 갖는다.
16허깅페이스의 새 Router(라우터) API 주소이다. 2025년 기준 공식 엔드포인트이다.
17사용할 AI 모델 이름이다. Qwen2.5-72B(큰 용량, 고성능)를 기본으로 사용한다.
18AI에게 질문을 보내고 답변을 받는 함수를 정의한다.
19.env 파일에서 HF_TOKEN 값을 가져온다.
20허깅페이스 서버에 내 키를 전달하는 헤더(header)를 만든다.
21~25AI에게 보낼 데이터(payload, 페이로드)를 만든다. OpenAI(오픈에이아이)와 동일한 메시지 형식을 사용한다.
26허깅페이스 서버에 POST(포스트) 요청을 보낸다.
27서버의 응답을 JSON(제이슨) 형식으로 변환한다.
28choices[0].message.content 경로에서 AI의 답변 텍스트를 꺼내 반환한다.
29~32/chat 주소로 POST 요청이 오면 ask_ai를 실행하고 결과를 반환한다.

2.5. 서버 실행 테스트

Terminal window
1
uvicorn main:app --reload
  • uvicorn (유비콘): 파이썬 서버 실행 도구이다.
  • main:app : main.py 파일의 app 객체를 실행한다는 뜻이다.
  • --reload : 코드 수정 시 자동으로 서버를 재시작한다.

브라우저에서 http://localhost:8000/docs 에 접속하면 자동 생성된 API(에이피아이) 문서를 확인할 수 있다.

요약

/docs (닥스) 페이지에서 /chat 엔드포인트를 직접 테스트해볼 수 있다. Try it out(트라이 잇 아웃) 버튼을 클릭하여 {"text": "안녕?"} 을 입력해 보자.


2.6. requirements.txt 작성

배포 시 필요한 파일이다. backend/requirements.txt 를 만들고 아래 내용을 입력한다.

1
fastapi
2
uvicorn
3
requests
4
python-dotenv

3단계. 리액트 프론트엔드(front-end) 만들기

3.1. 리액트 프로젝트 생성

Terminal window
1
cd ../frontend
2
npm create vite@latest . -- --template react
3
npm install
  • cd ../frontend : 백엔드 폴더에서 나와 프론트엔드 폴더로 이동한다.
  • npm create vite@latest . : 현재 폴더에 Vite(비트) 프로젝트를 생성한다.
  • -- --template react : 리액트 템플릿(template)으로 생성한다.
  • npm install : 필요한 패키지(package)들을 설치한다.

3.2. 채팅 화면 만들기

frontend/src/App.jsx 파일을 아래 코드로 교체한다.

1
import { useState } from "react"; // 01
2
import "./App.css"; // 02
3
4
const API = "http://localhost:8000/chat"; // 03
5
6
export default function App() { // 04
7
const [msgs, setMsgs] = useState([]); // 05
8
const [input, setInput] = useState(""); // 06
9
const [loading, setLoading] = useState(false); // 07
10
11
const send = async () => { // 08
12
if (!input.trim()) return; // 09
13
const userMsg = { role: "user", text: input }; // 10
14
setMsgs(prev => [...prev, userMsg]); // 11
15
setInput(""); // 12
16
setLoading(true); // 13
17
18
const res = await fetch(API, { // 14
19
method: "POST", // 15
20
headers: { "Content-Type": "application/json" }, // 16
21
body: JSON.stringify({ text: input }) // 17
22
}); // 18
23
const data = await res.json(); // 19
24
const botMsg = { role: "bot", text: data.reply }; // 20
25
setMsgs(prev => [...prev, botMsg]); // 21
26
setLoading(false); // 22
27
}; // 23
28
29
const onKey = (e) => { // 24
30
if (e.key === "Enter") send(); // 25
31
}; // 26
32
33
return ( // 27
34
<div className="wrap"> // 28
35
<h1>🤖 AI 챗봇</h1> // 29
36
<div className="box"> // 30
37
{msgs.map((m, i) => ( // 31
38
<div key={i} className={m.role}> // 32
39
<span>{m.role === "user" ? "🧑" : "🤖"}</span> // 33
40
<p>{m.text}</p> // 34
41
</div> // 35
42
))} // 36
43
{loading && <p className="loading">생각 중...</p>} // 37
44
</div> // 38
45
<div className="input-row"> // 39
46
<input // 40
47
value={input} // 41
48
onChange={e => setInput(e.target.value)} // 42
49
onKeyDown={onKey} // 43
50
placeholder="메시지를 입력하세요" // 44
51
/> // 45
52
<button onClick={send}>전송</button> // 46
53
</div> // 47
54
</div> // 48
55
); // 49
56
} // 50
설명
01리액트의 useState(유즈스테이트) 훅을 불러온다. 화면의 상태(데이터)를 관리한다.
02CSS(씨에스에스) 스타일 파일을 불러온다.
03파이썬 서버의 주소를 상수로 저장한다. 나중에 배포 주소로 바꿔야 한다.
04App 컴포넌트(component)를 기본(default) 내보내기로 정의한다.
05msgs(메시지 목록) 상태를 빈 배열로 초기화한다.
06input(입력창) 상태를 빈 문자열로 초기화한다.
07loading(로딩) 상태를 false로 초기화한다. AI가 답변 중일 때 true가 된다.
08send(전송) 함수를 비동기(async, 에이싱크)로 정의한다.
09입력값이 비어있으면 함수를 종료한다.
10사용자가 보낸 메시지 객체를 만든다. role(롤)은 “user”이다.
11기존 메시지 목록에 사용자 메시지를 추가한다. ...prev는 기존 목록을 펼치는 문법이다.
12메시지 전송 후 입력창을 비운다.
13로딩 상태를 true로 바꿔 “생각 중…” 문구를 표시한다.
14~18파이썬 서버에 POST(포스트) 요청을 보낸다. body에 사용자 메시지를 담는다.
19서버 응답을 JSON(제이슨) 형식으로 변환한다.
20AI 봇의 메시지 객체를 만든다. role은 “bot”이다.
21메시지 목록에 봇 메시지를 추가한다.
22로딩 상태를 false로 바꿔 “생각 중…” 문구를 숨긴다.
24~26키보드 Enter(엔터) 키를 누르면 send 함수를 실행한다.
27~49화면에 그릴 JSX(제이에스엑스) 코드이다.
30~38메시지 목록을 표시하는 영역이다. msgs.map으로 각 메시지를 하나씩 그린다.
32className(클래스네임)에 role 값(“user” 또는 “bot”)을 넣어 스타일을 구분한다.
37loadingtrue일 때만 “생각 중…” 문구를 표시한다.
39~47입력창과 전송 버튼 영역이다.

3.3. CSS(씨에스에스) 스타일 작성

frontend/src/App.css 파일을 아래 코드로 교체한다.

1
.wrap { max-width: 600px; margin: 40px auto; font-family: sans-serif; }
2
.box { border: 1px solid #ccc; height: 400px; overflow-y: auto; padding: 16px; }
3
.user { text-align: right; margin: 8px 0; }
4
.bot { text-align: left; margin: 8px 0; }
5
.user p, .bot p { display: inline-block; padding: 8px 12px; border-radius: 8px; }
6
.user p { background: #d1e7ff; }
7
.bot p { background: #f0f0f0; }
8
.loading { color: #888; font-style: italic; }
9
.input-row { display: flex; gap: 8px; margin-top: 8px; }
10
.input-row input { flex: 1; padding: 8px; }
11
.input-row button { padding: 8px 16px; cursor: pointer; }
  • 최소한의 스타일만 적용하여 채팅 레이아웃을 구성한다.
  • .user.bot으로 사용자와 봇 메시지를 좌우로 구분한다.

3.4. 프론트엔드 실행 테스트

Terminal window
1
npm run dev

브라우저에서 http://localhost:5173 에 접속하여 챗봇이 동작하는지 확인한다.

요약

파이썬 서버(uvicorn)와 리액트 개발 서버(npm run dev)를 동시에 실행해야 한다. 터미널 창을 두 개 열어서 각각 실행한다.


4단계. Render(렌더)에 배포하기

4.1. GitHub(깃허브)에 코드 올리기

참고

GitHub(깃허브)란? 코드를 온라인에 저장하고 공유하는 서비스이다. Render(렌더)는 깃허브 저장소를 연결하여 자동으로 배포한다.

  1. https://github.com 에서 새 저장소(repository, 리포지토리)를 만든다.
  2. 프로젝트 루트(my-chatbot/)에 .gitignore 파일을 만들고 아래 내용을 입력한다.
1
backend/.env
2
backend/.venv/
3
frontend/node_modules/
  1. 터미널에서 아래 명령어를 실행하여 코드를 깃허브에 올린다.
Terminal window
1
git init
2
git add .
3
git commit -m "first commit"
4
git remote add origin https://github.com/내아이디/my-chatbot.git
5
git push -u origin main

4.2. 파이썬 백엔드 배포

  1. https://render.com 에 접속하여 GitHub(깃허브) 계정으로 로그인한다.
  2. New(뉴)Web Service(웹 서비스) 를 클릭한다.
  3. 깃허브 저장소를 연결하고 아래와 같이 설정한다.
항목입력값
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
  1. Environment(환경변수) 탭에서 아래 값을 입력한다.
Key(키)Value(값)
HF_TOKEN허깅페이스에서 발급받은 API(에이피아이) 키
  1. Create Web Service(크리에이트 웹 서비스) 버튼을 클릭하면 배포가 시작된다.
  2. 배포 완료 후 https://my-chatbot-xxxx.onrender.com 형태의 주소가 생성된다.

4.3. 리액트 프론트엔드 배포 전 수정

frontend/src/App.jsxAPI 상수를 Render(렌더) 주소로 변경한다.

1
const API = "https://my-chatbot-xxxx.onrender.com/chat";
  • localhost:8000 을 배포된 파이썬 서버 주소로 바꾼다.
  • 이 작업 후 깃허브에 다시 push(푸시)한다.

4.4. 리액트 프론트엔드 배포

  1. Render(렌더)에서 New(뉴)Static Site(스태틱 사이트) 를 클릭한다.
  2. 같은 저장소를 연결하고 아래와 같이 설정한다.
항목입력값
Root Directory(루트 디렉토리)frontend
Build Command(빌드 커맨드)npm install && npm run build
Publish Directory(퍼블리시 디렉토리)dist
  1. Create Static Site(크리에이트 스태틱 사이트) 버튼을 클릭한다.
  2. 배포 완료 후 생성된 주소로 접속하면 챗봇을 사용할 수 있다.

요약

Render(렌더) 무료 플랜은 15분간 요청이 없으면 서버가 절전 모드로 전환된다. 처음 요청 시 30초~1분 정도 응답이 느릴 수 있다. 이는 정상 동작이다.


4.5. 배포 오류 해결

4.5.1. Conflicting peer dependency

  1. 배포중 아래와 같이 오류 발생시 alt
  2. 에러 로그에 npm error ..., Conflicting peer dependency 가 포함되어 있을 경우 의존성 버전이 안맞아 실패한 것이다.
  3. 배포 프로젝트의 루트 폴더에 .npmrc 파일을 생성하고 아래의 코드를 추가한다.
legacy-peer-deps=true

alt 4. 깃허브에 푸쉬한다. 5. 렌더에 재배포 한다. alt

5단계. 응용하기

5.1. 다른 AI 모델로 바꾸기

main.pyHF_URL 을 변경하면 다른 AI 모델을 사용할 수 있다.


5.2. 캐릭터 챗봇으로 만들기

AI에게 역할을 부여하면 특정 캐릭터처럼 대화할 수 있다. ask_ai 함수의 messages 부분을 수정한다.

1
def ask_ai(q: str) -> str:
2
token = os.getenv("HF_TOKEN")
3
headers = {"Authorization": f"Bearer {token}"}
4
5
# 캐릭터 역할 설정 (system 메시지로 전달)
6
system = "You are a helpful Korean cooking teacher. Answer only about Korean food."
7
8
payload = {
9
"model": HF_MODEL,
10
"messages": [
11
{"role": "system", "content": system}, # 역할 설정
12
{"role": "user", "content": q} # 사용자 질문
13
],
14
"max_tokens": 300
15
}
16
res = requests.post(HF_URL, headers=headers, json=payload)
17
data = res.json()
18
return data["choices"][0]["message"]["content"]
  • system 역할의 메시지를 messages 배열 맨 앞에 추가하면 AI가 해당 캐릭터처럼 행동한다.
  • system 내용을 바꾸면 요리 선생님, 영어 튜터, 게임 캐릭터 등 다양한 챗봇을 만들 수 있다.

참고

system 역할 메시지는 영어로 작성할 때 더 정확하게 동작한다. 한국어 지시도 가능하지만 영어를 권장한다.


전체 흐름 요약

1
사용자 입력
2
3
리액트 (fetch POST /chat)
4
5
파이썬 FastAPI (/chat 엔드포인트)
6
7
허깅페이스 API (AI 모델 호출)
8
9
AI 응답 반환
10
11
리액트 화면에 메시지 출력

요약

막히는 부분이 있으면 각 단계의 console.log(리액트) 또는 print(파이썬)로 데이터 흐름을 확인하는 것이 디버깅(debugging, 디버깅)의 기본이다.