0강. RAG 실습 환경 구축

0. 학습 목표
→ 이 과정 전체에서 사용할 작업 폴더와 도구를 한 번에 준비하고, 준비된 것을 실행해 확인합니다.
0.1 이번 글에서 다룰 내용
이 과정에서는 지식재산권 질의응답 문서를 근거로 답하는 프로그램을 만듭니다.
그 프로그램이 지금 상태에서 실행되는지 먼저 확인해 봅니다.
쉘 프롬프트
# 이 과정에서 사용할 도구가 지금 있는지 확인
python3 -c "import chromadb"
ollama list
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'chromadb'
ollama: command not found
두 줄 모두 실패합니다.
문서를 저장할 프로그램도 없고, 답변을 만들 모델도 없습니다. 코드를 아무리 잘 써도 실행할 수 없는 상태입니다.
이번 강의는 이 두 줄이 정상으로 나오게 만드는 강의입니다.
마지막에 같은 명령을 다시 실행해 결과가 어떻게 달라지는지 확인합니다.
준비할 것은 여섯 가지입니다.
| 준비할 것 | 무엇을 하는가 | 어느 강의에서 쓰는가 |
작업 폴더 rag-basic과 가상환경 |
이 과정에서 만드는 파일을 한곳에 모으고, 설치한 패키지가 시스템 파이썬을 건드리지 않게 한다 | 0강~3강 전체 |
| VSCode | 파일을 만들고 코드를 작성한다. 명령 실행은 쉘 프롬프트에서 한다 | 0강 5절, 2강, 3강 |
| 패키지 세 개 | 벡터 저장, HTTP 요청, 설정 파일 읽기 | 2강, 3강 |
| Ollama와 모델 두 개 | 텍스트를 벡터로 바꾸고 답변을 만든다 | 1강~3강 |
| 기초 데이터 | 이 과정에서 검색 대상이 되는 질의응답 10건 | 2강, 3강 |
설정 파일 .env와 config.py |
모델 이름과 경로를 코드 바깥에 둔다 | 2강, 3강 |
이 여섯 가지 중 어느 하나라도 빠지면 1강부터 진행할 수 없습니다. 그래서 강의를 시작하기 전이 아니라 첫 강의로 둡니다.
이번 강의에서 만드는 것은 환경과 설정 파일이며, RAG 코드는 2강부터 작성합니다. 이번 강의를 마치면 프로젝트 폴더가 다음 상태가 됩니다.
rag-basic/
├── .venv/ # 가상환경
├── .env # 설정 값
├── config.py # 설정을 읽는 모듈
└── data/
├── ip_qa_basic.json # 배포받은 기초 데이터 10건
└── 출처.md # 데이터 출처와 가공 내용
0.2 이번 강의 실습 내용
학습자가 직접 하는 작업은 1절부터 7절까지 이어집니다.
절마다 앞 절에서 만든 것 위에 다음 것을 얹으므로, 각 절이 무엇을 받아 무엇을 넘기는지 먼저 확인합니다.
1절에서는 작업 폴더와 가상환경을 만들고 VSCode로 그 폴더를 엽니다.
이후 모든 설치와 실행이 이 폴더 안에서 일어나고, 파일 작성은 열어 둔 VSCode에서 합니다.
2절에서는 패키지 세 개를 설치합니다.
세 개뿐인 이유와 각각이 어느 강의에서 쓰이는지 함께 확인합니다.
3절에서는 Ollama를 설치하고 모델 두 개를 준비합니다.
두 모델이 합쳐 약 4.6GB이므로 이 절이 가장 오래 걸립니다.
실습실 사정에 따라 압축 파일로 전달받아 적용하는 방법도 함께 다룹니다.
4절에서는 배포받은 기초 데이터를 작업 폴더에 배치합니다.
파일이 제대로 놓였는지 건수로 확인합니다.
5절에서는 설정 파일을 만듭니다.
모델 이름과 경로를 코드 안에 직접 쓰지 않고 .env에 모으는 이유를 확인하고, 그 값을 읽는 config.py를 만듭니다.
6절에서는 지금까지 준비한 것을 한 번에 점검합니다.
0.1에서 실패했던 두 줄을 다시 실행해 결과가 달라지는 것을 확인합니다.
7절에서는 설치한 것을 되돌리는 방법을 확인합니다.
실행할 필요는 없지만, 수업이 끝나거나 처음부터 다시 시작해야 할 때를 위해 알아 둡니다.
| 절 | 하는 일 | 앞 절에서 받는 것 | 다음 절에 넘기는 것 |
| 1 | 작업 폴더·가상환경 생성과 편집기 열기 | 없음 | 활성화된 rag-basic/.venv와 열려 있는 VSCode |
| 2 | 패키지 세 개 설치 | 가상환경 | chromadb·requests·python-dotenv |
| 3 | Ollama 설치와 모델 준비 | 없음 (가상환경과 무관) | bge-m3, qwen3.5:4b |
| 4 | 기초 데이터 배치 | 작업 폴더 | data/ip_qa_basic.json 10건 |
| 5 | 설정 파일 작성 | 패키지와 모델 이름 | .env와 config.py |
| 6 | 전체 점검 | 1~5절의 결과 전부 | 1강을 시작할 수 있는 상태 |
| 7 | 되돌리는 방법 확인 | 설치한 환경 | 초기 상태로 되돌리는 절차 |
이번 강의를 마치면 다음을 할 수 있습니다.
- 가상환경을 만들어 활성화하고, 활성화 여부를 프롬프트 표시와
which python3으로 판단한다. - 명령 실행은 쉘 프롬프트에서, 파일 작성은 VSCode에서 한다는 역할 구분에 따라 작업한다.
- Ollama를 설치해 모델을 내려받고, 모델 목록과 서비스 상태를 명령으로 확인한다.
- 모델 이름과 경로를
.env에 두고config.py로 읽어, 값을 바꿀 때 코드를 고치지 않아도 되게 만든다. - 설치한 가상환경·패키지·데이터를 되돌릴 때 무엇이 함께 지워지고 무엇이 남는지 구분한다.
선수 지식은 쉘에서 명령을 실행해 본 경험입니다. 편집기 사용 경험은 필요하지 않으며 1.3에서 여는 방법부터 확인합니다. 파이썬 문법은 5절의 설정 파일에서 처음 나오며, 그 코드는 이 강의에서 그대로 사용합니다.
이번 강의에서는 RAG가 무엇이고 왜 필요한지를 다루지 않으며, 이 내용은 1강에서 이어집니다. 임베딩과 벡터 저장 코드도 작성하지 않습니다. 여기서는 그 코드를 실행할 수 있는 상태를 만드는 것까지만 합니다.
💡 사용 환경
호스트 운영체제: Ubuntu 24.04 (실습 PC)
실제 실행 환경: Ubuntu 24.04 자체. 가상 머신·컨테이너·WSL을 거치지 않고 직접 실행
사용 쉘: Bash. 로컬 쉘을 직접 실행하며 원격 접속을 쓰지 않음
프로그래밍 언어: Python. Ubuntu 24.04에 기본 설치된 3.12 계열
프로젝트 폴더: 홈 아래 rag-basic. 이 강의에서 만들고 3강까지 이름이 바뀌지 않음
경로 형식: POSIX 슬래시 경로(/)
파일 편집기: VSCode. 명령 실행은 쉘 프롬프트에서 하고, 파일 만들기와 코드 작성은 VSCode에서 함
사용 모델: 임베딩 bge-m3, 답변 생성 qwen3.5:4b. 둘 다 Ollama로 실행
적용 버전: 특정 숫자로 고정하지 않음. Python은 우분투 기본 버전, Ollama는 공식 설치 스크립트가 받아오는 버전
1. 작업 폴더와 가상환경 만들고 편집기로 열기
→ 이 과정에서 만드는 파일을 모을 폴더와 격리된 파이썬 환경을 만들고, 그 폴더를 편집기로 엽니다.
0.1에서 확인했듯이 지금은 패키지도 모델도 없습니다. 설치를 시작하기 전에 설치한 것이 어디에 놓일지부터 정합니다.
1.1 작업 폴더 만들기
쉘 프롬프트

# 이 과정 전체에서 사용할 작업 폴더
mkdir -p ~/rag-basic
cd ~/rag-basic
pwd
/home/사용자이름/rag-basic
앞으로 모든 명령은 이 폴더 안에서 실행합니다. 이 폴더 이름은 0강부터 3강까지 바뀌지 않습니다. 새 창을 열면 다시 cd ~/rag-basic으로 들어와야 합니다.
8. RAG 강좌의 다음 단계에서는 폴더 이름이 rag-ip로 바뀝니다. 단계마다 폴더를 나누어 앞 단계의 결과가 섞이지 않게 하기 위해서입니다.
1.2 가상환경 만들고 활성화하기
가상환경은 이 프로젝트에서 설치한 패키지를 이 폴더 안에만 두는 장치입니다. 시스템 파이썬과 다른 과정의 환경을 건드리지 않습니다.
쉘 프롬프트

# 가상환경 생성과 활성화
python3 -m venv .venv
source .venv/bin/activate
ensurepip is not available 같은 오류가 나오면 다음 명령으로 설치한 뒤 다시 실행합니다.
쉘 프롬프트
# venv 모듈이 없을 때만 실행
sudo apt install -y python3-venv
활성화되면 프롬프트 맨 앞에 (.venv)가 붙습니다.
(.venv) 사용자이름@호스트:~/rag-basic$
이 표시가 없으면 이후 명령이 시스템 파이썬에서 실행되어 설치한 패키지를 찾지 못합니다. 2강과 3강에서 ModuleNotFoundError가 나는 원인 중 가장 흔한 것이 이 표시를 놓친 경우입니다.
어떤 파이썬이 쓰이고 있는지 직접 확인할 수 있습니다.
쉘 프롬프트
# 지금 실행되는 파이썬의 위치 확인
which python3
/home/사용자이름/rag-basic/.venv/bin/python3
경로에 .venv가 들어 있으면 가상환경이 활성화된 것입니다. /usr/bin/python3이 나오면 활성화되지 않은 상태이므로 source .venv/bin/activate를 다시 실행합니다.
1.3 VSCode로 작업 폴더 열기
이 과정에서 만들 파일은 여섯 개입니다.
폴더를 편집기로 한 번 열어 두면 파일 목록과 편집 화면을 함께 보면서 작업할 수 있습니다.
이 과정에서는 VSCode를 사용합니다.
쉘 프롬프트

# 작업 폴더를 VSCode로 열기
cd ~/rag-basic
code .
code .의 마침표는 지금 위치한 폴더를 뜻합니다. VSCode 창이 열리고 왼쪽 파일 목록에 .venv 폴더가 보이면 정상입니다.
.env처럼 점으로 시작하는 파일은 우분투에서 숨김 파일로 취급되어 파일 관리자에는 보이지 않지만, VSCode의 파일 목록에는 그대로 보입니다. 5절에서 .env를 만들면 목록에 나타나는지 확인하게 됩니다.
⚠ 자주 겪는 오류
code .을 실행했는데 창이 열리지 않으면 화면이 없는 환경에서 실행한 것입니다. 이 과정은 실습 PC에서 직접 실행하는 것을 전제로 합니다.
snap 설치 중 권한 오류가 나면 sudo를 빠뜨린 것입니다. 설치 명령에는 sudo가 필요합니다.
2. 패키지 세 개 설치하기
→ 가상환경 안에 이 과정에서 사용할 패키지를 설치합니다.
1절에서 가상환경이 활성화되었습니다. 이제 그 안에 패키지를 설치합니다. 활성화된 상태에서 설치해야 .venv 폴더 안으로 들어갑니다. 프롬프트에 (.venv)가 있는지 다시 확인합니다.
쉘 프롬프트

# 이 과정에서 사용할 패키지 세 개
pip install chromadb requests python-dotenv
세 개뿐입니다. 각각이 하는 일과 쓰이는 곳은 다음과 같습니다.
| 패키지 | 하는 일 | 사용하는 강의 |
chromadb |
벡터와 원문을 저장하고 가까운 것을 찾아 준다 | 2강, 3강 |
requests |
Ollama에 HTTP 요청을 보낸다 | 2강, 3강 |
python-dotenv |
.env 파일의 설정 값을 읽는다 |
이 강의 5절부터 |
설치가 끝나면 실제로 불러올 수 있는지 확인합니다.
쉘 프롬프트

# 세 패키지를 모두 불러올 수 있는지 확인
python3 -c "
import chromadb, requests, dotenv
print('chromadb :', chromadb.__version__)
print('세 패키지 모두 정상')
"
chromadb의 버전 숫자는 설치 시점에 따라 다릅니다. 버전을 특정 숫자로 고정하지 않습니다. 이 과정에서 쓰는 기능은 오래된 버전부터 지금까지 동작하는 것들이며, 버전에 따라 표기가 달라지는 부분은 2강에서 두 가지 표기를 함께 안내합니다.
⚠ 자주 겪는 오류
pip: command not found가 나오면 가상환경이 활성화되지 않은 것입니다. source .venv/bin/activate를 실행하고 프롬프트에 (.venv)가 붙는지 확인합니다.
ModuleNotFoundError: No module named 'dotenv'가 나오면 패키지 이름을 dotenv로 설치한 경우입니다. 설치할 때는 python-dotenv, 코드에서 불러올 때는 dotenv입니다. 이름이 다릅니다.
3. Ollama 설치하고 모델 두 개 준비하기
→ 텍스트를 벡터로 바꾸고 답변을 만들 모델을 준비합니다.
2절까지는 파이썬 쪽 준비였습니다. 모델은 파이썬 패키지가 아니라 별도의 프로그램이 관리합니다. 그 프로그램이 Ollama입니다.
파이썬 코드 안에 모델이 들어 있지 않고, 코드는 Ollama에 요청을 보내 결과를 받습니다. 이 구조가 왜 그런지는 1강 4절에서 다루고, 여기서는 설치하고 동작하는 것까지 확인합니다.
3.1 이미 설치되어 있는지 먼저 확인하기
실습실에 미리 설치된 경우가 있으므로 먼저 확인합니다.
쉘 프롬프트

# Ollama가 이미 있는지 확인
ollama list
모델 목록이 나오면 이미 설치된 것입니다. 3.2를 건너뛰고 3.3으로 갑니다. ollama: command not found가 나오면 3.2부터 진행합니다.
3.2 Ollama 설치하기
쉘 프롬프트
# 공식 설치 스크립트로 Ollama 설치
curl -fsSL https://ollama.com/install.sh | sh
설치가 끝나면 Ollama가 systemd 서비스로 등록되어 자동으로 실행됩니다. 별도로 실행 명령을 입력할 필요가 없습니다.
쉘 프롬프트
# 서비스가 실행 중인지 확인
systemctl status ollama --no-pager | head -3
active (running)이 보이면 정상입니다. 보이지 않으면 다음 명령으로 시작합니다.
쉘 프롬프트
# 서비스가 멈춰 있을 때만 실행
sudo systemctl start ollama
3.3 모델 두 개 내려받기
이 과정에서 쓰는 모델은 두 개입니다. 하는 일이 다릅니다.
| 모델 | 하는 일 | 크기 | 사용하는 강의 |
bge-m3 |
텍스트를 숫자 벡터로 바꾼다 | 약 1.2GB | 2강, 3강 |
qwen3.5:4b |
근거를 받아 답변 문장을 만든다 | 약 3.4GB | 1강, 3강 |
쉘 프롬프트
# 임베딩 모델과 답변 생성 모델 내려받기
ollama pull bge-m3
ollama pull qwen3.5:4b
두 모델이 합쳐 약 4.6GB입니다. 네트워크 상태에 따라 오래 걸리므로 수업 시간에 받지 않도록 미리 준비합니다. 여러 대가 동시에 내려받으면 실습실 네트워크가 감당하지 못하므로, 그런 경우에는 3.4의 압축 파일 전달 방법을 사용합니다.
받은 뒤 목록을 확인합니다.
쉘 프롬프트
# 내려받은 모델 확인
ollama list
두 이름이 모두 보이면 정상입니다. 이름 뒤에 :latest가 붙어 보일 수 있습니다. 내려받을 때 태그를 지정하지 않았다는 뜻이며 같은 모델입니다.
3.4 압축 파일로 전달받은 모델을 적용하기
여러 대가 동시에 4.6GB를 내려받으면 실습실 네트워크가 감당하지 못합니다. 이미 모델을 받아 둔 PC에서 파일을 압축해 전달하면, 전달받은 PC는 다시 내려받지 않고 같은 모델을 바로 사용할 수 있습니다.
Ollama는 받은 모델을 두 폴더에 나눠 보관합니다. 어느 하나만 옮기면 동작하지 않습니다.
쉘 프롬프트
# Ollama가 모델을 보관하는 위치와 그 안의 폴더 확인
ls /usr/share/ollama/.ollama/models
blobs manifests
| 폴더 | 담고 있는 것 |
blobs |
모델 파일 본체. 용량의 대부분을 차지한다 |
manifests |
모델 이름·태그와 본체 파일을 연결하는 정보 |
blobs만 옮기면 파일은 있는데 ollama list에 이름이 나오지 않고, manifests만 옮기면 이름은 나오는데 실행할 파일이 없습니다. 두 폴더를 함께 옮겨야 하므로 models 폴더를 통째로 압축합니다.
3.4.1 모델을 이미 받은 PC에서 압축하기
강사 PC 또는 먼저 내려받기를 마친 PC에서 실행합니다.
쉘 프롬프트

# models 폴더를 통째로 압축해 홈 폴더에 만든다
sudo tar czf ~/ollama-models.tar.gz -C /usr/share/ollama/.ollama models
ls -lh ~/ollama-models.tar.gz
-C /usr/share/ollama/.ollama models는 그 위치로 이동한 뒤 models 폴더만 압축한다는 뜻입니다. 이렇게 해야 압축 파일 안에 models/blobs/… 구조가 그대로 들어가고, 푸는 쪽에서 경로가 어긋나지 않습니다.
만들어진 ollama-models.tar.gz를 USB나 공유 폴더로 전달합니다.
3.4.2 전달받은 PC에서 압축 풀고 적용하기
전달받은 파일을 Downloads 폴더에 둡니다. 실습 PC의 계정 이름이 basiclike라면 실제 경로는 /home/basiclike/Downloads/ollama-models.tar.gz입니다.
쉘 프롬프트

# 전달받은 압축 파일이 제자리에 있는지 확인
ls -lh ~/Downloads/ollama-models.tar.gz
파일이 보이면 압축을 풉니다.
쉘 프롬프트

# Ollama 보관 위치에 압축을 풀고 소유권을 맞춘 뒤 서비스 재시작
sudo tar xzf ~/Downloads/ollama-models.tar.gz -C /usr/share/ollama/.ollama
sudo chown -R ollama:ollama /usr/share/ollama/.ollama/models
sudo systemctl restart ollama
세 줄이 각각 하는 일이 다릅니다.
| 명령 | 하는 일 |
tar xzf … -C /usr/share/ollama/.ollama |
압축을 Ollama 보관 위치에 푼다. 3.4.1에서 models를 통째로 묶었으므로 폴더 구조가 그대로 맞는다 |
chown -R ollama:ollama |
푼 파일의 소유자를 Ollama 서비스 계정으로 바꾼다 |
systemctl restart ollama |
서비스를 다시 시작해 새로 들어온 모델을 읽게 한다 |
chown이 필요한 이유는 우분투의 Ollama가 ollama라는 전용 계정의 서비스로 동작하기 때문입니다. 압축을 푼 파일은 명령을 실행한 사람의 소유가 되므로, 소유자를 바꿔 주지 않으면 서비스가 그 파일을 읽지 못합니다.
쉘 프롬프트

# 내려받지 않았는데도 모델이 보이는지 확인
ollama list
ollama pull을 실행하지 않았는데도 bge-m3와 qwen3.5:4b가 목록에 나오면 전달이 정상적으로 끝난 것입니다.
⚠ 자주 겪는 오류
압축을 풀었는데도 ollama list에 모델이 보이지 않으면 대부분 소유권 문제입니다. chown 명령을 다시 실행하고 sudo systemctl restart ollama로 서비스를 재시작한 뒤 다시 확인합니다.
tar: ...: Cannot open: No such file or directory가 나오면 압축 파일 경로가 틀린 것입니다. ls -lh ~/Downloads/ollama-models.tar.gz로 파일이 실제로 그 자리에 있는지 먼저 확인합니다.
3.5 필요 없는 모델 삭제하기
다른 과정에서 받아 둔 모델이 있어 디스크가 부족하면 지울 수 있습니다. 이 과정에서 쓰는 두 모델은 지우지 않습니다.
3.5.1 사용하지 않는 모델 삭제하기
쉘 프롬프트
# 목록을 먼저 확인하고 지울 이름을 정한다
ollama list
쉘 프롬프트
# 지울 모델 이름을 정확히 적어 삭제 (아래는 예시 이름)
ollama rm 모델이름:태그
모델 파일만 지워지며 Ollama 자체는 남습니다. 지운 모델이 다시 필요하면 ollama pull로 받으면 되지만 내려받는 시간이 다시 걸립니다.
4. 배포받은 기초 데이터 배치하기
→ 이 과정에서 검색 대상이 될 데이터를 작업 폴더에 놓습니다.
3절까지 도구가 갖춰졌습니다. 이제 그 도구로 다룰 데이터를 작업 폴더에 놓습니다.
강사가 배포한 기초데이터 폴더에는 파일 두 개가 들어 있습니다.
| 파일 | 내용 |
ip_qa_basic.json |
지식재산권 질의응답 10건 |
쉘 프롬프트
# 작업 폴더에 data 폴더를 만들고 배포받은 파일 두 개를 복사
mkdir -p ~/rag-basic/data
cp /전달받은경로/기초데이터/ip_qa_basic.json ~/rag-basic/data/
ls ~/rag-basic/data
ip_qa_basic.json
파일이 제대로 놓였는지 건수로 확인합니다.
쉘 프롬프트
# 데이터 건수와 첫 항목의 키 확인
python3 -c "
import json
rows = json.load(open('data/ip_qa_basic.json', encoding='utf-8'))
print('건수 :', len(rows))
print('첫 항목 키 :', list(rows[0].keys()))
"
건수 : 10
첫 항목 키 : ['id', 'type', 'title', 'date', 'question', 'answer']
10건이 나오고 키가 여섯 개면 정상입니다. 이 파일 안에 무엇이 들어 있는지는 2강에서 자세히 봅니다. 여기서는 배치가 제대로 되었는지만 확인합니다.
출처.md를 한 번 열어 두십시오. 이 데이터는 실제 공개 데이터를 수업용으로 다듬은 것이며, 원본은 다르게 생겼습니다. 무엇을 어떻게 다듬었는지 그 파일에 항목별로 적혀 있고, 2강 1절에서 같은 표를 함께 봅니다.
5. 설정 파일 만들기
→ 모델 이름과 경로를 코드 바깥에 두는 구조를 만듭니다.
4절까지 도구와 데이터가 준비되었습니다. 이제 그것들을 코드에서 어떻게 부를지 정합니다.
5.1 값을 코드 바깥에 두는 이유
모델 이름과 경로 같은 값을 코드 안에 직접 쓰면 어떻게 되는지 봅니다. 이 과정에서 만들 파일 여섯 개 중 네 개가 모델 이름이나 저장 경로를 사용합니다. 값을 코드마다 적어 두면, 모델을 바꿀 때 네 파일을 모두 열어 같은 문자열을 찾아 고쳐야 합니다. 한 곳을 빠뜨리면 저장할 때와 검색할 때 다른 모델을 쓰게 되는데, 이 경우 오류가 나지 않고 결과만 이상해집니다.
그래서 값은 .env 파일 한 곳에 모으고, 코드는 config.py를 통해서만 읽게 합니다.
.env (값) → config.py (읽어서 전달) → build_docs.py / embedder.py / store.py / search.py / ask.py
5.2 .env 만들기
1.3에서 열어 둔 VSCode에서 만듭니다. 왼쪽 파일 목록의 rag-basic 위에서 새 파일을 만들고 이름을 .env로 지정한 뒤, 아래 내용을 넣고 저장합니다.
파일 이름 앞의 점을 빠뜨리지 않도록 주의합니다. env로 저장하면 config.py가 값을 읽지 못합니다.

OLLAMA_BASE_URL=http://127.0.0.1:11434
EMBEDDING_MODEL=bge-m3
LLM_MODEL=qwen3.5:4b
CHROMA_PATH=chroma_db
COLLECTION_NAME=ip_docs
TOP_K=3
MIN_SIMILARITY=0.35
각 값이 무엇인지는 다음과 같습니다. 지금 다 이해할 필요는 없으며, 해당 강의에서 다시 설명합니다.
| 키 | 값의 뜻 | 사용하는 강의 |
OLLAMA_BASE_URL |
Ollama 서버 주소 | 2강, 3강 |
EMBEDDING_MODEL |
텍스트를 벡터로 바꿀 모델 | 2강, 3강 |
LLM_MODEL |
답변을 만들 모델 | 3강 |
CHROMA_PATH |
벡터를 저장할 폴더 이름 | 2강, 3강 |
COLLECTION_NAME |
벡터 저장소 안의 문서 묶음 이름 | 2강, 3강 |
TOP_K |
검색할 때 가져올 문서 수 | 3강 |
MIN_SIMILARITY |
근거로 인정할 최소 유사도 | 3강 |
MIN_SIMILARITY의 0.35는 지금 시점에서는 가정값입니다. 이 과정에서는 이 값을 그대로 쓰고, 자기 데이터에서 재어 정하는 방법은 8. RAG 강좌 다음 단계에서 다룹니다.
5.3 config.py 만들기
같은 방식으로 rag-basic 폴더에 config.py 파일을 만들고 아래 내용을 넣습니다. .env와 같은 위치여야 합니다.

from __future__ import annotations
import os
from dataclasses import dataclass
from functools import lru_cache
from pathlib import Path
from dotenv import load_dotenv
PROJECT_DIR = Path(__file__).resolve().parent
load_dotenv(PROJECT_DIR / ".env")
@dataclass(frozen=True)
class Settings:
ollama_base_url: str = os.getenv("OLLAMA_BASE_URL", "http://127.0.0.1:11434")
embedding_model: str = os.getenv("EMBEDDING_MODEL", "bge-m3")
llm_model: str = os.getenv("LLM_MODEL", "qwen3.5:4b")
chroma_path: Path = PROJECT_DIR / os.getenv("CHROMA_PATH", "chroma_db")
collection_name: str = os.getenv("COLLECTION_NAME", "ip_docs")
top_k: int = int(os.getenv("TOP_K", "3"))
min_similarity: float = float(os.getenv("MIN_SIMILARITY", "0.35"))
@lru_cache(maxsize=1)
def get_settings() -> Settings:
return Settings()
세 부분이 이 파일에서 하는 일입니다.
PROJECT_DIR을 __file__ 기준으로 잡아 두면 어느 위치에서 실행해도 .env와 chroma_db를 같은 곳에서 찾습니다. 현재 폴더 기준으로 잡으면 다른 폴더에서 실행했을 때 설정을 못 찾거나 엉뚱한 곳에 벡터를 저장하게 됩니다.
os.getenv("키", "기본값") 형태는 .env에 값이 없을 때 쓸 값을 함께 적어 둔 것입니다. 파일이 없거나 한 줄이 빠져도 프로그램이 멈추지 않습니다.
@lru_cache(maxsize=1)은 get_settings()를 여러 번 불러도 Settings 객체를 한 번만 만들게 합니다. 2강부터 이 함수를 여러 파일에서 호출하게 됩니다.
5.4 설정을 제대로 읽는지 확인하기
쉘 프롬프트

# config.py가 .env 값을 읽어 오는지 확인
python3 -c "
from config import get_settings
settings = get_settings()
print('임베딩 모델 :', settings.embedding_model)
print('답변 모델 :', settings.llm_model)
print('컬렉션 이름 :', settings.collection_name)
print('저장 경로 :', settings.chroma_path)
"
임베딩 모델 : bge-m3
답변 모델 : qwen3.5:4b
컬렉션 이름 : ip_docs
저장 경로 : /home/사용자이름/rag-basic/chroma_db
네 줄이 모두 나오면 정상입니다.
⚠ 자주 겪는 오류
ModuleNotFoundError: No module named 'config'가 나오면 rag-basic 폴더가 아닌 다른 위치에서 실행한 것입니다. cd ~/rag-basic으로 이동한 뒤 다시 실행합니다.
값이 .env에 적은 것과 다르게 나오면 .env 파일 이름이 env.txt처럼 저장된 경우가 많습니다. ls -a로 파일 이름이 정확히 .env인지 확인합니다.
6. 전체 환경을 한 번에 점검하기
→ 0.1에서 실패했던 명령을 다시 실행해 결과가 달라지는 것을 확인합니다.
1절부터 5절까지 다섯 가지를 준비했습니다. 이제 0.1에서 실패했던 두 줄을 다시 실행합니다.
쉘 프롬프트

# 0.1에서 실패했던 두 줄을 다시 실행
python3 -c "import chromadb"
ollama list
첫 줄은 아무것도 출력하지 않고 끝나면 정상입니다. 오류 없이 끝나는 것이 성공입니다. 둘째 줄은 모델 두 개가 나와야 합니다.
이어서 준비한 것을 항목별로 한 번에 확인합니다.
쉘 프롬프트

# 가상환경·패키지·설정·데이터·Ollama를 한 번에 점검
python3 -c "
import json, sys
from pathlib import Path
import requests
from config import get_settings
settings = get_settings()
print('1. 파이썬 위치 :', sys.executable)
print('2. 설정 읽기 :', settings.embedding_model, '/', settings.llm_model)
rows = json.load(open('data/ip_qa_basic.json', encoding='utf-8'))
print('3. 데이터 건수 :', len(rows))
response = requests.get(f'{settings.ollama_base_url}/api/tags', timeout=10)
names = [model['name'] for model in response.json()['models']]
print('4. Ollama 응답 :', response.status_code)
print('5. 등록된 모델 :', names)
chroma_exists = Path(settings.chroma_path).exists()
print('6. 벡터 저장 폴더 :', '아직 없음 (2강에서 생성)' if not chroma_exists else '있음')
"
확인할 항목은 다음과 같습니다.
| 항목 | 기대 결과 |
| 1. 파이썬 위치 | 경로에 rag-basic/.venv가 들어 있음 |
| 2. 설정 읽기 | bge-m3 / qwen3.5:4b |
| 3. 데이터 건수 | 10 |
| 4. Ollama 응답 | 200 |
| 5. 등록된 모델 | bge-m3와 qwen3.5:4b가 목록에 있음 (뒤에 :latest가 붙을 수 있음) |
| 6. 벡터 저장 폴더 | 아직 없음 |
6번이 "아직 없음"인 것이 정상입니다. 벡터 저장 폴더는 2강에서 문서를 저장할 때 만들어집니다.
여섯 항목이 모두 기대와 같으면 1강을 시작할 수 있습니다. 하나라도 다르면 해당 절로 돌아가 다시 확인합니다.
▶ 지금 해보세요
- 위 점검 명령을 실행해 여섯 항목을 모두 확인합니다.
- 새 쉘 창을 하나 열어
cd ~/rag-basic만 하고 같은 명령을 실행합니다. 어떤 오류가 나는지 적고, 그 원인을 1.2의 내용으로 설명합니다. - 그 창에서
source .venv/bin/activate를 실행한 뒤 다시 점검 명령을 실행해 정상으로 돌아오는지 확인합니다.
7. 설치한 환경을 되돌리는 방법
→ 수업이 끝나거나 처음부터 다시 시작할 때 무엇을 지우면 되는지 확인합니다.
지금 실행할 필요는 없습니다. 무엇이 함께 지워지고 무엇이 남는지 알아 두는 것이 목적입니다.
7.1 가상환경과 데이터 삭제하기
이 과정에서 만든 것만 지우는 절차입니다. 두 가지로 나뉩니다.
7.1.1 가상환경과 설치한 패키지 삭제하기
쉘 프롬프트
# 가상환경 비활성화
deactivate
쉘 프롬프트
# 가상환경 폴더 삭제 (설치한 패키지 세 개가 함께 사라짐)
rm -rf ~/rag-basic/.venv
가상환경 폴더 하나만 지우면 그 안에 설치한 패키지도 함께 사라집니다. 시스템 파이썬에는 영향을 주지 않습니다. 다시 만들려면 1.2와 2절을 순서대로 실행하면 됩니다.
7.1.2 데이터와 작업 폴더 삭제하기
쉘 프롬프트
# 배치한 데이터와 이후 강의에서 만들 결과물 삭제
rm -rf ~/rag-basic/data
rm -rf ~/rag-basic/docs
rm -rf ~/rag-basic/chroma_db
쉘 프롬프트
# 작업 폴더 전체를 지울 경우
rm -rf ~/rag-basic
⚠ 주의
rm -rf는 되돌릴 수 없습니다. 마지막 명령은 작성한 config.py와 .env까지 모두 지우므로, 실습 결과를 남기려면 앞의 명령만 실행합니다.
7.2 Ollama와 모델은 남겨 두기
이 과정을 마친 뒤에도 Ollama와 모델은 남겨 두는 것을 권합니다. 8. RAG 강좌의 다음 단계에서 같은 모델을 그대로 사용하기 때문입니다.
7.1의 삭제 명령들은 Ollama와 내려받은 모델, 그리고 VSCode에 영향을 주지 않습니다. 지워지는 것은 rag-basic 폴더 안의 내용뿐입니다.
디스크가 부족해 모델을 지워야 한다면 3.5의 ollama rm으로 모델만 지우고 Ollama는 남겨 둘 수 있습니다. Ollama 자체를 지우는 방법은 설치 방식에 따라 다르므로 공식 문서를 확인합니다.
8. 다음에 만들 것 — LLM에 직접 물어 한계 확인하기
→ 다음 강의에서 확인할 것과 그 이유를 봅니다.
환경이 준비되었습니다. 그런데 이 환경으로 무엇을 왜 만드는지는 아직 확인하지 않았습니다.
1강에서는 코드를 쓰지 않습니다. 대신 방금 준비한 qwen3.5:4b 모델에 질문을 직접 던져 봅니다. 답은 나오지만 그 답을 업무에 쓸 수 없다는 것을 실행 결과로 확인하고, 왜 검색 단계를 따로 만들어야 하는지 정리합니다.
시작하기 전에 한 번 던져 보십시오. 아래 질문의 정답은 배포받은 데이터 안에 들어 있습니다.
쉘 프롬프트
# 배포 데이터 안에 정답이 있는 질문을 로컬 LLM에 던져 본다
ollama run qwen3.5:4b "특허심판원 국선대리인의 선임 및 운영에 관한 규칙은 언제부터 시행되었나요?"
화면에 나온 답이 맞는지 지금은 판단할 수 없습니다. 1강은 이 지점에서 시작합니다.