프롬프트가 실패하는 이유: 사양(spec)의 문제
실망스러운 AI 답변 대부분은 모델의 실패가 아니라 사양(specification)의 실패입니다. 언어 모델은 요청의 모든 모호함을 통계적으로 평균적인 해석으로 추측해 메우는데, 모호한 요청의 평균적인 해석은 모호한 답입니다. "원격 근무에 대해 써 줘"에는 수천 가지 타당한 독해가 있습니다. 블로그 글일 수도, 정책 메모일 수도, 장단점 목록일 수도 있고, 임원용일 수도 신입용일 수도 있으며, 200단어일 수도 2,000단어일 수도 있습니다. 모델은 하나를 골라야 하고, 가장 밋밋한 것을 고릅니다.
공학적 통찰은 프롬프트가 곧 사양이며, 사양이 개선되는 방식 그대로 개선된다는 것입니다. 중요한 자유도를 고정하면 됩니다. 네 개의 핀이 대부분의 일을 합니다. 과업: 동사와 산출물("온보딩에 대해 써 줘"가 아니라 "600단어 온보딩 이메일을 써 줘"). 독자: 누가 읽고 무엇을 이미 아는지. 제약: 길이, 톤, 형식, 제외할 것. 맥락: 모델이 추측할 수 없는 배경 사실 — 여러분의 제품, 상황, 실패했던 이전 시도.
구체성이 보상받는다는 증거는 탄탄합니다. 실무에서는 명시적인 독자와 길이 제약을 추가하는 것만으로도 출력 품질이 눈에 띄게 달라집니다. 유효한 답의 공간이 좁아지기 때문입니다. 유용한 습관 하나: 프롬프트를 쓴 뒤 "합리적인 두 사람이 이걸 읽고 서로 다른 산출물을 기대할 수 있나?"라고 물어보세요. 그렇다면 모델은 둘 중 한 명을 실망시킬 것이고, 누구를 실망시킬지는 여러분이 고를 수 없습니다.
Before (vague — average answer guaranteed):
"Write about remote work."
After (specified — 4 pins):
"Write a 600-word article arguing that hybrid schedules
beat fully-remote for junior engineers.
Audience: engineering managers at startups (assume they
already know the standard remote-work pros/cons).
Tone: direct, conversational, no buzzwords.
Structure: hook, 3 arguments each with one concrete
example, one counterargument addressed, action-oriented
close. Do NOT discuss cost savings or real estate."측정 가능하게 효과 있는 기법: 역할, 퓨샷, 분해
프롬프트 엔지니어링에는 검증된 진짜 기법이 쌓였고, 민간전승도 함께 쌓였습니다. 하중을 견디는 부분만 추리면 이렇습니다.
역할 부여("당신은 이 문서의 오류를 검토하는 시니어 세무사입니다")가 효과 있는 이유는 모델이 세무사가 되어서가 아니라, 출력 분포가 그 장르의 어휘·신중함·구조 쪽으로 이동하기 때문입니다. 톤과 깊이 조정에 가장 효과적이고, 사실 정확도에는 가장 효과가 없습니다. 의사를 연기하는 모델이 의학적으로 더 정확해지는 게 아니라 말투만 더 임상적으로 변합니다. 역할은 문체를 정하는 데 쓰고, 권위를 만들어내는 데 쓰지 마세요.
퓨샷(few-shot) 예시는 형식과 스타일에 가장 지렛대가 큰 기법입니다. 입력-출력 쌍 두세 개가 설명 문단 여러 개를 이깁니다. 여러분이 말로 표현할 생각조차 못 할 것들 — 라벨이 얼마나 간결한지, 엣지 케이스가 어떻게 생겼는지, "좋음"이 실제로 무엇을 뜻하는지 — 을 지정해 주기 때문입니다. 예시는 다양하게 유지하세요. 모델은 예시의 패턴을 편향까지 포함해 공격적으로 복제합니다(예시가 전부 긍정적이면 출력도 긍정적으로 쏠립니다).
다단계 작업에서는 분해가 단일 메가 프롬프트를 이깁니다. "이 계약서를 읽고, 위험 조항을 찾고, 그에 대한 이메일 초안을 써 줘"는 품질 기준이 서로 다른 세 과업을 섞은 것입니다. 세 개의 프롬프트로 나누면 중간 산출물을 검사하고 교정할 수 있습니다. 마찬가지로 쓰기 전에 계획을 요구하면("먼저 목차만 나열하고 기다려") 구조적 문제를 한 줄만 고치면 되는 시점에 잡아냅니다.
사고 사슬 지시("단계별로 생각해")는 산수·논리형 문제에 효과가 있지만, 요즘의 추론 특화 모델은 이를 내부적으로 수행하는 경우가 많습니다. 오늘날 더 큰 이득은 마무리 전에 "네 답이 내가 명시한 제약을 지키는지 검증하라"고 요구하는 것입니다.
Few-shot format specification (2 examples do the work):
"Classify each support ticket. Respond in exactly this format.
Ticket: 'App crashes when I upload a photo over 10MB'
-> category: bug | severity: high | team: mobile
Ticket: 'Would love a dark mode option'
-> category: feature-request | severity: low | team: design
Ticket: 'I was charged twice this month'
->"출력 스키마: 프로그램이 읽을 수 있는 답 받아내기
AI의 답이 다운스트림 어딘가 — 스프레드시트, 스크립트, 또 다른 프롬프트 — 로 흘러가는 순간, 자유 형식 산문은 부채가 됩니다. 해법은 출력 스키마를 지정하는 것입니다. 응답의 정확한 형태를 협상 불가 조건으로 명시하세요.
세 가지 관행이 스키마를 지켜지게 만듭니다. 첫째, 스키마를 설명하지 말고 보여주세요. "title, risk_level(low/medium/high 중 하나), reasons(문자열 배열) 키를 가진 JSON으로 응답하라"도 좋지만, 값이 채워진 JSON 예시를 붙여 넣는 게 더 좋습니다. 예시는 설명이 열어두는 디테일 — 따옴표 스타일, 대소문자, 빈 배열 허용 여부 — 을 고정하기 때문입니다. 둘째, 탈출구를 막으세요. 모델은 JSON을 마크다운 펜스로 감싸거나, "요청하신 JSON입니다:"를 앞에 붙이거나, 친절한 맺음말을 더하길 좋아합니다. 명시적으로 말하세요. "JSON 객체만 출력하라. 코드 펜스 금지, 앞뒤 설명 금지." 셋째, 실패를 설계에 넣으세요. 모델이 스키마 안에서 "할 수 없었다"고 말할 방법(status 필드, null 허용 답변)을 마련하세요. 그러지 않으면 필수 필드를 비워두는 대신 그럴듯한 창작으로 채웁니다. 바로 그것이 탐지할 수 없는 실패입니다.
스키마는 프로그래밍과 무관한 작업도 개선합니다. "X, Y, Z 열을 가진 표" 또는 "각각 동사로 시작하는 정확히 다섯 개의 불릿"을 요구하면 모델이 생각을 조직하게 되고, 빠진 조각이 한눈에 보입니다. 구조화된 오답은 찾기 쉽지만 유창한 오답은 그렇지 않습니다. 그래도 기계가 파싱하는 것은 반드시 검증하세요. 현대 모델의 스키마 준수율은 높지만, API 수준의 구조화 출력 기능을 쓰지 않는 한 보장되지는 않습니다.
"Analyze the review below. Output ONLY this JSON —
no code fences, no text before or after:
{
"sentiment": "positive",
"confidence": 0.92,
"topics": ["shipping", "packaging"],
"actionable_complaint": true,
"status": "ok"
}
If the text is not a product review, output:
{ "status": "not_a_review" }
and nothing else."반복 개선 루프: 프롬프트를 코드처럼 다루기
중요한 작업에서 첫 시도에 좋은 프롬프트를 쓰는 사람은 없습니다. 일관되게 강한 결과를 얻는 사람들은 루프를 돌리고 있습니다. 초안, 테스트, 진단, 수정 — 디버깅과 같은 루프입니다.
진단이 기술입니다. 출력이 실망스러우면 프롬프트에 손대기 전에 실패의 이름부터 붙이세요. 형식이 틀렸나? 스키마나 예시를 추가하세요. 깊이가 틀렸나? 독자 지정이 없거나 잘못됐습니다. 내용이 틀렸나? 모델에게 없는 맥락을 가정한 것이니 배경 사실을 추가하세요. 지시를 무시했나? 프롬프트 중간에 파묻혔을 수 있습니다. 모델은 프롬프트의 처음과 끝을 중간보다 무겁게 취급하므로, 핵심 제약을 맨 위로 옮기고 가장 중요한 것 하나를 끝에서 재진술하세요. 자신만만한 오답? 환각을 확실하게 고치는 프롬프트 문구는 없습니다. 원천 자료를 제공하고 그 자료에서만 답하라고 지시해야 합니다.
한 번에 하나만 바꾸세요. 다섯 군데를 한꺼번에 고쳐서 출력이 좋아졌다면 어느 부분이 중요했는지 아무것도 배우지 못한 것입니다. 프롬프트도 코드처럼 미신이 빨리 쌓입니다("우린 항상 이 문단을 넣어. 이유는 아무도 기억 못 해").
두 가지 습관이 일반 사용자와 숙련자를 가릅니다. 프롬프트 라이브러리를 유지하세요. 잘 작동한 프롬프트는 용도 메모와 출력 예시 하나와 함께 저장하세요. 몇 달을 재사용하게 됩니다. 그리고 프롬프트를 신뢰하기 전에 입력 두 개 이상으로 테스트하세요. 단일 예시에 맞춰 조정된 프롬프트는 데이터 포인트 하나로 학습한 모델처럼 그 예시에 조용히 과적합됩니다.
프롬프트로 고칠 수 없는 것
잘 만든 프롬프트는 모델이 산출하는 것의 상한선을 올려주지만, 어떤 한계는 모델 자체의 것이고, 아닌 척하면 시간만 낭비합니다.
어떤 프롬프트도 모델이 학습하지 않은 것을 알게 만들지 못합니다. 어제 여러분의 회의, 지난주 발표된 논문, 회사 내부 가격 정책이 그렇습니다. 답에 그 정보가 필요하다면 프롬프트 안에 있어야 합니다. 여러분이 직접 넣든 검색 시스템이 넣든 말입니다. 관련해서, 프롬프트는 실시간 데이터 접근 권한을 주지 않습니다. "현재 가격"을 물으면 모델은 가격처럼 생긴 숫자를 만들어냅니다.
어떤 프롬프트도 환각을 제거하지 못합니다. 근거 자료 제공은 줄여줄 뿐입니다. 원천 자료를 줘도 모델은 가끔 제공된 사실과 기억 속 사실을 섞습니다. 사실 관계 작업의 규칙은 그대로입니다. 모델이 초안을 쓰고, 여러분이 검증합니다. 제공한 텍스트에 대한 인용(문단 번호가 잘 작동합니다)을 요구하고, 표본 검사하고, 구체적이고 편리하고 검증 불가능한 디테일을 가장 의심하세요.
어떤 프롬프트도 모델을 자기 출력의 신뢰할 만한 심판으로 만들지 못합니다. "확실해?"는 대부분 여러분이 원하는 듯한 방향으로의 공손한 자기 수정을 끌어낼 뿐입니다. 모델은 아첨(sycophancy) 경향이 있어 사용자의 입장이 틀렸을 때조차 동의합니다. 독립적인 검사(새로운 대화, 다른 모델, 또는 여러분 자신의 전문성)가 대화 안에서의 어떤 안심시키기보다 가치 있습니다.
이 경계를 아는 것 자체가 프롬프트 기술입니다. 최고의 실무자는 문구가 도움이 되는 곳 — 사양, 예시, 스키마, 분해 — 에 노력을 쓰고, 문구가 소용없는 곳에서는 다른 도구를 꺼냅니다.