
API 비용 청구서를 받고 멍해진 적 있으신가요? 저는 뉴스 기사 100개를 자동 요약하는 배치 작업을 돌리고 나서 그 기분을 처음 느꼈습니다. 입력 토큰보다 출력 토큰이 더 많이 나온 청구서였는데, 원인을 파고들다 보니 생각보다 단순한 데 있었습니다. 출력 토큰을 줄이는 방법은 여러 갈래가 있고, 어떤 방향이 맞는지에 대해서도 의견이 갈립니다. 직접 실험하면서 정리한 내용을 공유합니다.
전처리 텍스트가 비용을 얼마나 잡아먹는가
배치 작업을 돌렸을 때 모델이 매번 이런 식으로 출력을 시작하고 있었습니다. "이 기사는 경제 분야를 다루고 있으며, 다음과 같은 내용을 요약하겠습니다." 요약 본문이 나오기 전에 이미 토큰을 수십 개씩 써버리는 것이었습니다. 100개 기사면 그 전처리 텍스트만으로도 무시하지 못할 분량이 됩니다.
여기서 전처리 텍스트(preamble)란 모델이 본문 답변을 시작하기 전에 자동으로 붙이는 도입 문장을 말합니다. 쉽게 말해 "알겠습니다, 제가 이런 방식으로 답변하겠습니다" 같은 자기 선언 문구입니다. 모델 입장에서는 자연스러운 흐름이지만, API를 쓰는 입장에서는 순수한 낭비입니다.
"전처리 설명 없이 요약만 바로 출력해줘"라는 한 줄을 프롬프트에 추가했더니 출력 길이가 30% 줄었습니다. 솔직히 이건 예상 밖이었습니다. 한 줄짜리 지시가 비용의 30%를 건드릴 줄은 몰랐거든요. 그 한 줄을 쓰기 전까지 저는 비용 최적화를 위해 모델 선택이나 배치 처리 방식을 고민하고 있었습니다. 정작 가장 쉬운 개선이 프롬프트 안에 있었던 겁니다.
이 경험을 하고 나서 저는 출력 최적화의 순서에 대해 생각을 바꾸게 됐습니다. 많은 분들이 max_tokens나 JSON 구조화를 먼저 떠올리는데, 사실 가장 먼저 해야 할 건 불필요한 껍데기를 걷어내는 것입니다. 내용을 줄이기 전에 불필요한 포장을 없애는 것이 먼저입니다.
같은 논리로 후처리 텍스트(postamble), 즉 "이상으로 답변을 마치겠습니다. 추가 질문이 있으시면 언제든지"로 끝나는 마무리 문구도 제거 대상입니다. 이런 마무리 문구는 사람과 대화할 때는 자연스럽지만, 자동화 파이프라인에서는 순전한 비용입니다. 제거하지 않을 이유가 없습니다.
JSON 출력 강제로 구조화된 토큰 절약
JSON 출력 방식은 출력 토큰 절약에서 가장 확실한 효과를 보여줬습니다. "제목, 핵심 내용, 키워드를 JSON으로 반환해줘"라고 지시하면 모델은 필드 값만 채워 넣습니다. 자유 텍스트 요약 대비 토큰이 절반 이하로 줄었고, 파싱도 훨씬 쉬워졌습니다.
구조화된 출력(Structured Outputs)이란 JSON 스키마를 미리 지정해서 모델이 그 형식에 맞는 출력만 내놓도록 강제하는 방식입니다. OpenAI API에서는 이 기능을 공식 파라미터로 지원하고 있습니다. 스키마를 지정하면 필요한 필드만 출력에 나오기 때문에 설명 텍스트가 끼어들 공간이 처음부터 없습니다.
구조화된 출력이 효과적인 상황을 정리하면 다음과 같습니다. 데이터 파이프라인에서 특정 필드만 추출해야 할 때, 같은 작업을 수천 건 단위로 반복하는 배치 처리, 출력 결과를 곧바로 DB나 다른 시스템에 넣어야 할 때, 모델 답변의 형식 일관성이 품질에 직결되는 작업이 해당됩니다.
다만 JSON 형식이 모든 상황에 맞는 건 아닙니다. 서사형 글쓰기나 창의적 작업에서 JSON을 강제하면 오히려 출력 품질이 떨어집니다. 구조화된 출력은 정보 추출 작업에 특화된 도구라고 보는 게 맞습니다. 이걸 모든 작업에 적용하려는 충동을 경계해야 합니다. 저도 한동안 모든 프롬프트에 JSON을 강제해보다가 창의적 작업의 결과가 딱딱하고 제약된 느낌이 된다는 걸 뒤늦게 알았습니다.
max_tokens 파라미터 — 쓰면 편하지만 조심해야 하는 이유
max_tokens 파라미터를 쓰면 API 레벨에서 출력 길이를 강제로 제한할 수 있습니다. max_tokens란 모델이 한 번의 호출에서 생성할 수 있는 최대 토큰 수를 지정하는 파라미터입니다. 쉽게 말해 모델이 아무리 길게 쓰고 싶어도 이 숫자를 넘기면 강제로 잘린다는 뜻입니다.
여기서 제가 직접 써봤는데 느낀 문제가 있습니다. 모델이 문장 중간에서 잘려버리는 케이스가 생각보다 자주 발생합니다. 특히 JSON을 출력하다가 닫는 괄호 전에 잘리면 파싱 오류가 나고, 코드 블록이 중간에 끊기면 실행 자체가 안 됩니다. 이 경우 짧은 출력으로 아낀 토큰보다 오류 처리와 재시도에 쓰는 비용이 더 커집니다.
저는 max_tokens를 초기 설정에 빡빡하게 넣었다가 몇 번 깨진 뒤 이 파라미터에 대한 관점이 바뀌었습니다. "아끼는 도구"가 아니라 "안전망"으로 써야 한다는 것입니다. 평균 출력이 200토큰이라면 max_tokens는 300~400 정도로 잡는 게 현실적입니다. 파라미터로 빡빡하게 제한하는 것보다 프롬프트로 불필요한 내용을 줄이는 방향이 훨씬 안전합니다.
이 교훈을 더 일찍 배웠더라면 좋았을 것입니다. max_tokens로 비용을 절감하려다 오히려 재시도 비용이 발생하는 건 꽤 아이러니한 상황입니다. 비용을 줄이려는 설정이 비용을 늘리는 결과를 낳은 셈이니까요.
프롬프트 지시의 구체성이 일관성을 만든다
"짧게 요약해줘"라고 하면 모델마다, 때마다 결과가 다르게 나옵니다. "세 줄 이내"라고 해도 어떤 때는 짧은 세 줄, 어떤 때는 긴 세 줄이 나옵니다. 제가 직접 테스트해본 결과, "각 줄은 30자 이내, 총 세 줄"처럼 수치 기준을 명확히 하면 출력 일관성이 눈에 띄게 좋아졌습니다.
프롬프트 엔지니어링에서 말하는 출력 형식 제어(output format control)란 이처럼 길이, 구조, 형식을 프롬프트 안에서 명시적으로 지정하는 기법입니다. Anthropic 가이드에서도 모호한 길이 지시보다 구체적인 형식 지시가 효과적이라고 명시하고 있습니다.
여기서 제가 추가로 비판하고 싶은 지점이 있습니다. "짧게 답해줘"라는 지시로 출력을 줄이면 모델이 중요한 맥락이나 예외 상황 설명을 생략하는 경우가 생깁니다. 특히 코드 생성이나 전문 분석 작업에서 이런 식으로 출력을 무조건 줄이는 건 위험하다고 생각합니다. 짧은 출력으로 아낀 비용보다 그 오류를 수습하는 데 드는 시간과 비용이 훨씬 크게 돌아온 적이 제 경험상 한두 번이 아닙니다. 비용을 줄이는 것과 품질을 유지하는 것은 동시에 고려해야 하는 제약입니다. 어느 한쪽만 최적화하면 다른 쪽에서 반드시 손실이 옵니다.
출력 토큰 최적화의 올바른 순서
출력 토큰 최적화에서 우선순위를 정리하면 이렇습니다. 전처리·후처리 텍스트 제거가 첫 번째입니다. 불필요한 껍데기부터 없앱니다. 출력 형식 구체화가 두 번째로, 수치 기준으로 지시합니다. 구조화된 출력 적용은 데이터 추출 작업에 한정해 활용합니다. max_tokens 파라미터는 안전망으로만 씁니다.
결국 출력 토큰 절약의 핵심은 내용을 억지로 줄이는 게 아니라 불필요한 출력을 처음부터 만들지 않는 구조를 만드는 것입니다. 프롬프트 한 줄이 비용을 30% 바꿀 수 있다는 걸 직접 겪고 나서 프롬프트를 대하는 태도가 달라졌습니다. 어떤 방식이 자신의 작업에 맞는지 작은 단위로 실험해보는 것, 그게 가장 빠른 길입니다.
참고:
OpenAI API 레퍼런스 (max_tokens 파라미터) https://platform.openai.com/docs/api-reference/chat/create
Anthropic 출력 형식 제어 가이드 https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/control-output-format
OpenAI 구조화된 출력(Structured Outputs) 가이드 https://platform.openai.com/docs/guides/structured-outputs
Weights & Biases 프롬프트 엔지니어링 코스 https://www.wandb.courses/courses/prompting
OpenAI 토크나이저 도구 https://platform.openai.com/tokenizer