에이전틱스
도메인 4. 평가와 테스트, 최적화

4.6로깅과 관측성

예상 학습 시간 35

LLM 시스템은 같은 입력에도 다른 출력이 나올 수 있고 실패가 예외가 아니라 낮은 품질의 형태로 나타납니다. 이 수업에서는 무엇을 남길지, 다단계 파이프라인을 어떻게 잇는지, 그리고 경보를 어떤 지표에 걸어야 하는지를 다룹니다.

LLM 시스템의 관측성이 다른 점

일반적인 서비스에서 장애는 오류로 드러납니다. 상태 코드가 500이 되고 예외가 기록됩니다. LLM 시스템의 대표적인 실패는 다릅니다. 200 응답이 정상적으로 돌아오는데 내용이 틀린 것입니다.

이 차이가 관측 설계를 바꿉니다.

  • 오류율만 보는 대시보드는 품질 저하를 전혀 감지하지 못합니다.
  • 같은 입력에 다른 출력이 나올 수 있으므로, 로그 한 줄로는 재현이 되지 않습니다. 무엇을 입력했는지가 정확히 남아 있어야 합니다.
  • 비용이 트래픽과 선형으로 늘지 않습니다. 에이전트 루프가 길어지면 요청 수는 그대로인데 비용만 뜁니다.

따라서 LLM 시스템에서는 품질 대리 지표와 자원 사용 지표를 오류율과 같은 급으로 취급해야 합니다. 구체적으로는 응답이 스키마를 만족한 비율, 검증 단계를 통과한 비율, 도구 호출 실패율, 요청당 토큰, 루프 반복 횟수 같은 것들입니다.

시험에서는 "오류 로그에는 아무것도 없는데 사용자 불만이 있다"는 상황이 자주 주어집니다. 이때 정답은 대개 오류 로그를 더 자세히 보는 쪽이 아니라, 품질과 자원 지표를 새로 남기는 쪽입니다.

무엇을 남길 것인가

모든 것을 남기면 비용과 개인정보 위험이 커지고, 적게 남기면 진단이 불가능해집니다. 실무의 기준선은 다음과 같습니다.

항상 남긴다 (구조화된 필드로)

  • 요청 식별자와 상관 ID, 타임스탬프
  • 모델과 프롬프트 버전, 도구 구성 버전
  • 사용량 — 입력·출력 토큰, 캐시 읽기 토큰
  • 지연시간 — 단계별 소요 시간
  • 도구 호출 목록과 각 호출의 성공 여부
  • 종료 사유와 루프 반복 횟수

표본으로 남긴다

  • 프롬프트 원문과 응답 원문. 전수 저장은 비용과 개인정보 문제를 함께 키우므로 표본율을 정해 남기고, 실패 사례는 표본율과 무관하게 전수 보관합니다.

남기지 않거나 처리 후 남긴다

  • 개인 식별 정보, 자격 증명, 결제 정보. 저장 전에 마스킹하거나 아예 제외합니다.
log.info("llm_call", extra={
    "trace_id": trace_id,          # 요청 전체를 잇는 키
    "step": "generate",
    "model_version": model_id,
    "prompt_version": prompt_ver,
    "input_tokens": usage.input_tokens,
    "output_tokens": usage.output_tokens,
    "cache_read_tokens": getattr(usage, "cache_read_input_tokens", 0),
    "latency_ms": elapsed_ms,
    "stop_reason": resp.stop_reason,
    "schema_valid": is_valid,      # 품질 대리 지표
})

버전 필드가 특히 중요합니다. 프롬프트 버전이 로그에 없으면 "지난주와 이번 주 품질이 다르다"는 관찰을 특정 변경과 연결할 수 없습니다.

다단계 파이프라인을 잇는 상관 ID

검색, 생성, 검증처럼 여러 단계를 거치는 시스템에서 단계별 로그가 서로 이어지지 않으면 "가끔 느리다"는 민원을 추적할 수 없습니다. 평균 지연시간 그래프는 어느 단계가 범인인지 말해 주지 않습니다.

해법은 요청 하나에 상관 ID를 부여하고 모든 단계 로그에 그 ID와 단계별 소요 시간을 함께 남기는 것입니다. 그러면 느린 요청 하나를 골라 단계별로 펼쳐 볼 수 있습니다.

trace_id = new_trace_id()
timings = {}

with step(timings, "retrieve"):
    chunks = retrieve(query)
with step(timings, "generate"):
    draft = generate(query, chunks)
with step(timings, "verify"):
    result = verify(draft)

log.info("pipeline_done", extra={"trace_id": trace_id, **timings})

에이전트처럼 루프를 도는 구조에서는 반복 횟수와 각 반복의 도구 호출도 같은 상관 ID로 묶어야 합니다. 비용이 튀는 요청은 대개 루프가 길어진 요청인데, 반복 횟수를 남기지 않으면 총토큰만 크게 보이고 이유는 보이지 않습니다.

지연시간을 볼 때는 평균이 아니라 분위수를 봅니다. "가끔 느리다"는 민원은 정의상 꼬리 구간의 이야기이고, 평균 그래프에서는 보이지 않습니다.

경보와 대시보드 설계

모든 지표에 경보를 걸면 아무도 경보를 보지 않게 됩니다. 경보는 사람이 즉시 할 행동이 있는 것에만 겁니다.

경보에 적합한 것

  • 오류율과 도구 호출 실패율의 급증
  • 스키마 위반율이나 검증 실패율의 급증 — 품질 저하의 가장 빠른 신호입니다
  • 요청당 토큰이나 루프 반복 횟수의 급증 — 비용 사고의 조기 경보입니다
  • p95 지연시간이 합의된 목표를 넘는 상태의 지속

대시보드로 충분한 것

  • 전체 트래픽 추이, 모델별 사용 분포, 캐시 적중률의 완만한 변화

경보 임계는 절대값보다 기준선 대비 변화로 잡는 편이 오작동이 적습니다. 트래픽이 두 배가 되면 총토큰도 두 배가 되지만 그것은 사고가 아니고, 요청당 토큰이 두 배가 되면 사고입니다.

품질 저하는 대개 서서히 진행되므로 경보만으로는 잡히지 않습니다. 이를 위해 정기 평가를 운영에 붙여 둡니다. 운영 트래픽에서 표본을 뽑아 주기적으로 평가 파이프라인에 태우면, 배포 없이도 품질이 흘러내리는 것을 감지할 수 있습니다. 관측성의 마지막 조각은 실시간 지표가 아니라 이 정기 점검입니다.

시험 함정

  • 오류율만으로 LLM 시스템의 건강을 판단하는 선택지 — 대표적 실패는 정상 응답에 담긴 잘못된 내용입니다.
  • 모든 요청의 프롬프트와 응답 원문을 전수 저장하는 선택지 — 비용과 개인정보 위험이 함께 커지므로 표본 저장과 실패 전수 보관으로 나눕니다.
  • 로그에 프롬프트·모델 버전을 남기지 않는 선택지 — 품질 변화를 특정 변경과 연결할 수 없습니다.
  • 평균 지연시간 그래프로 "가끔 느리다"를 추적하는 선택지 — 꼬리 구간 문제는 분위수로 봐야 보입니다.
  • 총토큰 절대값에 경보를 거는 선택지 — 트래픽 증가와 사고를 구분하지 못하므로 요청당 값으로 잡습니다.
  • 실시간 경보만으로 품질 저하를 감지할 수 있다는 선택지 — 서서히 진행되는 저하는 정기 평가로 잡습니다.

실습 시나리오

실제 시험과 같은 형식의 시나리오 문제입니다.

검색, 생성, 검증 세 단계를 거치는 파이프라인에서 "가끔 응답이 아주 느리다"는 민원이 있습니다. 오류 로그에는 아무것도 남지 않고, 평균 응답 시간 대시보드도 평소와 같습니다. 로깅에 가장 먼저 보완해야 할 것은 무엇입니까?

빌드 연습 · 추적 가능한 로깅 붙이기

45
  1. 1.필수 필드 정의

    상관 ID, 버전, 사용량, 지연시간, 종료 사유를 포함한 로그 스키마를 정합니다.

    기대 결과 · 스키마가 문서로 정리되고 필드마다 용도가 한 줄씩 적혀 있습니다.

  2. 2.상관 ID 전파

    요청 진입점에서 ID를 만들어 모든 단계 로그에 전달합니다.

    기대 결과 · 한 요청의 모든 단계 로그를 ID로 조회할 수 있습니다.

  3. 3.단계별 소요 시간 기록

    검색·생성·검증 각각의 소요 시간을 밀리초 단위로 남깁니다.

    기대 결과 · 느린 요청 하나를 골라 단계별 시간 분해를 볼 수 있습니다.

  4. 4.민감정보 처리

    저장 전에 개인 식별 정보와 자격 증명을 마스킹하는 처리를 넣습니다.

    기대 결과 · 표본 저장된 프롬프트에 마스킹이 적용되어 있습니다.

  5. 5.경보 임계 설정

    요청당 토큰과 스키마 위반율에 기준선 대비 변화로 경보를 겁니다.

    기대 결과 · 트래픽이 늘어난 상황에서 오탐이 발생하지 않습니다.

출처 및 더 읽기