Agent가 20초 멈췄다면 — Trace와 Span으로 여는 관측성
← 전체 목차 · 이전: AI 숏드라마 캐릭터가 계속 변하는 이유 — 프롬프트가 아니라 자산 관리 · 다음: Agent 평가의 핵심 기준 — Outcome과 Trajectory
Agent 시스템은 천연의 블랙박스다. 사용자에게 던져줄 최종 답변만 기록하면 중간 과정은 영원히 사라지고, 문제가 생겼을 때 시간이 어디에 쓰였는지조차 말할 수 없다.
사용자가 프런트엔드에서 20초를 기다리는 동안 백엔드에서는 이런 일이 벌어졌을 수 있다.
| 백엔드 동작 | 횟수 |
|---|
| 대규모 모델 호출 | 3회 |
| 외부 도구 재시도 | 2회 |
| Handoff (다른 Agent 또는 사람에게 인계) | 1회 |
사용자가 체감한 "하나의 대기"는 시스템 내부에서는 여러 이기종 단계의 중첩이다.
Trace와 Span
- Trace — 한 번의 엔드 투 엔드 완전한 작업. 비유하면 한 편의 완결된 다큐멘터리.
- Span — 그 다큐멘터리의 각 장면으로, 작업 안에서 독립적으로 측정 가능한 모든 작은 단계를 나타낸다.
Span의 예시:
- 대규모 모델이 텍스트 한 단락을 생성했다
- Agent가 날씨 API를 한 번 호출했다
- 지식 베이스에서 검색을 한 번 했다
- Guardrail, 즉 안전 가드레일 차단이 발동했다
- 심지어 "사람의 개입을 그냥 기다리고 있었다"
5번이 핵심적인 반직관 지점이다. 대기 자체도 독립된 Span이 되어야 소요 시간을 귀속시킬 수 있다.
장면만으로는 부족하고 "편집 논리"가 있어야 한다
Span들은 인과 관계로 고리처럼 이어져야 리플레이를 보듯 이 사슬을 복원할 수 있다.
결정 → 동작 → 결과 → 다음 라운드 추론
↑ │
└──────── 인과 관계로 연결 ──────┘
복원해야 할 질문은 둘이다. 당시 어떤 결정을 내렸기에 이어지는 동작이 발동되었는가, 그리고 그 동작이 만든 결과가 어떻게 Agent를 다음 라운드 추론으로 이끌었는가.
Span 하나에 기록할 필드
| 필드 | 설명 |
|---|
| 작업 ID | 이번 작업의 식별자 |
| Agent | 지금 어느 Agent가 일하고 있는가 |
| 도구 | 어떤 도구를 썼는가 |
| 모델 버전 | 호출한 모델의 구체적 버전 |
| 시작 / 종료 시각 | 기간 |
| 최종 상태 | 작업 결과 상태 |
| 재시도 여부 | 중간에 재시도가 있었는가 |
| Token 소모 | 얼마나 소모했는가 |
| 입력 / 출력 요약 | 가장 핵심적인 항목 |
기록은 기록이고 프라이버시 레드라인은 넘지 않는다
자신의 디버깅 편의를 위해 사용자 프라이버시나 회사 기밀을 통째로 로그에 복사해 넣으면 절대 안 된다. 민감한 내용을 만나면 세 가지 중 하나다.
- 성실하게 마스킹 처리
- 해시값만 저장
- 데이터 참조 링크를 대신 둔다
무엇을 얻는가: 인과 위치 파악
"외부 도구 호출 실패"를 예로 들면, 이 메커니즘이 없으면 캄캄하지만 있으면 실패가 어느 부류인지 한눈에 보인다.
외부 도구 호출 실패
├── 대규모 모델이 생성한 파라미터 포맷이 틀림 (모델 측 문제)
├── 시스템 권한이 차단함 (정책/권한 측 문제)
├── 단순한 네트워크 타임아웃 (링크 측 문제)
└── 하류 업무 시스템이 요청을 직접 거절함 (하류 측 문제)
전역 연관 ID: 지연 귀속과 실행 사슬 재구성
로그 연관을 보면 사람의 확인 대기에서 막혔다는 것을 조회할 수 있다. 전역 연관 ID로 단계들을 꿰지 않으면 당시의 실행 사슬을 아예 재구성할 수 없다.
소요 시간 폭포 그래프에서 모델 생성(LLM) → 큐 대기(Queue) → 사람 확인(Human) 중 가장 긴 것이 바로 "사람 확인"인 경우가 흔하다. 전역 연관 ID는 Span을 Trace로 꿰는 물리적 수단이고, Trace ID는 트러블슈팅 시의 입구다.
관측성은 "출력문 두 줄 더 쓰기"가 아니다
초기 목표 → 결정과 행동 → 최종 결과
각 단계마다 「연속되고 쇠처럼 단단한 증거」로 추적 가능
미래의 Agent는 점점 더 똑똑해지고 자율적이 될 것이다. 자율적일수록 개발팀은 그것이 어떻게 한 걸음씩 최종 답변에 이르렀는지를 더 분명히 알아야 한다.
핵심 통찰
- 사용자가 체감한 "한 번의 대기"는 시스템 내부에서 여러 이기종 단계의 중첩이다 — 20초는 사용자에게 숫자 하나지만 백엔드에서는 모델 호출 3회 + 도구 재시도 2회 + Handoff 1회다. "요청 총 소요 시간"이라는 하나의 입도에서만 모니터링하는 방안은 "어디가 느린가"에 답할 수 없다. 쪼갤 수 있는 것을 원자로 취급했기 때문이다.
- 최종 답변만 저장하는 것은 시스템을 능동적으로 블랙박스로 만드는 것이다 — "중간 과정 유실"은 블랙박스의 결과가 아니라 정의다. Agent의 중간 과정은 비결정적이라 사후에 재실행으로 재현할 수 없으므로, 중간 상태는 한 번 적재하지 않으면 영구 유실이다. "요청을 리플레이하면 재현되는" 전통 CRUD 시스템과 본질적으로 다르다.
- Trace / Span의 가치는 "기록했다"가 아니라 "꿰었다"에 있다 — 고립된 Span 더미는 흩어진 로그 줄일 뿐이고, 인과 관계가 그것들을 사슬로 연결해야 비로소 결정 과정 복원을 논할 수 있다. 전역 연관 ID의 필요성이 여기서 나온다.
- 대기도 반드시 Span이어야 한다 — "사람 개입 대기", "큐 대기"를 명시적으로 Span으로 모델링하는 것이 가장 간과되기 쉬운 설계 요구다. 폭포 그래프에서 가장 긴 막대가 바로 "사람 확인"인 경우가 많은데, 대기에 Span을 만들지 않으면 그 시간은 Trace 위의 주인 없는 공백이 되고 귀속은 즉시 실패한다.
- 관측성의 산출물은 "귀인"이지 "데이터량"이 아니다 — 계측이 합격인지 판단하는 기준은 "외부 도구 호출 실패"라는 하나의 현상을 파라미터 포맷 / 권한 차단 / 네트워크 타임아웃 / 하류 거절이라는 서로 배타적이고 판정 가능한 네 갈래로 자를 수 있는가이다. 자르지 못하면 아무리 많이 기록해도 장소만 바꾼 캄캄함일 뿐이다.
- 기록의 경계는 트러블슈팅 편의가 아니라 안전 레드라인이 긋는다 — 마스킹 / 해시값 / 데이터 참조 링크는 본질적으로 모두 "연관 가능성은 남기고 가독성은 제거하는" 것이다.
- Agent의 자율성과 추적 가능성은 반드시 함께 성장해야 한다 — 자율성이 높아진다는 것은 중간 결정에 대한 사람의 직접 통제력이 떨어진다는 뜻이므로, 증거 사슬이 동반해 두꺼워지지 않으면 시스템의 통제 가능성은 순감소한다.
엔지니어링 실전 Tips
- 전역 연관 ID가 먼저, 계측은 그다음: "사슬 재구성 불가"의 원인은 언제나 "전역 연관 ID로 단계를 꿰지 않은 것"이다. ID가 기초 공사이고 필드는 인테리어이며, 순서를 뒤집을 수 없다.
- Handoff가 사슬이 끊어지기 가장 쉬운 지점: 다른 Agent나 사람에게 작업을 인계할 때 연관 ID가 따라가지 않으면 Trace가 두 동강 나는데, 하필 그 구간이 소요 시간이 가장 의심스러운 구간이다.
- "재시도 여부"를 로그 줄 수 세기가 아니라 명시적 필드로: 재시도를 직접 조회할 수 있어야지 사후 집계로 추측하게 만들면 안 된다.
- 입력·출력은 요약만 저장할 것: 가독성을 지키면서 부피를 자연히 압축한다. 비용과 프라이버시에 동시에 기여하는 항목이다.
- 민감 필드는 "복사"가 아니라 "참조"로: 데이터 참조 링크는 로그에 포인터만 두고 실제 내용은 기존 권한 체계에 남긴다. 트러블슈팅 링크가 데이터 자체의 접근 권한을 얻지 않아도 된다.
- 대기류 Span에 별도 알람을 걸 것: 폭포 그래프에서 가장 긴 막대가 "사람 확인"일 수 있으므로, 사람·큐 대기 시간을 따로 떼어 관찰하는 편이 총 소요 시간을 보는 것보다 문제를 일찍 드러낸다.
- "배타적 갈래로 자를 수 있는가"로 계측 품질을 자가 점검할 것: 어떤 현상을 기존 필드로 배타적 귀인으로 자를 수 없다면 필드가 부족한 것이다. "로그가 충분한가"보다 신뢰할 수 있는 검사 기준이다.