📚 Agentic AI - 기업용 자율 에이전트 개발 6장 · 에이전트 ④ RAG 문서검색 Agentic AI란

따라하기 — 인덱스를 저장하고 다시 불러오기

한 줄 요약

인덱스를 파일로 저장해 두면 다음부터는 불러오기만 하면 됩니다. 이걸 안 하면 실행할 때마다 임베딩을 다시 하며 시간과 비용을 버립니다 — 8장에서 가져다 쓸 때도 마찬가지고요.


1. 저장하지 않으면 어떻게 되나

아래는 개념 설명용 코드입니다 — 실습 파일에 넣지 않습니다.

# 저장 안 하는 버전
vs = FAISS.from_documents(chunks, emb)     # 매번 임베딩 15번
retriever = vs.as_retriever(...)

이러면 파일을 실행할 때마다 임베딩을 다시 합니다.

ch06_rag_agent.py 실행     → 임베딩 15번, 수십 초
ch06_rag_agent.py 다시 실행 → 임베딩 15번, 수십 초
ch08_multi_agent.py 실행   → 임베딩 15번, 수십 초   (ch06을 가져다 쓰므로)

우리 문서는 15조각이라 수십 초로 끝납니다. 10,000조각이면 몇 시간입니다. 그리고 매번 비용이 나갑니다.


2. 저장하고 불러오는 코드

아래는 code/ch06_rag_agent.py 의 일부입니다 — 위에서 이미 붙여 넣었으니 다시 넣지 마세요.

def build_index():
    emb = get_embeddings()

    if INDEX_DIR.exists():                                    # ← 이미 있나?
        print(f"  기존 인덱스를 불러옵니다 ({INDEX_DIR.name}) — 임베딩을 다시 하지 않습니다")
        return FAISS.load_local(str(INDEX_DIR), emb, allow_dangerous_deserialization=True)

    print("  인덱스를 새로 만듭니다 — 처음 한 번만 시간이 걸립니다")
    ...
    vs = FAISS.from_documents(chunks, emb)
    vs.save_local(str(INDEX_DIR))                             # ← 저장
    return vs

패턴은 단순합니다.

있으면 → 불러온다 (빠름)
없으면 → 만들고 저장한다 (느림, 한 번만)

이런 방식을 캐시(cache) 라고 부릅니다. "한 번 계산한 것을 보관해 뒀다 재사용한다"는 뜻입니다.


3. 두 번의 실행 비교

첫 실행

  인덱스를 새로 만듭니다 — 처음 한 번만 시간이 걸립니다
    문서 8쪽 로드
    조각 15개로 분할
    인덱스 저장 완료 → .../data/policy_index

두 번째부터

  기존 인덱스를 불러옵니다 (policy_index) — 임베딩을 다시 하지 않습니다

한 줄로 끝납니다. 실습을 반복할 때 이 차이가 큽니다.


4. 저장된 파일

data/policy_index/index.faiss46 KB — 벡터 15개index.pkl16 KB — 원문 텍스트와 metadata둘 다 있어야 불러올 수 있습니다. 하나만 옮기면 열리지 않습니다.
불러올 때도 이 두 파일을 함께 읽는다

두 개가 짝입니다.

파일 무엇
index.faiss 검색용 벡터 데이터
index.pkl 조각의 원문과 출처 정보

둘 다 있어야 동작합니다. 검색은 벡터로 하고, 찾은 뒤 원문을 꺼내 LLM에게 보여 줘야 하니까요.


5. allow_dangerous_deserialization=True — 이게 뭔가요

아래는 code/ch06_rag_agent.py 의 일부입니다 — 위에서 이미 붙여 넣었으니 다시 넣지 마세요.

FAISS.load_local(str(INDEX_DIR), emb, allow_dangerous_deserialization=True)

이름이 무섭습니다. "위험한 역직렬화를 허용한다" 는 뜻이죠.

index.pkl 은 파이썬의 pickle 형식입니다. pickle 파일은 불러올 때 그 안에 든 코드를 실행할 수 있습니다. 그래서 남이 준 pickle 파일을 여는 것은 위험합니다 — 악의적인 코드가 들어 있을 수 있으니까요.

LangChain은 이 위험을 알리려고 명시적으로 허용 표시를 하게 만들었습니다.

우리는 안전합니다. 이 파일은 바로 앞 줄에서 우리가 직접 만든 것이니까요. 인터넷에서 받은 인덱스 파일이라면 이 옵션을 켜기 전에 한 번 더 생각해야 합니다.

5장 7절의 eval 이야기와 같은 종류의 문제입니다 — 남이 만든 것을 실행할 때는 조심한다.


6. 언제 다시 만들어야 하나

인덱스는 만들어진 시점의 문서를 담고 있습니다. 이런 경우 다시 만들어야 합니다.

상황 다시 만들어야 하나
PDF 내용이 바뀌었다 ✓ 반드시
PDF를 추가했다 ✓ 반드시
chunk_size 를 바꿨다 ✓ 반드시
임베딩 모델을 바꿨다 ✓ 반드시
질문만 바꾼다 ✗ 필요 없음
k 를 바꾼다 ✗ 필요 없음

다시 만드는 법은 폴더를 지우는 것입니다.

터미널에서 실행 — 프로젝트 폴더 agentic_ai 에서, (agentic) 표시를 확인한 뒤.

# macOS
rm -rf data/policy_index

# Windows
rmdir /s /q data\policy_index

그리고 다시 실행하면 새로 만들어집니다.

이게 캐시의 함정입니다. 문서를 고쳤는데 인덱스를 안 고치면, 옛날 내용으로 답합니다. 오류도 나지 않아 잘못된 답인지 알아차리기 어렵습니다.

5장 8절의 그 이야기 — 에이전트가 틀리는 방식은 대개 "오류"가 아니라 "오류 없이 나오는 오답" — 이 여기서도 반복됩니다.

실제 서비스에서는 문서가 바뀌면 자동으로 다시 만들도록 합니다. 파일의 수정 시각을 비교하거나, 문서 관리 시스템에서 변경 알림을 받는 식입니다.


7. 인덱스는 어디에 두나

아래는 code/ch06_rag_agent.py 의 일부입니다 — 위에서 이미 붙여 넣었으니 다시 넣지 마세요.

INDEX_DIR = DATA / "policy_index"       # 만들어 둔 인덱스를 보관할 폴더

data/ 안에 두었습니다. 8장에서도 같은 인덱스를 씁니다.

[6장] 인덱스를 만든다
[7장] (RAG는 안 쓰지만 개념이 이어짐)
[8장] ch06_rag_agent 를 import → 인덱스를 불러온다

8장에서 from ch06_rag_agent import policy_tool 을 하면 build_index() 가 다시 실행됩니다. 그때 인덱스가 저장돼 있으면 즉시 불러오고, 없으면 몇십 초를 기다립니다.

그래서 6장에서 저장을 확실히 해 두는 것이 8장을 위한 준비이기도 합니다.


8. 이 패턴은 여기저기 쓰입니다

"비싼 계산은 한 번만 하고 저장한다"는 발상은 RAG에만 있는 게 아닙니다.

상황 캐시하는 것
RAG 임베딩 결과 (이 절)
웹 서비스 자주 쓰는 DB 조회 결과
이미지 처리 썸네일
컴파일 빌드 산출물

공통 함정도 같습니다 — 원본이 바뀌었는데 캐시를 안 지우면 옛날 것이 나옵니다.


스스로 해 보기

  1. data/policy_index 를 지우고 다시 실행해 보세요. 시간을 재 보세요.
    bash rm -rf data/policy_index time python code/ch06_rag_agent.py
    그리고 한 번 더 실행해 시간을 비교하세요.
  2. index.pkl 을 지우고 index.faiss 만 남긴 뒤 실행해 보세요. 어떻게 되나요?
  3. chunk_size200 으로 바꾸고 인덱스를 안 지운 채 실행해 보세요. 조각 수가 달라지나요? 왜 그럴까요?
  4. allow_dangerous_deserialization=True 를 지우고 실행해 보세요. 어떤 오류가 나나요?

3번이 이 절의 핵심 실험입니다. 코드를 고쳤는데 결과가 안 바뀌는 상황을 직접 겪어 보세요.


핵심 정리

  • 인덱스를 파일로 저장해 두면 다음부터는 불러오기만 하면 됩니다.
  • 패턴은 단순합니다 — 있으면 불러오고, 없으면 만들어 저장한다. 이걸 캐시라고 합니다.
  • 저장된 파일은 index.faiss(벡터)index.pkl(원문·출처) 두 개가 짝입니다.
  • allow_dangerous_deserialization=True 는 pickle 파일이 코드를 실행할 수 있어서 붙는 경고입니다. 내가 만든 것만 불러오세요.
  • 문서·chunk_size·임베딩 모델이 바뀌면 반드시 다시 만들어야 합니다. 폴더를 지우면 됩니다.
  • 캐시의 함정 — 원본이 바뀌었는데 안 지우면 오류 없이 옛날 답이 나옵니다.
  • 8장에서 이 인덱스를 그대로 씁니다. 여기서 저장해 두는 것이 8장 준비이기도 합니다.
← 이전 절04. 따라하기 정책 PDF를 잘라 벡터로 만들기다음 절 →06. 지어내지 않게 만드는 한 문장