내 문서를 AI가 읽어주게, 공짜로 — 내 PC에서 로컬 RAG 직접 돌려본 실측 (2026.7)
공공기관 PDF 80쪽을 통째로 집어넣었는데 뽑힌 글자가 0자였습니다. 삽질처럼 보이지만 이게 실은 데이터예요 — 스캔본이라 텍스트 레이어가 아예 없었거든요. 회사 대외비 문서는 챗GPT에 못 올리니 내 PC에 '문서 담당 인턴'을 하나 앉히자는 계산이었는데, 이 인턴이 첫날부터 문서 절반을 못 읽고 헛수고를 했습니다.
그래서 제대로 재봤습니다. 한국 공공문서 4종(텍스트 PDF·표 244쪽짜리 PDF·스캔 PDF·한글 HWPX)을 로컬에 인덱싱하고, 답이 문서에 있는 질문 10개 + 문서에 없는 함정 질문 2개를 던져서 어디까지 되고 어디서 깨지는지 숫자로 확인했어요. 전부 무료 도구, 전부 내 PC(RTX 4070 Ti SUPER)에서 돌았습니다.
잠깐 — 대부분은 로컬이 필요 없습니다
먼저 이 말부터 하고 시작할게요. 그냥 클라우드 쓰세요. 구글 NotebookLM 무료 플랜은 생각보다 넉넉합니다.
- 노트북 100개, 노트북당 소스 50개, 하루 채팅 50회 (구글 공식 고객센터 기준)
- 유료로 올려도 Google AI Pro가 월 29,000원이고요
문서 몇 개 요약하고 검색하는 용도라면 이 한도에 부딪힐 일이 거의 없어요. 무료 한도를 어떻게 쓰는지는 NotebookLM 활용법 글에서 따로 정리했습니다.
그럼 로컬 인턴을 굴릴 이유는 딱 하나예요. 클라우드에 올리면 안 되는 문서. 계약서, 인사자료, 미공개 기획서, 고객 명단 — 회사 규정상 외부 서버에 못 올리는 것들이죠. 이 경우에만 "내 PC에서 도는 AI"가 의미가 있습니다. 나머지 상황에서 로컬은 월급 대신 전기세를 내는 인턴일 뿐이에요.
어떻게 테스트했나
인턴을 뽑았으면 시켜보고 판단해야죠. 월급(전기세) 값을 하는지 보려고 조건을 이렇게 잡았습니다.
- 문서(코퍼스): 개인정보위 2025 업무계획(텍스트 PDF·12쪽) · 정보보호 실태조사 2024(표 많은 PDF·244쪽) · 대한민국 관보 1996(스캔 PDF·80쪽) · 개인정보위 보도자료(HWPX) — 전부 공공기관 공개문서라 누구나 같은 파일로 재현할 수 있습니다.
- 파이프라인(전부 무료·로컬): 텍스트 추출(pdftotext) → 700자 청크 → bge-m3 임베딩 → 코사인 유사도 top-3 검색 → 로컬 LLM이 그 3개 문단만 보고 답변.
- 모델:
gemma3:4b(3.3GB)와qwen2.5vl:7b(6.0GB) — ollama로 한 번에 하나씩 올려서 순차 실행. - 질문 12개: 문서에 답이 있는 10개(연도·비율·인원·표 안의 숫자) + 문서에 답이 없는 함정 2개(안 지어내는지 보려고).
- 프롬프트: "아래 문서만 근거로 답하고, 문서에 답이 없으면 '문서에 없음'이라고만 답하라."
실행 스크립트와 원본 결과(질문별 답변·소요시간)는 저장소에 그대로 커밋해 뒀습니다(test_runs/local-rag-20260712/).
1단계에서 벌써 절반이 걸립니다
RAG 튜토리얼은 대개 "문서를 넣으면 됩니다"로 시작하죠. 현실은 넣기 전에 반이 죽습니다. 이 인턴이 읽지도 못한 문서를 책상에 쌓아두고 일했다는 뜻이고, 그건 나중에 사람 몫의 야근으로 돌아옵니다.
| 문서 | 뽑힌 글자수 | 결과 |
|---|---|---|
| 개인정보위 업무계획(텍스트 PDF) | 12,901자 | 성공 (0.1초) |
| 정보보호 실태조사(표 PDF·244쪽) | 215,001자 | 성공 — 단 표 구조는 뭉개짐 |
| 관보 1996(스캔 PDF·80쪽) | 0자 | 완전 실패 |
| 개인정보위 보도자료(HWPX) | 0자 → 4,858자 | 실패 후 우회 성공 |
스캔 PDF는 통째로 증발합니다. 80쪽이 검색 대상에서 그냥 빠져요. 더 무서운 건 에러가 안 뜬다는 겁니다. 조용히 0자로 넘어가고, 나중에 "그 문서에 있던 내용"을 물으면 AI가 "문서에 없다"고 하거나 엉뚱한 답을 합니다. OCR을 따로 돌리지 않는 한 이 인턴은 그 문서를 읽은 적조차 없어요.
그리고 한국인만 겪는 함정이 하나 더 있습니다. HWPX. 정부 보도자료 첨부는 거의 한글 파일인데, 리브레오피스로 변환을 시도하니 source file could not be loaded로 아예 못 엽니다. 로컬 RAG 도구 대부분이 이 경로를 쓰니, 한글 파일은 사실상 지원되지 않는다고 보는 게 맞아요.
다만 여기서 우회로를 하나 찾았습니다. HWPX는 사실 ZIP + XML입니다. 압축을 풀어 본문 XML의 텍스트만 긁으면 4,858자가 그대로 나와요. 파이썬 표준 라이브러리만으로 열 줄이면 됩니다.
import zipfile, re
from xml.etree import ElementTree as ET
z = zipfile.ZipFile("보도자료.hwpx")
runs = []
for name in z.namelist():
if re.match(r"Contents/section\d+\.xml", name):
for el in ET.fromstring(z.read(name)).iter():
if el.tag.endswith("}t") and el.text: # <hp:t> = 텍스트 조각
runs.append(el.text)
print(" ".join(runs))
속도는 문제가 아니었습니다
속도만 놓고 보면 이 일꾼은 합격입니다. 인덱싱과 검색은 걱정할 게 없었어요.
- 인덱싱: 문서 4종 → 청크 247개 → bge-m3 임베딩 2.3초(모델이 이미 올라와 있을 때 · 초당 107.6청크). 모델을 처음 부를 때만 로딩 포함 11.5초가 붙습니다(초당 21.4청크).
- 검색: 질문당 중앙값 0.18초 — 단 회차에 따라 범위가 크게 달랐습니다(gemma3 회차 0.17~3.98초 · qwen 회차 0.18~0.19초)
- 답변 생성: 12질문 전체 기준 중앙값 0.85초(gemma3:4b · 0.7~1.5초) · 0.65초(qwen2.5vl:7b · 0.5~19.3초). 두 모델을 같은 잣대로 놓으려고 첫 질문을 뺀 11질문도 같이 적으면 0.9초(gemma3 · 0.8~1.5) · 0.6초(qwen · 0.5~0.9)입니다
- 질문 12개 전체(검색+생성 합): gemma3:4b 20.0초 · qwen2.5vl:7b 28.5초(이 중 19.3초가 첫 질문 한 방)
여기서 평균만 보면 안 보이는 게 있어서 꼬리까지 깝니다. 두 회차 다 첫 질문에서 한 번씩 크게 튀었는데, 튄 자리가 서로 달랐어요. gemma3 회차는 검색이 튀었습니다 — 첫 질문 3.98초(중간에 두 번 더 1.85초·1.91초, 마지막 질문도 0.23초로 살짝 올랐고, 그 밖의 8번은 0.17초대). 답변 생성은 오히려 첫 질문이 0.7초로 가장 빨랐고요. qwen 회차는 반대로 검색이 0.18초대로 내내 안정적인 대신 답변 생성 첫 질문이 19.3초였어요 — 모델이 GPU에 처음 올라가는 시간입니다. 즉 "질문당 1초 미만"은 두 번째 질문부터의 얘기이고, 두 종류의 콜드 스타트(검색 인덱스·생성 모델)를 다 넘기기 전까진 첫 질문에서 몇 초를 기다려야 합니다.
그걸 감안해도 "로컬은 느려서 못 쓴다"는 말은 이 규모에선 틀립니다. 문서 몇백 쪽 수준이면, 첫 질문만 넘기면 이 인턴은 커피 마시러 갈 틈도 없이 답을 내놓습니다. (물론 문서가 수만 건으로 늘면 얘기가 달라집니다 — 다른 실사용자들이 "수만 건 넘어가면 검색이 눈에 띄게 느려진다"고 보고합니다.)
진짜 차이는 '정직함'에서 났습니다
여기가 이 테스트의 핵심입니다. 같은 문서, 같은 검색 결과를 받은 두 일꾼이 전혀 다르게 행동했어요. 모르는 걸 물었을 때 인턴이 어떻게 나오느냐 — 사장 입장에선 이게 실력보다 중요합니다.
| gemma3:4b (3.3GB) | qwen2.5vl:7b (6.0GB) | |
|---|---|---|
| 정답 | 9 / 10 | 9 / 10 |
| 근거 문단에 없는 값을 답함 | 1건(Q07 '1,322' — 다른 표 조각의 숫자) | 0건 |
| 함정 질문 거부 | 1 / 2 | 2 / 2 |
| 질문당 검색(중앙값·범위) | 0.18초 (0.17~3.98) | 0.18초 (0.18~0.19) |
| 질문당 생성 — 12질문(중앙값·범위) | 0.85초 (0.7~1.5) | 0.65초 (0.5~19.3) |
| 질문당 생성 — 첫 질문 제외 11질문 | 0.9초 (0.8~1.5) | 0.6초 (0.5~0.9) |
작은 모델은 근거가 없으면 환각을 일으킵니다. "유효 응답 업체 수"를 물었을 때, 검색기가 정답 문단 대신 숫자만 빽빽한 산업별 통계표 조각을 물어왔어요. 정답은 6,500개인데 gemma3는 그 표에 있던 아무 숫자, "1,322"를 답했습니다. 표 안 어딘가에 실제로 있는 숫자라서 더 위험하죠.
함정 질문에서도 갈렸습니다. 코퍼스에는 2024년 조사만 있는데 "2025년 조사에서 침해사고 경험률은?"이라고 물었더니, gemma3는 2024년 수치인 0.3%를 그대로 갖다 붙였어요. 연도가 다른 걸 무시한 겁니다. 반면 qwen2.5vl:7b는 같은 상황에서 "문서에 없음"이라고 물러섰고, 근거 문단을 못 받은 질문에서도 숫자를 만들지 않았습니다.
정답 개수는 9대 9로 같았지만, 틀리는 방식이 달랐습니다. 문서 검색 AI에서 이건 성능 차이가 아니라 안전 차이예요. 3GB 아끼려다 가짜 숫자를 보고서에 넣는 것보다, 6GB 모델을 쓰고 "문서에 없음"을 받는 편이 훨씬 낫습니다.
그리고 검색 적중률 숫자를 조심하세요. '정답 문서를 찾아온 비율'만 보면 10/10, 100%입니다. 그런데 그중 1건은 문서만 맞고 문단이 틀렸어요. 문서 단위 적중률은 실제 정답률을 부풀립니다. RAG 홍보 자료의 90%대 수치를 볼 때 이 점을 꼭 의심해 보세요.
표는 정말 못 읽나 — 절반만 맞습니다
"로컬 RAG는 표를 못 읽는다"는 말이 정설처럼 돌아다닙니다. 실측해 보니 반만 맞았어요. 이 인턴은 표를 못 읽는 게 아니라, 표가 잘린 채 책상에 올라오면 아무 숫자나 집어 옵니다.
- 못 읽는 쪽: 위의 Q07처럼, 표가 텍스트로 납작해지면서 행·열 정렬이 무너진 조각이 검색에 걸리면 모델은 근처 숫자를 아무거나 집습니다.
- 읽는 쪽: 오히려 행/열을 봐야 풀리는 문제(허용오차 1.0에 대응하는 표본 크기)는 두 모델 다 6,436으로 정확히 맞혔습니다.
차이는 청크 운이었어요. 즉 일꾼 탓이 아니라 서류를 어떻게 잘라 주느냐의 문제입니다. 표가 청크 경계에서 잘리지 않고 한 덩어리로 들어오면 모델은 의외로 잘 읽습니다. 반대로 잘리면 그 표는 숫자 쓰레기가 되고요. 그래서 표가 중요한 문서라면 청크 크기를 키우거나, 애초에 표를 따로 뽑아 텍스트로 정리해 두는 게 답입니다.
bge-m3는 한국어 1위가 아닙니다
문서를 찾아오는 일꾼(임베딩)도 짚고 갈게요. 우리가 쓴 bge-m3를 "한국어 최고"라고 소개하는 글이 많은데, 그건 사실이 아닙니다. 공개된 MTEB 한국어 리더보드에서 bge-m3는 종합 9위권이고, multilingual-e5-large-instruct가 그보다 위에 있어요. 고려대 연구실이 낸 한국어 특화 모델 KURE-v1은 한국어 검색 벤치마크에서 bge-m3를 앞선다고 자체 발표했고요.
그럼 왜 bge-m3를 썼냐면 — 무료고, 다국어를 겸하고, ollama에서 명령 한 줄로 끝나기 때문입니다. 순위가 아니라 실용성 때문에 고른 거고, 우리 테스트에서 검색은 10/10으로 정답 문서를 다 찾아왔습니다. 한국어 정확도를 더 짜내야 한다면 KURE-v1 같은 한국어 특화 모델로 바꿔볼 여지가 있어요.
참고로 이력서만 화려하고 사실상 일을 안 하는 인턴도 있습니다. GPT4All이 그렇습니다. 깃허브 최신 릴리스가 2025년 2월이라, 2026년 7월 기준으로 17개월째 조용해요. "무료 로컬 AI 도구 top 10" 목록에 아직도 올라와 있으니 주의하세요.
그래서, 쓸만한가
우리 테스트 기준으로, 이 인턴을 뽑을지 말지는 이렇게 갈립니다.
- 문서를 클라우드에 못 올리는 상황이라면 — 예, 쓸만합니다. 무료 도구만으로 12개 질문에 20초(gemma3:4b 기준·검색+생성 합), 정답 9/10. 구독료 0원.
- 일꾼을 작은 걸로 아끼지 마세요. 3GB 모델은 근거가 없으면 숫자를 지어냅니다. 6GB짜리로 올리는 순간 "모른다"고 말할 줄 알게 돼요.
- 1단계(추출)를 반드시 눈으로 확인하세요. 스캔본·한글 파일은 조용히 0자로 빠집니다. 넣은 문서가 실제로 몇 자로 들어갔는지 세보지 않으면, AI가 "문서에 없다"고 할 때 그게 진짜 없는 건지 안 읽힌 건지 알 수 없습니다.
- 답에 숫자가 있으면 원문을 열어 대조하세요. 이건 클라우드든 로컬이든 똑같습니다.
- 올려도 되는 문서라면 그냥 NotebookLM 쓰세요. 무료 한도가 넉넉하고, 설치도 청크 설정도 필요 없습니다.
로컬 RAG는 "공짜 AI 비서"가 아니라 아직 손이 많이 가는 인턴입니다. 대신 이 인턴은 문서를 절대 밖으로 들고 나가지 않죠. 그 한 가지가 필요한 사람에게만 값어치가 있습니다.
정직하게 한계도 적어둘게요. 문서 4종·질문 12개·모델 2종·각 1회 실행이라 표본이 작습니다. 문서가 다르면 결과도 달라질 수 있어요(특히 표·이미지 비중이 높은 문서). 이 글의 숫자는 "우리 조건에서의 실측"이지 일반 법칙이 아닙니다.
혹시 회사 문서를 AI에 못 올려서 고민하신 적 있나요? 어떤 문서 형식에서 막히셨는지 궁금합니다.
참고자료
test_runs/local-rag-20260712/(이 저장소) — 실행 스크립트·질문별 답변 원문·소요시간·채점 라벨 전부 커밋- 코퍼스 원본: 개인정보보호위원회 2025년 주요업무 추진계획·보도자료(pipc.go.kr) · 2024 정보보호 실태조사(과기정통부·KISIA) · 대한민국 관보 제13432호(국가기록원)
- 구글 NotebookLM 공식 고객센터 — 무료/유료 플랜 한도(노트북 100개·소스 50개·채팅 50회/일)
- 구글 원(one.google.com) 한국 요금 페이지 — Google AI Pro 월 29,000원
- MTEB 한국어 리더보드(su-park/mteb_ko_leaderboard) · KURE-v1 모델 카드(고려대 nlpai-lab) — 한국어 임베딩 성능 비교
- GPT4All 깃허브 릴리스 — 최신 릴리스 2025-02(사실상 정체 상태 확인)
- 피카부랩스 '로컬 LLM RAG 4가지 함정' — 표·차트 파싱 실패, 대량 문서 시 속도 저하 등 다른 실사용자 보고
이 글은 cinevyze가 해당 도구를 실제로 테스트한 결과를 바탕으로 하며, 작성에 AI의 도움을 받았습니다. 본문의 추출 글자수·정답률·소요시간은 모두 위 실행 기록(run.yaml)에서 나온 실측치이고, NotebookLM 한도·요금·임베딩 순위처럼 우리가 직접 측정하지 않은 값은 공식 페이지와 공개 리더보드에서 확인해 표기했습니다. 테스트 조건(문서 4종·질문 12개·1회 실행)의 한계는 본문에 그대로 밝혔습니다.
댓글
댓글 쓰기