Agent가 20초 멈췄다면 — Trace와 Span으로 여는 관측성

← 전체 목차 · 이전: AI 숏드라마 캐릭터가 계속 변하는 이유 — 프롬프트가 아니라 자산 관리 · 다음: Agent 평가의 핵심 기준 — Outcome과 Trajectory

Agent 시스템은 천연의 블랙박스다. 사용자에게 던져줄 최종 답변만 기록하면 중간 과정은 영원히 사라지고, 문제가 생겼을 때 시간이 어디에 쓰였는지조차 말할 수 없다.

사용자가 프런트엔드에서 20초를 기다리는 동안 백엔드에서는 이런 일이 벌어졌을 수 있다.

백엔드 동작횟수
대규모 모델 호출3회
외부 도구 재시도2회
Handoff (다른 Agent 또는 사람에게 인계)1회

사용자가 체감한 "하나의 대기"는 시스템 내부에서는 여러 이기종 단계의 중첩이다.

Trace와 Span

  • Trace한 번의 엔드 투 엔드 완전한 작업. 비유하면 한 편의 완결된 다큐멘터리.
  • Span — 그 다큐멘터리의 각 장면으로, 작업 안에서 독립적으로 측정 가능한 모든 작은 단계를 나타낸다.

Span의 예시:

  1. 대규모 모델이 텍스트 한 단락을 생성했다
  2. Agent가 날씨 API를 한 번 호출했다
  3. 지식 베이스에서 검색을 한 번 했다
  4. Guardrail, 즉 안전 가드레일 차단이 발동했다
  5. 심지어 "사람의 개입을 그냥 기다리고 있었다"

5번이 핵심적인 반직관 지점이다. 대기 자체도 독립된 Span이 되어야 소요 시간을 귀속시킬 수 있다.

장면만으로는 부족하고 "편집 논리"가 있어야 한다

Span들은 인과 관계로 고리처럼 이어져야 리플레이를 보듯 이 사슬을 복원할 수 있다.

결정  →  동작  →  결과  →  다음 라운드 추론
 ↑                              │
 └──────── 인과 관계로 연결 ──────┘

복원해야 할 질문은 둘이다. 당시 어떤 결정을 내렸기에 이어지는 동작이 발동되었는가, 그리고 그 동작이 만든 결과가 어떻게 Agent를 다음 라운드 추론으로 이끌었는가.

Span 하나에 기록할 필드

필드설명
작업 ID이번 작업의 식별자
Agent지금 어느 Agent가 일하고 있는가
도구어떤 도구를 썼는가
모델 버전호출한 모델의 구체적 버전
시작 / 종료 시각기간
최종 상태작업 결과 상태
재시도 여부중간에 재시도가 있었는가
Token 소모얼마나 소모했는가
입력 / 출력 요약가장 핵심적인 항목

기록은 기록이고 프라이버시 레드라인은 넘지 않는다

자신의 디버깅 편의를 위해 사용자 프라이버시나 회사 기밀을 통째로 로그에 복사해 넣으면 절대 안 된다. 민감한 내용을 만나면 세 가지 중 하나다.

  1. 성실하게 마스킹 처리
  2. 해시값만 저장
  3. 데이터 참조 링크를 대신 둔다

무엇을 얻는가: 인과 위치 파악

"외부 도구 호출 실패"를 예로 들면, 이 메커니즘이 없으면 캄캄하지만 있으면 실패가 어느 부류인지 한눈에 보인다.

외부 도구 호출 실패
├── 대규모 모델이 생성한 파라미터 포맷이 틀림   (모델 측 문제)
├── 시스템 권한이 차단함                       (정책/권한 측 문제)
├── 단순한 네트워크 타임아웃                   (링크 측 문제)
└── 하류 업무 시스템이 요청을 직접 거절함       (하류 측 문제)

전역 연관 ID: 지연 귀속과 실행 사슬 재구성

로그 연관을 보면 사람의 확인 대기에서 막혔다는 것을 조회할 수 있다. 전역 연관 ID로 단계들을 꿰지 않으면 당시의 실행 사슬을 아예 재구성할 수 없다.

소요 시간 폭포 그래프에서 모델 생성(LLM) → 큐 대기(Queue) → 사람 확인(Human) 중 가장 긴 것이 바로 "사람 확인"인 경우가 흔하다. 전역 연관 ID는 Span을 Trace로 꿰는 물리적 수단이고, Trace ID는 트러블슈팅 시의 입구다.

관측성은 "출력문 두 줄 더 쓰기"가 아니다

초기 목표  →  결정과 행동  →  최종 결과
       각 단계마다 「연속되고 쇠처럼 단단한 증거」로 추적 가능

미래의 Agent는 점점 더 똑똑해지고 자율적이 될 것이다. 자율적일수록 개발팀은 그것이 어떻게 한 걸음씩 최종 답변에 이르렀는지를 더 분명히 알아야 한다.

핵심 통찰

  1. 사용자가 체감한 "한 번의 대기"는 시스템 내부에서 여러 이기종 단계의 중첩이다 — 20초는 사용자에게 숫자 하나지만 백엔드에서는 모델 호출 3회 + 도구 재시도 2회 + Handoff 1회다. "요청 총 소요 시간"이라는 하나의 입도에서만 모니터링하는 방안은 "어디가 느린가"에 답할 수 없다. 쪼갤 수 있는 것을 원자로 취급했기 때문이다.
  2. 최종 답변만 저장하는 것은 시스템을 능동적으로 블랙박스로 만드는 것이다 — "중간 과정 유실"은 블랙박스의 결과가 아니라 정의다. Agent의 중간 과정은 비결정적이라 사후에 재실행으로 재현할 수 없으므로, 중간 상태는 한 번 적재하지 않으면 영구 유실이다. "요청을 리플레이하면 재현되는" 전통 CRUD 시스템과 본질적으로 다르다.
  3. Trace / Span의 가치는 "기록했다"가 아니라 "꿰었다"에 있다 — 고립된 Span 더미는 흩어진 로그 줄일 뿐이고, 인과 관계가 그것들을 사슬로 연결해야 비로소 결정 과정 복원을 논할 수 있다. 전역 연관 ID의 필요성이 여기서 나온다.
  4. 대기도 반드시 Span이어야 한다 — "사람 개입 대기", "큐 대기"를 명시적으로 Span으로 모델링하는 것이 가장 간과되기 쉬운 설계 요구다. 폭포 그래프에서 가장 긴 막대가 바로 "사람 확인"인 경우가 많은데, 대기에 Span을 만들지 않으면 그 시간은 Trace 위의 주인 없는 공백이 되고 귀속은 즉시 실패한다.
  5. 관측성의 산출물은 "귀인"이지 "데이터량"이 아니다 — 계측이 합격인지 판단하는 기준은 "외부 도구 호출 실패"라는 하나의 현상을 파라미터 포맷 / 권한 차단 / 네트워크 타임아웃 / 하류 거절이라는 서로 배타적이고 판정 가능한 네 갈래로 자를 수 있는가이다. 자르지 못하면 아무리 많이 기록해도 장소만 바꾼 캄캄함일 뿐이다.
  6. 기록의 경계는 트러블슈팅 편의가 아니라 안전 레드라인이 긋는다 — 마스킹 / 해시값 / 데이터 참조 링크는 본질적으로 모두 "연관 가능성은 남기고 가독성은 제거하는" 것이다.
  7. Agent의 자율성과 추적 가능성은 반드시 함께 성장해야 한다 — 자율성이 높아진다는 것은 중간 결정에 대한 사람의 직접 통제력이 떨어진다는 뜻이므로, 증거 사슬이 동반해 두꺼워지지 않으면 시스템의 통제 가능성은 순감소한다.

엔지니어링 실전 Tips

  • 전역 연관 ID가 먼저, 계측은 그다음: "사슬 재구성 불가"의 원인은 언제나 "전역 연관 ID로 단계를 꿰지 않은 것"이다. ID가 기초 공사이고 필드는 인테리어이며, 순서를 뒤집을 수 없다.
  • Handoff가 사슬이 끊어지기 가장 쉬운 지점: 다른 Agent나 사람에게 작업을 인계할 때 연관 ID가 따라가지 않으면 Trace가 두 동강 나는데, 하필 그 구간이 소요 시간이 가장 의심스러운 구간이다.
  • "재시도 여부"를 로그 줄 수 세기가 아니라 명시적 필드로: 재시도를 직접 조회할 수 있어야지 사후 집계로 추측하게 만들면 안 된다.
  • 입력·출력은 요약만 저장할 것: 가독성을 지키면서 부피를 자연히 압축한다. 비용과 프라이버시에 동시에 기여하는 항목이다.
  • 민감 필드는 "복사"가 아니라 "참조"로: 데이터 참조 링크는 로그에 포인터만 두고 실제 내용은 기존 권한 체계에 남긴다. 트러블슈팅 링크가 데이터 자체의 접근 권한을 얻지 않아도 된다.
  • 대기류 Span에 별도 알람을 걸 것: 폭포 그래프에서 가장 긴 막대가 "사람 확인"일 수 있으므로, 사람·큐 대기 시간을 따로 떼어 관찰하는 편이 총 소요 시간을 보는 것보다 문제를 일찍 드러낸다.
  • "배타적 갈래로 자를 수 있는가"로 계측 품질을 자가 점검할 것: 어떤 현상을 기존 필드로 배타적 귀인으로 자를 수 없다면 필드가 부족한 것이다. "로그가 충분한가"보다 신뢰할 수 있는 검사 기준이다.