Code › tail-villain
LLM 비용에 예산선 두기
LLM 사용량이 늘어도 비용을 통제할 수 있도록 서버에 예산 경계를 둔 과정
LLM 기능은 잘 돌아가도, 비용이 어디까지 커질 수 있는지 모르면 제품이라고 부르기 어렵다.
tail-villain은 대화를 많이 한다. 로드맵을 만들고, 면접 질문을 던지고, 답변을 평가하고, 학습 리포트를 만든다. 사용자가 오래 연습할수록 제품 가치는 커지지만, 동시에 호출 횟수와 context 길이도 늘어난다. 그냥 좋은 모델을 붙이고 자연스럽게 대화하게 두면, 사용량이 늘수록 비용도 선형으로 커질 수 있다.
그래서 4월 26일부터 28일까지는 백엔드가 비용 상한과 계산 규칙을 강제하도록 운영 경계를 추가했다.
첫 번째 기준은 token cap이었다.
LLM 호출은 입력과 출력이 모두 비용으로 이어지고, 특히 출력 길이를 제품이 통제하지 않으면 한 번의 응답이 예상보다 길어질 수 있다. 이런 응답이 여러 사용자에게 반복되면 금방 운영 리스크가 되기 때문에, backend LLM operation에 필수 max output limit을 두고 입력도 schema validation을 거치도록 했다.
프론트에서 길이를 제한하는 것만으로는 부족했다. 사용자는 브라우저를 거치지 않고 API를 호출할 수도 있고, 프론트 로직은 실수로 우회될 수도 있기 때문에 비용에 직접 영향을 주는 규칙은 백엔드가 소유해야 했다.
이건 보안 규칙과 비슷하다. 화면에서 버튼을 숨기는 것과 서버에서 권한을 확인하는 것은 다르고, LLM 비용도 UI가 조심하는 것과 서버가 예산선을 강제하는 것이 다르다.
두 번째는 context 길이였다.
인터뷰 세션의 모든 메시지를 LLM에 계속 넣으면 한 턴이 쌓일 때마다 다음 호출의 입력 token과 비용이 증가한다. 사용자가 오래 연습할수록 제품 비용도 계속 커지는 구조다.
그래서 interview service에는 sliding window를 넣었다. 최근 대화 일부만 보내고 필요한 요약과 상태는 별도로 들고 가는 방식인데, 모든 원문을 매번 다시 보내지 않아도 현재 흐름을 유지할 수 있어야 했다.
물론 context를 줄이면 잃는 것도 있다. 오래된 발언의 세부 표현이나 앞선 모순을 놓칠 수 있다. 그래서 이 결정은 모델 품질을 무시한 비용 절감이 아니라, 세션이 길어져도 제품이 계속 동작하도록 하는 trade-off였다. 기억해야 할 것은 상태로 남기고, 매 턴에 다시 읽어야 하는 것은 제한한다.
비용을 다루기 시작하면 admin 화면도 단순 관리 도구가 아니게 된다.
4월 26일에는 user management와 함께 cost simulator가 붙었다. LLM 제품에서 unit economics를 확인하는 화면은 모델과 가격 정책을 결정하는 운영 도구다. 어떤 모델을 쓰고, 입력과 출력 token이 얼마나 나오며, 사용률이 올라가면 margin이 어떻게 변하는지 봐야 한다.
처음 simulator는 화면에서 계산하는 부분이 많았다. 빠르게 반응한다는 장점은 있지만, 수익률이나 가격 같은 business rule이 프론트에 남아 있으면 안 된다. 프론트 계산은 누구나 바꿔볼 수 있고, 시간이 지나면 백엔드 규칙과 어긋날 수 있다.
그래서 4월 28일에는 financial calculation logic을 backend로 옮겼다. 프론트는 입력을 받고 결과를 보여주는 역할에 집중하고, 비용과 margin을 계산하는 규칙은 서버가 담당한다. DTO validation과 error handling도 같이 붙여서, simulator가 단순 계산기가 아니라 제품 규칙을 반영하는 admin tool이 되도록 했다.
4월 27일의 refactor는 이 방향을 더 넓혔다.
cost simulator는 특정 vendor 몇 개만 가정하면 금방 낡는다. 그래서 모델 동기화 로직에서 vendor-specific filter를 제거하고, 유료 모델을 더 일반적으로 다룰 수 있게 바꿨다. 무료 모델은 제외하고, dropdown에서는 pricing metric과 profitability 기준으로 고를 수 있게 정리했다.
여기서 중요한 건 모델 목록을 많이 보여주는 게 아니었다. 운영자가 선택할 때 비용 구조를 같이 보게 만드는 것이었다. 같은 기능이라도 모델에 따라 응답 품질, 속도, 입력 비용, 출력 비용이 다르게 움직인다. simulator는 그 차이를 감으로 고르지 않게 해주는 장치다.
정렬 방향을 바꾸고, leaderboard처럼 보이던 중복 table을 덜어낸 것도 같은 맥락이었다. admin UI는 화려한 비교표보다 결정을 돕는 정보가 먼저다.
UX는 계산의 신뢰와 붙어 있었다.
simulator가 느리거나 flicker가 있으면 숫자를 믿기 어렵다. 그래서 state update를 paint cycle에 맞추고, 입력값이 바뀌면 짧게 debounce된 auto-simulation이 돌도록 했다. usage rate slider도 추가했다. 단순히 한 명의 평균 비용을 보는 게 아니라, 실제 사용률에 따라 margin이 어떻게 흔들리는지 확인하려면 그런 조절 장치가 필요했다.
loading skeleton이나 spinner도 사소해 보이지만, admin 화면에서는 중요하다. 데이터가 아직 안 온 것인지, 계산이 실패한 것인지, 값이 0인 것인지 구분되지 않으면 운영 판단이 흔들린다. 비용 화면에서 애매한 UI는 곧 애매한 의사결정으로 이어진다.
이 작업을 하면서 LLM 제품의 비용 관리는 나중에 붙이는 회계 기능이 아니라는 생각을 했다. token cap, context window, 모델 선택, simulator, admin rule은 모두 제품 동작의 일부다.
사용자에게는 자연스러운 대화처럼 보여야 한다. 하지만 내부에서는 한 턴마다 얼마까지 허용할지, 얼마나 많은 맥락을 다시 읽을지, 어떤 모델을 쓸지, 그 선택이 margin을 어떻게 바꾸는지 계속 관리해야 한다.
AI 기능은 마법처럼 보일수록 좋지만, 비용 구조까지 마법처럼 두면 오래 못 간다.
그래서 이날의 핵심은 비용을 아끼는 게 아니었다. 비용을 제품의 통제 가능한 상태로 끌어오는 일이었다.