LLM API를 처음 서비스에 붙였을 때 비용 계산은 단순해 보였다.
(물론 비용이 발생하니 과다하게 호출하는 것 관련해선… 고민 많이 했습니다. 아래 내용 보시면 아시겠지만…)
모델마다 입력 토큰과 출력 토큰 가격이 공개되어 있으니 사용한 토큰 수에 단가를 곱하면 된다.
개념적으로는 맞다.
입력 비용
=
입력 토큰 수 × 입력 토큰 단가
출력 비용
=
출력 토큰 수 × 출력 토큰 단가
총 비용
=
입력 비용 + 출력 비용
그런데 실제 서비스를 운영하면서 내가 궁금했던 것은 단순히 이번 달에 API 비용이 얼마 나왔느냐가 아니었다.
더 중요한 질문들이 생겼다.
어떤 기능이 비용을 가장 많이 사용하고 있는가?
검색 한 번에 평균 얼마가 발생하는가?
사용자가 늘어나면 비용이 어느 정도까지 증가할 수 있는가?
프롬프트를 수정한 뒤 비용이 왜 늘었는가?
RAG에 검색 문서를 더 많이 넣으면 비용이 얼마나 증가하는가?
같은 사용자가 검색 한 번을 했는데 실제 LLM 호출은 몇 번 발생했는가?
이 질문들은 월말 카드 청구액만 보고는 알 수 없었다.
그래서 도서 검색·추천 서비스를 운영하면서 검색 기록뿐 아니라 LLM 호출량과 추천 문장 사용량을 로그로 남기고, 월 단위 비용을 따로 계산하는 구조를 만들게 됐다.
월 총액만 알고 있으면 원인을 알 수 없다
예를 들어 한 달 API 비용이 20달러에서 다음 달 40달러가 되었다고 하자.
숫자만 보면 비용이 두 배가 됐다는 사실은 알 수 있다.
하지만 원인은 전혀 알 수 없다.
가능한 이유는 여러 가지다.
사용자가 두 배로 증가했을 수도 있다.
사용자 수는 그대로인데 검색 횟수가 늘었을 수도 있다.
검색 횟수도 그대로인데 프롬프트가 길어졌을 수도 있다.
RAG Context에 넣는 문서 수가 증가했을 수도 있다.
출력 문장을 더 길게 생성하게 바뀌었을 수도 있다.
한 요청에서 LLM을 호출하는 횟수가 늘어났을 수도 있다.
API 실패 후 재시도가 반복됐을 수도 있다.
이 상황에서 가지고 있는 정보가:
7월 API 비용 = $20
8월 API 비용 = $40
뿐이라면 문제를 분석하기 어렵다.
그래서 비용을 운영 지표로 사용하려면 최종 청구액보다 요청 단위 데이터를 먼저 가지고 있어야 한다고 생각하게 됐다.
내가 필요했던 것은 “API 비용”보다 “기능 하나의 비용”이었다
서비스 운영 관점에서는 모델 하나의 가격보다 기능 하나를 실행하는 데 얼마나 드는지가 더 중요했다.
예를 들어 내 도서 검색·추천 API에서는 사용자 요청 하나가 반드시 LLM 호출 한 번과 같지는 않았다.
흐름을 단순화하면 다음처럼 볼 수 있다.
사용자 검색
↓
검색어 처리
↓
Elasticsearch 검색
↓
도서 후보 생성
↓
LLM 추천 문장 생성
↓
추가 추천 문장 생성
↓
최종 응답
기능을 확장하면 한 사용자 요청에서도 여러 생성 작업이 생길 수 있다.
예를 들어:
추천 이유 생성
책 활용 방법 생성
기대 효과 생성
추천 질문 생성
을 각각 별도의 호출로 구현했다면 사용자가 검색 버튼을 한 번 눌렀다고 해서 API 비용 역시 한 번만 발생한다고 볼 수 없다.
사용자 관점에서는:
검색 1회
지만 서버에서는:
LLM 호출 1
LLM 호출 2
LLM 호출 3
일 수 있다.
이 차이를 모르고:
사용자 한 명이 검색 한 번 하는 데 얼마가 드는가?
를 계산하면 실제 비용을 상당히 잘못 예상할 수 있다.
그래서 비용 계산 단위를 모델이 아니라 기능으로 보기 시작했다
예를 들어 다음 두 기능이 같은 모델을 사용한다고 하자.
기능 A
간단한 추천 문장 하나를 만든다.
입력도 짧고 출력도 짧다.
기능 B
검색된 도서 여러 권의 제목, 저자, 키워드, 설명을 Context에 넣고 상세 추천 문장을 만든다.
둘 다 같은 모델 API를 호출한다.
하지만 비용 구조는 전혀 다를 수 있다.
기능 A
짧은 Prompt
+
짧은 Output
기능 B
System Prompt
+
사용자 질문
+
검색된 도서 Context
+
출력 형식 지시
+
긴 Output
따라서:
이 서비스는 어떤 모델을 사용하니까 요청당 비용이 얼마다.
라고 단순하게 계산하기 어렵다.
실제 비용을 결정하는 것은 모델 가격 × 실제 토큰 사용량 × 호출 횟수다.
그리고 토큰 사용량은 기능마다 달라진다.
입력 토큰은 사용자의 질문만 의미하지 않는다
LLM 비용을 처음 계산할 때 가장 쉽게 놓칠 수 있는 부분이 입력 토큰이다.
사용자가 다음처럼 짧은 질문을 했다고 하자.
마음이 지쳤을 때 읽을 책 추천해줘
사람이 보면 굉장히 짧다.
그래서:
이 정도 질문이면 API 비용도 거의 안 들겠네.
라고 생각하기 쉽다.
하지만 실제 LLM에 전달되는 입력은 사용자 문장 하나가 아니다.
내 서비스처럼 RAG를 사용하는 구조라면 대략 다음이 함께 들어갈 수 있다.
System Prompt
사용자 질문
검색된 책 1 정보
검색된 책 2 정보
검색된 책 3 정보
책별 keywords
책별 description
응답 작성 규칙
JSON 출력 형식
즉 실제 모델이 받는 입력은:
사용자 입력
+
개발자가 만든 Prompt
+
검색 결과 Context
+
출력 지시사항
이다.
그래서 사용자 입력 길이와 입력 토큰 비용은 전혀 같은 개념이 아니다.
RAG에서는 검색 결과 수가 API 비용과 연결된다
이 부분은 앞서 KNN의 k를 설명할 때와도 연결된다.
예를 들어 검색된 책을 3권만 LLM에 전달한다고 하자.
도서 1 description
도서 2 description
도서 3 description
그런데 검색 품질을 높이겠다는 이유로 10권을 전달하도록 바꾼다.
도서 1 description
도서 2 description
...
도서 10 description
검색 결과가 많아졌다는 것은 단순히 Elasticsearch에서 문서를 더 많이 가져왔다는 의미로 끝나지 않는다.
그 정보를 전부 LLM Context에 넣는다면 LLM 입력 토큰도 같이 증가한다.
구조가 이렇게 연결된다.
Retrieval Top K 증가
↓
검색 문서 증가
↓
Context 길이 증가
↓
Input Token 증가
↓
LLM 호출 비용 증가
따라서 RAG에서 Top K는 검색 품질 파라미터이면서 동시에 비용 파라미터가 될 수 있다.
이 때문에:
문서를 많이 넣으면 답변이 더 좋아질 것 같다.
는 이유만으로 Context를 계속 늘리는 것은 좋은 운영 방식이 아닐 수 있다.
실제로 필요한 것은:
답변 품질이 더 좋아지는 데 필요한 만큼의 Context만 제공하는 것
이다.
description 하나가 생각보다 비용에 큰 영향을 줄 수 있다
책 한 권의 정보가 다음 정도라면 큰 문제가 없어 보인다.
title
author
keywords
그런데 description이 포함되면 문서마다 길이가 크게 달라질 수 있다.
예를 들어 책 1권당 설명이 상당히 길고 이를 10권 넣는다고 생각해보자.
책 1 긴 설명
+
책 2 긴 설명
+
책 3 긴 설명
...
+
책 10 긴 설명
여기에 System Prompt와 JSON 출력 지시까지 붙는다.
그러면 사용자 질문은 한 줄인데 실제 API 입력은 훨씬 커질 수 있다.
그래서 비용을 줄인다고 사용자 입력 글자 수를 제한하는 것만으로는 큰 효과가 없을 수도 있다.
오히려 RAG 서비스에서는:
몇 개 문서를 넣고 있는가?
각 문서에서 어떤 필드를 넣고 있는가?
description 전체가 정말 필요한가?
중복되는 정보가 있는가?
를 먼저 확인하는 것이 더 효과적일 수 있다.
입력보다 출력이 더 비싼 모델도 있기 때문에 출력 길이도 중요하다
API 비용을 계산할 때 입력 토큰과 출력 토큰은 별도로 봐야 한다.
OpenAI의 현재 API 모델들도 입력 토큰과 출력 토큰 가격을 구분하고 있으며, 모델에 따라 출력 토큰 단가가 입력보다 높은 구조를 사용한다. 가격은 모델별로 다르고 변경될 수 있으므로 실제 운영에서는 공식 가격표를 기준으로 계산해야 한다.
이 차이가 중요한 이유는 간단하다.
프롬프트를 조금 줄이는 것만 신경 쓰면서 모델에게 다음과 같이 요청할 수도 있기 때문이다.
각 책마다
추천 이유
실용적인 활용 방법
기대 효과
추가 설명
관련 질문
을 자세하게 작성하세요.
출력 요구사항이 늘어날수록 생성되는 토큰 수도 증가할 수 있다.
특히 검색 결과가 여러 권이라면:
책 1 설명
책 2 설명
책 3 설명
...
형태로 출력량이 계속 커질 수 있다.
따라서 비용 최적화에서는:
Prompt가 얼마나 긴가?
뿐만 아니라:
모델에게 얼마나 긴 답을 요구하고 있는가?
도 봐야 한다.
“길게 써주세요”는 생각보다 비싼 요구가 될 수 있다
예를 들어 추천 문장을 만드는 목적이 사용자가 책을 선택하도록 돕는 것이라고 하자.
처음에는 다음 정도면 충분할 수 있다.
이 책을 추천하는 이유를
두 문장으로 설명한다.
그런데 프롬프트를 계속 개선하면서:
추천 이유를 자세하게 설명한다.
실제 활용 방법을 추가한다.
기대되는 효과를 추가한다.
감성적인 문장도 넣는다.
후속 질문 3개를 만든다.
로 확장될 수 있다.
사용자 경험은 좋아질 수 있다.
하지만 기능 하나의 출력도 함께 커진다.
이 과정에서 중요한 것은:
더 자세한 답변이 좋은가?
뿐만 아니다.
늘어난 출력이 실제 사용자 가치만큼 비용을 정당화하는가?
도 판단해야 한다.
이 질문은 가격표만 봐서는 답할 수 없다.
실제 기능별 토큰 로그가 있어야 한다.
그래서 호출할 때 토큰 사용량을 저장하는 것이 중요하다
내가 비용을 다시 설계한다면 LLM 호출마다 최소한 다음 정보를 연결해서 저장한다.
request_id
user_id 또는 익명 식별값
feature
model
input_tokens
output_tokens
total_tokens
estimated_cost
created_at
여기에서 특히 중요한 컬럼이 feature다.
예를 들면:
feature = search_recommendation
feature = personal_sentence
feature = recommend_question
feature = keyword_analysis
처럼 분리할 수 있다.
그러면 같은 모델을 사용해도 어느 기능에서 비용이 많이 발생하는지 알 수 있다.
feature가 없으면 비용을 줄일 위치를 찾기 어렵다
한 달 동안 다음 결과가 나왔다고 생각해보자.
총 입력 토큰: 많음
총 출력 토큰: 많음
총 비용: 증가
이 정보만으로는 무엇을 수정해야 할지 모른다.
반면 기능별로 분리되어 있다면:
검색 추천 45%
개인화 문장 30%
추천 질문 20%
기타 5%
같은 분포를 확인할 수 있다.
이 수치는 예시이지만, 이런 형태의 데이터가 있다면 판단 방법이 달라진다.
예를 들어 추천 질문 생성이 전체 비용의 상당 부분을 차지하는데 실제 사용자가 거의 클릭하지 않는다면 기능 자체를 다시 생각해볼 수 있다.
비용 최적화가:
싼 모델로 바꾸자.
만의 문제가 아니게 되는 것이다.
오히려:
사용자가 거의 쓰지 않는 생성 기능을 매 요청마다 실행하고 있지는 않은가?
가 더 큰 절감 포인트일 수 있다.
내가 실제 서비스에서 로그를 기능별로 나눈 이유
내 도서 검색·추천 서비스에서는 검색 관련 로그와 추천 문장 사용 기록을 별도로 관리하는 구조를 두었다.
예를 들어 검색 자체의 기록과 추천 문장에 관한 기록을 분리하면:
검색이 몇 번 발생했는가
추천 문장이 몇 번 생성됐는가
특정 기능이 얼마나 사용됐는가
를 따로 볼 수 있다.
이 구조는 단순 통계뿐 아니라 비용 분석에도 도움이 된다.
사용자 검색 요청이 1,000건인데 LLM 호출이 3,000건이라면:
검색 1회
=
평균 LLM 호출 3회
같은 구조가 숨어 있을 가능성을 확인할 수 있기 때문이다.
단순히 사용자 수만 가지고 API 비용을 예상하면 이런 차이를 놓칠 수 있다.
비용 계산은 요청 수 × 평균 비용으로 바뀐다
요청별 비용을 가지고 있으면 월 비용 예측도 훨씬 현실적으로 할 수 있다.
예를 들어 실제 로그에서:
기능 A 평균 비용 = CA
기능 B 평균 비용 = CB
기능 C 평균 비용 = CC
를 구했다고 하자.
그러면 예상 월 비용은 다음처럼 계산할 수 있다.
월 비용
=
A 기능 호출 수 × CA
+
B 기능 호출 수 × CB
+
C 기능 호출 수 × CC
이 방식의 장점은 사용자가 늘어날 때 단순히 전체 비용을 배수로 계산하지 않아도 된다는 것이다.
기능마다 사용 빈도가 다르기 때문이다.
“사용자 1명당 비용”도 생각보다 단순하지 않다
예를 들어 월간 사용자 1,000명이 있다고 하자.
이 숫자만으로는 비용을 계산하기 어렵다.
한 사람은 한 달에 한 번 검색하고, 다른 사람은 하루에 20번 검색할 수도 있다.
따라서:
월 사용자 수
보다 비용과 더 직접적으로 연결되는 것은:
사용자당 평균 검색 횟수
검색당 평균 LLM 호출 횟수
호출당 평균 토큰 수
다.
결국 다음과 같은 구조가 된다.
사용자 수
×
사용자당 요청 수
×
요청당 LLM 호출 수
×
LLM 호출당 평균 비용
이 식으로 생각하면 서비스를 무료로 제공할 수 있는 범위나 사용자별 사용 제한을 설계하기도 쉬워진다.
사용 제한은 비용 제어 장치가 될 수 있다
내 서비스에서는 특정 개인화 추천 문장 기능을 무제한으로 생성하지 않고 사용 주기를 제한하는 구조도 사용했다.
이런 제한은 단순히 서버 부하를 줄이는 목적만 있는 것은 아니다.
생성형 AI 기능에서는 호출할 때마다 비용이 발생할 수 있기 때문에 사용량 제한 자체가 비용 예측 가능성을 높여주는 장치가 될 수 있다.
예를 들어 사용자가 계속 새로고침할 때마다 개인화 문장을 새로 생성한다면 같은 사용자에게 같은 목적의 API 비용이 반복해서 발생할 수 있다.
반대로 이미 생성한 결과를 일정 기간 재사용한다면:
첫 요청
→ LLM 생성
→ 결과 저장
다음 요청
→ 기존 결과 재사용
구조가 가능하다.
이때는 LLM 호출을 줄이면서 사용자에게 동일한 기능을 제공할 수 있다.
캐시는 단순 속도 문제가 아니라 비용 문제이기도 하다
캐시를 생각하면 일반적으로 응답속도가 먼저 떠오른다.
하지만 LLM 서비스에서는 재사용 가능한 결과를 다시 생성하지 않는 것 자체가 비용 절감이 될 수 있다.
예를 들어 동일한 책에 대한 기본 소개 문장이 사용자마다 달라질 필요가 없다면 매번 LLM으로 새로 만들 이유가 있는지 검토할 수 있다.
항상 새로 생성해야 하는 데이터
vs
미리 생성해 재사용할 수 있는 데이터
를 구분할 필요가 있다.
OpenAI의 현재 일부 모델에는 cached input에 별도 가격 체계가 적용되기도 하지만, 지원 여부와 가격은 모델마다 다르므로 실제 모델의 공식 문서를 확인해야 한다.
서비스 자체의 애플리케이션 캐시와 API 공급자의 입력 캐싱은 서로 다른 개념이지만, 둘 다 동일한 계산이나 입력을 반복하는 비용을 줄일 수 있는지라는 관점에서는 함께 검토할 수 있다.
실패한 요청과 재시도도 비용에 포함된다
비용 로그를 만들 때 성공한 요청만 집계하면 실제 청구 비용과 차이가 생길 수 있다.
예를 들어 네트워크 문제나 JSON Parsing 실패 때문에 다음과 같은 코드가 있다고 하자.
첫 LLM 호출
↓
응답 형식 오류
↓
재시도
↓
두 번째 호출 성공
사용자에게는 답변 한 번만 보인다.
하지만 API는 두 번 호출됐다.
또 다음처럼 재시도 로직을 강하게 설정해두면:
1차 실패
2차 실패
3차 성공
하나의 사용자 요청이 세 번의 비용으로 이어질 수 있다.
그래서 비용 로그에서는:
사용자 요청 수
≠
LLM API 호출 수
라는 사실을 구분해야 한다.
JSON 출력 오류도 비용 문제다
LLM에게 JSON을 만들게 하고 파싱 실패 시 다시 요청하는 구조도 흔하다.
예를 들어:
추천 결과 생성
↓
잘못된 JSON
↓
Parsing Error
↓
LLM 다시 호출
이 경우 기능적으로는 단순한 출력 형식 오류지만 운영 비용 관점에서는 추가 API 호출이다.
그래서 구조화된 출력을 사용하는 기능에서는:
JSON 성공률
재시도 횟수
평균 LLM 호출 수
까지 측정하면 비용을 더 정확하게 이해할 수 있다.
RAG의 품질 개선이 비용 증가로 이어질 수도 있다
검색 품질을 개선하면서 이런 변경을 했다고 하자.
기존:
Top 3 문서
변경:
Top 10 문서
그리고 각 문서의 description까지 모두 LLM에 넣었다.
답변 품질은 좋아질 수 있다.
하지만 입력 토큰이 크게 증가할 수도 있다.
따라서 RAG 튜닝에서는 두 그래프를 같이 보고 싶다.
검색/답변 품질
vs
요청당 평균 비용
예를 들어:
Top 3
→ 품질 80
→ 비용 1
Top 5
→ 품질 90
→ 비용 1.4
Top 10
→ 품질 91
→ 비용 2.5
같은 결과가 실제 측정에서 나온다면 Top 10이 정말 필요한지 고민할 수 있다.
위 숫자는 원리를 설명하기 위한 예시지만, 이런 방식으로 실제 데이터를 측정해야 한다는 것이 핵심이다.
좋은 품질을 가장 싸게 만드는 것이 목표다
AI 서비스 비용을 줄인다고 하면 가장 먼저 저렴한 모델을 선택하려고 할 수 있다.
하지만 비용 최적화는 단순히 모델 가격 비교가 아니다.
예를 들어 더 저렴한 모델을 사용했는데 출력 실패가 늘어나 재시도가 두 배로 증가한다면 전체 비용이 기대만큼 줄지 않을 수도 있다.
반대로 조금 더 비싼 모델이 한 번에 원하는 구조의 답을 안정적으로 반환한다면 기능 전체 비용에서는 차이가 생각보다 작을 수도 있다.
따라서 내가 보고 싶은 지표는:
Token 단가
하나가 아니다.
오히려:
성공한 사용자 요청 1건을
완료하는 데 실제로 든 총 비용
이다.
이 기준에는 재시도도 포함된다.
환율 때문에 원화 비용은 또 달라진다
API 비용이 달러로 계산된다면 국내 서비스를 운영할 때는 원화 기준 비용도 생각해야 한다.
예를 들어 월 API 비용이 같은 달러 금액이더라도 환율이 변하면 원화 지출은 달라진다.
따라서 월간 비용 보고서를 만든다면:
USD 비용
해당 집계에 적용한 환율
KRW 환산 비용
을 함께 저장하거나 표시하는 편이 좋다.
중요한 것은 환율을 코드에 영구적으로 고정해 두고 몇 년 동안 사용하는 것이 아니다.
어떤 환율을 기준으로 계산했는지 기록해야 나중에 같은 보고서를 다시 봤을 때 숫자의 의미를 알 수 있다.
내가 월간 비용 리포트에서 보고 싶은 항목
월말에 단순히:
이번 달 AI 비용: 38,000원
만 받는 것보다 다음 형태가 훨씬 유용하다.
총 LLM 호출 수
총 Input Token
총 Output Token
기능별 호출 수
기능별 비용
요청당 평균 비용
사용자당 평균 비용
재시도 횟수
전월 대비 증감
USD 비용
원화 환산 비용
이런 정보가 있으면 비용이 증가했을 때 바로 다음 질문으로 넘어갈 수 있다.
사용자가 늘어서 증가했는가?
요청당 비용이 증가했는가?
특정 기능 호출이 늘었는가?
프롬프트가 길어졌는가?
출력량이 늘었는가?
총비용 증가를 두 종류로 나누면 이해하기 쉽다
월 API 비용이 증가하는 원인은 크게 두 종류로 볼 수 있다.
사용량 증가
사용자 증가
검색 증가
LLM 호출 증가
서비스가 성장하면서 자연스럽게 생기는 비용이다.
단위 비용 증가
사용자 수 동일
요청 수 동일
그런데
요청당 Input Token 증가
Output Token 증가
호출 횟수 증가
이 경우는 서비스 변경 때문에 비용 구조가 악화됐을 가능성을 확인해야 한다.
이 둘을 구분하지 않으면 비용이 늘었다는 이유만으로 잘못된 최적화를 할 수도 있다.
사용자가 두 배 늘어 비용이 두 배 된 것은 오히려 정상적인 상황일 수 있다.
반면 사용자 수가 그대로인데 비용이 두 배가 됐다면 원인을 찾아야 한다.
로그가 있으면 프롬프트 변경의 비용도 비교할 수 있다
예를 들어 추천 Prompt를 개선했다고 하자.
기존 Prompt
평균 입력 토큰:
A
평균 출력 토큰:
B
새로운 Prompt
평균 입력 토큰:
C
평균 출력 토큰:
D
그러면 단순히:
새로운 프롬프트의 답변이 더 좋아졌다.
에서 끝나지 않는다.
품질 개선량
vs
비용 증가량
을 같이 볼 수 있다.
특히 하루 요청이 적을 때는 작은 차이가 거의 느껴지지 않는다.
하지만 요청이 10만 건, 100만 건으로 늘어나면 요청당 작은 토큰 차이가 전체 비용에서는 큰 차이가 될 수 있다.
모델 가격을 코드에 박아두는 것도 조심해야 한다
비용 계산 코드를 다음처럼 만들 수 있다.
INPUT_PRICE = ...
OUTPUT_PRICE = ...
작은 프로젝트에서는 충분할 수 있다.
하지만 모델 가격이 변경되거나 모델을 교체하면 과거 로그의 비용 계산과 현재 비용 계산이 섞일 수 있다.
그래서 내가 다시 만든다면 가격 정보도 최소한 다음 기준으로 관리하고 싶다.
model
input_price
output_price
effective_from
그러면 요청 발생 당시의 모델과 가격을 기준으로 계산할 수 있다.
OpenAI API의 모델별 요금은 현재도 입력·캐시 입력·출력 등으로 구분되며 모델별 가격 차이가 있으므로 운영 서비스에서는 특정 블로그 글에 적힌 가격을 영구적인 상수처럼 사용하는 것보다 공식 모델 가격을 기준으로 관리하는 것이 안전하다.
실제 비용 계산식은 이렇게 본다
텍스트 모델의 기본 비용 구조를 단순화하면 다음처럼 표현할 수 있다.
Input Cost
=
Input Tokens
÷ 1,000,000
×
Model Input Price per 1M Tokens
Output Cost
=
Output Tokens
÷ 1,000,000
×
Model Output Price per 1M Tokens
따라서:
Request Cost
=
Input Cost
+
Output Cost
이다.
하지만 실제 서비스에서는 여기서 한 단계 더 나아간다.
Feature Cost
=
같은 사용자 기능을 완료하기 위해 발생한
모든 LLM Request Cost의 합
이 값이 내가 정말 알고 싶은 비용이다.
가장 중요한 지표는 결국 “유용한 결과 한 건의 비용”이다
토큰 수를 줄이는 것 자체가 서비스 목표는 아니다.
사용자에게 좋은 검색·추천 결과를 제공하는 것이 목적이다.
그래서 비용을 지나치게 줄여:
Context를 거의 제거
출력을 지나치게 짧게 제한
검색 후보도 최소화
했는데 결과 품질이 크게 떨어진다면 좋은 최적화라고 보기 어렵다.
반대로 Context와 출력을 무조건 크게 만들어 비용을 많이 쓰는 것도 좋은 구조는 아니다.
결국 내가 찾고 싶은 것은:
사용자가 만족할 만한 결과 한 건을 만드는 최소 비용
이다.
이 기준을 잡으려면 품질 지표와 비용 지표를 함께 기록해야 한다.
지금 다시 비용 로그를 설계한다면
현재 서비스를 다시 설계한다면 LLM 호출 기록을 다음 정도까지 남기고 싶다.
request_id
feature
model
input_tokens
output_tokens
cached_tokens
api_call_count
retry_count
estimated_usd
user_id_hash
created_at
그리고 검색 요청 로그와 request_id로 연결한다.
검색 요청
↓
request_id
↓
Elasticsearch 검색 로그
↓
LLM 호출 로그
↓
추천 결과 로그
그러면 사용자 요청 한 건이 시스템 내부에서 어떤 비용으로 이어졌는지 추적할 수 있다.
이렇게 하면 비용과 품질 문제를 같은 요청에서 볼 수 있다
예를 들어 어떤 검색 결과가 좋지 않았다고 하자.
request_id를 기준으로 확인하면:
검색어
Hybrid/KNN 결과
RAG Context
LLM Model
Input Tokens
Output Tokens
최종 추천 문장
비용
을 한 번에 볼 수 있다.
그러면 이런 질문에도 답할 수 있다.
Context를 많이 넣었는데 실제로 답변 품질이 좋아졌는가?
비용은 두 배가 됐는데 검색 결과에는 차이가 없었는가?
특정 검색어에서 반복적으로 토큰이 많이 사용되는 이유는 무엇인가?
이 지점부터 비용 로그가 단순 회계 데이터가 아니라 AI 서비스 튜닝 데이터가 된다.
마무리
LLM API 비용을 처음 볼 때는 모델 가격표부터 보게 된다.
입력 토큰 얼마, 출력 토큰 얼마를 확인한 뒤:
생각보다 싸다.
또는:
생각보다 비싸다.
라고 판단하기 쉽다.
하지만 실제 서비스를 운영하면서 더 중요한 것은 모델 하나의 단가가 아니었다.
사용자 기능 하나를 완료하기 위해 실제로 몇 번 호출하고, 얼마만큼의 입력과 출력을 사용하는가가 훨씬 중요했다.
특히 RAG 서비스에서는 사용자가 입력한 한 문장보다 검색 결과 Context가 훨씬 많은 입력 토큰을 만들 수 있다.
검색 결과를 더 많이 넣으면 Retrieval 품질에는 도움이 될 수 있지만 LLM 비용도 함께 증가할 수 있다.
추천 이유, 활용 방법, 기대 효과, 후속 질문처럼 생성 기능을 계속 추가하면 사용자 요청 하나가 여러 번의 LLM 호출로 이어질 수도 있다.
재시도와 JSON Parsing 실패 역시 사용자에게는 보이지 않지만 비용에는 포함된다.
그래서 지금은 AI 서비스 비용을 다음 순서로 생각한다.
모델 단가
↓
호출당 Token
↓
기능당 호출 횟수
↓
사용자당 기능 사용량
↓
월간 사용자 수
↓
전체 운영 비용
그리고 이 구조를 이해하려면 결국 요청 단위 로그가 있어야 한다.
월말 청구서는 얼마를 썼는지는 알려준다.
하지만 왜 그렇게 썼는지는 알려주지 않는다.
그래서 검색·추천 서비스를 다시 운영한다면 비용 데이터도 검색 품질 로그처럼 처음부터 설계할 것이다.
어떤 요청이 얼마나 많은 Context를 사용했고, 몇 번의 LLM 호출을 만들었으며, 얼마의 비용으로 어떤 결과를 생성했는지를 연결해서 볼 수 있게 만드는 것이다.
그 데이터가 있어야 비로소:
모델을 더 저렴한 것으로 바꿀지,
RAG Context를 줄일지,
출력 길이를 줄일지,
호출 자체를 캐시할지,
사용 빈도가 낮은 생성 기능을 제거할지
를 근거를 가지고 결정할 수 있기 때문이다.