“나 혼자 쓰는 Python AI Agent”를, 진짜 웹 서비스로 만들어 보기
한 번쯤 이런 생각 해본 적 있을 거예요.
“나 Python으로 AI agent 하나 만들어 놨는데… 나 말고 다른 사람은 어떻게 쓰지?”
로컬에서 python script.py만 돌려도 나 혼자 테스트하는 데는 아무 문제 없죠.
하지만 친구에게 보여준다거나, 팀원에게 데모를 해준다거나, 간단히 URL 하나 던져주고 “여기 들어가서 써봐”라고 하고 싶으면 얘기가 완전히 달라집니다.
이 글에서는 “로컬에서만 돌던 Python AI agent”를, 실제로 누가 들어와서 쓸 수 있는 웹 서비스로 만드는 전체 과정을 처음부터 끝까지 정리합니다.
우리가 사용할 스택은 딱 이 정도예요:
- Python: AI agent 본체
- FastAPI: backend API
- LangChain + LangGraph: tool-calling agent 구조
- OpenAI: LLM 엔진
- HTML + JavaScript: 간단한 chat UI
- Vercel: 무료 deploy
마지막에는 URL 하나 딱 공유하면, 누구든지 브라우저에서 바로 agent랑 대화할 수 있는 상태가 됩니다.

우리가 만들 구조 한 번에 보기
먼저 전체 그림부터 잡아볼게요.
우리가 원하는 건 아주 심플합니다:
- Python AI agent
- 기본적인 대화 가능
- 필요하면 “tool”을 호출해서 작업 수행
- 예제로는 간단히 “note 읽기 / 쓰기” 기능
- backend API (FastAPI)
- GET / : HTML page 반환 (UI)
- POST /agent :
- prompt를 받아서
- agent에 던지고
- 결과를 JSON으로 반환
- frontend (HTML + JavaScript)
- textarea + “Send” 버튼으로 구성된 아주 단순한 chat 화면
- 사용자가 텍스트 입력 → /agent로 fetch → 응답을 화면에 표시
- Vercel deploy
- 전체 앱을 하나의 URL로 공개
- 서버 직접 관리 X
- CLI 한 번으로 redeploy 가능
정리하면 이런 느낌이죠:
Browser ⇄ FastAPI backend API ⇄ AI Agent (LangChain + LangGraph + OpenAI)
이제 실제로 만들어 봅시다.
사용할 주요 도구들 정리
이번 튜토리얼에서 사용할 구성 요소를 먼저 짚고 갈게요.
- FastAPI
가볍고 빠른 Python web framework. 특히 API 만들기에 최적화. - Jinja2
FastAPI에서 HTML template을 렌더링할 때 쓰는 template engine. - LangChain
LLM 기반 app을 만들 때 반복되는 패턴을 추상화해주는 라이브러리. - LangGraph
“tool-calling agent”를 간단하게 구성할 수 있게 도와주는 layer. - OpenAI (langchain-openai)
GPT-4 계열 모델을 사용하는 LLM backend. - python-dotenv
.env 파일에 있는 환경변수를 Python app에 로딩. - Pydantic
FastAPI에서 request / response payload를 타입 안전하게 정의. - Node.js + Vercel CLI
Vercel CLI가 npm 패키지라 Node.js가 한 번 필요합니다.
app은 Python으로 돌아가고, Node.js는 배포 툴 용도라고 보면 돼요.
Step 1. 프로젝트 폴더 만들기
우선 폴더부터 하나 준비합니다.
mkdir deploy-ai-agent
cd deploy-ai-agent
그리고 이 디렉토리를 VS Code, Cursor, PyCharm 등 원하는 editor로 열어주면 됩니다.
Step 2. Node.js & Vercel CLI 설치
2-1. Node.js 설치
Vercel CLI는 npm으로 설치해야 하니까, 먼저 Node.js가 있어야 합니다.
- Node.js 공식 사이트 접속
- LTS 버전 다운로드 후 설치
- 설치 확인:
node -v
npm -v
2-2. Vercel CLI 설치
Node.js가 준비되면:
npm i -g vercel
설치 후 버전 체크:
vercel --version
이제 처음 vercel 명령을 실행하면 브라우저로 로그인하라고 할 거예요.
vercel
- 브라우저에서 Vercel 계정 로그인 or 신규 생성 (무료)
- 로그인 끝나면, 터미널에서 Ctrl + C로 명령 종료해도 됩니다.
이제 deploy 준비 완료.
Step 3. Vercel 템플릿으로 FastAPI 프로젝트 부트스트랩
Vercel에서 제공하는 FastAPI 템플릿을 기반으로 시작할 수 있습니다.
vercel init fastapi
그러면 현재 디렉토리 안에 fastapi/ 같은 하위 폴더가 생기고, 그 안에 예제 코드들이 들어가요.
튜토리얼에서는:
- fastapi 폴더 안의 파일들을 root (deploy-ai-agent) 폴더로 전부 복사
- 빈 fastapi 폴더는 삭제
- 기존에 들어있던 main.py, README.md 등 템플릿 코드는 정리
- main.py 내용은 싹 지우고 새로 작성
- README.md는 필요 없으면 삭제
이렇게 해서 root 폴더에만 코드가 모이는 구조로 맞춰 놓습니다.
Step 4. requirements.txt 설정 및 설치
requirements.txt 파일을 열어서 다음 패키지들을 추가합니다:
fastapi
uvicorn
Jinja2
langchain
langchain-openai
langgraph
python-dotenv
pydantic
그 다음 설치:
pip install -r requirements.txt
# 또는
pip3 install -r requirements.txt
하루짜리 toy project라면 global Python에 깔아도 크게 문제는 없지만,
실전이라면 virtualenv나 uv, poetry 같은 걸 쓰는 걸 추천합니다.
Step 5. AI Agent 코드 작성 (agent.py)
이제 본격적으로 agent 로직을 분리해서 관리해볼게요.
5-1. agent.py 파일 생성
touch agent.py
열고 상단에 필요한 import를 추가합니다.
# agent.py
from dotenv import load_dotenv
load_dotenv() # .env 파일에 있는 환경변수 로딩
from langchain_openai import ChatOpenAI
from langchain.tools import tool
from langgraph.prebuilt import create_tool_calling_agent
이렇게 하면 OPENAI_API_KEY가 .env에서 환경변수로 로딩되고,
ChatOpenAI, tool, create_tool_calling_agent로 agent를 구성할 수 있게 됩니다.
5-2. Tool 정의: read_note, write_note
이제 agent가 실제로 “할 수 있는 일”을 tool 형태로 만들어 줍니다.
여기서는 예제라서 가장 단순한 기능, 메모 읽기/쓰기를 tool로 만들게요.
import os
NOTES_FILE = "notes.txt"
@tool
def read_note() -> str:
"""
Read the contents of the notes file and return them as a string.
If the file does not exist, return a helpful message.
"""
if not os.path.exists(NOTES_FILE):
return "No notes have been saved yet."
with open(NOTES_FILE, "r", encoding="utf-8") as f:
return f.read()
@tool
def write_note(content: str) -> str:
"""
Append the given content as a new line to the notes file.
Returns a confirmation message describing what was saved.
"""
with open(NOTES_FILE, "a", encoding="utf-8") as f:
f.write(content + "\n")
return f"Note saved: {content}"
정리하면:
- read_note()
- notes.txt가 존재하면 내용을 읽어 반환
- 없으면 “아직 저장된 메모 없음” 메시지
- write_note(content)
- 전달받은 문자열을 한 줄 append
- 어떤 내용이 저장됐는지 간단히 설명하는 문자열 반환
이렇게 @tool decorator를 붙여서 정의해 두면,
나중에 agent가 “아 이 상황에서는 write_note를 써야겠다”라고 스스로 결정해서 호출할 수 있습니다.
5-3. LLM, system message, tool-calling agent 설정
tool 목록과 agent의 역할(system message)을 정의합니다.
tools = [read_note, write_note]
SYSTEM_MESSAGE = (
"You are a helpful note-taking assistant. "
"You can read existing notes and write new notes using the available tools. "
"Use the tools whenever they help the user."
)
llm = ChatOpenAI(
model="gpt-4o", # 필요에 따라 다른 모델 사용 가능 (예: gpt-4.1 등)
temperature=0.2, # 낮을수록 출력이 덜 랜덤해짐
)
agent = create_tool_calling_agent(
llm=llm,
tools=tools,
system_message=SYSTEM_MESSAGE,
)
핵심 포인트:
- LLM + tools + system_message 조합으로 agent를 구성
- LangGraph의 create_tool_calling_agent가 내부에서 tool 선택, 호출 등을 알아서 처리
5-4. 외부에서 쓰기 좋은 helper 함수: run_agent
이제 FastAPI에서 agent를 쉽게 호출할 수 있도록
run_agent(prompt: str) -> str 형태의 헬퍼를 하나 만들어둡니다.
def run_agent(user_input: str) -> str:
"""
Run the tool-calling agent with a single user message and
return the final response as plain text.
"""
try:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": user_input,
}
]
}
)
messages = result["messages"]
last_message = messages[-1]
content = last_message.get("content", "")
if isinstance(content, list):
content = " ".join(
part.get("text", "") if isinstance(part, dict) else str(part)
for part in content
)
return content
except Exception as e:
return f"Error running agent: {e}"
이제 나중에 run_agent("Hello")만 호출하면
tool까지 포함된 전체 agent 로직이 돌아가고, 최종 답변 텍스트만 딱 얻을 수 있습니다.
5-5. 간단 테스트
파일 맨 아래에 임시 테스트 코드를 추가해 봅니다.
if __name__ == "__main__":
response = run_agent("Hello, how are you?")
print(response)
터미널에서:
python agent.py
# 또는
python3 agent.py
실행해 보면, 경고 메시지가 조금 보일 수는 있어도
마지막에는 “Hello! ~~” 같은 assistant 응답이 찍힐 거예요.
동작이 확인되면, deploy 전에 이 if __name__ == "__main__": 부분은 지우거나 주석 처리해둡니다.
Step 6. .env에 OpenAI API Key 설정
이제 비밀스러운 부분, API key입니다.
6-1. .env 파일 생성
프로젝트 root에 .env 파일을 하나 만듭니다.
OPENAI_API_KEY=여기에_당신의_시크릿_API_키
6-2. OpenAI API key 발급
OpenAI platform에서 다음 순서로 진행합니다.
- https://platform.openai.com/api-keys 접속
- Create new secret key 클릭
- 결제 수단 등록 필요 (테스트 용도로 쓰면 몇 cent 수준)
- 생성된 key를 복사해서 .env에 붙여넣기
영상 스크립트에서도 “이 키는 나중에 삭제할 거다”라고 언급했듯이,
key는 항상 유출될 수도 있다는 전제로 신중하게 다루는 게 좋습니다.
우리는 load_dotenv()를 이미 agent.py 맨 위에서 호출했기 때문에
langchain-openai는 자동으로 OPENAI_API_KEY를 읽어 사용하게 됩니다.
Step 7. FastAPI backend 구성 (main.py)
이제 agent를 외부에서 쓸 수 있도록 API로 감싸는 작업을 합니다.
7-1. import 정리
main.py를 열고 다음과 같이 작성합니다.
# main.py
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from agent import run_agent
7-2. FastAPI app & templates 초기화
app = FastAPI()
templates = Jinja2Templates(directory="templates")
여기서 templates 디렉토리 안에 index.html을 둘 예정입니다.
7-3. Request / Response 모델 정의
POST /agent에서 사용할 payload 타입을 Pydantic으로 정의합니다.
class AgentRequest(BaseModel):
prompt: str
class AgentResponse(BaseModel):
response: str
이렇게 해두면 FastAPI가 body를 자동으로 파싱하고 validation도 해줍니다.
7-4. 홈 라우트: HTML 렌더링
사용자가 브라우저로 접속했을 때 보여줄 화면입니다.
@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
return templates.TemplateResponse(
"index.html",
{"request": request},
)
FastAPI에서 Jinja2를 쓸 때는 {"request": request}가 꼭 필요합니다.
7-5. /agent 라우트: AI 호출
이제 핵심 API입니다.
@app.post("/agent", response_model=AgentResponse)
async def call_agent(payload: AgentRequest):
user_prompt = payload.prompt
result = run_agent(user_prompt)
return AgentResponse(response=result)
흐름은 단순해요.
- frontend에서 {"prompt": "내용"}을 보내면
- call_agent가 run_agent(prompt) 실행
- 최종 answer를 {"response": "..."} 형태로 반환
7-6. 로컬 개발용 서버 실행 코드
로컬에서 테스트할 때는 uvicorn을 직접 띄워야 합니다.
(나중에 Vercel에 올릴 때는 이 부분을 주석 처리할 거예요.)
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
reload=True,
)
Step 8. Frontend HTML (templates/index.html)
이제 브라우저에서 쓸 수 있는 아주 간단한 UI를 만들어볼게요.
8-1. templates 디렉토리 만들기
mkdir templates
8-2. index.html 작성
templates/index.html 파일을 만들고, 다음과 같이 작성합니다
(내용은 필요에 따라 조금씩 바꿔도 됩니다):
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>Python AI Agent Demo</title>
<style>
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 700px;
margin: 40px auto;
padding: 0 16px;
}
h1 {
margin-bottom: 0.5rem;
}
textarea {
width: 100%;
min-height: 120px;
padding: 8px;
box-sizing: border-box;
}
button {
margin-top: 8px;
padding: 8px 16px;
cursor: pointer;
}
#response {
margin-top: 16px;
white-space: pre-wrap;
border: 1px solid #ddd;
padding: 12px;
border-radius: 4px;
min-height: 80px;
}
.loading {
opacity: 0.7;
font-style: italic;
}
</style>
</head>
<body>
<h1>AI Agent Chat</h1>
<p>간단한 메모를 저장하거나, 그냥 대화해 보세요.</p>
<form id="agent-form">
<textarea id="prompt" placeholder="메시지를 입력하세요..."></textarea>
<br />
<button type="submit">Send</button>
</form>
<div id="response"></div>
<script>
const form = document.getElementById("agent-form");
const promptInput = document.getElementById("prompt");
const responseDiv = document.getElementById("response");
form.addEventListener("submit", async (e) => {
e.preventDefault();
const prompt = promptInput.value.trim();
if (!prompt) return;
responseDiv.textContent = "Thinking...";
responseDiv.classList.add("loading");
try {
const res = await fetch("/agent", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt }),
});
if (!res.ok) {
responseDiv.textContent = "Error: " + res.statusText;
responseDiv.classList.remove("loading");
return;
}
const data = await res.json();
responseDiv.textContent = data.response || "(no response)";
} catch (err) {
responseDiv.textContent = "Error: " + err;
} finally {
responseDiv.classList.remove("loading");
}
});
</script>
</body>
</html>
요약하자면:
- form: textarea + button
- JavaScript:
- form submit 이벤트 가로채기
- fetch("/agent", { method: "POST", body: JSON.stringify({ prompt }) })
- 응답 JSON에서 response를 꺼내 #response에 출력
- “Thinking…” 같은 간단한 loading state 표시
Step 9. 로컬에서 전체 흐름 테스트
이제 구성 요소가 다 모였습니다.
- .env에 OPENAI_API_KEY 설정
- agent.py / main.py / templates/index.html 준비
- requirements.txt 설치 완료
이 상태에서:
python main.py
# 또는
python3 main.py
uvicorn이 떠 있고, log에:
Uvicorn running on http://0.0.0.0:8000
라고 나오면 브라우저에서
- http://localhost:8000
- 또는 http://127.0.0.1:8000
에 접속해 봅니다.
textarea에 이렇게 적어볼까요?
“hello world, can you save a note saying hi?”
Send를 누르면 잠시 후 응답으로
“Note saved: hi”
혹은 이와 비슷한 문구
가 나올 거예요. 그리고 프로젝트 폴더에 notes.txt라는 파일도 생깁니다.
그 안에는 hi가 저장되어 있겠죠.
이제:
- 브라우저에서 직접 agent와 대화하고
- tool(read_note, write_note)까지 실제로 호출되는 흐름이 로컬 기준으로 완성됐습니다.
Step 10. Vercel 배포 준비
이제 “나만 쓰는” 단계는 끝났고,
URL 하나로 누구에게나 보여줄 수 있도록 배포를 해봅시다.
10-1. main.py의 uvicorn 실행 코드 주석 처리
Vercel은 자체적으로 app을 run해주기 때문에,
if __name__ == "__main__" 아래 부분은 production에서는 필요 없습니다.
# if __name__ == "__main__":
# import uvicorn
# uvicorn.run(
# "main:app",
# host="0.0.0.0",
# port=8000,
# reload=True,
# )
이렇게 막아두고 commit / deploy하는 게 안전합니다.
10-2. .env는 절대 같이 올리지 않기 (.vercelignore)
영상에서도 언급됐듯이, .env 파일을 그대로 deploy해버리면
환경에 따라 API key가 노출될 위험이 있습니다.
그래서 Vercel에게 “이 파일은 무시해라”고 알려줄 필요가 있어요.
프로젝트 root에 .vercelignore 파일 생성:
.env
이제 vercel deploy할 때 .env는 업로드 대상에서 제외됩니다.
실제 key는 Vercel 내에서 따로 설정할 예정이에요.
Step 11. Vercel 환경변수에 OPENAI_API_KEY 추가
Vercel CLI로 env를 등록합니다.
vercel env add OPENAI_API_KEY
순서는 대략 이렇습니다.
- key 이름 확인: OPENAI_API_KEY
- value 입력: .env에 넣었던 OpenAI API key를 그대로 붙여넣기
- 어느 environment에 사용할지 선택:
- Production
- Preview
- Development
보통 전부 선택해도 무방합니다.
CLI에서 space로 선택, Enter로 확정.
이렇게 하면 .env 없이도 Vercel에서 app이 OPENAI_API_KEY를 읽을 수 있습니다.
Step 12. 진짜로 deploy 해 보기
이제 준비는 끝났습니다. 터미널에서:
vercel deploy
을 실행하면, CLI가 몇 가지를 물어봅니다.
- 기존 project에 link할 건지, 새로 만들 건지
- project name (예: deploy-ai-agent)
- code가 있는 directory (지금 디렉토리면 Enter)
- setting 수정 여부 (처음에는 No)
그 뒤 Vercel이:
- build
- package
- deploy
를 순서대로 진행하고, 마지막에:
- preview URL
- inspect 링크
를 보여줍니다.
preview URL을 브라우저로 열어보면,
로컬에서 보던 것과 같은 UI가 Vercel domain으로 떠 있을 거예요.
예를 들면:
같은 식으로요.
여기서 “Hello World”를 입력하고 Send를 눌러보면
일반 chat bot처럼 잘 응답하는 걸 확인할 수 있습니다.
Step 13. Vercel에서 file system tool이 안 되는 이유
영상에서 마지막 부분에 나왔던, 중요한 포인트 하나가 있습니다.
로컬에서는 write_note tool이 잘 돌아가는데,
Vercel에 올려서 “note 저장해 줘”라고 하면 오류가 터지는 상황입니다.
메시지는 대략 이런 식이죠:
“File system is read-only”
왜 그럴까요?
- Vercel의 Python runtime은 serverless 환경입니다.
- 각 request는 짧게 실행되는 함수처럼 동작하고,
- local file system은 쓰기 권한이 제한되어 있거나,
- 쓰더라도 요청이 끝난 뒤에는 사라질 수 있습니다.
즉, Vercel 환경에서는:
- notes.txt 같은 local 파일을 영구 저장소로 쓰면 안 됩니다.
- 이건 “어디까지나 예제”일 뿐이고, 실제 서비스에 쓰면 문제 소지가 큽니다.
그래서 나중에 production으로 갈 때는:
- tool을 DB나 외부 API, Cloud Storage로 연결하는 식으로 바꾸는 게 좋습니다.
- 예: Postgres, MongoDB, Redis, S3 등
- file system을 건드리는 tool은 serverless 환경에서는 가급적 피하는 게 안전합니다.
그래도 “단순 chat agent”로 쓰는 데는 문제 없습니다.write_note, read_note를 빼버리고, 일반 Q&A tool들만 연결해도 충분히 쓸 수 있어요.
여기서부터는 “다음 단계” 이야기
지금까지 한 걸 정리하면:
- Python으로 만든 AI agent를
- FastAPI backend API로 감싸고
- HTML + JavaScript로 간단한 UI를 붙이고
- Vercel로 deploy해서
- URL 하나로 누구에게나 공유 가능한 상태를 만들었습니다.
물론 이게 “production-grade 완성품”은 아닙니다.
- 인증(로그인/권한 관리)도 없고
- rate limit도 없고
- logging/metrics도 최소 수준이고
- local file system을 쓰는 tool은 Vercel에 맞지 않고
하지만, 이 튜토리얼의 목표는 **“최대한 빨리, 실제로 돌아가는 데모를 만드는 것”**이기 때문에,
그 기준에서는 충분히 만족스러운 상태예요.
이제 여기서부터는 당신이 원하는 방향으로 확장하면 됩니다.
예를 들어:
- write_note 대신 외부 API를 호출하는 tool 만들기
- database를 붙여서 user별 note를 저장하는 진짜 note service로 확장
- SSE나 WebSocket으로 streaming response를 구현해서 ChatGPT 스타일 UX 만들기
- 여러 agent를 orchestration해서 더 복잡한 workflow 구성
등등, 거의 무한히 확장 가능합니다.
자주 나올 법한 질문들 (FAQ)
마지막으로, 이 구조를 쓰다 보면 대부분 비슷한 질문을 하고 가더라고요.
몇 가지를 미리 정리해 봤습니다.
Q1. app은 Python인데, 왜 Node.js를 깔아야 하나요?
app 자체는 100% Python으로 돌아갑니다.
Node.js는 오직 하나, Vercel CLI 설치용이에요.
- vercel 명령이 npm 패키지라, Node.js가 필요
- deploy는 vercel deploy로 하고
- 실제 runtime에서는 Python이 사용됩니다.
Q2. FastAPI 대신 Flask를 써도 되나요?
가능은 합니다. 다만:
- Vercel 공식 template가 FastAPI 기준으로 되어 있고
- FastAPI가 ASGI, type hint, Pydantic과 잘 어울려서
최근 기준으로는 FastAPI가 더 편한 경우가 많습니다.
이미 Flask stack이 익숙하다면 Flask로 해도 되지만,
새로 시작하는 입장이라면 FastAPI 쪽이 장점이 많아요.
Q3. HTML template는 꼭 templates/에 넣어야 하나요?
FastAPI + Jinja2 컨벤션이 그렇습니다.
templates = Jinja2Templates(directory="templates")
라고 선언해두면:
- templates/index.html처럼
- 해당 디렉토리 기준으로 template 파일을 찾습니다.
경로만 맞으면 디렉토리 이름을 바꿀 수도 있지만,
templates/가 기본 패턴이라 같이 따라가는 편이 편합니다.
Q4. 로컬에서는 note 저장이 잘 되는데, Vercel에서는 왜 안 되죠?
앞에서 말했듯이:
- Vercel의 serverless 환경에서는 local file system이 read-only에 가깝고,
- request가 끝나면 환경이 날아가 버릴 수 있어서,
- notes.txt 같은 방식은 영속적인 저장소로 쓰기에 적합하지 않습니다.
실서비스에서는:
- database
- external API
- cloud storage
같은 곳으로 tool을 연결하는 쪽이 맞습니다.
Q5. OpenAI API key를 안전하게 관리하는 법은?
핵심은 세 가지입니다.
- .env를 절대 git repo에 commit하지 않는다.
- .vercelignore에 .env를 추가해서 배포에도 포함시키지 않는다.
- 실제 production secret은 vercel env add로 Vercel 내부에 저장한다.
이렇게 하면 로컬에서는 .env,
Vercel에서는 environment variable로 key를 읽게 됩니다.
Q6. OpenAI 대신 다른 LLM provider를 쓸 수 있나요?
네, 얼마든지요.
- ChatOpenAI 대신 다른 wrapper (예: Anthropic, Groq, local model 등)를 쓰고,
- 그 wrapper가 LangChain과 연동만 되어 있다면,
- 전체 agent 구조는 그대로 재사용할 수 있습니다.
agent는 일종의 “brain slot”을 가진 구조라,
그 자리에 어떤 모델을 꽂을지 갈아끼우는 느낌으로 생각하면 편합니다.
Q7. agent의 성향이나 역할을 바꾸고 싶으면?
SYSTEM_MESSAGE 내용을 바꾸면 됩니다.
SYSTEM_MESSAGE = (
"You are a planning assistant that helps users break down big goals into tasks..."
)
이렇게 바꿔주면, agent는 “메모 도우미”에서
“플래닝 코치” 같은 롤로 자연스럽게 전환됩니다.
더 정교하게 조정하고 싶으면:
- tool 목록을 다르게 구성
- temperature 및 model 변경
- 추가적인 guardrail logic을 바깥에서 감싸기
같은 방법이 있습니다.
Q8. 이 구조를 바로 production에 써도 되나요?
솔직히 말하면, 그대로 쓰기에는 부족합니다.
Production 관점에서 필요한 것들:
- auth / 권한 관리
- rate limiting
- logging / monitoring / alerting
- error handling, retry 정책
- database 설계, migration 관리
- 비용 모니터링
이번 튜토리얼은 **“빠르게 작동하는 prototype / 데모”**를 목표로 했기 때문에,
그 위에 production-grade 요소들을 하나씩 쌓아 올리는 건 별도 작업이라고 보는 게 좋습니다.
Q9. ChatGPT처럼 streaming response도 구현할 수 있나요?
네, 가능합니다.
- OpenAI가 streaming API를 제공하고 있고
- FastAPI는 StreamingResponse로 chunk 단위 응답을 보낼 수 있으며
- frontend에서는 EventSource나 ReadableStream 같은 방식으로 처리하면 됩니다.
다만 이 글에서는 “구조를 이해하는 데 초점을 맞춰서”
일단 완성 답변만 한 번에 보내는 방식으로 구현했습니다.
Q10. 비용은 얼마나 드나요?
대략적인 감각은 이렇습니다.
- Vercel free tier:
- 소규모 데모, 개인 프로젝트 수준에서는 대부분 무료 안에서 해결
- OpenAI:
- 모델/입·출력 토큰 수/사용량에 따라 다르지만,
- 가볍게 테스트하고 소규모로 쓰는 정도면 한 달에 몇 달러 선에서 충분한 경우가 많습니다.
실제 과금 구조는 OpenAI dashboard에서 꼭 확인해 두는 게 좋습니다.
Q11. GitHub repo가 필수인가요?
필수는 아닙니다.
Vercel CLI로 로컬 폴더에서 직접 deploy가 가능하거든요.
(이번 글에서 한 방식이 바로 그거죠.)
하지만 코드 이력을 관리하고 협업하려면,
결국 GitHub 같은 repo를 쓰는 쪽이 훨씬 좋습니다.
Q12. tool을 더 추가하려면 어떻게 하나요?
@tool decorator를 그대로 따라 쓰면 됩니다.
@tool
def get_weather(city: str) -> str:
"""
Get the current weather in the specified city using an external API.
"""
# 실제 weather API 호출 로직
return f"It's sunny in {city}."
그다음:
tools = [read_note, write_note, get_weather]
처럼 리스트에 추가하면, agent는 이 tool을 자동으로 고려하게 됩니다.
여기까지 따라오셨다면, 이제는
“Python으로 만든 AI agent를 실제 웹 서비스로 내보내는 방법”
을 감으로 설명할 수 있는 단계까지 오신 거예요.
이제 당신 취향에 맞는 tool / LLM / UI를 얹어서
자신만의 AI 서비스로 확장해 보세요.
로컬에서만 돌던 작은 script가, 어느새 URL 하나짜리 “서비스”가 되는 순간이 꽤 짜릿하니까요
'SW > Python' 카테고리의 다른 글
| FastAPI + React + Clerk로 B2B SaaS 애플리케이션 구축하기 (2025 SEO 최적화 가이드) (0) | 2026.01.31 |
|---|---|
| Python Requests로 API 호출하는 방법 한 번에 정리하기 (GET·POST·인증까지) (0) | 2026.01.27 |
| 파이썬으로 머신러닝 엔지니어 되는 법: 0부터 시작하는 전체 로드맵 (2025 가이드) (0) | 2025.12.26 |
| 2025년 기준 Python 개발 환경 세팅 가이드 – Cursor, uv, Docker까지 한 번에 정리 (0) | 2025.12.23 |
| Python Anti-Pattern 총정리: list concatenation 성능 함정부터 mutable default argument까지 한 번에 (0) | 2025.12.19 |