토큰 비용은 누가 지불하는가? 사용자의 지갑을 털지 않는 AI 플러그인 설계하기
요약
AI 플러그인 설계 시 발생하는 토큰 비용 부담 문제를 다룹니다. 사용자가 직접 API 키를 등록하고 결제해야 하는 과정에서 발생하는 높은 이탈률을 방지하기 위한 설계 전략과 비용 구조의 변화를 설명합니다.
핵심 포인트
- 사용자에게 직접적인 결제 요구는 높은 이탈률을 유발함
- AI 서비스가 고정 요금제에서 사용량 기반 결제로 전환되는 추세임
- 제공자(Shipping side) 관점에서의 비용 설계가 제품 성공의 핵심임
- 결제 전 무료 체험(Free trial)을 통한 온보딩 경험 제공이 중요함
제 AI 챗봇 플러그인에서 가장 큰 이탈이 발생한 지점은 기능 페이지나 설정 화면이 아니었습니다. 바로 이 문장 바로 앞이었습니다: "API 키를 가져오고 결제를 설정하세요." 사람들은 플러그인을 설치했습니다. 활성화도 했습니다. 하지만 한 번도 들어본 적 없는 회사의 카드 정보를 등록하고, 눈에 보이는 가격도 없는 수도꼭지(faucet)를 열어야 하는 시점에서 떠나버렸습니다. 저는 설치 횟수와 실제로 실행된 채팅 수를 비교하고 나서야 이 사실을 알게 되었습니다. 그 격차는 거대한 협곡과 같았습니다.
토큰 비용이라는 이 보이지 않는 수도꼭지는 제작자가 아닌 사용자 측에서 열립니다. 저는 WordPress 플러그인을 제작하며 AI가 포함된 제품을 출시하는데, 이러한 비대칭성을 깨닫는 데 시간이 좀 걸렸습니다. 이 포스트는 비용을 두 개의 지갑, 즉 AI를 사용하는 측(당신이 지불함)과 AI를 제공하는 측(사용자가 지불함)으로 나누어 설명하며, 제가 실제로 작성한 방어 기제들을 바탕으로 두 번째 측을 위한 설계에 대부분의 시간을 할애합니다.
설정 (Setup)
가격과 요금제는 빠르게 변합니다. 아래 내용은 제가 확인했을 당시를 기준으로 하며, 각 벤더의 가격 페이지에서 확인하시기 바랍니다. 코드는 뼈대(skeleton) 형태입니다. 가격 테이블, 통화 형식, 제공업체 분기(provider branching), 그리고 귀하의 측면에서의 nonce 체크를 직접 채워 넣으세요.
- 사용하는 측 (Using side): Claude 구독 (현재 가격 확인 필요), Codex CLI
- 제공하는 측 (Shipping side): OpenRouter, 다양한 제공업체 API
- 대상: 직접 제작한 WordPress 플러그인 (AI 챗봇)
비용은 누군가의 지갑으로 들어간다
최근까지 AI 도구들은 고정된 월간 요금제였습니다. 하지만 그 체계가 무너지고 있습니다. GitHub Copilot은 에이전트 기반 워크로드(agentic workloads)가 고정 요금 모델을 지속 불가능하게 만든다는 근거를 들어, 2026년 6월 1일자로 요청 횟수 대신 입력(input), 출력(output), 그리고 캐시된 토큰(cached tokens)에 의해 소비되는 크레딧을 사용하는 사용량 기반 결제(usage-based billing) 방식으로 전환했습니다.
이 소식에 따른 일반적인 규칙은 간단합니다. AI 연산에는 실제 비용이 들며, 그 돈은 누군가의 지갑으로 들어간다는 것입니다. 고정 요금제는 단지 제공업체가 그 비용을 흡수하여 사용자에게 매끄러운 표면만을 보여주었을 뿐입니다. 사용량 기반 결제는 수도꼭지를 다시 사용자에게 돌려주었습니다. 1인 개발에서도 마찬가지입니다. 당신이 지불하거나, 사용자가 지불해야 합니다. 비용은 허공에 떠 있을 수 없습니다.
사용하는 측 vs 제공하는 측
당신이 지불할 때는 주도권을 쥐게 됩니다. 고정 요금제(Flat)와 사용 사례별 종량제(Metered)로 나누고, 자율 실행(Autonomous runs)의 길이를 청크(Chunk) 단위로 조절하며, 턴(Turn)당 부하를 가볍게 유지하세요. 이는 당신의 작업 방식에 맞춰 확장되므로 관리가 용이한 상태를 유지할 수 있습니다.
어려운 쪽은 제공하는 측(Shipping side)입니다. 제품에 AI를 넣으면 당신이 설계하는 동안 사용자가 비용을 지불하게 됩니다. 당신의 지갑에는 자연스러운 제동 장치가 있어 비싸다고 느껴지는 것은 사용하지 않지만, 당신의 제동 장치는 사용자의 지갑까지 닿지 않습니다. 위에서 언급한 이탈률(Drop-off)은 바로 이러한 비대칭성이 가시화된 결과입니다.
또한 당신에게 불리하게 작용하는 WordPress 특유의 가정이 있습니다. 사람들은 플러그인이 무료로 작동할 것이라고 기대합니다.
이 방법이 가장 효과적이었습니다. 결제 수단을 등록하기 전에 사용자가 채팅이 한 번 실행되는 것을 볼 수 있게 하세요. 저는 온보딩 (Onboarding) 과정에서 OpenRouter의 무료 티어 (Free tier)를 사용하여 처음에는 API 키 및 카드 등록 단계를 건너뛸 수 있도록 합니다. 작동하는 것을 확인한 후에야 사용자는 실제 사용을 위한 키 (Key) 등록을 고민하게 됩니다.
하지만 무료 티어가 근간이 되어서는 안 됩니다. 무료 티어에는 속도 제한 (Rate limit)과 속도 제한이 있으며, 서비스 제공업체의 변심에 따라 약관이 변경될 수 있습니다. 이를 "한 번 체험하기" 용도의 입구로 취급하고, 처음부터 사용자의 자체 키로 넘어가는 경로를 보여주세요. 무료 티어에 의존하는 설계는 해당 티어의 정책이 변경되는 날 바로 작동을 멈추게 됩니다.
설계 단계에서 폭주를 막는 제한 사항 (Caps)
일일 상한선 (Daily ceiling)은 총량을 제한하고, 최소 간격 (Minimum interval)은 연속적인 호출이나 에러 루프 (Error loops)를 방지합니다. 특히 간격 보호 (Interval guard)가 가장 중요합니다. 아무도 지켜보지 않는 동안 호출이 무한 루프를 도는 최악의 상황은 대부분 이 하나의 체크만으로도 방지할 수 있습니다.
function rapls_chat_check_limits( $user_id, $daily = 100, $min_interval = 2 ) {
$today = 'rapls_chat_count_' . $user_id . '_' . gmdate( 'Ymd' );
$last = 'rapls_chat_last_' . $user_id;
...
폭주 (Runaways) 현상은 악의적인 의도뿐만 아니라 단순한 설정 실수나 에러 루프로 인해서도 발생합니다. 이것은 사용자를 신뢰하느냐의 문제가 아닙니다. 선의의 사고는 언제든 발생할 수 있으므로, 설계 단계에서 그 경로를 차단해야 합니다.
모델 계층화 (Model tiering): 저렴하게 시작하고, 필요할 때만 격상하기
단순한 질문에 최상위 모델을 사용하는 것은 과잉 대응입니다. 사용자의 명시적인 선택을 우선하되, 그렇지 않은 경우에는 요청의 비중에 따라 라우팅 (Route)하고, 답변이 부실할 경우 한 번만 모델을 격상 (Escalate)하세요.
function rapls_chat_pick_model( $user_id, $message ) {
$chosen = get_user_meta( $user_id, 'rapls_chat_model', true );
if ( $chosen ) {
...
주의할 점이 있습니다. 격상이 실행될 때 해당 요청은 저렴한 모델과 강력한 모델 모두를 실행하게 되므로 비용이 두 배로 들 수 있습니다. 재시도 (Retry)를 한 번으로 제한하고, 두 번의 호출 모두 상한선 (Cap)에 포함시키며, 격상 조건은 엄격하게 유지하세요. 저렴하게 처리하되, 반드시 필요할 때만 높이세요.
입력 및 출력 토큰 (Tokens) 전송량 줄이기
고정된 시스템 프롬프트 (System Prompt)는 매번 동일하므로, 제공업체 (Provider)가 지원한다면 이를 캐시 (Cache)하고 변경되는 질문만 전송하세요. 출력 토큰 (Output Tokens)은 종종 입력 토큰 (Input Tokens)보다 비용이 더 많이 들기 때문에, 응답 길이를 제한하고 간결하게 작성하도록 유도하세요. 짧고 핵심을 찌르는 답변이 지갑과 채팅 모두에 더 좋습니다. 제공업체별 차이점 (엔드포인트 (Endpoint), 인증 (Auth), 캐시 지시문 (Cache Directive)의 형태 등)은 rapls_chat_call_api 내부에 유지하여 상위 코드에서 신경 쓰지 않도록 하세요.
function rapls_chat_call_api( $model, $message, $options = array() ) {
$provider = rapls_chat_provider_of( $model );
$system = rapls_chat_system_prompt(); // 고정된 페르소나, 매번 동일함
...
캐시 지시문의 형태, 엔드포인트, 인증 방식은 모두 제공업체마다 다르므로, 위의 예시는 한 벤더의 스타일을 따르고 있습니다. 실제 코드에는 분기 처리가 필요하며 사양이 변경될 수 있으므로 최신 문서를 확인하세요. OpenRouter와 같이 여러 제공업체를 전면에 내세운 단일 엔드포인트를 사용하면 이러한 분기 처리를 줄일 수 있으며, 무료 티어 온보딩 (Onboarding)과도 잘 어우러집니다.
투명성: 보이지 않는 수도꼭지를 보이는 것으로 바꾸기
기록된 사용량에 가격표를 곱하여 대략적인 수치를 산출하고 이를 보여주세요. 먼저 예상치를 보여준 다음, 월간 누적액을 보여줍니다.
const RAPLS_CHAT_PRICE = array(
'cheap-model' => array( 'in' => 0.0, 'out' => 0.0 ), // 가격표를 참조하여 채움
'strong-model' => array( 'in' => 0.0, 'out' => 0.0 ),
...
이를 사용자의 프로필 화면 모델 선택기 옆에 표시하면, 사용자가 스스로 조정할 수 있습니다. 예상치는 실제 청구서와 일치하지 않을 것이므로 '예상치'라고 라벨을 붙이세요. 그럼에도 불구하고 사용량과 대략적인 수치를 확인하는 것만으로도 불안감이 크게 줄어듭니다. 왜냐하면 불안의 원인은 금액 그 자체가 아니라, 알 수 없다는 사실이었기 때문입니다.
내가 저지른 실수들
- 좋은 결과물을 만들면 사람들이 비용을 지불할 것이라고 가정하는 것. 벽(Wall)은 비용을 지불하지 않습니다. 그들은 얼마를 내야 할지 모를 뿐입니다.
- 최상위 모델 (Top model)을 기본값으로 설정하는 것. 사용자 입장에서는 가장 비싼 수도꼭지를 조용히 끝까지 틀어버리는 것과 같습니다.
- 한도 (Caps) 없이 출시하는 것. 당신의 지갑은 본능적으로 멈추지만, 당신의 본능은 사용자의 지갑까지 닿지 않습니다.
- 무료 진입로를 독점하는 것. 사용자가 문 앞에서 주춤한다면, 보호해야 할 수익 자체가 발생하지 않습니다.
- 답변이 길수록 친절하다고 생각하는 것. 긴 답변은 비용이 더 많이 들고, 읽는 데 시간이 더 걸리며, 채팅에서는 장황하게 느껴집니다.
이 모든 실수들은 사용하는 사람의 관점이 아닌, 배포하는 사람의 관점으로 설계했기 때문에 발생했습니다.
미래의 나에게 남기는 노트
토큰 비용은 항상 누군가의 지갑으로 청구됩니다. 당신이 지불할 때는 고삐를 쥐고 있지만, 제품을 출시할 때는 당신이 설계하는 동안 사용자가 비용을 지불하게 되는 반전이 발생합니다. 먼저 어떤 지갑을 목표로 할지 결정하세요. 'Bring-your-own-key (사용자 본인의 API 키 사용)' 방식은 진입로를 구축하는 데 공을 들이는 것을 의미하며, 'Author-pays (개발자 지불)' 방식은 한도와 가격 책정을 방어하는 것을 의미합니다. 그다음 무료 진입로, 선택 가능한 모델, 티어링 (Tiering), 한도 설정, 그리고 투명성을 고려하세요. 이 모든 것은 당신이 지불하지 않는 수도꼭지 너머에 다른 누군가의 지갑이 있다는 사실을 기억하기 위한 방법입니다.
사용자 화면에 직접 보이는 미터기(Meter)를 구현하는 것은 여전히 나의 할 일 목록에 있습니다. 수도꼭지 반대편에는 항상 지갑이 존재합니다. 그것이 내가 잊지 말아야 할 부분입니다.
참고 문헌
원문은 Zenn에 일본어로 작성되었습니다. 저는 WordPress 플러그인을 만듭니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기