LangSmith로 체인 디버깅·추적하기
· LangSmith는 LangChain으로 만든 체인·에이전트가 내부에서 실제로 무엇을 주고받았는지 그대로 기록·추적해 주는 관측(observability) 도구입니다.
· 환경 변수 몇 개만 켜 두면 프롬프트 완성본, 모델 응답, 토큰·지연 시간, 중간 단계가 자동으로 대시보드에 쌓여, "왜 이런 답이 나왔는지"를 눈으로 따라갈 수 있습니다.
· 디버깅뿐 아니라 입력-출력 쌍을 모아 데이터셋·평가(evaluation)로 발전시킬 수 있어, 체인을 꾸준히 개선하는 토대가 됩니다.
체인을 몇 줄로 엮어 돌리면 결과는 금방 나옵니다. 그런데 막상 엉뚱한 답이 나왔을 때가 문제예요. 프롬프트에 변수가 제대로 채워졌는지, 모델이 받은 최종 문장이 무엇이었는지, 중간 단계에서 어디가 틀어졌는지 겉으로는 보이지 않기 때문입니다. 오늘은 이렇게 보이지 않던 체인 내부를 그대로 들여다보게 해 주는 LangSmith를 차근차근 살펴보겠습니다.
🧩 체인은 왜 디버깅하기 어려울까
LangChain의 체인은 프롬프트 → 모델 → 출력 파서처럼 여러 조각이 파이프로 연결된 흐름입니다. 편리한 만큼, 문제가 생겨도 중간 과정이 눈에 보이지 않는다는 단점이 있어요. 우리가 보는 건 맨 앞의 입력과 맨 뒤의 출력뿐이고, 그 사이에서 벌어진 일은 블랙박스처럼 가려져 있습니다.
그래서 예상과 다른 답이 나오면 print를 여기저기 끼워 넣어 보지만, 이 방법은 금세 한계에 부딪힙니다. 특히 에이전트처럼 모델이 스스로 도구를 여러 번 호출하는 구조에서는, 어떤 순서로 무엇을 호출했는지 로그만으로 재구성하기가 쉽지 않습니다.
디버깅의 핵심은 "모델에게 실제로 전달된 최종 입력"과 "각 단계가 주고받은 중간 값"을 그대로 보는 것입니다. 추측이 아니라 기록으로요.
🔍 LangSmith가 보여 주는 것
LangSmith는 LangChain 팀이 만든 관측(observability) 플랫폼입니다. 체인이 실행될 때마다 그 과정을 트레이스(trace)라는 단위로 자동 기록하고, 웹 대시보드에서 하나씩 펼쳐 볼 수 있게 해 줍니다. 대략 다음과 같은 정보가 담깁니다.
중요한 점은, 이 모든 기록이 코드를 거의 고치지 않아도 쌓인다는 것입니다. LangChain 내부가 각 단계를 실행할 때 알아서 트레이스를 남기도록 설계돼 있기 때문이에요.
⚙️ 환경 변수로 추적 켜기
LangSmith를 켜는 가장 간단한 방법은 환경 변수 몇 개를 설정하는 것입니다. 코드 로직은 그대로 두고, 실행 환경에만 "추적을 켜라"고 알려 주는 방식이에요. 보통 다음 값을 지정합니다.
# 추적 기능을 켠다
export LANGSMITH_TRACING=true
# LangSmith에서 발급받은 API 키
export LANGSMITH_API_KEY="발급받은_키"
# 기록을 모아 둘 프로젝트 이름(없으면 기본 프로젝트로)
export LANGSMITH_PROJECT="my-first-trace"
이렇게 설정한 뒤에는 평소 쓰던 체인 코드를 그대로 실행하기만 하면 됩니다. 별도의 기록용 코드를 끼워 넣을 필요가 없어요.
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
prompt = ChatPromptTemplate.from_messages([
("system", "너는 간결하게 답하는 비서야."),
("human", "{question}"),
])
chain = prompt | ChatOpenAI(model="gpt-4o-mini") | StrOutputParser()
# 이 호출이 자동으로 LangSmith에 트레이스로 기록된다
answer = chain.invoke({"question": "에베레스트의 높이는?"})
print(answer)
실행이 끝나면 LangSmith 대시보드의 해당 프로젝트에 방금 실행이 하나의 트레이스로 나타납니다. 환경 변수만 껐다 켜는 것으로 개발 중에는 추적을 켜고, 필요 없을 땐 끄는 전환도 간단합니다.
🪜 트레이스(trace) 읽는 법
대시보드에서 트레이스 하나를 열면, 체인이 거친 단계가 트리 구조로 펼쳐집니다. 각 항목이 무엇을 뜻하는지 간단히 정리하면 다음과 같습니다.
| 단계 유형 | 무엇을 담고 있나 |
|---|---|
| Chain | 전체 흐름을 감싸는 상위 단계. 하위 단계들을 품고 있습니다. |
| Prompt | 변수가 채워져 완성된 최종 프롬프트를 보여 줍니다. |
| LLM | 모델에 넘긴 입력과 받은 응답, 토큰·지연 시간이 기록됩니다. |
| Parser | 출력 파서가 모델 응답을 어떤 형태로 바꿨는지 보여 줍니다. |
| Tool | 에이전트가 호출한 도구와 그 입력·결과가 담깁니다. |
디버깅할 때 가장 먼저 볼 곳은 보통 Prompt 단계입니다. 여기서 모델에게 실제로 전달된 문장을 확인하면, 변수가 비었거나 엉뚱한 값이 들어간 문제를 한눈에 잡아낼 수 있어요. 그다음 LLM 단계에서 모델의 날것 그대로의 응답을 보면, 문제가 입력 탓인지 모델 탓인지 가릴 수 있습니다.
📈 추적에서 평가로 이어 가기
LangSmith가 단순한 로그 뷰어에 그치지 않는 이유는, 쌓인 기록을 품질을 다듬는 재료로 쓸 수 있기 때문입니다. 실행하며 모인 입력-출력 쌍 중 좋은 예를 모으면 데이터셋(dataset)이 되고, 이 데이터셋을 기준 삼아 체인을 바꿔 가며 평가(evaluation)할 수 있습니다.
예를 들어 프롬프트 문구를 손봤을 때, 같은 입력 묶음에 대해 이전 버전과 새 버전의 답을 나란히 비교하는 식입니다. "느낌상 좋아졌다"가 아니라, 같은 질문에 어떻게 달라졌는지를 기록으로 확인하며 개선할 수 있다는 뜻이에요.
추적은 "지금 왜 이렇게 됐나"를 보는 일이고, 평가는 "바꾼 게 정말 나아졌나"를 확인하는 일입니다. LangSmith는 이 둘을 같은 기록 위에서 이어 줍니다.
🔧 실무 팁
- 프로젝트 이름을 나눠라 —
LANGSMITH_PROJECT를 기능이나 실험별로 다르게 주면, 트레이스가 섞이지 않아 나중에 찾기 쉽습니다. - 먼저 볼 곳은 Prompt 단계 — 엉뚱한 답이 나오면 모델을 의심하기 전에, 모델에게 간 최종 입력부터 확인하는 습관이 좋습니다.
- 민감 정보에 주의 — 입력·출력이 그대로 기록되므로, 개인정보나 비밀 값이 흘러 들어가지 않도록 신경 써야 합니다.
- 운영 환경에서는 선택적으로 — 모든 호출을 추적하면 부담이 될 수 있어, 환경 변수로 필요한 구간만 켜 두는 방식을 고려하세요.
❓ 자주 묻는 질문 (FAQ)
Q. LangSmith를 쓰려면 코드를 많이 고쳐야 하나요?
A. 대부분은 환경 변수 설정만으로 충분합니다. LangChain 내부가 각 단계를 실행하며 자동으로 트레이스를 남기기 때문에, 기존 체인 코드를 그대로 두고도 기록이 쌓입니다.
Q. LangChain을 안 쓰는 코드도 추적할 수 있나요?
A. 네. 일반 함수에 추적용 데코레이터를 붙이는 방식도 제공돼, LangChain 바깥의 호출도 트레이스로 남길 수 있습니다. 다만 가장 손쉬운 건 역시 LangChain과 함께 쓰는 경우입니다.
Q. 그냥 print 로그와 무엇이 다른가요?
A. print는 흩어진 텍스트에 그치지만, LangSmith는 단계들을 트리 구조로 연결하고 토큰·지연 시간까지 함께 보여 줍니다. 게다가 기록을 모아 데이터셋·평가로 이어 갈 수 있다는 점이 크게 다릅니다.
마무리
정리하면, LangSmith는 보이지 않던 체인 내부를 트레이스로 드러내 주는 관측 도구입니다. 환경 변수 몇 개만 켜 두면 완성된 프롬프트, 모델 응답, 토큰·지연 시간, 중간 단계가 자동으로 기록돼, "왜 이런 답이 나왔는지"를 추측이 아니라 기록으로 따라갈 수 있습니다. 나아가 쌓인 입력-출력을 데이터셋과 평가로 발전시키면, 체인을 손볼 때마다 정말 나아졌는지 확인하며 꾸준히 개선할 수 있어요. 다음 편에서는 여러 체인을 상황에 따라 갈라서 연결하는 분기·라우팅 이야기로 이어가 보겠습니다.
댓글
댓글 쓰기