
월말에 Anthropic 청구서를 받고 나서야 "어, 이게 왜 이렇게 많이 나왔지?"라고 뒤늦게 당황한 경험이 있는가. 나는 있다. 그것도 한 번이 아니라 여러 번. Claude API를 SaaS 서비스에 붙이기 시작했을 때, 비용 관리가 이렇게 복잡한 문제가 될 거라고는 생각도 못 했다. 지금 돌아보면 그 당황스러움이 결국 꽤 중요한 인프라를 만드는 계기가 됐다.
기능별 cost attribution이 안 된다는 것, 처음엔 몰랐다
처음 Claude API를 붙였을 때는 Anthropic 콘솔 대시보드만 보면 충분할 거라고 생각했다. 그건 완전히 착각이었다. 대시보드는 조직 전체 토큰 소비량을 하나의 숫자로 보여줄 뿐이었다. 서비스에는 문서 요약 기능과 챗봇 기능이 함께 있었는데, 어느 쪽이 비용을 더 많이 쓰는지 전혀 알 수가 없었다. 어느 달에는 비용이 갑자기 크게 올라서 원인을 찾으려고 했는데, 어느 기능이 문제인지조차 파악이 안 됐다. 결국 추측에 의존해서 접근할 수밖에 없었다.
여기서 cost attribution이란 전체 비용을 기능별, 사용자별로 분리해서 귀속시키는 것을 의미한다. 일반 서비스라면 서버 비용을 기능별로 쪼개는 일이 그나마 예측 가능하지만, LLM은 입력 컨텍스트 길이와 출력 토큰 수에 따라 호출마다 비용이 천차만별이라 더욱 까다롭다.
해결책으로 선택한 건 API 호출 레이어에 미들웨어를 추가하는 방식이었다. 응답의 usage 필드, 즉 input_tokens와 output_tokens 값을 기능 이름, 사용자 ID, 타임스탬프와 함께 DB 로그 테이블에 저장했다. 처음에는 단순 INSERT로 충분했지만, 트래픽이 늘면서 API 응답 지연이 생기기 시작했다. 그때 비동기 큐를 도입해 로깅을 메인 흐름에서 분리했는데, 이후로는 응답 속도에 영향을 주지 않으면서도 완전한 기록 보존이 가능해졌다. 로깅을 동기 방식으로 넣었을 때는 DB 부하가 높은 시간대에 API 응답 속도가 눈에 띄게 느려지는 문제가 있었다. 비동기로 분리하고 나서야 이 문제가 해소됐다.
Anthropic의 공식 Admin API가 있고, 시간 버킷 단위 집계와 모델별·워크스페이스별 분류를 지원한다는 건 알고 있었다. 하지만 이 API는 워크스페이스 단위까지만 집계를 지원한다. SaaS처럼 수천 명의 최종 사용자가 있는 서비스에서 사용자 한 명 한 명의 비용을 뽑아내려면 결국 애플리케이션 레이어에서 직접 구현하는 수밖에 없다.
Enterprise Analytics API라는 게 2025년 중반부터 별도로 제공되고 있긴 하다. 모델별, 컨텍스트 창별, 추론 리전별 데이터를 제공하고 per-user 수준 데이터를 프로그래밍 방식으로 접근할 수 있다고 한다. 그런데 내 경험상 이건 엔터프라이즈 플랜 가입자에게만 제공되는 유료 기능이다. AI 비용 투명성은 모든 규모의 서비스에 필요한 기본 역량인데, 플랜에 따라 차등 제공된다는 점은 솔직히 아쉽다. 스타트업이나 소규모 팀이라면 결국 직접 구현해야 한다는 현실을 받아들이고 시작하는 게 낫다. 처음부터 직접 구현 방향으로 잡으면 나중에 플랜 업그레이드 여부와 무관하게 데이터 소유권을 가져갈 수 있다는 장점도 있다.
핵심 포인트를 정리하면 이렇다. Admin API는 조직·워크스페이스 단위 집계만 지원하므로 per-user 추적은 앱 레이어에서 직접 구현해야 한다. API 응답의 input_tokens, output_tokens를 기능명·사용자 ID와 함께 DB에 기록하는 미들웨어가 가장 현실적인 출발점이다. 트래픽 증가 후에는 비동기 큐로 로깅을 분리해야 응답 지연을 막을 수 있다. Enterprise Analytics API는 엔터프라이즈 플랜 전용으로 중소 팀에서는 접근이 제한될 수 있다.
중복 집계 버그와 실시간 대시보드, 그 사이에서 배운 것
미들웨어 로깅을 구축한 뒤 한동안은 잘 돌아가는 것처럼 보였다. 그런데 Agent SDK를 붙이고 나서 이상한 일이 생겼다. 토큰 집계 수치가 실제 청구액과 맞지 않았고, 어떤 날은 2배에서 3배 가까이 부풀려져 있었다.
원인은 병렬 툴 호출 시 발생하는 중복 집계 문제였다. Claude Agent SDK에서 병렬로 툴을 호출하면 동일한 message ID를 공유하는 응답이 스트리밍 방식으로 여러 번 수신될 수 있는데, ID 기반 중복 제거 없이 단순히 합산하면 실제보다 훨씬 높은 토큰 수가 기록된다. 이 버그를 프로덕션에서 발견했을 때는 이미 한 달치 비용 데이터가 부정확하게 쌓인 상태였고, 소급 수정에만 꽤 많은 시간이 걸렸다. 데이터를 소급 수정하는 건 단순히 숫자를 고치는 게 아니라, 이미 그 데이터를 기반으로 만들어진 리포트와 의사결정을 전부 재검토해야 한다는 의미여서 비용이 컸다. 돌이켜보면 초기 설계 단계에서 message ID 기준 중복 제거 로직을 먼저 넣었어야 했다. Agent SDK를 쓸 계획이라면 이 부분을 반드시 미리 고려해야 한다.
이 경험 이후 Grafana Cloud와 Admin Usage API를 연동해 실시간 대시보드를 구성했다. Grafana Cloud와의 공식 통합은 Prometheus 레이블링 방식으로 입출력 토큰, 모델, 워크스페이스 ID, 서비스 티어 등을 메트릭 시리즈로 수집한다. Prometheus 레이블링이란 각 메트릭 데이터에 key=value 형태의 식별자를 붙여서 다차원 필터링이 가능하게 만드는 방식이다. 외부 익스포터 없이 Grafana Cloud가 직접 처리하는 구조라서 운영 부담이 낮다는 점도 실제로 써보고 나서 만족스러웠다.
대시보드에서 핵심 지표로 설정한 건 일일 토큰 소비량, 기능별 비용 비율, 사용자당 평균 비용, 그리고 캐시 히트율이다. 캐시 히트율은 동일한 프롬프트 컨텍스트가 재사용되는 비율인데, 이 수치가 낮으면 입력 토큰 비용이 불필요하게 반복 발생하고 있다는 신호다. 이 대시보드 덕분에 특정 날 비용이 갑자기 급등했을 때 원인을 30분 만에 찾아낸 적이 있다. 시스템 프롬프트 버그로 인해 매 요청마다 5,000토큰짜리 불필요한 컨텍스트가 붙고 있었다. 로깅 인프라가 없었다면 며칠이 지나도 눈치채지 못했을 것이다. 그 달 청구서를 보고 나서야 문제를 인식했다면, 이미 며칠치 낭비가 쌓인 뒤였을 것이다.
비용 알림도 빠질 수 없었다. 시간당 토큰 소비량이 평균의 2배를 넘으면 Slack으로 알림이 오도록 설정했는데, 실제로 비정상 트래픽이나 프롬프트 인젝션 공격을 조기에 탐지하는 데 도움이 되었다. 프롬프트 인젝션이란 악의적인 사용자가 입력값을 통해 시스템 프롬프트를 우회하거나 모델의 동작을 조작하려는 공격을 의미한다. 보안 이슈이기도 하지만, 비용 급등의 원인이 되기도 한다. 비용 알림을 보안 탐지 수단으로도 활용할 수 있다는 건 구축해보고 나서야 알게 된 부가적인 이점이었다.
Claude API 비용 추적은 처음에는 "그냥 콘솔 보면 되겠지"로 시작했다가, 결국 미들웨어, 비동기 큐, 중복 제거 로직, 실시간 대시보드까지 쌓아가는 여정이 된다. 내 경험상 이 인프라를 초기부터 설계해 두는 것과 나중에 뒤늦게 붙이는 것은 공수 면에서 두세 배 차이가 난다. API를 막 붙이기 시작하는 단계라면, 최소한 usage 필드 로깅과 message ID 기반 중복 제거만큼은 처음부터 넣어두길 권한다. 나중에 데이터가 엉켜있을 때 수습하는 것보다 훨씬 쉽다.
참고
- Anthropic Admin API - Usage & Cost Report: https://platform.claude.com/docs/en/build-with-claude/usage-cost-api
- Anthropic Enterprise Analytics API (Finout, 2025): https://www.finout.io/blog/anthropics-enterprise-analytics
- Grafana Cloud + Anthropic Integration: https://grafana.com/blog/how-to-monitor-claude-usage-and-costs
- Claude Agent SDK - Cost Tracking: https://platform.claude.com/docs/en/agent-sdk/cost-tracking