k
korAI
중급 전체
중급2026-05-316분

AI가 '모른다'고 할 때 — RAG로 내 데이터를 직접 먹이는 법

모델의 학습 데이터 한계를 넘어, 사내 문서나 최신 정보를 실시간으로 Claude에 주입하는 RAG 패턴을 단계별로 익힙니다.

RAGretrievalcontext-injection

RAG가 필요한 순간

Claude는 학습 컷오프 이후의 사실을 모르고, 회사 내부 문서에는 더더욱 접근할 수 없습니다. Retrieval-Augmented Generation(RAG) 은 이 한계를 우회하는 가장 실용적인 방법입니다. 사용자의 질문과 관련된 문서 조각을 검색해 프롬프트에 삽입하면, 모델은 그 맥락을 바탕으로 답변을 생성합니다.

RAG의 핵심 공식: 검색(Retrieve) → 주입(Augment) → 생성(Generate)


1단계 — 컨텍스트 주입 구조 잡기

가장 단순한 RAG는 외부 검색 결과를 user 메시지 앞에 붙이는 것입니다. 아래는 TypeScript로 구현한 기본 패턴입니다.

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

// 실제 환경에서는 벡터 DB(예: Pinecone, pgvector)에서 가져옵니다
function retrieveRelevantChunks(query: string): string[] {
  // 예시: 사내 FAQ 문서 조각
  return [
    "[출처: 사내규정 v2.3] 연차는 입사 1년 후 15일이 부여됩니다.",
    "[출처: HR공지 2026-04] 2026년부터 반차 단위는 2시간으로 변경됩니다.",
  ];
}

async function ragQuery(userQuestion: string): Promise<string> {
  const chunks = retrieveRelevantChunks(userQuestion);

  const context = chunks
    .map((chunk, i) => `[문서 ${i + 1}] ${chunk}`)
    .join("\n");

  const response = await client.messages.create({
    model: "claude-haiku-4-5",
    max_tokens: 1024,
    system:
      "당신은 사내 HR 어시스턴트입니다. 반드시 제공된 문서를 근거로만 답변하고, " +
      "문서에 없는 내용은 '문서에서 확인할 수 없습니다'라고 명시하세요.",
    messages: [
      {
        role: "user",
        content:
          `## 참고 문서\n${context}\n\n## 질문\n${userQuestion}`,
      },
    ],
  });

  const content = response.content[0];
  return content.type === "text" ? content.text : "";
}

// 실행
(async () => {
  const answer = await ragQuery("2026년 반차는 몇 시간 단위로 쓸 수 있나요?");
  console.log(answer);
})();

2단계 — 컨텍스트 품질이 답변 품질을 결정한다

RAG에서 흔히 저지르는 실수는 관련 없는 문서를 너무 많이 넣는 것입니다. 모델은 노이즈가 많을수록 핵심을 놓칩니다.

| 전략 | 설명 | 효과 | |------|------|------| | Top-K 제한 | 유사도 상위 3~5개 청크만 사용 | 토큰 절약, 정확도 향상 | | 출처 명시 | 각 청크에 [출처: ...] 태그 부착 | 환각 감지 용이 | | 청크 크기 조정 | 200~500 토큰 단위로 분할 | 검색 정밀도 향상 | | 시스템 프롬프트 제약 | "문서 외 답변 금지" 명시 | 할루시네이션 억제 |


3단계 — RAG 도입 전 체크해야 할 것들

  • [ ] 검색 소스가 정기적으로 업데이트되는가? (stale data 위험)
  • [ ] 청크 분할 시 문장/단락 경계를 지키고 있는가?
  • [ ] 시스템 프롬프트에 "문서 기반 답변" 제약을 명시했는가?
  • [ ] 검색 결과가 0건일 때의 폴백(fallback) 처리가 있는가?
  • [ ] 민감 문서가 포함되는 경우 접근 권한 필터링을 했는가?
  • [ ] 답변에 출처(문서 번호/파일명)를 표시해 검증 가능하게 했는가?