
안녕하세요! 오늘은 Ollama 기반 RAG 챗봇을 Flask로 구축하는 방법을 알아보겠습니다.
이 튜토리얼에서는 Ubuntu 24.04 환경에서 Ollama, Flask, 그리고 RAG 기술을 결합해 나만의 AI 챗봇 웹 서비스를 만드는 전체 과정을 다룹니다.
특히 자체 지식 파일을 연동해 특정 분야에 특화된 답변을 생성하는 똑똑한 챗봇을 만드는 것이 핵심 목표입니다.
서버 환경 설정부터 설치 방법, 웹 서비스에 필요한 패키지 설치는 물론이고 예제 소스 코드까지의 전 과정을 상세하게 다루었습니다.
CloudV 또는 IwinV 에서 서버를 생성하셨으면, Ubuntu 24.04 기본 설치 상태에서 아래 과정을 그대로 따라만 하셔도 나만의 챗봇이 탄생합니다.
서버 종류가 많아서 어떤 사양을 선택해야할지 모르실 경우, 금전적 여유가 되신다면 GPU서버를 사용해 보세요. 당연하지만, 서버 성능이 받쳐주면 결과도 빠르게 얻을 수 있습니다.
아래는 스마일서브의 대표적인 GPU 서버 옵션 세 가지입니다.
– [CloudV GPU 서버] — 안정적인 장기 운영용 서버
– [IwinV GPU 서버] — 즉시 구축 가능한 클라우드 환경
– [CloudV GPU 베어메탈 서버] — 합리적인 요금으로 빠른 테스트
튜토리얼을 따라 챗봇이 만들어지면, 소스코드를 살짝 보완하여 여러분이 가지고 계신 홈페이지에 어울리게 배치해 보시기 바랍니다.
1. Ollama 설치 및 대규모 언어 모델(LLM) 준비
우선 LLM(Large Language Model)이라 함은 거대 언어 모델이고, 챗봇의 두뇌 역할을 담당합니다. Ollama는 로컬에서 다양한 LLM을 쉽게 사용할 수 있게 해주는 프레임워크 입니다. 도구라고 생각하시면 쉬워요.
최근 1년 사이 우리나라에 ChatGPT 붐이 일어나고 Claude 나 Gemini 라는 유사한 서비스를 글로벌 IT기업에서 발표를 하고 있는 한편, 한쪽에서는 여러 단체, 기업에서 많은 사람들이 AI시스템을 스스로 구축하고 사용할 수 있도록 LLM을 생성하고 배포하기도 합니다.
그래서 우리는 이 LLM을 가지고 내가 가진 데이터로 추가 학습을 시켜 챗봇을 만들 수 있는 것이죠.
우리는 한국 사람이니 한국어를 이해하고 답변하는데 능한 모델로 다운로드 해야 합니다. 저는 Gemma3:27B 나 Qwen3:14B 모델을 추천하지만, 여기에서는 Gemma3:27B 기준으로 설명 드리겠습니다. 모델 다운로드하고 사용하기 위해 코드에서 지정하는 부분만 다르므로 가지고 계신 서버 성능에 따라 모델을 선택하시기 바랍니다.
( Ollama 로고 | 사이트 바로가기 : https://ollama.com)

( Gemma3 로고 | 사이트 바로가기 : https://ai.google.dev/gemma/docs/core?hl=ko)
* 참고
– 앞으로 진행하는 모든 명령에 대해서는 root 사용자로 작업합니다. 일반 사용자에서 작업을 원하실 경우 모든 명령 앞에 sudo 를 붙여주세요.
– 본문에서 일반 따옴표가 둥근 따옴표로 바뀌거나, 대시 두 개가 하나로 변환 출력되는 문제가 있습니다.
이 부분을 참고하여 명령어를 실행 환경에서 직접 타이핑하여 입력하시기 바랍니다.
1) Ollama 설치 및 실행
우선 시스템의 패키지를 최신 상태로 업데이트하고, Ollama 설치 및 시스템 서비스로 등록, 실행합니다.
# apt update
# apt -y upgrade
# curl https://ollama.ai/install.sh | sh
# systemctl enable –now ollama
2) 모델 다운로드
위에서 말씀드린바와 같이 한국어 성능이 우수한 Gemma3:27B 모델을 사용해 보겠습니다. 여러분의 서버 사양에 따라 더 가벼운 모델 1B, 4B, 12B 등을 선택할 수도 있습니다.
# ollama pull gemma3:27b
명령 한줄로 쉽게 다운로드가 완료 되었습니다.
지금 다운로드 받은 이 모델이 Ollama API를 통해 챗봇의 핵심 역할을 수행하게 됩니다.
ollama pull 명령으로 다운로드 되지않는 모델도 HuggingFace에서 다운로드 받고, 양자화 또는 병합 작업을 거쳐 Ollama로 가동할 수 있습니다. 이것은 챗봇 만드는 것과 다른 맥락이므로 여기에서는 다루지 않겠습니다.
* 참고 : 메모리 부족
현재 서버에서 다운로드 받은 모델을 실행할 수 있는지 아래와 같이 확인해 봅니다.
# ollama run gemma3:27b 안녕?
Error: 500 Internal Server Error: memory layout cannot be allocated
서버의 자원이 충분하여 정상적인 답변을 하면 다행이지만, 위와 같은 메시지가 출력된다면 서버 메모리 부족으로 보시면 됩니다.
해결책으로는 서버의 메모리 크기를 늘리거나, 아래와 같이 낮은 품질의 초 저용량 모델을 다운로드 받아 사용하면 됩니다. (이경우, 하단 app.py 소스코드에서 모델명 변경 필요)
# ollama pull gemma3:1b
2. Python 기반 챗봇 웹 서비스 구축
본격적으로 Python과 Flask를 이용해 웹 서버와 챗봇 인터페이스를 만듭니다. 안정적인 개발 환경을 위해 가상환경을 설정하는 것부터 시작합니다.
1) 가상환경 설정 및 활성화
프로젝트에 필요한 패키지들이 시스템 전체 환경에 영향을 주지 않도록 가상환경을 만들어 관리하는 것이 좋습니다.
다음과 같이 가상환경을 만들어줄 pip3-venv 패키지를 설치합니다. 이어서 myenv라는 이름의 가상환경을 만들고 적용합니다.
# apt -y install python3-pip python3-venv python3-full
# python3 -m venv myenv
# source myenv/bin/activate
source myenv/bin/activate 명령을 실행하면 명령어 앞에 (myenv)가 붙어 가상환경이 활성화되었음을 확인할 수 있습니다.
2) 프로젝트 구조 설계
깔끔한 관리를 위해 프로젝트 디렉토리 구조를 미리 잡는 것이 중요합니다. 아래와 같이 구성할 예정입니다.
project/
├── app.py # Flask 웹서버 및 챗봇 로직 파일 (핵심)
├── static/ # CSS, 폰트, 이미지 등 정적 파일
│ ├── style.css # (선택 사항) 외부 CSS 파일. 필자는 이 파일을 생성하지 않고, chat.html 파일에 내용을 포함시켰습니다.
│ └── fonts/
│ └── NanumSquareRoundL.ttf
├── templates/ # HTML 템플릿 파일
│ └── chat.html # 챗봇 웹 인터페이스
└── knowledge/ # RAG에 사용할 지식 파일
├── test.txt
├── test2.txt
└── …
3) 필수 Python 패키지 설치
웹 프레임워크인 Flask, Ollama API 통신을 위한 requests, 그리고 다양한 지식 파일(.docx, .xlsx, .pdf, .ods 등)을 읽기 위한 라이브러리들을 설치합니다.
# pip install jsonlines flask requests ezodf pdfplumber odfpy chromadb python-docx pandas openpyxl sentence-transformers faiss-cpu
ChromaDB와 FAISS는 RAG를 위한 벡터 데이터베이스 역할을 하며, sentence-transformers는 텍스트를 벡터로 변환(임베딩)하는 데 사용됩니다.
말이 어려우신 분을 위해 조금 쉽게 설명을 드리자면…
RAG 관련 라이브러리들 (핵심)
– sentence-transformers : 문장을 숫자로 바꿔주는 도구입니다. 사람은 문장을 그대로 이해하지만 컴퓨터는 그렇게 하지 못합니다. 그래서 AI가 문장의 의미를 이해할 수 있도록 숫자 형태로 변환합니다.
– ChromaDB, FAISS : 변환된 숫자들을 저장하고, 나중에 비슷한 내용을 빠르게 찾을 수 있게 해주는 데이터베이스입니다.
여러분이 책 수백 권을 가지고 있다고 생각해보세요. 누군가 질문을 하면 관련된 내용이 있는 책을 찾아서 답변해야 하는데, 일일이 책을 다 뒤지면 시간이 오래 걸리겠죠? RAG는 미리 책의 내용을 정리해서 색인(인덱스)을 만들어두고, 질문이 오면 관련된 부분만 빠르게 찾아서 AI에게 전달해 주는 방식입니다. 이렇게 하면 AI가 더 정확하고 빠르게 답변할 수 있습니다.
4) 웹서버 로직 파일(app.py) 및 HTML 템플릿 작성
(1) 디렉토리 및 폰트 준비
웹페이지 구성에 필요한 디렉토리를 모두 미리 생성하고, 사용자 친화적인 디자인을 위해 무료 폰트(나눔스퀘어라운드)를 다운로드합니다.
# mkdir -p templates static/fonts knowledge
# wget -P static/fonts/ https://github.com/innks/NanumSquareRound/raw/master/NanumSquareRoundL.ttf
(2) 웹서버 로직 (app.py)
– 파일 위치 : project 최상위 디렉토리
아래 파일을 다운로드 받아서 압축을 풀고 app.py 라는 이름의 파일로 내용을 붙여넣습니다.
이 소스에는 Flask 서버 설정, Ollama API 통신 로직, 그리고 RAG를 위한 지식 파일 로드 및 검색 로직이 모두 담겨있습니다.
# vi app.py
💾 app.zip
(3) HTML 템플릿 (chat.html)
– 파일 위치 : templates 디렉토리 내
아래 필요한 파일 하나만 다운로드 받아서 압축을 풀고 templates 디렉토리 내에 chat.html 이라는 이름의 파일로 내용을 붙여넣습니다.
이 파일은 사용자가 질문을 입력하고 챗봇의 답변을 확인할 수 있는 웹 인터페이스를 제공합니다.
# vi templates/chat.html
💾 chat.zip // 일반 버전
💾 chat_img.zip // 답변에 이미지 URL이 있을경우, 이미지로 변환하여 출력하는 버전
3. RAG(검색 증강 생성)를 활용한 지식 데이터 연동
우리가 만드는 챗봇의 핵심 강점은 바로 RAG를 통해 자체 지식 파일에 기반한 답변을 할 수 있다는 점입니다.
⭐ RAG의 작동 원리 ⭐
RAG는 LLM이 학습하지 않은 최신 정보나 특정 기업/조직의 내부 자료를 활용할 수 있게 해주는 기술입니다.
위에서 동작 원리를 쉽게 설명 드렸지만, 여기에는 조금 더 자세하게 설명 하겠습니다. 그만큼 중요한 챗봇 원리의 핵심이기 때문입니다.
– 앱 구동 & 파일 로드 (load_knowledge_from_folder()) : 서버 시작 시 knowledge 디렉토리 안의 모든 문서 파일(docx, xlsx, pdf, txt 등)에서 텍스트를 추출합니다.
– 청크(Chunk) 분할 : 추출된 텍스트를 의미가 손상되지 않도록 적절한 크기(예 : 문단 단위, 특정 토큰 수 기준)로 잘게 나눕니다.
– 임베딩 (Embedding) : 각 청크를 임베딩 모델을 사용하여 고차원 벡터(숫자 배열)로 변환합니다. 이 벡터는 텍스트의 의미를 담고 있습니다.
– 벡터 DB 저장 (ChromaDB) : 청크 텍스트, 해당 벡터, 고유 ID 등을 ChromaDB와 같은 벡터 데이터베이스에 저장합니다.
– 사용자 질문 : 사용자가 질문을 입력하면, 이 질문도 임베딩 모델로 벡터화됩니다.
– 벡터 유사도 검색 : 질문 벡터와 가장 의미적으로 유사한 Top-K개의 청크 벡터(즉, 관련 지식 조각)를 벡터 DB에서 빠르게 검색해 가져옵니다.
– LLM 호출 : 검색된 관련 지식(청크 텍스트)을 사용자 질문과 함께 LLM(Gemma3:27B)에게 전달합니다. 이로써 LLM은 단순한 일반 지식이 아닌, 제공된 지식을 바탕으로 답변을 생성합니다.
– 사용자에게 응답 : LLM이 생성한 자연어 답변을 사용자에게 출력합니다.
1) 지식 파일 준비
knowledge 디렉토리에 답변에 사용될 모든 지식 파일(ex: 회사의 주소록, 서비스 매뉴얼, FAQ 등)을 넣어두세요.
여기에서는 간단히 스마일서브 주소만 넣어보겠습니다.
# cat << ‘EOF’ > knowledge/test.txt
스마일서브 주소
본사 : 경기도 성남시 분당구 대왕판교로 644번길 86 KT동판교빌딩 3층
IDC-SMILE : 서울시 금천구 가산디지털1로 33-33 대륭테크노타운2차 2층
EOF
2) Flask 개발 서버 테스트
모든 파일 준비가 끝났다면, 개발 환경에서 웹 서버를 가동해 봅니다.
⚠️ 주의 : 이 명령어는 테스트 용이며, 보안에 취약하여 실제 운영 환경에서는 사용하면 안 됩니다. 프로덕션 환경에서의 구동 방법은 아래에 있습니다.
# sudo env “PATH=$PATH” python3 app.py –host 0.0.0.0 –port 80
챗봇이 잘 동작되는지 확인하기 위해 웹 브라우저에서 서버 IP로 접속 후, 챗봇에 질문을 해봅니다.
http://{서버IP}
User : 스마일서브 IDC-SMILE 주소 알려줘
Assistant : 서울시 금천구 가산디지털1로 33-33 대륭테크노타운2차 2층

답변이 딱딱하긴 하지만 knowledge 파일에 있는 내용에 기반하여 정확하게 답변하는 것을 확인할 수 있습니다.
4. 프로덕션 환경을 위한 웹 서버 구성 (Gunicorn + Nginx)
Flask HTML서버는 테스트용 환경일 뿐, 실제 서비스에는 적합하지 않으며 아래 경고처럼 메세지가 출력됩니다.
WARNING: This is a development server. Do not use it in a production deployment.
때문에 프로덕션에서는 웹서버 + WSGI (Gunicorn) 구성으로 가는 것을 추천합니다.
아래와 같이 동작하도록 세팅해 보겠습니다.
Client (Browser)
↓
Nginx (Reverse Proxy, HTTPS 가능)
↓
Gunicorn (WSGI App Server)
↓
Flask (app.py + templates/chat.html)
1) Nginx 웹서버 설치 및 리버스 프록시 설정
Nginx를 설치하고 Gunicorn이 구동될 포트(여기서는 8000)로 요청을 전달하는 리버스 프록시 설정을 추가합니다.
# apt -y install nginx
# vi /etc/nginx/sites-available/chatbot
|
server { location / { |
설정 파일을 활성화하고 설정 문법에 이상이 없는지 체크 합니다. 그리고 Nginx를 재시작합니다.
# ln -s /etc/nginx/sites-available/chatbot /etc/nginx/sites-enabled/
# nginx -t
# systemctl reload nginx
2) SSL 인증서 생성 (HTTPS 적용)
보안과 클립보드 API 같은 브라우저 기능을 정상적으로 사용하기 위해 Let’s Encrypt를 이용해 SSL 인증서를 발급받아 HTTPS를 설정합니다.
(사전 확인 사항) 도메인이 서버 IP로 올바르게 연결(DNS 등록)되어 있는지, 그리고 해외망에서 80 포트 접근이 허용되어 있는지 확인해야 합니다. 해외망에서 접근해야 하는 이유는 Let’s Encrypt 인증서 발급을 위해 올바른 웹사이트인지 도메인으로 접근을 해보기 때문입니다. 접근 해오는 IP를 알지 못하므로, Elcap방화벽 등에서 해외망 80번 포트 접근이 막혀있다면 임시적으로 허용해 주세요.
# apt -y install certbot python3-certbot-nginx
# certbot –nginx -d chatbot.cloudv.kr –register-unsafely-without-email –agree-tos
이 명령이 성공적으로 실행되면 Nginx 설정 파일이 자동으로 업데이트되어 443 포트(HTTPS)가 활성화됩니다.
3) Gunicorn (WSGI) 웹서버 구동
Gunicorn을 설치하고 워커 프로세스를 띄워 Flask 애플리케이션을 실행합니다.
# pip install gunicorn jsonlines
테스트/개발 단계 (싱글 스레드) : 1개의 스레드만 사용해 챗봇을 가동합니다.
# gunicorn -w 1 -b 127.0.0.1:8000 app:app –timeout 300
고사양/운영 환경 (멀티 스레드) : 서버의 CPU 코어 수만큼 워커를 띄워 부하를 분산합니다.
# gunicorn -w $(nproc) -b 127.0.0.1:8000 app:app –timeout 300
Gunicorn 실행 후, 콘솔에는 (워커 수만큼) RAG 지식 로딩 메시지가 출력되는 것을 확인할 수 있습니다.
이제 설정한 도메인으로 접속하면 HTTPS 환경에서 챗봇 서비스를 이용할 수 있습니다.
최종 접속 주소 예시 : https://chatbot.cloudv.kr
참고 사항
소스코드 수정 시 : app.py나 chat.html을 수정했다면, 변경 사항을 웹에 반영하기 위해 gunicorn을 반드시 재시작해야 합니다.
지식 파일 변경 시 : 임베딩 모델을 변경하거나, RAG가 지식을 제대로 찾지 못하는 경우 벡터 데이터베이스를 초기화해야 할 수 있습니다.
# rm -rf chroma_storage
다양한 파일 형식 지원 : .ods 파일처럼 셀 병합이 많은 스프레드시트는 데이터 인식률이 낮아질 수 있습니다.
답변 품질을 높이기 위해 별도의 스크립트를 사용해 데이터를 단일 라인의 텍스트 파일로 변환하여 knowledge 폴더에 넣는 것을 강력히 추천합니다.
맺음말
여기까지 오시느라 정말 수고 많으셨습니다!
어떠신가요? 위 과정을 따라오신 분이라면, 단순히 남이 만든 서비스를 사용하는 것이 아니라 ‘내 손으로 직접 AI 챗봇을 만들었다’는 뿌듯함과 자부심을 느끼고 계실 겁니다. 처음에는 어렵게 느껴졌던 용어들과 명령어들이 이제는 조금씩 익숙해지셨을 거예요.
이제 시작입니다.
지금 만드신 챗봇은 기본 골격일 뿐입니다. 여기에 여러분만의 창의력을 더해보세요.
– 챗봇의 말투나 성격을 바꾸고 싶으신가요?
– 특정 분야의 전문 지식을 더 추가하고 싶으신가요?
– 사용자 인터페이스를 더 예쁘게 꾸미고 싶으신가요?
– 음성 인식 기능을 추가하고 싶으신가요?
이 모든 것이 가능합니다. app.py 파일을 수정하고 systemctl restart gunicorn으로 서비스를 재시작하면 여러분의 아이디어가 바로 반영됩니다.
챗봇이 앞으로 어떤 모습으로 성장해 나갈지는 이제 여러분의 상상력과 열정에 달려 있습니다. 고객 상담 봇으로 발전시킬 수도 있고, 개인 비서로 만들 수도 있으며, 교육용 튜터로 키워낼 수도 있습니다. 가능성은 무궁무진합니다.
목표를 세우셨으면 작은 변화부터 시도해보세요. 개발을 하실때 조심해야 할 것은 한 번에 많은 걸 바꾸려다 오류가 생기면 원인을 찾기 어렵습니다. 그래서 코드를 수정하기 전에 반드시 백업을 하고 진행하시기 바랍니다.
막히는 부분이 있다면 검색하고, 커뮤니티에 질문하며 배워가세요. 모든 개발자가 그렇게 성장합니다.
이 가이드를 통해 여러분만의 강력하고 똑똑한 RAG 챗봇 서비스를 성공적으로 구축하셨기를 바랍니다. 그리고 이것이 여러분의 AI 개발 여정의 멋진 시작점이 되길 진심으로 응원합니다.



