본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 24. 18:43

Multi-Shot vs Zero-Shot: 예시를 추가하는 것이 실제로 정확도를 떨어뜨리는 경우

요약

최신 지시어 튜닝 및 추론 모델 환경에서 과거의 Few-shot 방식이 오히려 성능 저하를 일으킬 수 있음을 경고합니다. 예시가 노이즈로 작용하여 정확도를 낮추고 토큰 비용을 높이는 구체적인 상황을 분석합니다.

핵심 포인트

  • 최신 모델은 예시 없이도 지시어만으로 충분히 작업 수행 가능
  • Few-shot 예시가 모델의 출력을 특정 패턴으로 편향시킬 위험 존재
  • 고재현율 추출 작업 시 예시가 모델의 추출 범위를 제한할 수 있음
  • 불필요한 예시 추가는 토큰 비용 상승과 성능 퇴보를 유발

도서: Prompt Engineering Pocket Guide: Techniques for Getting the Most from LLMs
저자의 다른 저서: Thinking in Go (2권 시리즈) — Complete Guide to Go Programming + Hexagonal Architecture in Go
내 프로젝트: Hermes IDE | GitHub — Claude Code 및 기타 AI 코딩 도구를 사용하여 작업하는 개발자를 위한 IDE
나: xgabriel.com | GitHub

"Few-shot 예시를 추가하세요"는 인터넷에서 가장 많이 제공되는 프롬프트(Prompt) 조언입니다. Stack Overflow, Twitter, 그리고 프롬프트 엔지니어링(Prompt-engineering)을 다루는 YouTube 채널의 절반이 그렇게 말합니다. 2022년에는 이 방식이 매우 잘 작동했습니다. 하지만 현재는 실제 운영(Production) 작업의 상당 부분에서 적극적으로 틀린 조언이 되었습니다. 예시가 단순히 도움이 되지 않는 수준을 넘어, 정확도를 떨어뜨리고, 토큰(Token) 비용을 폭증시키며, 출력을 예시가 취한 형태에 편향되게 만듭니다. 결국 성능 저하(Regression)를 배포하고는 모델을 탓하게 됩니다. 이 포스트는 성능 저하가 운영 환경에 도달하기 전에 이를 포착하는 방법에 관한 것입니다.

Cargo Cult가 되어버린 2022년의 조언
GPT-3가 최첨단(Frontier)이었던 시절, Few-shot은 작은 기적이었습니다. 기본 모델(Base model)은 작업 프레임워크(Task framings)를 즉각적으로 이해하지 못했습니다. 정답이 어떤 모습이어야 하는지 보여주어야만 했습니다. "언어 모델은 Few-shot 학습자이다(language models are few-shot learners)"라는 용어를 만든 2020년 논문은 단순히 멋을 부리려던 것이 아니었습니다. 그것은 실제적인 능력의 격차였습니다.

모델 세대가 세 번 지나면서 상황이 변했습니다. 지시어 튜닝된 모델(Instruction-tuned models, 예: GPT-4o, Claude Sonnet 4, Gemini 2.5)은 예시 없이도 "이 텍스트에서 모든 날짜를 추출하여 JSON으로 반환하세요"라는 명령을 이해합니다. 추론 모델(Reasoning models, 예: o-series, 확장된 사고 기능을 가진 Claude Opus, Gemini의 사고 변형 모델들)은 한 발 더 나아갑니다. 이들은 종종 작업을 설명하고 한 단계 물러나 생각할 때 더 나은 성능을 보입니다. 이때 예시는 모델이 실제 입력값으로부터 모호함을 해소해야 하는 노이즈(Noise)가 되어버립니다.

조언은 업데이트되지 않았습니다. 사람들은 2022년의 블로그 포스트가 시켰다는 이유만으로 Claude 4.7 프롬프트에 똑같은 "여기에 입력이 있고, 여기에 출력이 있습니다" 패턴을 붙여넣습니다. 그러고는 왜 자신의 평가(Evals) 결과가 이상하게 나오는지 의아해합니다.

예시가 해가 되는 세 가지 작업 형태
모든 작업이 그런 것은 아닙니다. Few-shot은 여전히 좁은 범위의 분류(Narrow classification), 새로운 출력 형식(Novel output formats), 그리고 몇 가지 수학적 패턴(이에 대해서는 나중에 더 자세히 다룹니다)에서는 제 역할을 합니다.

하지만 세 가지 형태에서는 예시를 추가할 때 정확도가 떨어지며, 이 세 가지는 실제 서비스(production) 환경에서 끊임없이 나타나는 형태들입니다.

첫째, 고재현율 추출 (High-recall extraction). 문서에서 특정 클래스에 속하는 모든 엔티티(entity)를 추출하는 작업입니다. 이름, 날짜, 품목(line items), 청구 참조(claim references), 트랜잭션 ID 등이 이에 해당합니다. 실패 모드(failure mode)는 다음과 같습니다: 하나의 예시가 200단어 분량의 지문에서 4개의 날짜를 추출한다면, 모델은 암묵적으로 "이 작업은 약 4개의 항목을 반환한다"라고 학습하게 되고, 실제 문서에 11개가 있더라도 4개에서 멈춰버립니다. 재현율(Recall)이 떨어지는 것입니다. 해결책은 더 긴 예시를 제공하는 것이 아닙니다. 그것은 단지 기준점(anchor)을 옮길 뿐입니다. 해결책은 예시를 아예 제공하지 않는 것입니다.

둘째, 창의적 생성 (Creative generation). 마케팅 문구, 대체 텍스트(alt text), 특정 어조를 가진 요약 등이 해당합니다. 이때 예시는 프롬프트 내에서 가장 구체적인 요소가 되므로, 모델은 예시의 리듬, 문장 길이, 어휘를 그대로 복제합니다. 당신은 다양성을 원했지만, 결과물은 모두 예시와 똑같이 들리는 50개의 출력물을 얻게 됩니다. 더 나쁜 것은, 랜딩 페이지의 A/B 테스트에서 모델의 예시 문구가 실제 서비스 문구에 그대로 유출되는 현상이 나타나기 시작한다는 점입니다. 해결책은 어조를 산문(prose) 형태로 설명한 뒤 모델을 믿는 것입니다.

셋째, 엄격한 형식 지시 이행 (Strict-format instruction-following). "A, B, C 필드를 포함한 JSON으로 출력할 것; 서문 금지; 마크다운 펜스(markdown fences) 금지"와 같은 지시입니다. 스키마만 제공하고 예시를 넣지 않은 버전은 Claude 4나 GPT-4o에서 잘 작동합니다. 하지만 원샷(one-shot) 예시를 추가하면 모델은 예시의 구조적 선택 사항들, 즉 인용 스타일, 필드 순서, JSON을 코드 펜스로 감쌀지 여부 등을 복제하기 시작합니다. 만약 예시에 마지막 줄바꿈(trailing newline)이 포함되어 있었다면, 이제 출력물의 절반에 마지막 줄바꿈이 포함될 것입니다. 결함을 하드코딩(hard-coded)해버린 셈입니다.

이 세 가지 공통된 패턴은 다음과 같습니다: 예시가 과도하게 기준점(over-anchors) 역할을 한다는 것입니다. 모델은 예시를 힌트(hint)가 아닌 선례(precedent)로 취급합니다. 이미 작업을 이해하고 있는 모델에게 이는 퇴보(regression)입니다.

왜 최첨단 추론 모델(frontier reasoning models)이 퓨샷(few-shot) 계산법을 뒤집는가: 추론 모델은 답변하기 전에 생각합니다. 모델은 계획을 세우고, 스케치하고, 수정하기 위해 숨겨진 토큰(hidden tokens)을 할당합니다. 당신이 퓨샷 예시를 건네주면, 모델은 실제 문제를 해결하는 대신 예시의 구조를 모방하는 데 추론 예산(reasoning budget)을 소비합니다. 이는 추적 도구(trace tools)를 통해 직접 확인할 수 있습니다.

사고 추적(thinking trace)은 예시를 참조하고, 이를 모방하려 시도하며, 자신의 출력을 그에 맞추도록 스스로를 제약합니다. 모델이 처음부터 스스로 추론하기를 원하는 작업에서 이는 일종의 세금(tax)과 같습니다. o-series 문서는 이를 명시적으로 지적합니다: 퓨샷 프롬프팅(few-shot prompting)을 최소화하고, 명확한 작업 설명을 선호하십시오. Claude 4.x를 위한 Anthropic의 프롬프트 엔지니어링(prompt-engineering) 가이드에서도 확장된 사고(extended thinking)에 대해 동일하게 언급합니다. 예시는 추론 체인(reasoning chain)을 단락(short-circuit)시킬 수 있습니다. 이는 사소한 효과가 아닙니다. 제가 내부적으로 한 팀이 실행하는 것을 본 '형식 포함 수학(math-with-formats)' 벤치마크에서, Claude Opus의 확장된 사고 모드에 대해 3-shot 프롬프트를 제로샷(zero-shot)으로 전환했을 때 정확도가 6포인트 변동되었습니다. 퓨샷 버전은 그들이 실제로 배포해 오던 버전이었습니다.

당신의 작업에서 이를 증명하는 30줄의 절제 실험(ablation)
이 글을 맹신하지 마십시오. 모델 카드(model card)도 맹신하지 마십시오. 실제 작업과 실제 데이터를 사용하여 절제 실험(ablation)을 직접 수행하십시오. 30줄의 Python 코드입니다:

import asyncio
import json
from anthropic import AsyncAnthropic

client = AsyncAnthropic()
MODEL = "claude-sonnet-4-5"
ZERO_SHOT = "Extract every date mentioned in the text. Return JSON array of ISO-8601 strings. No preamble."
FEW_SHOT = ZERO_SHOT + """
Example input: " We met on March 3rd 2024 and again on the 7th. "
Example output: [ " 2024-03-03 " , " 2024-03-07 " ] """

async def run ( prompt : str , text : str ) -> list [ str ]:
    msg = await client . messages . create (
        model = MODEL ,
        max_tokens = 512 ,
        messages = [{
            " role " : " user " ,
            " content " : f " { prompt } \n\n Text: \n { text } "
        }],
    )
    return json . loads ( msg . content [ 0 ]. text )

async def main ( eval_set : list [ dict ]) -> None :
    for variant , prompt in [( " zero " , ZERO_SHOT ), ( " few " , FEW_SHOT )]:
        preds = await asyncio . gather (
            * [ run ( prompt , row [ " text " ]) for row in eval_set ]
        )
        hits = sum ( set ( p ) == set ( r [ " truth " ]) for p , r in zip ( preds , eval_set ))
        print ( f " { variant } : { hits } / { len ( eval_set ) } exact-match " )

asyncio . run ( main ( json .

load(open("eval.json")))))) 그것이 전부입니다. 실제 트래픽에서 추출한 50개의 라벨링된 예시를 대상으로 실행해 보면, 1분도 채 되지 않는 실제 시간(wall time) 내에 그 격차(또는 격차의 부재)를 확인할 수 있습니다. 절대적인 점수보다 중요한 것은 정답의 형태입니다. 만약 50개의 샘플 전체에서 Zero-shot (제로샷)이 4점 차이로 승리한다면, 귀하의 Few-shot (퓨샷) 프롬프트는 정확도와 토큰을 낭비하고 있는 것입니다.

정직하게 실행하기 위한 두 가지 참고 사항이 있습니다. 첫째, 예시를 다양하게 구성하십시오. 좋지 않은 Few-shot 결과는 패턴의 문제가 아니라 잘못된 예시 때문일 수 있습니다. 세 가지 다른 예시를 시도해 보십시오. 세 가지 모두 Zero-shot에 패배한다면, 해당 패턴이 작업에 적합하지 않은 것입니다. 둘째, 점수뿐만 아니라 오답을 살펴보십시오. 만약 Few-shot은 재현율 부족(under-recalling)으로 실패하고 Zero-shot은 환각(hallucinating)으로 실패한다면, 이는 해결 방법이 다른 서로 다른 문제입니다.

예시가 실제로 도움이 되는 경우
Few-shot은 여전히 세 가지 작업 형태에서 제 역할을 다합니다. 따라서 무조건 버리지는 마십시오.

1. 명확하지 않은 라벨을 가진 좁은 도메인의 분류 (Narrow-domain classification): 예를 들어, `T1-billing-disputed-charge`와 같은 이름이 붙은 14개의 내부 카테고리로 지원 티켓을 분류하는 경우입니다. 모델은 라벨만 보고 귀하의 분류 체계(taxonomy)가 무엇을 의미하는지 알 수 없습니다. 클래스당 두 개의 예시를 제공하면 모델은 경계선을 학습하게 되며, 명확한 라벨의 경우 One-shot (원샷)만으로도 충분합니다. 정확도가 "추측" 단계에서 "유용" 단계로 도약합니다.

2. 새로운 출력 형식 (Novel output formats): 아무도 본 적 없는 커스텀 DSL (Domain-Specific Language) 형태의 출력이 필요한 경우입니다. 내부 규칙 엔진을 위한 설정값이나 맞춤형 쿼리 언어 등이 해당됩니다. 이때는 설명하지 말고 보여주십시오. 모델은 산문(prose)보다 예시를 더 빠르게 파싱하기 때문에, 두 개의 예시가 400단어 분량의 명세서보다 효과적입니다.

3. 수학을 위한 Few-shot Chain-of-thought (사고의 사슬): "단계별로 생각해 보자"라는 트릭을 풀이 과정이 포함된 예시와 결합하는 방식입니다. 이는 여전히 효과가 있습니다. 예시는 정답의 형태가 아니라 추론 스타일(reasoning style)을 고정(anchor)하며, 수학에서는 이것이 승리 요인입니다. 추론 모델(Reasoning models)들은 이미 이 방식을 상당 부분 흡수했지만, 비추론 계층(생각 과정을 거치지 않는 Sonnet, GPT-4o-mini 등)에서는 여전히 수치를 변화시킵니다.

만약 귀하의 작업이 이 세 가지에 해당하지 않는다면, 기본적으로 Zero-shot을 사용하고 Ablation (절제 연구)을 통해 예시가 도움이 된다는 것이 증명될 때만 예시를 추가하십시오.

예시의 개수보다 길이가 더 중요합니다. 대부분의 팀이 놓치는 부분이 바로 여기입니다. 손실은 예시의 개수가 아니라 예시의 길이에 따라 커집니다. 각 예시가 15 토큰(tokens)인 Five-shot 프롬프트는 괜찮습니다. 하지만 단 하나의 예시가 800 토큰(전체 문서와 전체 추출 내용 포함)인 One-shot 프롬프트는 조용히 정확도를 망가뜨리는 주범이 됩니다. 모델은 실제 입력을 처리하는 동안 '이것이 좋은 예시이다'라는 800 토큰의 정보를 Attention (주의 집중) 메커니즘 내에 유지해야 합니다. 이 과정에서 신호 대 잡음비 (Signal-to-noise ratio)가 무너집니다.

토큰 경제성 (Token economics) 측면에서도 같은 방향의 문제가 발생합니다. Prompt Caching (프롬프트 캐싱, Anthropic의 cache_control 또는 OpenAI의 automatic prefix caching)을 통해 고정하지 않는 한 예시는 캐싱되지 않습니다. 만약 One-shot 예시가 800 토큰인데 백만 건의 요청을 보낸다면, 동일한 예시를 반복하는 데 8억 토큰을 소비하게 됩니다. 이는 정확도를 저해할 뿐만 아니라 다섯 자리 숫자의 청구 금액을 만들어낼 수 있는 비용 문제입니다.

두 가지 실무적인 규칙을 제안합니다: 첫째, 각 예시의 길이를 해당 작업에 대한 모델의 유효 컨텍스트 윈도우 (Context window)의 약 10% 이내로 제한하십시오. 만약 2k 토큰 입력을 처리하고 있다면, 각 예시는 200 토큰 미만이어야 합니다. 공격적으로 다듬으십시오. 모델에는 전체 문서가 필요한 것이 아니라, 입출력의 형태 (Input-output shape)가 필요할 뿐입니다. 만약 예시를 해당 제한치 이하로 압축할 수 없다면, 해당 작업에는 아마도 다른 기술이 필요할 것입니다. Schema-guided decoding (스키마 가이드 디코딩), Structured Output API (구조화된 출력 API), 또는 Fine-tuning (미세 조정)이 운영 경제성 측면에서 '거대하고 고정된 예시'를 사용하는 것보다 훨씬 낫습니다.

긴 예시가 진정으로 필요한 경우에는 Prompt Caching이 해결책이 될 수 있습니다. 예시 블록에 `cache_control: {"type": "ephemeral"}`을 설정하면, 첫 번째 요청 이후에는 캐시 TTL (Time-to-live, Anthropic의 경우 기본 5분)이 만료될 때까지 여러 요청에 걸쳐 예시 비용이 분할 amortised 됩니다. 이는 비용을 절감해주지만, Attention 희석 (Attention dilution) 문제를 해결해주지는 않습니다. 캐싱 여부와 상관없이, 800 토큰의 예시는 여전히 200 토큰의 입력을 압도합니다.

결론: Few-shot은 기본값이 아니라 도구입니다. 2022년의 조언은 2022년 모델들에게는 맞았습니다. 모델 세대가 세 번 바뀌고 난 지금, Few-shot은 측정하기 전에 사용하는 것이 아니라, 측정한 후에 사용하는 도구입니다.

배포 시 지켜야 할 세 가지 규칙: 기본값은 Zero-shot으로 설정하십시오.

Ablation (절제 실험)을 통해 예시가 귀하의 작업에 도움이 된다는 것이 증명되었을 때만 예시를 추가하십시오. 추론 모델 (Reasoning models)의 경우, Zero-shot (제로샷) 쪽으로 훨씬 더 기울어야 합니다. 예시는 사고 과정 (Thinking trace)과 경쟁하게 됩니다. 예시의 개수보다 예시의 길이가 더 중요합니다. 긴 예시는 귀하가 보내는 모든 요청에 부과되는 세금과 같습니다. 위의 30줄은, 점수와 비용을 동시에 낭비하게 만들었던 600토큰 규모의 Few-shot (퓨샷) 블록을 처음 삭제하는 순간 그 가치를 스스로 증명할 것입니다. 예시를 삭제했을 때 귀하의 작업에서 결과가 더 좋아졌던 프롬프트는 무엇인가요? 전후 수치를 댓글로 남겨주세요. 이 내용이 유용했다면, 'The Prompt Engineering Pocket Guide'는 Zero-shot, Few-shot, Chain-of-thought (사고의 사슬), Self-consistency (자기 일관성), 그리고 이들 중 절반을 조용히 대체한 Structured-output (구조화된 출력) 패턴 등 각 프롬프팅 기술이 언제 제 역할을 하는지 깊이 있게 다룹니다. Ablation discipline (절제 실험 규율)에 관한 장은 이 포스트와 직접적으로 연결되는 부분입니다. 즉, 테스트를 실행하는 방법, 오답을 읽는 방법, 그리고 언제 '모범 사례 (Best practice)'가 귀하의 특정 작업에서 Cargo cult (맹목적 모방)가 되었는지 파악하는 방법을 다룹니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0