이번 시간에는 AI가 답변을 생성하는 과정에서 어떤 작업이 수행되었는지, 그리고 답변에 문제가 발생했을 경우 어느 단계에서 어떤 오류가 발생했는지 추적하고 분석하는 방법을 알아보겠습니다.
이를 위해 LLM 애플리케이션의 동작을 관찰하고 분석할 수 있도록 도와주는 LLM Observability의 개념과 필요성에 대해 살펴보겠습니다.
Evaluation(평가) vs Observability(관측 가능성)
: AI Agent 개발에서 "잘 동작하는가?"를 확인하는 것은 단순 모델 응답 확인 이상을 의미합니다.
기존 RAG 시스템이 검색 및 답변 생성의 결과 품질(RAGAS 등) 위주로 평가했다면, AI Agent는 도구(Tool) 선택, 호출 매개변수(Arguments), 실행 순서 등 과정 전체가 평가 대상이 됩니다.
┌──────────────────────────────────────────────────────────┐
│ Evaluation │
│ "이 결과(답변/검색)의 점수가 좋은가, 나쁜가?" (점수 판정) │
└────────────────────────────┬─────────────────────────────┘
│ (점수가 낮은 원인을 추적하려면?)
▼
┌──────────────────────────────────────────────────────────┐
│ Observability │
│ "어떤 실행 과정(Trace)을 거쳐 이 결과가 나왔는가?" (과정 관측) │
└──────────────────────────────────────────────────────────┘
기존 백엔드 Observability로는 부족한가?
: 전통적인 Web/API 서버 분야에서는 Logs, Metrics, Traces를 통해 시스템 상태를 관측해 왔습니다.
200 OK, 500 Server Error), Latency, CPU/Memory 사용량, DB Latency.200 OK여도 서비스는 실패할 수 있습니다.ex)
200 OK)이었으나, 전혀 연관 없는 문서를 가져온 경우⇒ 따라서 LLM Observability는 기존 시스템 지표 외에 프롬프트, 모델 파라미터, 토큰 수, 검색 쿼리, Tool Arguments, Agent Step 등을 추가로 관측해야 합니다.
LLM Observability에서 관측해야 하는 정보
| 영역 | 관측 항목 | 확인하려는 문제 |
|---|---|---|
| Request | 사용자 입력, 세션, 시간 | 어떤 요청에서 문제가 발생했는가? |
| Prompt | System Prompt, User Prompt, 버전 | 프롬프트 변경이 원인이었는가? |
| Model | Provider, Model Name, Parameter | 특정 모델 또는 설정의 문제인가? |
| Token / Cost | Input Token, Output Token, 요청 비용 | 비용과 Context 사용량이 증가했는가? |
| Latency | 전체·모델·Tool·검색 시간 | 어느 단계가 느린가? |
| Retrieval | Query, 문서, Score | 검색 결과가 적절했는가? |
| Tool | 이름, 인자, 결과, 오류 | 올바른 도구를 올바른 인자로 호출했는가? |
| Agent Step | 단계 수, 반복 횟수, 종료 이유 | 불필요한 Loop가 있었는가? |
| Output | 최종 답변, 종료 사유 | 어떤 답변이 사용자에게 전달되었는가? |
| Evaluation | Correctness, Groundedness, Safety, Feedback | 결과의 품질은 어떠한가? |
LLM Observability의 핵심 단위: Trace, Span, Run, Step
Trace란 무엇인가
: Trace는 사용자 요청 하나가 시스템 내부에서 어떤 경로로 처리되었는지를 기록한 전체 실행 기록입니다. 전통적인 애플리케이션에서 하나의 HTTP 요청이 API Handler, Database, External API를 거치는 경로를 추적하는 것과 비슷합니다.
→ Trace: 사용자 요청 1건이 들어와서 최종 답변이 나갈 때까지의 전체 실행 파이프라인 기록.
[Trace: 하나의 사용자 요청 전체 실행 기록]
├── Span 1: Prompt Construction (프롬프트 조립)
├── Span 2: Vector Search / Retrieval (문서 검색)
├── Span 3: Agent Decision / Tool Call (주문 조회 도구 실행)
├── Span 4: LLM Generation (최종 답변 생성)
└── Span 5: Guardrail Check (안전성 검증)
Span 또는 Run이란?
: Trace가 전체 요청이라면 Span 또는 Run은 Trace 안의 개별 작업 기록입니다. 예를 들어 하나의 Trace 안에 Prompt 구성 Span, Retrieval Span, Tool 호출 Span, LLM 호출 Span이 들어갈 수 있습니다.
Step이란?
Step은 Agent가 한 번 판단하고 행동한 단위입니다. Tool 하나를 호출한 단계, Observation을 읽고 재판단한 단계, 최종 답변을 결정한 단계가 각각 Step이 될 수 있습니다.
& Step 정보를 통해 아래 문제를 파악할 수 있습니다.
| 문제 | 확인할 항목 |
|---|---|
| Tool을 호출하지 않음 | 기대한 Tool Span의 부재 |
| Tool을 너무 많이 호출함 | Step Count, Loop Count |
| 잘못된 순서로 호출함 | Span의 시간순 배열 |
| 종료하지 못함 | Max Step 도달, Stop Reason |
| 특정 단계가 느림 | 각 Step의 Latency |
실전 사례 분석: 야구 Agent의 Trace 실패 사례
: Trace 분석 도구(LangSmith, LangFuse 등)로 실행 기록을 열어보면, 서버는 정상 응답했지만 Agent의 중간 상태 관리가 실패한 것을 확인할 수 있습니다.
# Trace ID: baseball_agent_run_042
User Input 1: "롯데 오늘 야구 일정 알려줘"
Step 1 (Router LLM Call):
output:
should_call_tool: true
tool_name: find_kbo_game
args:
team_id: LOTTE
date: 2026-08-16
Step 2 (Tool Call):
tool: find_kbo_game
args:
team_id: LOTTE
date: 2026-08-16
result:
total: 1
games:
- away_team_name: NC
home_team_name: 롯데
stadium_id: SAJIK
stadium_name: 사직
game_date: 2026-08-16
start_time: "18:00"
Step 3 (State Update):
expected:
selected_game:
stadium_name: 사직
home_team_name: 롯데
away_team_name: NC
actual:
selected_game: null
User Input 2: "어디서 경기하는거야?"
Step 4 (Router LLM Call):
input_context:
selected_game: null
output:
should_call_tool: false
needs_clarification: true
clarification_reason: team_required_for_schedule_lookup
Step 5 (LLM/Answer Call):
output: "어느 팀 경기인지 알려주시면 경기 장소를 확인해드릴게요."
selected_game으로 승격되지 않아 후속 질문 context가 사라짐."어디서"가 직전 경기 장소를 묻는 질문인데, 독립적인 경기 조회 질문처럼 처리됨.find_kbo_game 결과가 1건이면 반드시 selected_game에 저장"어디서", "경기장", "구장", "거기" 포함 시 selected_game.stadium_name 우선 사용Metrics: 운영 상태를 수치로 파악하기
| Metric (지표) | 설명 | 모니터링 목적 및 비유 |
|---|---|---|
| TTFT (Time To First Token) | 첫 번째 토큰이 출력되기까지 걸린 시간 | 체감 속도 평가 (웹페이지 로딩 속도와 유사) |
| Total Latency | 전체 요청부터 최종 응답까지의 소요 시간 | 전체 UX 품질 평가 |
| Token Usage & Cost | 요청당 Input/Output 토큰 수 및 발생 비용 | 운영 예산 관리 및 비용 최적화 |
| Step Count | Agent가 한 답변을 내기 위해 거친 루프 횟수 | 무한 루프(Infinite Loop) 발생 여부 감지 |
| Error Rate | LLM API, Retrieval, Tool 호출 실패율 | 시스템 안정성 모니터링 |
| Quality Score | Correctness, Groundedness 등의 자동 평가 점수 | 실시간 답변 품질 추세 파악 |
& Cost vs Quality의 트레이드오프
: 완벽한 Agent Trace는 필수 Tool을 여러 번 호출하므로 단발성 답변보다 Latency(응답시간)와 Cost(비용)가 증가합니다. Observability는 무조건 비용을 줄이는 것이 아니라, ‘비용 상승 대비 답변 정확도 증가가 타당한가’를 판단하는 기준을 제공합니다.
| 관점 | 핵심 질문 |
|---|---|
| 품질 | 답변이 정확하고 근거가 충분한가? |
| 비용 | 요청 하나당 비용이 감당 가능한가? |
| 속도 | 사용자가 기다릴 수 있는 시간인가? |
| 안정성 | 실패율과 중단율이 낮은가? |
| 안전성 | 민감정보와 위험한 행동을 통제하는가? |
Observability 도입 시 주의사항: 데이터 보안 및 Privacy
Trace 데이터를 상세하게 남길수록 디버깅은 쉬워지지만, 보안 및 민감 정보 유출 위험이 크게 높아집니다.
Trace에 남는 위험 데이터
설계 시 결정해야할 항목
Masking / PII Anonymization: Trace 수집 단계에서 개인정보 자동 마스킹 처리.
Access Control (접근 제어): Trace 로그를 조회할 수 있는 엔지니어 권한 관리.
Retention Policy (보관 기간): 일정 기간(예: 30일) 경과 후 Trace 자동 파기.
Dataset 변환 시 익명화: 실패한 Trace를 테스트 데이터셋으로 전환할 때 식별 가능한 정보 제거.
| 결정 항목 | 검토 질문 |
|---|---|
| 저장 필드 | 이 필드가 실제 디버깅에 필요한가? |
| 마스킹 | 이름·전화번호·주소·결제정보를 가릴 것인가? |
| Prompt 저장 | 원문 전체 대신 버전·해시·일부 샘플만 저장할 수 있는가? |
| Context 저장 | 내부 문서 원문을 저장해도 되는가? |
| 보관 기간 | Trace를 며칠 또는 몇 개월 보관할 것인가? |
| 접근 권한 | 누가 Trace를 읽고 다운로드할 수 있는가? |
| Dataset 변환 | 실패 Trace를 테스트 데이터로 옮길 때 익명화했는가? |
| 감사 기록 | 누가 어떤 Trace를 조회했는가? |
실무 적용을 위한 최소 설계안
Step1 ) 요청 식별자 연결
모든 요청에 trace_id, session_id, user_id 또는 익명화된 사용자 식별자를 연결합니다. 서로 다른 로그와 Span을 하나의 요청으로 묶을 수 있어야 합니다.
Step2 ) 핵심 실행 기록 수집
사용자 요청
사용한 모델과 Prompt 버전
Retrieval Query와 문서 식별자
Tool 이름과 인자
각 단계의 시작·종료 시각
최종 답변과 종료 사유
Step3 ) 운영 지표 집계
Latency, Token, Cost, Error Rate, Step Count를 요청 단위와 일·시간 단위로 집계합니다. 특정 배포 이후 어느 지표가 변했는지 확인할 수 있어야 합니다.
Step4 ) 품질 평가 연결
Correctness, Groundedness, Safety, User Feedback을 Trace에 연결합니다. 점수가 낮은 Trace를 바로 열어 실행 과정을 확인할 수 있어야 합니다.
Step5 ) 마스킹과 접근제어 적용
개인정보와 내부 문서를 분류하고, 저장 전 마스킹하거나 접근 권한을 제한합니다. 보관 기간과 삭제 절차도 정합니다.
Tip) Trace를 읽는 사고방식
→ Trace를 볼 때는 최종 답변부터 비난하기보다 다음 순서로 원인을 좁히는 것이 좋습니다.
→ 해당 순서를 따르면 문제를 Prompt 문제, Retrieval 문제, Tool 문제, 모델 문제, 실행 제어 문제로 분류하기 쉽습니다.
1. 입력이 정상적으로 들어왔는가?
2. 필요한 Prompt와 Context가 구성되었는가?
3. Retrieval Query가 질문의 핵심을 반영했는가?
4. 관련 문서가 검색되었고 score가 충분했는가?
5. Agent가 필요한 Tool을 모두 호출했는가?
6. Tool 인자와 호출 순서가 적절했는가?
7. Observation을 다음 판단에 반영했는가?
8. 모델이 제공된 근거를 사용했는가?
9. Guardrail과 종료 조건이 정상 작동했는가?
10. 비용·Latency·반복 횟수는 허용 범위인가?
정리

LangSmith Observability