LangChain `SemanticChunker` 사용 시 `AttributeError` 해결 과정 (feat. Wrapper 클래스)

문건희·2025년 8월 30일

제목: LangChain SemanticChunker 사용 시 AttributeError 해결 과정 (feat. Wrapper 클래스)

태그: LangChain, SemanticChunker, SentenceTransformer, AttributeError, HuggingFaceEmbeddings


1. 들어가며: 문제 상황 겪기

최근 RAG(Retrieval-Augmented Generation) 파이프라인의 성능을 높이기 위해, LangChain에서 제공하는 SemanticChunker를 도입하는 과정에서 흥미로운 오류를 만났습니다.

의미 기반으로 텍스트를 분할하기 위해 sentence-transformers 라이브러리로 한국어 임베딩 모델을 불러와 SemanticChunker에 전달했는데, 아래와 같은 에러가 발생했습니다.

AttributeError: 'SentenceTransformer' object has no attribute 'embed_documents'

분명 임베딩 모델 객체를 넘겨줬는데, 왜 embed_documents라는 속성이 없다는 오류가 발생했을까요? 이 글에서는 이 문제의 원인을 분석하고, LangChain의 아키텍처를 이해하며 어떻게 해결했는지 그 과정을 공유하고자 합니다.

2. 오류 발생 코드

문제를 일으켰던 코드는 다음과 같습니다. sentence-transformers로 모델을 로드하여 SemanticChunkerembeddings 인자로 바로 전달했습니다.

from sentence_transformers import SentenceTransformer
from langchain_experimental.text_splitter import SemanticChunker

# 1. sentence-transformers로 임베딩 모델 직접 로드
model_name = "snunlp/KR-SBERT-V40K-klueNLI-augSTS"
embedding_model = SentenceTransformer(model_name)

# 2. SemanticChunker에 그대로 전달
text_splitter = SemanticChunker(
    embeddings=embedding_model, #
    breakpoint_threshold_type="percentile" 
)

# 3. 문서 생성 시도 -> AttributeError 발생!
chunks = text_splitter.create_documents([full_text])

3. 오류의 원인 분석: API 호환성 문제

결론부터 말하면, 이 문제는 **LangChain이 기대하는 '표준 인터페이스'**와 sentence-transformers 라이브러리가 제공하는 객체의 인터페이스가 달라서 발생했습니다.

마치 전기 콘센트와 플러그의 모양이 맞지 않는 것과 같습니다.

**SemanticChunker (콘센트)**는 LangChain 생태계의 부품으로, embed_documents라는 이름의 메소드('세모 모양 플러그')를 가진 임베딩 객체를 받도록 설계되어 있습니다.

**SentenceTransformer 객체 (전자제품)**는 encode라는 메소드('동그란 모양 플러그')를 통해 문장을 임베딩합니다.

SemanticChunkerembedding_model.embed_documents()를 호출하려고 했지만, 실제 객체에는 embed_documents가 없고 encode만 있으니 AttributeError가 발생한 것입니다.

4. 해결 방법: LangChain 래퍼(Wrapper) 클래스 사용하기

LangChain은 이런 문제를 해결하기 위해 외부 라이브러리를 LangChain 표준에 맞게 감싸주는 래퍼(Wrapper) 클래스를 제공합니다. sentence-transformers를 위한 래퍼가 바로 **HuggingFaceEmbeddings**입니다.

HuggingFaceEmbeddings는 내부에 SentenceTransformer 모델을 품고, 외부에는 LangChain이 알아볼 수 있는 embed_documents 메소드를 노출시켜주는 '모양 변환 어댑터' 역할을 합니다.

수정된 코드

# langchain_community에서 어댑터 역할을 할 래퍼 클래스를 임포트
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_experimental.text_splitter import SemanticChunker

# 1. 사용할 모델 이름 정의
model_name = "snunlp/KR-SBERT-V40K-klueNLI-augSTS"

# 2. SentenceTransformer 대신 HuggingFaceEmbeddings 래퍼 사용
# 이제 embedding_model은 LangChain 표준을 따르는 객체가 됩니다.
embedding_model = HuggingFaceEmbeddings(model_name=model_name)

# 3. SemanticChunker에 호환되는 객체 전달
text_splitter = SemanticChunker(
    embeddings=embedding_model,
    breakpoint_threshold_type="percentile" 
)

# 4. 정상적으로 실행됨!
chunks = text_splitter.create_documents([full_text])

print("성공적으로 청킹 완료!")

5. 결론 및 핵심 요약

이번 오류 해결 과정을 통해 다음과 같은 중요한 점을 배울 수 있었습니다.

LangChain과 같은 프레임워크는 단순히 기능의 집합이 아니라, 정해진 '약속(Interface)'에 따라 각 부품이 유기적으로 연결되는 시스템이다.

외부 라이브러리를 LangChain과 연동할 때는, 해당 라이브러리를 직접 사용하기보다 LangChain이 제공하는 래퍼 클래스가 있는지 먼저 확인하는 습관을 들이는 것이 좋습니다. 이 래퍼들이 바로 서로 다른 모양의 플러그와 콘센트를 연결해주는 고마운 '어댑터'이기 때문입니다.

혹시 저와 같은 AttributeError를 만나신 분들께 이 글이 도움이 되기를 바랍니다.

0개의 댓글