LLM API 비용, 팀별로 정확하게 나누는 법: 토큰 미터링과 예산 단계 설계

zerokdevops·4일 전

사내에서 LLM을 쓰기 시작하면 몇 달 안에 꼭 이런 질문이 나온다.

"이번 달 LLM 비용, 어느 팀이 어떤 기능에 얼마 썼어요?"

공급자 청구서에는 모델별 합계만 있다. 팀도, 사용자도, 기능도 없다. 그래서 이 질문에 답하려면 공급자와 코드 사이에 있는 게이트웨이가 직접 장부를 써야 한다. 이 글은 그 장부를 어떻게 설계하는지 정리한 것이다.

목표는 한 문장이다.

"이번 달 팀 X는 모델 Z와 기능 W에 $Y를 썼고, 이 숫자는 공급자 청구서와 $V 이내로 일치한다."

1. 요청마다 비용을 계산하고, 그 시점의 가격을 같이 저장한다

미터링 이벤트에는 토큰을 종류별로 나눠 담는다.

항목왜 따로 담나
input_tokens기본 입력 단가
cached_input_tokens캐시 입력은 보통 기본가보다 훨씬 싸다. 합쳐 버리면 그 할인만큼 장부가 틀어진다
output_tokens기본 출력 단가
reasoning_tokens추론 모델의 내부 토큰. 요율이 따로 있는 경우가 많다

비용은 요청 시점에 계산하고, 그때의 단가를 이벤트에 스냅샷으로 남긴다.

cost = in × price.input
     + cached × price.cached_input
     + out × price.output
     + reasoning × price.reasoning

나중에 가격이 바뀌어도 과거 어느 날의 비용이든 그대로 재현된다. 월말 정산이 "논쟁"이 아니라 "계산"이 되는 이유가 이 스냅샷이다.

공급자 응답에 사용량 정보가 빠진 경우에는 토큰 수를 추정하되 estimated: true로 표시한다. 추정치 비중을 지표로 추적하면, 공급자가 사용량 보고 방식을 바꿨을 때 바로 알 수 있다.

2. 귀속 축은 네 개면 충분하다

모든 이벤트에 아래 네 필드를 붙이고, 일 단위 롤업을 이 축 조합으로 만든다.

  • 모델별: alias와 실제 provider_model_id 둘 다. 별칭은 우리 관점, 모델 ID는 공급자 관점이다.
  • 팀별: team (필요하면 cost_center)
  • 사용자별: principal, 그리고 에이전트가 누군가를 대신해 호출했다면 on_behalf_of
  • 기능별: 등록된 feature 이름. 등록 안 된 호출은 unregistered로 남겨서 그것도 리포트에 보이게 한다

롤업 테이블은 작게 유지한다. 중간 규모 조직이라면 하루 수천 행 수준이라, 대시보드와 정산이 ETL 프로젝트가 아니라 GROUP BY 한 줄로 끝난다.

-- 이번 달 팀별 비용
SELECT team, alias_class, SUM(cost) AS cost
FROM rollup_daily
WHERE day >= date_trunc('month', now())
GROUP BY 1, 2 ORDER BY 3 DESC;

3. 예산은 "단계"와 "동작"으로 설계한다

일일 토큰 쿼터와 월 예산은 다른 물건이다. 쿼터는 새벽 3시의 폭주를 막고, 예산은 한 달을 관리한다. 둘 다 둔다.

예산에는 임계값마다 정해진 동작을 붙인다. 숫자는 조직마다 다르지만 동작은 설계로 정해 둔다.

단계기본 임계값동작
소프트80%거부 없음. 팀 채널에 소진 예측 알림 ("이 속도면 27일에 소진")
경고95%팀 리드에게도 알림. 응답 헤더에 X-LLM-Budget: 96% 같은 경고 포함
하드100%비싼 모델 클래스만 429 budget_denied로 거부. 싼 클래스는 계속 허용
초과110%진행 중이던 요청 때문에 정산 시점에 넘긴 경우. 운영·재무에 알림

핵심은 하드 단계를 전체 차단이 아니라 클래스 선택적으로 만드는 것이다. 100%에서 전부 막으면, 이미 쓰기로 한 저렴한 코딩 보조 기능까지 멈춰서 오히려 손해다. 무엇을 먼저 끊을지는 장애 순간이 아니라 미리 레지스트리 설정에 정책으로 적어 둔다.

파일럿 예산에는 반드시 만료일을 둔다. 만료 없는 파일럿 예산은 사연이 붙은 상시 예산일 뿐이다.

4. 알림은 심각도 세 단계, 의미를 고정한다

비용 알림이 실패하는 전형적인 모습은 두 가지다. 알림이 너무 많아서 무시되거나, 중요한 알림이 엉뚱한 채널에 묻히거나.

심각도의미보내는 곳
info예측 정보, 조치 불필요팀 채널
warn이번 주 안에 조치 필요팀 채널 + 팀 리드
crit지금 당장 위험플랫폼 온콜 + 장애 관리 시스템 웹훅

예를 들어 "기능의 7일 비용이 30일 평균의 3배"는 warn, "팀 일일 비용이 평소의 5배"나 "단일 요청이 기준 금액 초과"는 crit이다. 같은 이벤트를 채널(사람용)과 웹훅(시스템용)으로 함께 보내고, 웹훅 페이로드 스키마는 고정해 둔다.

5. 대시보드에 넣지 않을 것도 정한다

대시보드는 네 개면 된다. 조직 전체 실시간 비용, 팀별 예산 소진, 모델별 비용(폴백 비율과 캐시 절감 포함), 사용자별 비용(공개 범위 제한).

요청별 비용은 대시보드에 넣지 않는다. 그건 트레이스에서 본다. 대시보드는 집계, 트레이스는 현미경이다. 현미경을 대시보드에 올리면 아무도 믿지 않는 로그 뷰어가 된다.

사용자별 비용 순위도 기본값은 팀 범위 공개로 둔다. 미터링 데이터 자체는 개인정보가 아니어도, "누가 가장 많이 쓰나" 순위표는 사회적 파급력이 있다.

6. 월말에는 공급자 청구서와 대사한다

게이트웨이 장부의 합계를 공급자 청구서와 비교하고, 허용 오차를 넘으면 crit 알림을 띄운다. 차이가 나는 흔한 원인은 캐시 토큰 미분리, 추정치 비중 증가, 가격표 갱신 누락이다. 요청 시점 가격 스냅샷이 있으면 이 비교가 쿼리 몇 줄로 끝난다.


정리

  • 토큰은 종류별로 나누고, 요청 시점 가격을 이벤트에 스냅샷으로 남긴다
  • 귀속 축은 모델·팀·사용자·기능 네 개
  • 예산은 단계별 동작으로 설계하고, 하드 차단은 비싼 클래스에만
  • 알림은 info/warn/crit 의미를 고정하고 채널과 웹훅을 분리
  • 월말 대사로 장부를 검증한다

이 글은 제가 쓴 『AI 게이트웨이 플레이북』 한국어판 4장(쿼터, 예산, 비용 통제)을 요약한 것입니다. 책에는 모델 레지스트리, 키리스 인증과 6단계 RBAC, MCP 서버, RAG 어시스턴트, 운영 런북과 40개 항목 체크리스트까지 담았습니다. 책은 저의 실무 경험을 바탕으로 AI 도구의 도움을 받아 집필·번역했습니다.

profile
DevOps 엔지니어 · LLM 게이트웨이, 쿠버네티스, GitOps

0개의 댓글