사내 규정이나 제품 매뉴얼을 담당하고 있으면 같은 질문을 하루에도 몇 번씩 받습니다. “연차는 며칠 전에 올려야 하나요”, “이 장비 초기화 절차가 어디 적혀 있죠”. 한 번 답하는 데 3분이면 끝나지만 하루 열 번이면 30분, 한 달이면 열 시간이 넘습니다. 문서를 아무리 잘 정리해도 사람들은 문서를 뒤지는 대신 아는 사람에게 묻습니다. AI 챗봇 만들기 무료 방법을 찾는 이유가 대개 여기에 있습니다. 이 글에서는 돈을 들이지 않고 업무용 챗봇을 만드는 세 가지 경로를 비교하고, 사내 문서를 붙여서 실제로 답하게 만드는 코드까지 정리합니다.
“무료”에는 세 가지 결이 있다

먼저 구분해야 할 게 있습니다. 무료라고 부르는 방식들이 서로 다른 대가를 요구하기 때문입니다. 어떤 건 사용량 한도가 걸려 있고, 어떤 건 내 PC 성능을 대신 씁니다.
| 방식 | 비용 | 대가 | 사내 문서 반입 | 적합한 상황 |
|---|---|---|---|---|
| 챗봇 서비스의 커스텀 기능 | 무료 등급 존재 | 기능·횟수 제한, 배포 범위 제한 | 업로드 필요 | 혼자 쓰거나 팀 내 소수 |
| API 무료 등급 + 직접 개발 | 무료 등급 존재 | 분당·일일 호출 한도 | 외부 전송됨 | 사내 시스템에 붙일 때 |
| 로컬 모델(Ollama 등) | 완전 무료 | 내 PC의 RAM·시간 | 외부로 안 나감 | 보안 규정이 엄격할 때 |
보안 검토가 걸리는 문서를 다룬다면 세 번째부터 보는 게 맞습니다. 반대로 공개해도 무방한 매뉴얼이라면 첫 번째가 30분이면 끝납니다.
가장 빠른 길 — 코드 없이 30분
개발 없이 시작하려면 이미 쓰고 있는 AI 서비스의 “커스텀 챗봇” 기능을 쓰면 됩니다. ChatGPT의 GPTs, Google Gemini의 Gem, Claude의 프로젝트 기능이 모두 같은 구조입니다. 지시문을 적고, 참고할 파일을 올리고, 이름을 붙이면 끝입니다.
- 사내 문서를 하나의 PDF나 텍스트 파일로 합칩니다. 여러 개로 나뉘어 있으면 답변 품질이 떨어집니다.
- 커스텀 챗봇을 새로 만들고 지시문에 역할·근거 범위·모르는 경우의 행동 세 가지를 명시합니다.
- 문서를 첨부합니다.
- 실제로 자주 받는 질문 10개를 던져 보고, 틀린 답이 나온 항목을 지시문에 예외로 추가합니다.
무료 등급에서 어디까지 되는지는 서비스마다 다르고 정책도 자주 바뀝니다. 만들기는 되는데 링크로 공유가 안 되는 경우가 흔하니, 팀에 배포할 계획이라면 만들기 전에 공유 조건부터 확인하세요. 공유가 막혀 있으면 아래 두 방법으로 넘어가야 합니다.
API로 직접 만들기 — 무료 등급 활용
사내 시스템이나 사내망 페이지에 붙이려면 API를 써야 합니다. Google AI Studio에서 키를 발급받으면 무료 등급으로 시작할 수 있습니다. 다만 분당 요청 수와 하루 요청 수에 한도가 있고, 이 수치는 수시로 바뀌므로 공식 요금 페이지에서 확인하는 게 안전합니다.
# 파이썬 3.9 이상에서
pip install google-genai
# 발급받은 키를 환경변수로 (윈도우 파워셸)
$env:GEMINI_API_KEY = "여기에_발급받은_키"
# 맥 / 리눅스
export GEMINI_API_KEY="여기에_발급받은_키"
키를 코드에 직접 적지 말고 환경변수로 두는 습관을 처음부터 들이세요. 나중에 저장소에 올렸다가 키가 유출되는 사고가 가장 흔한 형태입니다.
import os
from google import genai
from google.genai import types
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
# 챗봇의 성격과 답변 규칙. 여기가 사실상 챗봇의 전부다.
SYSTEM = """너는 우리 회사 총무팀 안내 챗봇이다.
아래 사내 규정에 적힌 내용만 근거로 답한다.
규정에 없는 내용은 지어내지 말고 "규정에 없어 총무팀에 확인이 필요합니다"라고 답한다.
답변은 3문장 이내로 짧게 한다."""
# 사내 문서를 텍스트로 저장해두고 통째로 읽어서 붙인다
with open("사내규정.txt", encoding="utf-8") as f:
docs = f.read()
# 모델 이름은 자주 바뀐다. 공식 문서의 최신 목록에서 확인하고 바꿔 쓸 것.
MODEL = "gemini-2.5-flash"
chat = client.chats.create(
model=MODEL,
config=types.GenerateContentConfig(
system_instruction=SYSTEM + "\n\n[사내 규정]\n" + docs,
temperature=0.2, # 낮출수록 지어내는 답이 줄어든다
),
)
print("질문을 입력하세요. 종료하려면 그냥 엔터.")
while True:
q = input("\n나: ").strip()
if not q:
break
res = chat.send_message(q)
print("봇:", res.text)
핵심은 system_instruction입니다. 여기에 사내 문서 전문을 붙이고 “여기 있는 내용만 근거로 답하라”고 못박는 것만으로 엉뚱한 답이 크게 줄어듭니다. temperature를 0.2 정도로 낮추는 것도 같은 목적입니다. 창의적인 글쓰기가 아니라 규정 안내가 목적이니까요.
보안이 걸린다면 로컬 모델
인사 규정이나 고객 정보가 섞인 문서를 외부 API로 보내는 게 부담이라면, 모델 자체를 PC에 설치하는 방법이 있습니다. Ollama가 가장 간편합니다. 설치 후 명령 한 줄로 모델을 받아서 바로 쓸 수 있고, 네트워크가 끊긴 상태에서도 동작합니다.
# 설치 후 터미널에서 모델 하나 받아오기 (약 5GB, 최초 1회)
ollama pull llama3.1
# 바로 대화해 보기
ollama run llama3.1
# 한국어 답변 품질이 아쉬우면 다른 모델도 받아서 비교
ollama pull qwen2.5
# 받아둔 모델 목록 확인
ollama list
Ollama를 실행해두면 localhost:11434에 API 서버가 함께 뜹니다. 그래서 위의 API 방식과 코드 구조가 거의 같습니다. 나중에 방식을 바꾸기도 쉽습니다.
import requests
with open("사내규정.txt", encoding="utf-8") as f:
docs = f.read()
SYSTEM = "아래 사내 규정에 있는 내용만 근거로 답한다.\n\n" + docs
def ask(question):
res = requests.post(
"http://localhost:11434/api/chat",
json={
"model": "llama3.1",
"messages": [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": question},
],
"stream": False,
},
timeout=120,
)
res.raise_for_status()
return res.json()["message"]["content"]
print(ask("연차는 며칠 전에 신청해야 하나요?"))
대신 조건이 있습니다. 8GB 모델을 쾌적하게 돌리려면 RAM이 16GB 이상은 되어야 하고, GPU가 없으면 답변 한 번에 수십 초가 걸릴 수 있습니다. 또 같은 질문이라도 상용 서비스보다 한국어 답변이 어색한 경우가 있으니, 모델 두세 개를 받아서 실제 질문으로 비교해 보고 고르는 편이 낫습니다.
문서가 길면 관련 부분만 골라 넣는다
문서를 통째로 프롬프트에 넣는 방식은 A4 열 장 정도까지는 잘 동작합니다. 그보다 길어지면 두 가지 문제가 생깁니다. 무료 등급의 토큰 한도에 걸리고, 문서 중간에 있는 내용을 모델이 놓치기 시작합니다.
제대로 된 해법은 문서를 벡터로 변환해 검색하는 RAG 구성이지만, 시작 단계에서는 단어가 겹치는 문단만 골라 넣는 것만으로도 체감 차이가 큽니다.
# 문서가 길면 통째로 넣지 말고 질문과 관련된 부분만 골라 넣는다
def find_relevant(docs, question, window=800, top=3):
# 문단 단위로 자른 뒤, 질문에 나온 단어가 많이 겹치는 문단을 고른다
blocks = [b for b in docs.split("\n\n") if b.strip()]
words = set(question.replace("?", " ").split())
def score(block):
return sum(1 for w in words if w in block)
ranked = sorted(blocks, key=score, reverse=True)
picked = [b for b in ranked[:top] if score(b) > 0]
return "\n\n".join(picked)[: window * top]
context = find_relevant(docs, "연차 신청 기한이 어떻게 되나요?")
print(context)
이 함수가 돌려준 context를 문서 전문 대신 프롬프트에 넣으면 됩니다. 정확도가 부족해지면 그때 벡터 검색을 도입해도 늦지 않습니다. 처음부터 벡터 DB를 붙이려다 설치 단계에서 포기하는 경우가 훨씬 많습니다.
팀에 배포하기 — 화면 붙이는 데 20줄
터미널에서만 돌아가면 팀원들이 쓰지 않습니다. Streamlit을 쓰면 채팅 화면을 20여 줄로 만들 수 있습니다. pip install streamlit으로 설치하고 아래 파일을 만든 뒤 streamlit run app.py로 실행하면 브라우저가 열립니다.
# app.py — 실행: streamlit run app.py
import os
import streamlit as st
from google import genai
from google.genai import types
st.title("총무팀 안내 챗봇")
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
@st.cache_resource # 새로고침해도 대화가 초기화되지 않게
def get_chat():
with open("사내규정.txt", encoding="utf-8") as f:
docs = f.read()
return client.chats.create(
model="gemini-2.5-flash",
config=types.GenerateContentConfig(
system_instruction="아래 규정만 근거로 답하라.\n\n" + docs,
temperature=0.2,
),
)
if "history" not in st.session_state:
st.session_state.history = []
for role, text in st.session_state.history:
st.chat_message(role).write(text)
if q := st.chat_input("궁금한 것을 물어보세요"):
st.chat_message("user").write(q)
answer = get_chat().send_message(q).text
st.chat_message("assistant").write(answer)
st.session_state.history.append(("user", q))
st.session_state.history.append(("assistant", answer))
사내망에서 다른 사람도 접속하게 하려면 streamlit run app.py --server.address 0.0.0.0으로 실행하고 방화벽에서 해당 포트를 열어주면 됩니다. 이때 아무나 접속할 수 있게 되므로, 사내망 안쪽인지 반드시 확인하세요. 슬랙이나 팀즈에 붙이는 방식도 있지만, 우선은 화면 하나로 반응을 본 다음에 결정하는 편이 낫습니다.
주의할 점
- 무료 등급은 입력 데이터가 모델 개선에 쓰일 수 있습니다. 유료 등급에서는 학습에 쓰지 않는다고 명시하는 서비스가 많지만, 무료 등급은 조건이 다른 경우가 있습니다. 개인정보나 미공개 자료를 넣기 전에 해당 서비스의 데이터 이용 정책을 확인하세요. 확인이 어렵다면 로컬 모델이 답입니다.
- “모르면 모른다고 답하라”를 지시문에 반드시 넣으세요. 이 문장이 없으면 규정에 없는 내용도 그럴듯하게 지어냅니다. 사내 안내 챗봇에서 이건 단순 오답이 아니라 잘못된 행정 안내가 됩니다.
- 답변 하단에 “AI가 생성한 답변이며 최종 확인은 담당자에게” 같은 안내를 고정으로 붙이세요. 지시문 마지막 줄에 한 문장 추가하면 됩니다.
- 문서가 갱신되면 챗봇도 갱신해야 합니다. 규정이 바뀌었는데 챗봇이 옛날 내용을 답하는 순간 신뢰를 잃습니다. 문서 파일을 읽어오는 구조로 만들어두면 파일만 교체하면 되니, 이 글의 코드처럼 파일에서 읽는 방식을 권합니다.
- 요금제와 모델 이름은 자주 바뀝니다. 이 글의 코드에 적힌 모델 이름이 몇 달 뒤에는 없어질 수 있습니다. 호출이 갑자기 실패하면 먼저 공식 문서의 모델 목록부터 확인하세요.
마무리
한 번에 전사용 챗봇을 만들려고 하면 문서 정리 단계에서 멈춥니다. 가장 자주 받는 질문 다섯 개와 그 답이 적힌 문서 한 개로 시작하세요. 이 정도면 한 시간 안에 동작하는 것이 나오고, 실제로 써 보면 무엇이 부족한지도 바로 보입니다.
- 최근 한 달간 반복해서 받은 질문 5개를 적어 봅니다.
- 그 답이 들어 있는 문서를 텍스트 파일 하나로 만듭니다.
- 위의 API 코드나 Ollama 코드를 복사해 문서 경로만 바꿔 실행합니다.
- 5개 질문을 던져 보고 틀린 답이 나온 것만 지시문에 규칙으로 추가합니다.
다음 글에서는 API 요청 시 자주 만나는 오류코드 401, 403, 429를 정리합니다. 이번 글처럼 API 키를 다루다 보면 반드시 마주치는 숫자들이라, 각각이 무엇을 뜻하고 어디부터 확인해야 하는지 짚어 보겠습니다.