THINK 판단 단계

프롬프트 엔지니어링이란? 원리부터 실무까지, 확률을 우리 쪽으로 당기는 법

프롬프트 엔지니어링이란? 원리부터 실무까지, 확률을 우리 쪽으로 당기는 법

프롬프트 엔지니어링(prompt engineering)은 대규모 언어 모델(LLM, Large Language Model)에게서 원하는 결과를 얻기 위해 입력 문장, 즉 프롬프트(prompt, AI에게 건네는 지시문과 자료)를 설계하고 다듬는 기술입니다. 모델 자체를 다시 학습시키지 않고, 오직 건네는 말과 그 말에 곁들이는 맥락만으로 출력을 원하는 방향으로 끌고 갑니다.

한눈에 보기

  • 프롬프트 엔지니어링은 AI에게 무엇을, 어떤 형식으로, 어떤 예시와 함께 부탁할지 다듬어 원하는 답이 나올 가능성을 높이는 기술입니다.
  • 그냥 시키기(제로샷)에서 예시 보여 주기(퓨샷), 풀이 과정 적게 하기(사고 사슬), 도구 쓰게 하기(ReAct)로 기법이 발전해 왔습니다.
  • 마법 문장은 없으므로 역할·과제·맥락·형식·톤을 나눠 적고, 결과를 보며 고쳐 가는 습관이 가장 확실합니다.

한 문장으로 말하면: 잘 물어 확률을 당기는 기술

이런 상황을 떠올려 보세요. 동네에서 빵집을 하는데 배달앱 리뷰에 답글을 달 시간이 없어 ChatGPT에 "리뷰 답글 써 줘"라고 부탁했습니다. 돌아온 답은 "소중한 리뷰 감사합니다! 앞으로도 최선을 다하겠습니다" 같은 뻔한 문장입니다. 그런데 부탁을 바꿔 "너는 동네 빵집 사장이다. 아래 리뷰에 두세 문장으로 답해 줘. 손님이 칭찬한 메뉴 이름을 꼭 넣고, 말투는 다정하지만 과장 없이"라고 적으니 훨씬 쓸 만한 답이 나옵니다. 모델은 그대로이고 묻는 방식만 바꿨을 뿐입니다. 이 차이를 체계적으로 다루는 일이 프롬프트 엔지니어링입니다.

이 정의의 핵심은 '확률'에 있습니다. 언어 모델은 매 순간 다음에 올 후보 토큰(token, AI가 글을 읽고 쓰는 조각 단위로, 보통 단어 하나보다 조금 작은 단위)들의 확률 막대그래프를 세우고 그중 하나를 골라 문장을 이어 붙입니다. 그 확률을 정하는 것은 두 가지입니다. 하나는 모델이 학습으로 갖춘 성질이고, 다른 하나는 우리가 방금 건넨 말입니다. 같은 질문이라도 어떻게 묻느냐에 따라 막대그래프의 모양이 달라집니다.

그래서 프롬프트 엔지니어링을 한 문장으로 다시 옮기면, 애초에 잘 물어 원하는 답이 나올 확률을 우리 쪽으로 당기는 일입니다. 마법 주문을 외우는 일이라기보다, 모델이 이미 가진 능력을 정확히 겨냥해 꺼내는 작업에 가깝습니다.

좋은 프롬프트와 나쁜 프롬프트의 차이: 막연한 부탁과 역할·형식·조건을 적은 부탁이 어떻게 다른 답을 끌어내는지 비교한 그림

설계된 게 아니라 발견된 것: 요리에 가까운 기술

프롬프트 기법을 이해할 때 먼저 잡아 둘 관점이 하나 있습니다. 이 기법들은 누군가 책상에서 이론으로 설계한 것이 아니라, 실제로 써 보며 발견한 것이라는 점입니다. 보통의 공학은 물리학처럼 원리를 먼저 세우고 그에 맞춰 도구를 만듭니다.

프롬프트 기법의 역사는 정반대로 흘렀습니다. 거대한 예측 기계가 먼저 세상에 나왔고, 수많은 사람이 그 기계를 이리저리 써 보며 '이렇게 물으니 더 잘하더라'를 하나씩 캐냈습니다. 요리나 원예에 가깝습니다. 해 보고, 되는 것을 남깁니다.

이 관점을 잡으면 뒤에 나올 기법이 한 줄기로 꿰입니다. 제로샷에서 퓨샷으로, 다시 사고 사슬(CoT)과 ReAct로 넘어가는 흐름은 각 기법이 앞선 기법의 한계에서 자라난 결과입니다. 그리고 그 방향은 모두 하나를 가리킵니다. 모델이 스스로 더 많이 생각하고, 더 많이 행동하게 만드는 쪽입니다.

실무자에게 이 관점이 중요한 이유가 있습니다. 프롬프트에는 정답 공식이 없습니다. 도메인과 모델, 과제가 바뀌면 잘 통하던 프롬프트도 흔들립니다. 그러니 '한 번 만든 마법 문장'을 붙잡기보다, 계속 실험하고 고쳐 가는 태도가 이 기술의 성격에 맞습니다.

그냥 시키기: 제로샷의 힘과 한계

가장 단순한 방식은 그냥 시키는 것입니다. 예시도 요령도 없이 원하는 일을 말로 지시합니다. 이것을 제로샷(zero-shot)이라 부릅니다. 여기서 '샷(shot)'은 모델에게 미리 보여 주는 예시의 개수를 뜻합니다. 예시를 하나도 주지 않으니 제로샷입니다.

제로샷은 생각보다 잘 통합니다. '이 문단을 세 줄로 요약해 줘', '이 문장을 영어로 옮겨 줘', '회의록에서 할 일만 뽑아 줘' 같은 지시는 예시 없이도 대체로 원하는 답을 줍니다. 사실 챗봇에 던지는 질문 대부분이 제로샷입니다. 우리가 평소 쓰는 바로 그 방식입니다.

그런데 일이 까다로워지면 결과가 들쭉날쭉해집니다. 특히 흔들리는 것은 형식입니다. '긍정인지 부정인지만 답해'라고 했는데 장황한 설명을 늘어놓거나, 표로 달라고 했는데 문장으로 답합니다. 지시만으로는 우리가 머릿속에 그린 결과 모습을 모델이 정확히 맞추지 못합니다.

제로샷의 이 한계가 다음 방법을 불렀습니다. 말로 아무리 설명해도 통하지 않을 때, 차라리 원하는 모습을 직접 보여 주면 어떨까요. 여기서 예시를 곁들이는 기법이 나옵니다.

패턴을 세우는 예시: 퓨샷과 문맥 속 학습

퓨샷: 리뷰와 감성(긍정·부정) 예시 몇 개로 패턴을 세우면 모델이 같은 형식으로 답하는 모습

제로샷의 한계를 메운 발견은 단순합니다. 말로 설명하지 말고, 예시를 몇 개 보여 주는 것입니다. 예시를 몇 개 주면 퓨샷(few-shot), 딱 하나면 원샷(one-shot)입니다. 고객 리뷰를 긍정·부정으로 나누는 과제로 비교하면 차이가 분명합니다.

제로샷으로 '다음 리뷰가 긍정인지 부정인지 판단해 줘'라고만 하면 어떤 때는 '긍정', 어떤 때는 '긍정입니다, 왜냐하면…' 하고 형식이 흔들립니다. 반면 퓨샷은 앞에 본보기를 깔아 줍니다. '리뷰: "포장이 꼼꼼했다." → 긍정 / 리뷰: "두 번이나 환불받았다." → 부정' 같은 예시 몇 줄을 먼저 놓고, 마지막에 판단할 리뷰만 남겨 두면 모델은 앞 예시들이 세운 틀을 이어받아 '긍정' 한 단어만 내놓습니다.

여기서 눈여겨볼 점은 예시가 답의 내용만이 아니라 형식까지 정해 주었다는 것입니다. 원하는 모습을 몇 번 보여 주니 모델이 그 모습을 따라 그립니다. 특히 애매한 경계 사례(예: '배송은 느렸지만 물건은 마음에 든다')를 판단할 때, 앞선 예시들이 판단 기준까지 함께 세워 줍니다. 빵집 리뷰 답글이라면 마음에 드는 답글 두세 개를 예시로 붙여 두는 것만으로 말투가 훨씬 안정됩니다.

예시 몇 개가 왜 이렇게 힘이 셀까요. 이 기계의 본업이 '이런 흐름 다음엔 이런 것이 온다'를 잇는 일이기 때문입니다. 예시는 '이런 흐름'을 눈앞에 직접 깔아 줍니다. 그러면 모델은 자기가 가장 잘하는 일, 곧 깔린 패턴을 이어 가기만 하면 됩니다. 이렇게 주어진 문맥 안의 예시만으로 그 자리에서 요령을 잡는 능력을 문맥 속 학습(in-context learning)이라 부릅니다. GPT-3를 소개한 논문 제목이 바로 'Language Models are Few-Shot Learners'였습니다.

여기서 오해 하나를 바로잡아 두겠습니다. 퓨샷은 모델을 영구히 똑똑하게 만들지 않습니다. 건넨 예시는 이번 대화에서만 힘을 발휘합니다. 모델 내부의 숫자를 다시 학습시키는 파인튜닝(fine-tuning, 미세조정)과는 전혀 다릅니다. 이미 가진 패턴 잇기 능력에 정확한 본보기를 깔아 줄 뿐입니다. 그래서 예시의 질이 곧 답의 질을 좌우합니다.

생각을 소리 내게 하기: 사고 사슬(CoT)과 그 확장

분류나 요약을 넘어 여러 단계의 추론이 필요한 문제로 가면 예시만으로도 부족해집니다. 수학 문장제나 논리 퍼즐에서 모델이 곧장 답만 내놓으면 자주 틀립니다. 여기서 나온 발견이 사고 사슬(chain-of-thought, CoT) 프롬프팅입니다. 모델에게 답을 바로 내지 말고 풀이 과정을 단계별로 적으라고 시키는 방법입니다.

방법은 의외로 단순하고, 크게 두 갈래가 있습니다. 하나는 풀이 과정이 적힌 예시를 몇 개 보여 주는 방식으로, 2022년 Wei 외 연구진이 '사고 사슬 프롬프팅'이라는 이름으로 제안했습니다(퓨샷 CoT). 다른 하나는 예시 없이 '단계별로 생각해 보자(Let's think step by step)'라는 한 문장만 붙이는 방식으로, 같은 해 Kojima 외 연구진이 보고했습니다(제로샷 CoT). 어느 쪽이든 모델은 중간 계산과 근거를 문장으로 풀어 놓고, 그 위에서 최종 답을 냅니다.

왜 통할까요. 언어 모델은 자기가 쓴 글을 다시 읽으며 한 토큰씩 이어 씁니다(자기회귀, autoregressive). 앞서 써 둔 추론 과정이 그다음 토큰의 확률을 좋은 쪽으로 밀어 줍니다. 스스로 만든 문장이 다음 단계의 발판이 되는 셈입니다. 견적 금액을 따질 때 "품목별 단가와 수량을 먼저 적고 합계를 내 줘"라고 시키면 틀리는 일이 줄어드는 것도 같은 원리입니다.

CoT에서 갈라져 나온 확장들도 같은 방향을 가리킵니다. 자기 일관성(self-consistency)은 추론 경로를 여러 번 뽑아 가장 많이 나온 답을 골라 정확도를 높입니다. 생각의 나무(Tree of Thoughts, ToT)는 한 줄기 사슬 대신 여러 갈래로 생각을 뻗고 유망한 가지를 골라 탐색합니다. 어려운 문제를 여러 방향으로 두드려 보고 되는 길을 남기는 방식입니다. 제로샷에서 퓨샷으로, CoT에서 ToT로 이어지는 흐름은 모두 '모델이 스스로 더 생각하게 만드는' 축 위에 놓여 있습니다.

프롬프트 기법의 진화: 제로샷, 퓨샷, CoT, ReAct 순으로 모델이 더 많이 생각하고 행동하게 되는 흐름

생각에 행동 더하기: ReAct와 도구 사용

생각만으로는 넘을 수 없는 벽이 있습니다. 모델은 학습한 시점까지의 지식만 갖고 있고, 최신 정보나 실시간 데이터는 알지 못합니다. 여기서 나온 발견이 ReAct(Reasoning + Acting)입니다. 이름 그대로 추론(Reasoning)과 행동(Acting)을 번갈아 엮습니다.

ReAct의 흐름은 이렇습니다. 모델이 먼저 '무엇을 알아야 하나'를 생각하고(Reason), 검색이나 계산 같은 도구를 불러 행동하고(Act), 그 결과를 관찰(Observe)한 뒤 다시 생각으로 돌아옵니다. 이 사고-행동-관찰 순환을 답이 나올 때까지 되풀이합니다. 예컨대 '오늘 서울 날씨에 맞춰 옷을 추천해 줘'라는 요청이면, 모델은 날씨 조회 도구를 부르고, 돌아온 결과를 근거로 추천을 완성합니다.

ReAct는 오늘날 AI 에이전트(agent, 목표를 받으면 스스로 여러 단계를 계획하고 도구를 써 가며 일을 끝내는 AI 프로그램)의 뼈대에 해당합니다. 검색, 코드 실행, 데이터베이스 조회 같은 외부 도구와 언어 모델을 연결하는 구조가 여기서 나왔습니다. 프롬프트가 단순한 '한 줄 주문'을 넘어, 모델이 스스로 행동을 계획하고 실행하는 절차로 넓어진 것입니다. 자세한 작동은 AI 에이전트 글에서 다룹니다.

정리하면 프롬프트 기법의 무게중심은 '어떻게 한 문장으로 잘 시키나'에서 '무엇을 모델 곁에 놓아 스스로 생각하고 행동하게 하나'로 옮겨 왔습니다. 이 흐름의 다음 자리에, 모델 앞에 놓을 자료 전체를 설계하는 컨텍스트 엔지니어링이 있습니다.

디코딩 파라미터로 확률의 결을 조절하기

프롬프트 문장 못지않게 출력을 좌우하는 것이 디코딩(decoding, 확률 막대그래프에서 다음 토큰을 실제로 골라내는 과정) 설정입니다. 모델이 세운 확률 막대그래프에서 다음 토큰을 어떻게 고를지 정하는 손잡이들입니다. 프롬프트 엔지니어링을 실무에 쓸 때는 반드시 함께 다뤄야 합니다.

가장 널리 쓰는 손잡이는 온도(temperature)입니다. 값이 낮으면(예: 0에 가까움) 확률이 높은 토큰에 답이 몰려 결과가 일관되고 안정적입니다. 값이 높으면 확률 막대가 평평해져 덜 뻔하고 다양한 답이 나옵니다. 사실 확인이나 분류처럼 정확성이 중요한 일은 낮게, 창작이나 아이디어 내기는 조금 높게 두는 편이 맞습니다.

후보를 잘라 내는 방식도 있습니다. top-k는 확률 상위 k개 토큰만 후보로 남깁니다. top-p(누적 확률 샘플링, nucleus sampling)는 확률을 큰 순서로 더해 누적값이 p에 이를 때까지의 토큰만 남깁니다. 둘 다 엉뚱하고 확률 낮은 토큰이 튀어나오는 것을 막으면서도 적당한 다양성을 지키는 장치입니다. ChatGPT 같은 대화 화면에서는 이 값을 직접 바꿀 수 없는 경우가 많고, 주로 API(프로그램끼리 정해진 방식으로 요청과 답을 주고받는 창구)로 모델을 부를 때 정합니다.

기법과 파라미터 한눈에 비교하기

지금까지 본 프롬프트 기법을 한 표로 견주면 각자의 쓰임이 또렷해집니다.

기법 예시·과정 제공 잘 맞는 과제 특징
제로샷 없음 요약·번역·간단 지시 가장 빠르고 간편, 형식이 흔들림
퓨샷 예시 몇 개 분류·형식 고정 예시가 내용과 형식을 함께 지정
CoT 풀이 과정 유도 수학·논리·다단계 추론 중간 과정이 답의 발판
ReAct 추론+도구 호출 검색·계산·실시간 정보 에이전트의 기본 골격

디코딩 파라미터도 함께 보면 좋습니다. 프롬프트와 짝을 이뤄 출력의 성격을 정하기 때문입니다. 프롬프트를 아무리 잘 짜도 디코딩 설정이 과제와 맞지 않으면 결과가 흔들립니다. 둘을 한 세트로 보는 것이 실무 감각입니다.

파라미터 낮을 때 높을 때 권장 상황
temperature 일관·안정 다양·창의 정확성엔 낮게, 창작엔 높게
top-p 후보 좁힘 후보 넓힘 안정성과 다양성의 균형
top-k 상위 소수만 상위 다수 엉뚱한 토큰 억제

실무에서 쓰는 법: 구조화와 메타 프롬프팅

실무에서 프롬프트를 짤 때는 즉흥적으로 쓰기보다 구조를 잡는 편이 좋습니다. 역할(누구로서 답할지), 과제(정확히 무엇을 할지), 맥락(어떤 배경과 자료가 있는지), 형식(어떤 모양으로 답할지), 톤(어떤 어조인지)을 나눠 분명히 적으면 결과가 눈에 띄게 안정됩니다. 이처럼 역할·과제·맥락·형식·톤 같은 요소 목록을 정해 두고 차례로 채우는 틀이 여럿 나와 있습니다. 그림의 CRAFT는 그런 틀의 한 예로, 항목 이름은 틀마다 조금씩 다릅니다.

CRAFT 프레임워크: 맥락(Context)·역할(Role)·행동(Action)·형식(Format)·대상(Target)의 머리글자로 프롬프트 요소를 나눠 차례로 채우는 틀의 한 예

앞의 빵집 장면에 이 틀을 대 보면 다음과 같습니다. 부탁하기 전에 다섯 칸을 채웠는지만 확인해도 결과가 달라집니다.

항목 빵집 리뷰 답글 예시
역할 너는 동네 빵집 사장이다
과제 아래 리뷰에 답글을 쓴다
맥락 리뷰 원문, 우리 가게 대표 메뉴 이름
형식 두세 문장, 칭찬받은 메뉴 이름을 꼭 넣는다
톤 다정하지만 과장하지 않는다

실전에서 쓸모 있는 기법이 하나 더 있습니다. 메타 프롬프팅(meta prompting), 곧 프롬프트로 프롬프트를 고치는 방법입니다. 모델에게 '이 프롬프트의 약점을 지적하고 더 나은 버전으로 고쳐 줘'라고 시키면, 모델이 지시를 다듬어 줍니다. 좋은 프롬프트를 처음부터 완벽하게 쓰려 애쓰기보다, 초안을 만들고 모델과 주고받으며 다듬는 흐름이 훨씬 효율적입니다.

메타 프롬프팅: 초안 프롬프트를 모델에게 보여 주고 약점을 지적받아 고쳐 가는 과정

무게중심이 컨텍스트로 옮겨 간다는 말은 실무에서 특히 실감이 납니다. 지시 한 줄보다 무엇을 곁에 놓느냐가 중요해집니다. 관련 문서를 검색해 프롬프트에 끼워 넣는 검색 증강 생성(RAG, Retrieval-Augmented Generation, 답하기 전에 관련 문서를 먼저 찾아 붙여 주는 방식)이 널리 쓰이는 것도 같은 까닭입니다. 긴 자료를 넣을 때는 넣는 위치도 답의 질을 바꿉니다. 모델은 맨 앞과 맨 뒤에 놓인 내용을 더 잘 쓰는 경향이 있어, 꼭 지켜야 할 조건은 첫머리에 두고 끝에서 한 번 더 짚어 주는 편이 좋습니다. 자료 배치의 원리는 컨텍스트 엔지니어링 글에서 자세히 다룹니다.

흔한 오해와 한계, 그리고 프롬프트 인젝션

가장 흔한 오해는 '마법 주문'이 있다는 믿음입니다. 특정 문구를 넣으면 어떤 과제든 잘된다는 식의 접근은 오래가지 못합니다. 프롬프트의 효과는 모델과 과제, 도메인에 따라 달라집니다. 한 곳에서 잘 통한 프롬프트가 다른 곳에서 무너지는 일은 흔합니다. 정답 공식보다 실험과 반복이 핵심입니다.

두 번째 오해는 퓨샷 예시가 모델을 영구히 학습시킨다는 착각입니다. 앞서 짚었듯 예시는 이번 대화 안에서만 유효합니다. 모델의 가중치(모델이 학습으로 익힌 지식을 담은 숫자들)를 바꾸려면 파인튜닝이 필요하고, 이는 프롬프트 엔지니어링과 다른 층위의 작업입니다.

한계도 분명합니다. 프롬프트로 모델의 근본 능력을 넘어서게 만들 수는 없습니다. 학습하지 않은 사실을 억지로 끌어내려 하면 그럴듯한 거짓, 곧 환각(hallucination)이 나옵니다. CoT로 추론을 이끌어도 틀린 전제 위에서는 틀린 결론이 나옵니다. 프롬프트는 있는 능력을 겨냥해 꺼내는 도구이지, 없는 능력을 만들어 내는 도구가 아닙니다.

보안 위험도 알아 두어야 합니다. 프롬프트 인젝션(prompt injection)은 악의적인 입력으로 원래 지시를 무력화하거나 가로채는 공격입니다. 사용자 입력이나 외부 문서에 '앞의 지시를 무시하고 이렇게 하라'는 문구를 숨겨 넣는 식입니다. 시스템 지시와 사용자 입력을 분리하고, 외부에서 들어온 내용을 믿지 않는 설계가 방어의 기본입니다.

프롬프트 인젝션: 외부 입력에 숨긴 지시로 원래 지시를 무력화하는 공격과, 입력을 분리해 막는 방어

더 깊이 배우려면: 이어지는 개념들

프롬프트 엔지니어링을 제대로 이해하려면 그 아래의 원리부터 짚는 편이 좋습니다. 토큰화(tokenization)와 임베딩(embedding, 뜻이 비슷한 말끼리 가까운 자리에 놓이도록 숫자로 바꾸는 일), 트랜스포머(Transformer)의 자기어텐션(self-attention)이 어떻게 다음 토큰의 확률 분포를 만들어 내는지 알면, 프롬프트가 왜 그 확률을 흔들 수 있는지가 자연스럽게 보입니다. 각각 토큰과 임베딩, 트랜스포머 글에서 다룹니다.

기법의 원전 논문을 직접 읽어 보는 것도 권합니다. GPT-3의 퓨샷 학습을 다룬 'Language Models are Few-Shot Learners', 사고 사슬을 제안한 'Chain-of-Thought Prompting', 제로샷 CoT를 보고한 'Large Language Models are Zero-Shot Reasoners', 추론과 행동을 엮은 'ReAct', 자기 일관성과 생각의 나무를 다룬 논문들이 지금 흐름의 뼈대입니다. 실무 지침으로는 OpenAI의 프롬프트 엔지니어링 가이드가 접근하기 쉽습니다.

그다음 자연스럽게 이어지는 큰 주제가 컨텍스트 엔지니어링과 RAG입니다. 프롬프트가 '어떻게 묻나'라면, 컨텍스트 엔지니어링은 '무엇을 곁에 놓나'입니다. 검색으로 근거 문서를 붙이고, 대화 기억을 관리하고, 도구를 연결하는 설계가 여기에 속합니다. AI 에이전트로 넘어가면 ReAct의 순환이 실제 시스템으로 구현되는 모습을 볼 수 있습니다.

마지막으로, 프롬프트만으로 부족할 때의 선택지도 알아 두면 좋습니다. 도메인 특화 성능이 필요하면 파인튜닝을, 실시간 지식이 필요하면 RAG를 검토합니다. 프롬프트 엔지니어링, 컨텍스트 설계, 파인튜닝은 서로를 대신하는 관계가 아니라 상황에 맞춰 조합하는 도구들입니다.

실전에 적용하려면

프롬프트 설계를 실제 제품 품질로 끌어올리려면 체계적인 평가·튜닝 과정이 필요합니다. 젠아이랩스(GenAI Labs)의 AI 컨설팅 서비스가 이 과정을 함께합니다.

개발자를 위한 심화

이 부분은 직접 구현하는 개발자를 위한 내용입니다.

토큰 경계가 프롬프트를 배신할 때

프롬프트를 잘 쓴다는 것은 결국 모델이 실제로 보는 입력 단위, 즉 토큰을 이해한다는 뜻입니다. 사람은 문장을 단어와 의미 덩어리로 읽지만, 대규모 언어 모델(LLM)은 바이트쌍 인코딩(BPE) 같은 방식으로 잘린 조각을 봅니다. 영어에서는 흔한 단어 하나가 토큰 하나에 대응하는 경우가 많지만, 한국어는 사정이 다릅니다. 조사와 어미가 붙는 교착어(낱말 뒤에 조사·어미가 붙어 뜻을 더하는 언어)여서 '학교에서는' 같은 한 어절이 여러 토큰으로 쪼개집니다. 이 조각 단위가 프롬프트 설계에 생각보다 큰 영향을 줍니다.

가장 흔한 함정이 숫자와 자릿수 처리입니다. 모델은 '12345' 같은 수를 반드시 한 덩어리로 보지 않습니다. 토크나이저에 따라 '123'과 '45'로 나뉘거나 자릿수별로 쪼개집니다. 그래서 큰 수의 곱셈이나 자릿수 정렬을 그냥 시키면 엉뚱한 답이 나옵니다. 실무에서는 계산을 프롬프트 안에서 억지로 시키기보다, 자릿수를 공백으로 분리해 넣거나 아예 계산기·코드 실행 도구로 넘기는 편이 안전합니다. 프롬프트의 문제가 아니라 입력 표현의 문제라는 점을 놓치면 원인을 엉뚱한 곳에서 찾게 됩니다.

토큰 경계는 형식 지정에서도 말썽을 부릴 수 있습니다. 구분자를 고를 때는 모델이 학습 데이터에서 자주 봤을 법한 패턴(코드 블록의 백틱 세 개, '###', XML 태그 등)을 쓰면 안정성이 올라갑니다. 잘 쓰이지 않는 유니코드 기호를 구분자로 넣으면 오히려 토큰이 지저분하게 쪼개져 역효과가 날 수 있습니다.

토큰 수는 비용과 속도에도 바로 이어집니다. 같은 뜻을 담아도 장황한 지시문은 입력 토큰을 늘려 요금과 지연을 키웁니다. 특히 한국어 프롬프트는 같은 내용이라도 영어보다 토큰이 더 많이 나오는 경향이 있어, 반복 호출이 많은 서비스라면 지시문을 영어로 쓰고 사용자 입력만 한국어로 받는 절충안을 고려할 만합니다. 다만 결과는 도메인과 모델에 따라 갈리므로, 실제 토큰 수와 품질을 함께 재 보고 판단해야 합니다.

가중치가 되는 위치: 긴 컨텍스트의 배치

긴 프롬프트를 넣는다고 모든 내용이 똑같이 반영되지는 않습니다. 모델은 컨텍스트의 맨 앞과 맨 뒤에 있는 정보를 잘 활용하지만, 한가운데에 묻힌 정보는 놓치기 쉽습니다. 흔히 '중간에서 길을 잃는다(lost in the middle)'고 부릅니다. 그래서 가장 중요한 지시와 제약 조건은 시스템 프롬프트나 사용자 메시지 첫머리에 두고, 반드시 지켜야 할 출력 형식은 맨 끝에 한 번 더 짚어 주는 식으로 앞뒤를 함께 잡습니다. RAG라면 재순위(re-ranking, 검색 결과를 관련도로 다시 매기는 일)로 추린 문서 가운데 관련도가 높은 것을 앞쪽과 뒤쪽에 놓고 덜 중요한 것을 가운데로 보내는 재배치가 도움이 됩니다. 원인과 설계 요령은 컨텍스트 엔지니어링 글에 모았습니다.

출력을 강제하는 기술: 제약 디코딩과 스키마 고정

프롬프트로 '반드시 JSON으로만 답하라'고 아무리 강하게 지시해도, 모델은 확률로 다음 토큰을 고르는 기계라 가끔 설명 문장을 덧붙이거나 형식을 깨뜨립니다. 자연어 지시만으로 형식을 100% 보장할 수는 없습니다. 그래서 나온 것이 디코딩 단계에서 아예 규칙에 어긋나는 토큰을 확률 분포에서 지우는 방식입니다. 흔히 제약 디코딩(constrained decoding) 또는 구조화 출력(structured output)이라 부릅니다.

작동 원리는 직관적입니다. 모델이 다음 토큰의 확률 분포를 내놓으면, 미리 정한 문법(예: JSON 스키마)에 맞지 않는 토큰의 확률을 0으로 눌러 버립니다. 여는 중괄호 다음에는 문자열 키나 닫는 중괄호만 허용하고, 나머지 후보는 아예 고르지 못하게 막는 식입니다. 이렇게 하면 문법적으로 항상 유효한 출력이 나옵니다. 정규식이나 문맥 자유 문법(CFG, 허용되는 문장 구조를 규칙으로 적은 표기법)으로 허용 집합을 정의하는 라이브러리들이 이미 널리 쓰입니다.

이 방식은 형식 오류를 없애 주지만 공짜는 아닙니다. 후보 토큰을 걸러 내려면 단계마다 문법 상태를 검사해야 해서 약간의 추가 부담이 붙습니다. 더 미묘한 문제는 모델을 지나치게 좁은 틀에 가두면 내용의 질이 떨어질 수 있다는 점입니다. 예를 들어 사고 사슬처럼 자유롭게 추론하는 과정을 막고 곧장 정답 필드만 채우게 강제하면, 추론이 필요한 문제에서 정확도가 오히려 내려갑니다. 그래서 '추론은 자유 텍스트로 하게 두고, 최종 결과만 구조화'하는 이중 단계 설계가 실무의 정석에 가깝습니다.

함수 호출(function calling)이나 도구 사용(tool use) 기능도 결국 이 구조화 출력의 응용입니다. 모델에게 쓸 수 있는 함수의 이름과 인자 스키마를 주면, 모델은 자유 문장 대신 정해진 형식의 호출 명세를 내놓습니다. 프롬프트 엔지니어링이 자연어 다루기에서 인터페이스 설계로 넘어가는 지점이 바로 여기입니다. 잘 정의된 스키마와 명확한 필드 설명이 장황한 지시문보다 훨씬 안정적으로 작동합니다.

샘플링을 넘어서: 자기 일관성과 검증 루프

한 번 물어 한 번 답을 받는 방식은 확률적 출력의 변덕에 그대로 노출됩니다. 같은 프롬프트라도 온도(temperature)가 0이 아니면 호출마다 답이 달라집니다. 이 변덕을 약점이 아니라 자원으로 뒤집는 기법이 자기 일관성(self-consistency)입니다. 같은 문제를 온도를 조금 높여 여러 번 풀게 한 뒤, 나온 답들 가운데 다수결로 최종 답을 정합니다. 추론 경로는 제각각이어도 같은 답으로 모이는 경로가 여럿이면 그 답이 정답일 확률이 높다는 발상입니다.

이 방식은 특히 수학이나 논리 문제처럼 정답이 분명한 과제에서 단일 CoT보다 정확도를 끌어올립니다. 대신 호출 횟수만큼 비용과 지연이 늘어납니다. 다섯 번 샘플링하면 비용도 대략 다섯 배입니다. 그래서 모든 요청에 무작정 쓰기보다, 오답 비용이 큰 핵심 판단에만 골라 쓰는 편이 현실적입니다. 정답 검증이 어려운 개방형 생성(예: 글쓰기)에는 다수결이라는 개념 자체가 잘 맞지 않는다는 점도 유의해야 합니다.

한 걸음 더 나아가면 생성한 답을 다시 모델에게 검토시키는 검증 루프(verification loop)로 넘어갑니다. 초안을 만들고, 별도 프롬프트로 오류를 찾게 하고, 그 지적을 반영해 고쳐 쓰게 하는 식입니다. 생성기와 비평가의 역할을 나누면 한 번에 완성하라고 시킬 때보다 결과가 안정됩니다. 다만 모델이 자기 실수를 스스로 못 보는 경우도 흔해, 검증 단계에 다른 모델을 쓰거나 규칙 기반 검사(예: 코드라면 실제 실행, 수치라면 재계산)를 섞는 편이 신뢰도가 높습니다.

이런 다단계 구성은 사실상 프롬프트 하나가 아니라 프롬프트들의 파이프라인입니다. 단계마다 역할, 입력, 출력 형식을 분명히 정하고, 실패했을 때의 재시도 정책까지 설계해야 합니다. 어떤 기법을 언제 쓸지는 정확도 요구와 비용 여유 사이의 저울질입니다. 아래 표는 대표적인 접근을 호출 횟수, 잘 맞는 과제, 주의점 기준으로 비교합니다.

기법 대략적 호출 수 잘 맞는 과제 주의점
단일 호출 1회 단순 질의, 요약 출력 변덕에 취약
자기일관성 N회(예: 3~10) 수학·논리 등 정답형 비용이 N배, 개방형엔 부적합
검증 루프 2~3회 코드·사실 검증 자기검증 한계, 외부 검사 병행
도구 사용(ReAct 계열) 가변 계산·검색 필요 도구 오류 전파, 지연 증가

표에서 보듯 비용은 대체로 정확도와 맞바꾸는 관계입니다. 실무에서 흔한 실수는 시제품 단계에서 온갖 기법을 겹겹이 쌓아 놓고, 정작 운영 단계의 요금과 응답 시간을 계산하지 않는 것입니다. 사용자가 1초 안에 답을 기대하는 대화형 서비스라면 다섯 번 샘플링 후 다수결은 애초에 후보가 되지 않습니다. 반대로 야간에 문서 수천 건을 한꺼번에 정리하는 작업이라면 지연은 문제가 되지 않으니 정확도를 위해 호출을 늘려도 좋습니다.

비용 감각을 기르려면 개념 검증 단계부터 토큰 사용량과 호출 횟수를 로그로 남기는 습관이 필요합니다. 어떤 프롬프트가 평균 몇 토큰을 쓰고 재시도가 몇 번 일어나는지 숫자로 보면 판단이 선명해집니다. 프롬프트 하나를 줄여 얻는 절감이 사소해 보여도, 하루 수백만 호출이면 이야기가 달라집니다. 프롬프트 엔지니어링은 품질만이 아니라 운영 경제성까지 함께 다루는 공학입니다.

재현성이라는 골칫거리: 프롬프트를 코드처럼 관리하기

잘 만든 프롬프트도 시간이 지나면 흔들립니다. 모델 제공사가 뒤에서 모델을 업데이트하면 같은 프롬프트가 어제와 다른 답을 내놓기도 합니다. 온도를 0으로 낮춰도 완전한 결정성이 보장되지 않는 경우가 있어, '똑같은 입력에 똑같은 출력'이라는 소프트웨어의 상식이 여기서는 잘 통하지 않습니다. 이 불확실성을 관리하지 못하면 어제 잘 되던 기능이 오늘 조용히 망가집니다.

그래서 성숙한 팀은 프롬프트를 소스 코드와 똑같이 다룹니다. 버전 관리 시스템에 프롬프트를 넣어 변경 이력을 남기고, 어떤 프롬프트가 어떤 모델 버전과 짝인지 함께 기록합니다. 이를 프롬프트옵스(PromptOps)라고도 부릅니다. 프롬프트를 코드 곳곳에 흩어 두지 않고 별도 파일이나 템플릿으로 분리하면, 검토와 되돌리기가 쉬워지고 비개발 직군도 개선에 참여할 수 있습니다.

변경이 개선인지 개악인지 확인하려면 평가 데이터셋이 꼭 있어야 합니다. 대표적인 입력 수십에서 수백 건과 기대 결과를 정리해 두고, 프롬프트를 바꿀 때마다 이 셋에 돌려 점수 변화를 봅니다. 정답이 분명한 과제는 정확도로, 개방형 과제는 채점 기준(rubric)을 만들어 다른 모델에게 채점을 맡기는 'LLM 심판(LLM-as-a-judge)' 방식을 씁니다. 감으로 '좋아진 것 같다'고 배포하면, 고친 뒤 예전에 되던 기능이 깨지는 회귀(regression) 문제가 생기기 쉽습니다.

핵심은 프롬프트 개선을 일회성 손질이 아니라 반복 가능한 실험으로 만드는 것입니다. 한 번에 한 가지만 바꾸고, 같은 평가 셋에 돌리고, 숫자로 비교하고, 기록을 남깁니다. 이렇게 하면 '요리에 가까운 기술'로 시작한 프롬프트 엔지니어링이 점차 측정 가능한 공학으로 자리를 잡습니다. 재현성을 포기하지 않는 태도가 시제품과 운영 시스템을 가르는 진짜 경계입니다.

보완 · 한눈에 보기와 빵집 리뷰 답글 장면, 요청문 점검표를 더하고, 개발자용 내용을 심화 절로 옮겼다.

작성: AI (Claude Opus 4.8)

출처

  1. Language Models are Few-Shot Learners (GPT-3)
  2. Chain-of-Thought Prompting Elicits Reasoning in LLMs
  3. ReAct: Synergizing Reasoning and Acting in Language Models
  4. Self-Consistency Improves Chain-of-Thought Reasoning
  5. Tree of Thoughts: Deliberate Problem Solving with LLMs
  6. Large Language Models are Zero-Shot Reasoners
  7. OpenAI Prompt Engineering Guide
뉴스레터로 매주 받아보기 기술 블로그 목록