“쓸수록 더 잃는다” LLM 토큰 비용 통제 전략 5가지
기업에서는 난해한 클라우드 청구서의 내용을 해석하기 위한 목적으로 핀옵스 부서를 구축하는 데만 10년을 소비했다. 그렇게 해서 유휴 컴퓨팅 인스턴스가 실행 상태로 방치되지 않도록 하는 방법을 알아냈는데, 그 성과를 즐길 틈도 없이 이번에는 생성형 AI로 인해 이보다 훨씬 더 불투명하고 변화의 속도도 빠른 지출 계층이 새로 탄생했다.
충격적인 AI 청구서는 허리케인처럼 업계 전반을 강타하고 있다. 대규모 언어 모델(LLM) 비용의 급증도 문제지만 아키텍처 측면에서 더 심층적인 문제는 바로 귀속이다. 돈이 정확히 어디로 가고 있으며, 그것이 비즈니스에 정확히 어떤 가치를 제공하고 있는가?
API 호출이 자동화된 에이전트와 프롬프트 템플릿 계층으로 둘러싸이면 애플리케이션은 블랙박스가 되어 토큰 생성에 자본을 소비한다. 기능 엔진이 LLM으로 인사말을 출력하거나 저가치 데이터를 처리하는 데 매달 수천 달러를 소비한다면 그건 혁신이 아니라 뚜껑이 열린 맨홀, 즉 위험한 구멍이 된다. 아키텍처 성숙이란 토큰을 다른 모든 제한된 리소스와 동일하게 취급하는 것을 의미한다.
다행히 AI 지출을 통제하는 데 활용할 수 있는 몇 가지 유용한 옵션이 존재한다. 이 글에서 소개하는 5가지 핵심 도구다.
모델 라우팅
압정만으로 해결할 수 있는 작업에 네일건을 꺼내들지 말라.
클로드 오퍼스(Claude Opus) 같은 최신 고성능 모델은 현존하는 가장 정교한 소프트웨어 시스템이다. 극히 복잡하고 난해한 사용례를 처리할 역량을 갖췄지만 컴퓨팅, 즉 비용도 그만큼 막대하게 소비한다. 많은 상황에서 이런 모델은 필요 이상으로 과도하다.
사람들은 API와 요구사항을 프로토타이핑하고 구상할 때 자연스럽게 가용한 가장 강력한 모델부터 시작한다. 제대로 작동하도록 하는 것이 주 목적이지, 모델의 한계를 붙잡고 씨름하고 싶어하지는 않기 때문이다. 그러나 프로덕션에서는 사용 가능한 가장 낮은 성능의 모델을 찾아내는 것이 절대적으로 중요하다.
경우에 따라서는 모델 선택을 조정하고 수작업을 통해 어떤 모델이 작동할지 찾아내는 방식으로 대처할 수 있다. 그러나 규모가 큰 엔터프라이즈 아키텍처에서는 조건부 라우팅 계층을 사용하는 방법이 있다 라우트LLM(RouteLLM), 시맨틱 라우터(Semantic Router)와 같은 프레임워크를 사용하면 단순 분류, 기본적인 텍스트 파싱, 사용자 의도 감지 등을 GPT-4o 미니(mini), 클로드 3 하이쿠(Haiku)와 같은 빠르고 저렴한 유틸리티 모델로 동적으로 전달할 수 있다.
라우팅과 지출 배분에 고급 AI 게이트웨이를 사용할 수도 있다. 인프라 수준에서 이 로직을 전용 AI API 게이트웨이(예를 들어 콩(Kong), 클라우드플레어 AI 게이트웨이(Cloudflare AI Gateway), 포트키(Portkey) 등)로 감싸면 궁극적인 통제력을 얻게 된다. 성숙한 게이트웨이를 사용하면 “캐스케이드 라우팅”을 구현해서 주 LLM이 속도 제한이나 지연 급증에 직면할 때 더 저렴한 모델 또는 오픈소스 모델로 자동으로 전환할 수 있다. 더 중요한 것은 AI API 게이트웨이가 텔레메트리를 중앙화해 블랙박스를 제거한다는 점이다. 따라서 테넌트 또는 마이크로서비스별로 엄격한 토큰 예산을 적용할 수 있다. 인지 작업을 위한 로드 밸런서를 구축하는 셈이다.
물론 AI 게이트웨이 자체도 복잡성과 비용을 수반하므로 그런 요소를 반영해 균형을 맞춰야 한다. 핵심은 프로젝트에 맞는 적절한 크기의 모델이 있다는 것이다. 당면한 작업을 완수하기에 충분히 좋은 골디락스 모델로 요청을 라우팅함으로써 상당한 비용을 절약할 수 있다.
참고: 모델 라우팅의 또 다른 추세는 “컴퓨팅 송환”이다. 컴퓨팅 송환이란 클라우드에서 생성형 AI 엔드포인트를 임대하지 않고 로컬 하드웨어에서 모델(많은 경우 오픈소스 모델)을 실행하는 것을 의미한다. 즉, 다른 온프레미스 옵션의 모든 절충과 혜택이 여기에도 적용된다.
시맨틱 캐싱
전통적인 웹 앱에서 캐싱은 해결된 문제다. 데이터베이스 앞에 레디스(Redis)를 두고, 정확한 쿼리를 캐시된 페이로드에 매핑하면 끝이다. 그러나 LLM에서는 전통적인 캐싱이 작동하지 않는다. 인간의 언어가 갖는 무한대의 변동성 때문이다. “비밀번호를 어떻게 재설정하나요?”와 “로그인 정보를 잊어버렸어요”는 전달하는 의도는 동일함에도 서로 완전히 다른 문자열이다.
지나치게 정확한 일치에 의존하면 적중률(hit rate)이 사실상 0이 되고 모든 표현 치환에 대해 전체 토큰 비용을 지불해야 한다.
바로 이 부분에 시맨틱 캐싱이 활용된다. 시맨틱 캐싱은 의미의 정규식이라고 할 수 있다. 원시 텍스트 문자열을 해시하지 않고, 입력되는 프롬프트를 빠른 임베딩 모델에 집어넣어 이전에 답변한 프롬프트와의 유사성을 검색한다. 신뢰도 임계값(예를 들어 0.92)을 설정하고 임계값을 충족하면 캐시된 응답을 제공한다(LLM을 생략하므로 관련 비용이 전혀 발생하지 않음).
이렇게 하면 아키텍처 측면에서 이중의 효과를 얻게 된다. 첫째, 시맨틱 캐시 적중 시 그쿼리의 추론 비용은 정확히 0이 된다. 둘째, 응답 지연이 몇 초에서 몇 밀리초 수준으로 낮아진다. GPT캐시(GPTCache)와 같은 전용 프레임워크를 사용하거나, 더 가벼운 인프라를 선호한다면 기존 포스트그레SQL 데이터베이스 내에서 pgvector를 사용해 임베딩을 저장하고 매칭하는 방법으로도 구현할 수 있다.
단, 동적 라우팅과 마찬가지로 시맨틱 캐싱에도 엄격한 아키텍처 측면의 계산이 필요하다. 생성 비용을 임베딩 및 조회 비용과 맞바꾸는 것이기 때문이다. 캐시를 확인하기 위해서도 여전히 프롬프트를 토큰화하고 저렴한 모델(예: text-embedding-3-small)을 호출하고 벡터 검색을 실행해야 한다.
또한 시맨틱 평탄화도 실질적인 위험이다. 유사성 임계값 튜닝은 섬세한 작업이다. 너무 낮게 설정하면 애플리케이션은 미묘한 차이가 있는 여러 사용자 질문에 포괄적이고 매번 재활용되는 답변을 내놓기 시작한다. 시맨틱 캐싱은 개방적이고 창의적인 생성형 AI 애플리케이션에서는 사실상 쓸모가 없지만 검색 증강 생성(RAG) 구현, 고객 지원 봇, 내부 지식 기반과 같이 사용자가 똑 같은 20개의 질문을 1,000가지 방식으로 묻는 환경에서는 사용 가능한 가장 효과적인 비용 절감 수단이다.
프롬프트 캐싱
시맨틱 캐싱이 주어진 의도에 대한 응답을 저장한다면 프롬프트 캐싱은 질문을 컨텍스트화하는 데 필요한 데이터를 저장한다. 사용자가 입력한 프롬프트는 생성형 AI 엔드포인트로 전송된다. 그러나 애플리케이션이 RAG 파이프라인, 데이터베이스 또는 기타 소스에서 프롬프트를 구성하는 데 필요한 방대한 컨텍스트 정보를 반복적으로 수집하고 전송하는 것이 아니라 컨텍스트 캐시에 해당 정보가 사전에 로드된다. 모델은 캐시된 데이터에 새 질문을 적용하기만 하므로 지연과 입력 비용이 모두 대폭 절감된다.
프롬프트 캐싱의 핵심 개념은 입력되는 프롬프트에 대한 관련 컨텍스트 데이터를 AI 엔진 자체가 보존한다는 것이다. 이렇게 캐시된 토큰의 비용은 원시 입력 토큰에 비해 50~90%나 할인된다. 다만 처리 방식은 업체마다 다르다.
오픈AI의 경우 프롬프트 캐싱이 자동으로 적용되지만, 잘 활용하려면 앱이 엔드포인트를 어떻게 사용하는지에 주의를 기울여야 한다. 오픈AI가 강제하는 최소 임계값은 1,024토큰이다. 더 중요한 점은 토큰 0부터 시작해 바이트 단위까지 정확한 프리픽스 매치가 필요하다는 것이다. 시스템 명령의 최상단에 동적 변수(예를 들어 타임스탬프나 사용자 ID)를 삽입하는 경우 캐시가 즉시 무효화되고, 모든 후속 토큰에 대해 정가가 청구된다.
앤트로픽 클로드와 구글 제미나이 등은 명시적 캐싱을 사용한다. 전용 API 엔드포인트를 통해 정적 문서(컨텍스트 데이터)를 지정된 TTL과 함께 업로드하거나, JSON 페이로드에 엄격한 캐시 제어 중단점을 삽입하는 방법으로 아키텍처에 명확히 캐시를 설계해 넣어야 한다. 명시적 캐싱에서는 많은 경우 “쓰기 프리미엄”을 선불로 지불해야 하지만 무거운 RAG 데이터가 몇 분이 아닌 몇 시간 동안 메모리에 유지되도록 보장할 수 있다.
프롬프트 규율
모델이 방대한 양의 토큰을 소비할 수 있다고 해서 반드시 그걸 다 소비해야 하는 것은 아니다.
지금은 하나의 프롬프트에서 100만~200만 개의 토큰을 소화할 수 있는 여러 모델이 존재한다. 따라서 이 성능만 믿고 PDF 파일 전체, 코드 베이스 전체 또는 지난 3년 동안의 로그를 페이로드에 쏟아붓고 LLM이 알아서 처리하도록 하는 주먹구구식 사용례에 대한 유혹이 생길 수밖에 없다.
핀옵스 관점에서는 이렇게 하면 안 된다. 보내는 모든 토큰에는 비용이 따른다. 게다가 엔지니어링 관점에서도 컨텍스트 윈도우를 가득 채우면 “혼탁한 중간(muddy middle)”, 즉 컨텍스트 부패에 직면한다. 컨텍스트 부패란 모델이 콘텐츠 중간 부분의 정보를 제대로 파악하지 못하는 현상이다. 페이로드가 커질수록 성능과 정확도가 떨어진다.
이 문제에 대한 해결책은 엄격한 RAG 다이어트다. 느슨한 RAG 구현에서는 벡터 데이터베이스에서 상위 20개 결과를 가져와 무작정 프롬프트에 이어 붙일 수 있다. 아키텍처의 성숙을 위해서는 이런 토큰이 고가의 LLM에 도달하기 전에 훨씬 더 엄격한 필터링 프로세스가 필요하다.
여기서 리랭킹(reranking)이 핵심이 된다. 리랭킹은 수집된 프롬프트 컨텍스트를 가져와 효율적으로 구조화된 다음 LLM에 도달하도록 한다. 원시 검색 결과를 주 모델로 바로 보내는 것이 아니라, 작고 매우 효율적인 크로스 인코더(예: 코히어 리랭크(Cohere Rerank) 또는 오픈소스 BGE 모델 등)를 사용한다. 저렴한 벡터 데이터베이스에 그물을 넓게 던져 50개의 잠재적인 일치 항목을 가져온 다음 리랭커로 전달해서 사용자의 구체적인 프롬프트를 기준으로 실질적인 관련성을 점수화한다. 리랭커는 쓸데없는 덩어리를 가차 없이 걷어내 관련성이 극히 높은 상위 3~4개의 청크만 값비싼 프론티어 모델에 전달되도록 한다.
방대하고 값비싼 LLM 컨텍스트 페이로드 대신 작고 저렴한 리랭링 단계를 사용하는 것이다. 아키텍처 관점에서 계산해 보면 이 방식이 거의 항상 압도적으로 유리하다. 크로스 인코더로 인해 파이프라인에 100밀리초의 지연이 추가될 수 있지만 프롬프트 토큰 수를 80% 이상 줄이는 동시에 최종 생성 결과의 정확도도 높여준다. 생성형 AI 비용 플레이북에서 LLM이 읽어야 할 양을 줄이는 것은 투입 대비 효과가 매우 큰 수단 중 하나다.
응답 제약
기본적으로 LLM은 정중하고 대화에 적극적이며 말을 장황하게 한다. API에 데이터를 요청하면 곧바로 “여기 요청하신 JSON입니다”로 시작해 “다른 필요한 것이 있으면 알려주세요!”라고 끝맺는다.
웹 인터페이스에서는 이 특성이 매력적이다. 그러나 애플리케이션의 API 아키텍처 관점에서 보면 비용이 줄줄 새는 구멍이다. 생성 토큰(출력)은 거의 대부분 프롬프트 토큰(입력)보다 3~5배 비싸다. 즉, 사교적인 인사말 하나하나가 가장 값비싼 상품을 소모하는 셈이다.
LLM의 응답을 적절히 조정하기 위해서는 API 수준의 엄격한 통제가 필요하다. 첫째, max_tokens는 서식 툴이 아니라 통제 불능의 생성 루프를 차단하는 장치로 취급해야 한다(max_tokens에 의존해 응답을 줄이면 잘려서 파싱할 수 없는 JSON이 결과로 생성되는 경우가 많음). 둘째, 중지 시퀀스(stop_words)를 사용한다. 모델이 SQL 쿼리 하나만 출력하면 되는 경우 마크다운 닫힘 태그(“`) 또는 단어 “Explanation:”을 중지 시퀀스로 설정하면 계산 작업이 끝나는 순간 모델이 연결을 끊도록 강제할 수 있다.
또한 현대의 API는 사용자가 정의한 엄격한 스키마를 따르도록 모델을 강제하는 구조화된 출력(또는 엄격한 JSON 모드)도 갖췄다. 이것을 무관용 시스템 프롬프트(“유효한 JSON만 출력해. 불필요한 대화 텍스트와 인사말은 모두 생략해. 이 원칙을 어기면 시스템이 작동하지 않는다”)와 결합해 사용하면 LLM은 챗봇이 아니라 전통적인 API 엔드포인트처럼 동작하게 된다.
아키텍처 측면의 균형을 위해서는 여기서 모델의 추론 능력이 저하될 정도로 엄격하게 입력을 제한하지 말아야 한다. LLM은 내부 작업 메모리 없이 토큰 출력을 반복하면서 “생각한다”. 따라서 복잡한 논리 문제를 풀도록 지시하고는 추론할 여지를 주지 않고 true 또는 false라는 하나의 부울 값을 출력하도록 강제하면 정확도가 크게 떨어지게 된다. 핀옵스의 진정한 목표는 단어 수의 최소화를 강제하는 것이 아니라, 값비싼 모든 출력 토큰이 실제 계산 작업(예를 들어 연쇄적 사고 추론)을 수행하도록 하는 것이다.