본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 16. 07:37

LangChain을 이용한 문서 로더(Document loaders) 및 청킹(chunking)

요약

Node.js 환경에서 LangChain을 사용하여 로컬 파일을 로드하고 청킹하는 방법을 다룹니다. Document 객체의 구조와 TextLoader, DirectoryLoader의 사용법, 그리고 정밀한 검색을 위한 문서 분할 전략을 설명합니다.

핵심 포인트

  • LangChain의 Document 객체 구조(pageContent, metadata) 이해
  • TextLoader와 DirectoryLoader를 이용한 파일 인입 방법
  • RAG 성능 향상을 위한 효율적인 청킹(Chunking) 전략
  • chunkSize와 chunkOverlap 파라미터의 중요성

이 포스트는 Node.js에서의 로컬 파일 인입(ingestion) 및 청킹(chunking)을 다룹니다. LangChain 기초(LCEL, 패키지, 에이전트)에 대해서는 LangChain 개요 포스트를 참조하세요. 임베딩(embeddings), pgvector, 그리고 전체 RAG 흐름에 대해서는 pgvector를 이용한 RAG 포스트를 참조하세요. 해당 포스트는 하나의 스플리터(splitter)를 인라인으로 사용하지만, 이 포스트는 로더(loaders)와 스플리터 선택에 대해 더 깊이 있게 다룹니다.

사전 요구 사항 (Prerequisites)

  • Node.js 버전 26
  • langchain, @langchain/core, @langchain/classic, 및 @langchain/textsplitters 설치
npm i langchain @langchain/core @langchain/classic @langchain/textsplitters

더 많은 로더 유형(웹, 클라우드, 오디오)은 독립적인 통합 패키지에 포함되어 있습니다. 문서 로더 통합(document loader integrations) 페이지를 참조하세요.

Document 타입

모든 로더는 @langchain/core로부터 Document 인스턴스를 반환합니다:

  • pageContent - 청크(chunk) 또는 파일의 텍스트
  • metadata - 인용(citations)에 사용되는 선택적 키/값 쌍 (소스 경로, 섹션, 페이지)
import { Document } from '@langchain/core/documents';

const doc = new Document({
...

단일 파일 로드하기

일반 텍스트 또는 마크다운(markdown) 파일에는 TextLoader를 사용하세요:

import { TextLoader } from '@langchain/classic/document_loaders/fs/text';

const loader = new TextLoader('./notes/pgvector.txt');
...

로더는 metadata.source를 파일 경로로 설정합니다. RAG 답변의 인용을 위해 이를 유지하세요.

디렉토리 로드하기

파일이 많은 경우 DirectoryLoader를 사용하세요. 확장자를 로더 팩토리(loader factories)에 매핑합니다:

import { DirectoryLoader } from '@langchain/classic/document_loaders/fs/directory';
import { TextLoader } from '@langchain/classic/document_loaders/fs/text';

...

PDF, CSV, JSON 로더는 다른 통합 패키지를 통해 사용할 수 있습니다. 이 포스트에서는 .txt.md 파일을 사용합니다.

문서 분할하기 (Split documents)

청킹 (Chunking)은 검색 (retrieval)을 더욱 정밀하게 만듭니다. 하나의 커다란 파일을 임베딩 (embedding)하는 대신, 서로 겹치는 작은 부분들로 분할하세요. TextLoader 또는 DirectoryLoader에서 생성된 docs 배열을 스플리터 (splitter)에 전달합니다.

가장 중요한 두 가지 파라미터 (parameter)는 다음과 같습니다:

  • chunkSize - 청크당 목표 최대 크기 (스플리터에 따라 문자 수 또는 토큰 수)
  • chunkOverlap - 경계 부분에서 문맥 (context)이 손실되지 않도록 인접한 청크 간에 공유되는 텍스트 양

chunkSize: 800, chunkOverlap: 120으로 시작한 다음, 문서의 스타일과 답변 품질에 따라 조정하세요.

import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';

const splitter = new RecursiveCharacterTextSplitter({
...

스플리터 비교 (Splitter comparison)

위의 예제는 대부분의 RAG 설정에서 기본으로 사용되는 RecursiveCharacterTextSplitter를 사용합니다. 대안은 다음과 같습니다:

스플리터 (Splitter)최적의 용도
RecursiveCharacterTextSplitter기본 선택지; 단락, 문장, 단어 순으로 시도함
...

문자 기반 (Character-based):

import { CharacterTextSplitter } from '@langchain/textsplitters';

const splitter = new CharacterTextSplitter({
...

토큰 기반 (Token-based):

import { TokenTextSplitter } from '@langchain/textsplitters';

const splitter = new TokenTextSplitter({
...

청크가 모델의 컨텍스트 윈도우 (context window) 내에 반드시 들어와야 하는 경우에는 토큰 기반 분할을 사용하세요. 산문 (prose)에 대한 RAG를 구현할 때는 문자 기반 재귀적 분할 (character-based recursive splitting)이 일반적인 시작점입니다.

파이프라인을 통한 메타데이터 (Metadata through the pipeline)

문서를 수동으로 생성할 때 메타데이터를 전달하거나, 로더 (loader)의 메타데이터에 의존하세요. 스플리터는 각 청크에 메타데이터를 보존합니다:

const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: 400,
  chunkOverlap: 60
...

splitDocuments(docs)를 실행한 후, 각 청크는 부모 문서로부터 source와 같은 필드를 유지합니다. 청크를 벡터 데이터베이스 (vector database)에 저장하거나 인용 (citation)을 표시할 때 이러한 필드를 사용하세요.

파라미터 선택하기 (Choosing parameters)

  • 짧은 FAQ 또는 API 문서 - 정밀한 검색 (retrieval)을 위해 더 작은 chunkSize (300–500) 사용
  • 긴 가이드 또는 블로그 포스트 - 섹션을 하나로 유지하기 위해 더 큰 chunkSize (800–1200) 사용
  • 더 많은 중첩 (More overlap) - 답변이 청크 경계에 걸쳐 있을 때 도움이 되지만, 저장 공간 및 임베딩 (embedding) 비용을 증가시킴
  • 더 적은 중첩 (Less overlap) - 중복되는 청크가 줄어들지만, 분할 지점에서 문맥 (context)을 잃을 위험이 있음

사용자의 도메인에서 발생하는 실제 질문들을 통해 튜닝하세요.

데모 (Demo)

이 포스트를 위한 Runnable 로더 및 스플리터 (splitter) 스크립트는 langchain-loaders-chunking-demo 폴더에 있습니다. 코드 데모를 통해 확인하세요.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0