← 모든 글

tool 호출 디버깅 — 100번 중 5번 망가지는 이유

LLM tool use 파이프라인에서 100번 중 5번 나오는 간헐 오류의 실제 원인을 분해하고, 결제·정산 자동화를 직접 운영하는 HEDVION 팀이 적용한 디버깅·안정화 방법을 공유한다.

결제·정산 현장에서 5%는 어떤 무게인가

"100번 중 95번은 성공"이라고 읽으면 어딘가 괜찮아 보인다. 그런데 우리 팀이 실제로 운영하면서 처음 체감한 건 그 5%가 만들어내는 후처리 비용이다. 하루 정산 건수가 2,000건인 시스템에서 5%는 100건이다. 그 100건이 전부 수작업 확인 대상이 된다. 월 기준으로 환산하면 3,000건의 예외 케이스가 매달 쌓이고, 그걸 처리하는 데 드는 시간이 자동화로 아낀 시간을 야금야금 잠식한다.

더 위험한 건 오류가 "조용히" 실패한다는 점이다. 결제 승인 이후 정산 금액 계산 단계에서 tool 호출이 잘못된 파라미터를 넘겼을 때, 시스템이 에러를 명확하게 던지면 그나마 낫다. 우리가 실제로 겪은 케이스에서는 부가세 계산 tool 이 간헐적으로 공급가액 수치를 그대로 세액으로 반환했고, 모델은 그것을 정상 데이터로 처리해서 다음 단계로 넘겼다. 이 오류가 정산 파일에 들어간 채로 3일치가 나간 뒤에야 발견됐다. 발견 시점이 늦어질수록 수습 비용은 기하급수적으로 커진다.

tool 호출 파이프라인의 실패 해부학

LLM tool use 파이프라인은 단순해 보이지만 실패 지점이 여럿 직렬로 연결된 구조다.

사용자 입력 → 모델이 tool 선택 → 파라미터 생성 → tool 실행 → 결과 반환 → 모델이 최종 응답 생성

각 단계는 독립적으로 실패할 수 있고, 실패 양상도 다르다. 모델이 잘못된 tool 을 선택하는 건 로그를 보면 즉시 눈에 띈다. 훨씬 잡기 어려운 건 올바른 tool 을 선택했는데 파라미터 타입이 미묘하게 다른 경우다. 정산 금액 계산 tool 의 amount 필드가 integer 를 기대하는데 모델이 "12500" 같은 string 을 넘기면, 언어에 따라 암묵적 형변환이 일어나서 그냥 동작하거나 조용히 버그로 이어진다. 런타임에서 에러가 나지 않으니 추적이 안 된다.

가장 위험한 실패 지점은 "결과 해석 단계"다. tool 이 에러를 반환했는데 모델이 그 에러 메시지를 정상 응답 데이터처럼 읽고 처리를 계속하는 경우다. 우리 팀에서는 외부 PG사 API 호출 결과를 파싱하는 tool 에서 이 패턴을 겪었다. PG사 응답에서 트랜잭션 상태가 PENDING 으로 왔을 때, tool 이 이걸 명확히 분기 처리하지 않고 그냥 반환하면 모델은 "정상 완료"로 해석하는 경향이 있었다. 이 케이스 하나가 전체 간헐 오류의 22%를 차지했다.

3개월 로그 분석으로 밝혀낸 오류 원인 분포

우리 팀이 3개월간 tool 호출 로그를 분석해서 집계한 오류 원인 분포다 (n ≈ 4,800회 tool 호출 기준, 이 중 5.1%가 오류):

원인 비중
tool 설명 모호성으로 인한 잘못된 tool 선택 38%
파라미터 타입 불일치 (스키마 위반) 27%
tool 결과 해석 오류 (에러를 정상으로 처리) 22%
컨텍스트 누적으로 인한 비정상 결정 9%
기타 (타임아웃, 외부 API 오류 전파) 4%

압도적 1위는 tool 설명의 모호성이다. "거래 정보를 조회한다"는 설명이 붙은 tool 이 세 개 있었을 때, 모델은 컨텍스트에 따라 셋 중 아무거나 골랐다. 각각 다른 DB 테이블을 다른 조건으로 조회하는데도. 우리는 각 tool 의 description 에 "언제 써야 하는가" 뿐만 아니라 "이것이 아닌 다른 tool 을 써야 하는 경우"를 명시적으로 추가했다. 예를 들어 do_not_use_when: "실시간 결제 상태 확인이 필요할 때는 payment_status_check tool 을 사용하라" 식으로. 이 조치 하나로 tool 선택 오류가 38%에서 9%로 줄었다.

파라미터 타입 불일치 27%는 스키마 검증을 파이프라인 앞단에 추가하는 것만으로 대부분 잡을 수 있다. Zod 나 Pydantic 같은 런타임 검증 라이브러리를 tool 래퍼에 씌우고, 검증 실패 시 에러 메시지를 tool result 로 모델에게 피드백하면 된다. 우리 측정 기준으로는 이 피드백을 받은 모델이 파라미터를 수정해서 재시도하는 비율이 83%였다. 사람이 개입하지 않고 모델 스스로 자정한다.

컨텍스트 오염: 대화가 길어질수록 쌓이는 위험

결제·정산 자동화 에이전트는 단발성 쿼리보다 다단계 작업 흐름을 처리하는 경우가 많다. "이번 달 전체 정산 마감하고 예외 건 뽑아서 보고서 만들어라" 같은 작업은 내부적으로 수십 번의 tool 호출이 직렬로 이어진다. 컨텍스트에 이전 tool 결과들이 누적되면서 오염이 발생한다.

우리가 경험한 구체적 패턴: 정산 마감 워크플로우에서 앞단에 "4월 데이터"를 조회하는 tool 호출이 있었고, 그 결과가 컨텍스트에 남아 있는 상태에서 "5월 데이터" 처리 tool 을 호출할 때, 모델이 5월 tool 에 4월 날짜 범위를 파라미터로 넘기는 현상이 전체 케이스의 4%에서 발생했다. 해결책은 두 가지를 병행했다. 첫째, 각 단계의 tool 결과를 컨텍스트에 원본으로 남기지 않고 "처리 완료, 결과 요약: 건수 OO건, 총액 OO원" 형태로 압축해서 원본 JSON 은 제거했다. 둘째, 날짜 범위나 대상 거래처처럼 워크플로우 전체에서 변하지 말아야 하는 파라미터는 system prompt 에 고정값으로 박아두어 모델이 매 turn 마다 재결정하지 않게 했다.

temperature 설정도 간과하기 쉬운 변수다. 우리 시스템에서 tool 선택 단계를 temperature 0.7 에서 0.0 으로 바꿨을 때, tool 선택 오류가 약 30% 감소했다. 창의성이 필요한 건 최종 응답 텍스트 생성 단계뿐이고, tool 선택과 파라미터 결정은 결정론적이어야 한다. Claude API 기준으로 동일 요청 내에서 단계별 temperature 분리가 불가능하다면, tool 선택 전용 호출과 응답 생성 전용 호출을 물리적으로 분리하는 방식으로 우회할 수 있다.

HEDVION 팀의 실제 대응 시나리오: 세금계산서 자동화

가상이 아닌, 우리가 실제로 설계하고 운영하는 파이프라인을 기반으로 설명한다.

시나리오: 세금계산서 발행 자동화 에이전트. 사용자가 "이번 달 거래처 A에게 세금계산서 발행해줘"라고 입력하면, 에이전트가 거래 내역 조회 → 공급가액 계산 → 부가세 계산 → 세금계산서 API 호출 → 발행 확인 순서로 tool 을 호출한다.

이 파이프라인에서 5% 오류가 나면 세금계산서가 잘못된 금액으로 발행된다. 국세청 API 특성상 당일 취소가 불가한 케이스가 존재해서 다음 날 처리해야 하고, 거래처에 정정 통보가 나가야 한다. 100건 중 5건이 이 흐름에 빠지면 자동화의 이점이 상당 부분 사라진다. 우리가 이 시나리오에 적용한 대응 구조는 세 층위다.

1층: 파이프라인 각 단계에 검증 gate 추가. 부가세 계산 tool 결과에 대해 "공급가액 × 0.1 = 세액" 이라는 산술 검증을 래퍼에서 수행한다. 검증을 통과하지 못하면 tool 결과를 모델에게 정상으로 반환하지 않고 오류 메시지를 피드백해서 재시도를 유도한다.

2층: 임계값 이상 금액은 사람 확인 삽입. 세금계산서 발행 API 호출 직전에 "발행 예정 내용: 공급가 OOO원, 세액 OOO원, 거래처 A — 확인 후 진행하겠습니다"라는 confirm 단계를 넣는다. 금액이 100만 원 이상이면 자동 진행이 아닌 담당자 승인을 요구한다. 자동화지만 금액 리스크에 비례해서 사람 개입 지점을 설계한다.

3층: 실패를 손실이 아닌 대기 상태로. 발행 실패 시 단순 에러 반환이 아니라, 실패 내역을 별도 큐에 적재하고 담당자에게 슬랙 알림이 가는 폴백을 연결했다. 이 구조 덕분에 5% 오류가 "완전 손실"이 아닌 "처리 대기"로 분류되고, 다음 날 아침 일괄 재처리가 가능해졌다.

지금 당장 써먹을 수 있는 실행 시사점

간헐 오류를 추적하고 줄이면서 우리가 정리한 것들이다. 이론이 아니라 배포 환경에서 실제로 효과를 확인한 순서대로 적는다.

1. tool description 에 "쓰지 말아야 할 때"를 명시하라. 설명 텍스트 끝에 이 tool 을 사용하지 말아야 하는 경우: [상황 A], [상황 B] 를 추가하라. 비슷한 tool 이 둘 이상 있을 때 모델의 혼동을 가장 빠르게 줄이는 방법이다. 우리 기준으로 tool 선택 오류 38% → 9% 감소.

2. 파이프라인 앞단에 런타임 스키마 검증을 붙이고, 실패 메시지를 모델에게 피드백하라. Zod, Pydantic 등 어느 것이든 상관없다. 검증 에러를 tool result 로 돌려주면 모델이 스스로 수정 재시도한다. 이 루프를 최대 2회까지 허용하면 파라미터 오류의 80% 이상이 사람 개입 없이 해소된다.

3. 워크플로우 전역 파라미터는 system prompt 에 고정하라. 날짜 범위, 대상 거래처, 처리 기준 등 단계 전체에서 변하지 말아야 하는 값을 모델이 매번 컨텍스트에서 재추론하게 두지 마라. 시작 시점에 확정해서 system prompt 에 박아두는 것이 컨텍스트 오염 방어에 효과적이다.

4. 모델이 생성한 파라미터 원본(파싱 전) JSON 을 반드시 로그로 남겨라. 파싱 후 데이터만 저장하면 오류 원인의 절반이 사라진다. 원본 JSON 이 있어야 어떤 사용자 입력 패턴이 어떤 파라미터 오류를 유발하는지 분석할 수 있다. 이 로그 없이는 간헐 오류를 재현하기 불가능에 가깝다.

5. 오류를 0으로 만들려 하지 말고, 오류를 복구 가능하게 만들어라. LLM 파이프라인에서 간헐 오류를 완전히 없애는 건 현실적으로 어렵다. 결제·정산 자동화에서 올바른 목표는 "5%를 1%로 줄이는 것" 과 "남은 1%가 발생했을 때 사람이 명확하게 개입할 수 있는 구조를 갖추는 것"을 동시에 하는 것이다. 폴백 큐, 알림, 재처리 UI 는 tool 파이프라인 설계 초기에 함께 만들어야 한다. 나중에 붙이려면 두 배 힘들다는 것을 우리는 이미 경험했다.

— by mings

* 위 링크는 인프런 affiliate 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

📚 추천 강의
한 입 크기로 잘라먹는 바이브코딩 (with Claude Code)
Claude Code로 바이브코딩, 개발자라면 꼭 들어야 할 필수 강의
강의 보러가기 →

* 위 추천 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.