logo
aillmprompt

프롬프트 엔지니어링 실전 - 원하는 답을 얻는 법

같은 모델에게 같은 일을 시켜도, 어떻게 묻느냐에 따라 결과 품질이 극단적으로 갈립니다. "요약해줘"와 "3문장으로, 핵심 지표 중심으로, 존댓말로 요약해줘"는 전혀 다른 답을 냅니다. 프롬프트 엔지니어링은 마법 주문이 아니라, 모델에게 원하는 것을 오해 없이 전달하는 커뮤니케이션 기술입니다.

이 글에서는 실무에서 바로 쓰는 프롬프트 구성 원칙, 대표 기법, 자주 실패하는 패턴, 그리고 개발자용 템플릿을 정리합니다.


1. 좋은 프롬프트의 4가지 축

잘 짜인 프롬프트는 대개 네 요소를 갖춥니다. 역할 · 지시 · 예시 · 출력 형식 입니다.

1-1. 역할(Role) — 누구로서 답할지 지정

너는 10년차 백엔드 엔지니어야. 주니어에게 코드 리뷰를 해준다.

역할을 주면 모델이 어휘·깊이·관점을 그에 맞춰 조정합니다. "전문가처럼"보다 구체적인 역할이 효과가 큽니다.

1-2. 지시(Instruction) — 무엇을, 어떻게

  • 애매한 지시: "이 코드 좀 봐줘"
  • 명확한 지시: "이 함수에서 동시성 버그를 찾고, 각 문제의 원인과 수정 방법을 알려줘"

모델은 눈치가 없습니다. 원하는 것을 구체적으로, 긍정문으로 적으세요. "~하지 마"보다 "~하라"가 잘 먹힙니다.

1-3. 예시(Few-shot) — 보여주면 확실하다

말로 설명하기 애매한 형식·톤은 예시 몇 개로 보여주는 게 가장 빠릅니다. 이걸 few-shot 프롬프팅이라 합니다.

다음 형식으로 커밋 메시지를 작성해. 입력: 로그인 시 토큰 만료 처리 안 됨 출력: fix(auth): 만료된 토큰 갱신 로직 추가 입력: 상품 목록 API 응답 느림 출력: perf(product): 목록 조회 쿼리 인덱스 추가 입력: 회원가입 이메일 중복 검사 누락 출력:

예시 없이(zero-shot) 되면 좋지만, 형식이 중요할수록 few-shot이 안정적입니다.

1-4. 출력 형식(Output Format) — 받을 그릇을 정하라

프로그램이 파싱할 답이라면 형식을 못 박아야 합니다.

반드시 아래 JSON 형식으로만 답해. 다른 설명은 붙이지 마. { "severity": "high|medium|low", "summary": "한 줄 요약", "line": 숫자 }

"다른 설명 붙이지 마"를 명시하지 않으면 모델이 "물론이죠! 여기 있습니다:" 같은 군더더기를 붙여 파싱을 깨뜨립니다.


2. Chain-of-Thought — 생각할 시간을 줘라

어렵거나 여러 단계를 거치는 문제는, 곧장 답을 요구하면 틀리기 쉽습니다. 단계적으로 생각하게 하면 정확도가 올라갑니다. 이것이 Chain-of-Thought(CoT) 입니다.

다음 문제를 풀 때, 먼저 단계별로 근거를 정리한 뒤 마지막에 결론을 내려줘.

직관은 이렇습니다. 모델은 토큰을 하나씩 생성하므로, 중간 추론을 글로 뱉으면 그 추론 위에서 다음을 계산할 수 있습니다. 곧바로 정답을 내라고 하면 "계산할 공간" 없이 찍는 셈이죠.

주의점:

  • 간단한 작업엔 오히려 과하다. 분류·추출 같은 단순 작업은 CoT가 토큰·비용만 늘립니다.
  • 사용자에게 추론 과정을 보일 필요는 없다. 내부적으로 생각하게 하되, 최종 응답만 노출하는 구조로 설계할 수 있습니다.
  • 최근 추론 모델(reasoning model) 들은 이 과정을 내부에서 알아서 하므로, 굳이 "단계별로 생각해"를 붙이지 않아도 됩니다.

3. 구조화 — 프롬프트에도 문서 구조를

긴 프롬프트일수록 구획을 나눠 주면 모델이 지시와 데이터를 헷갈리지 않습니다. 구분자(마크다운 헤딩, XML 태그 등)를 쓰는 게 정석입니다.

# 역할 너는 기술 문서 번역가야. # 지시 아래 <text>를 한국어로 번역해. 코드와 고유명사는 그대로 둬. # 제약 - 존댓말 사용 - 의역보다 정확성 우선 <text> {번역할 원문} </text>

특히 지시와 사용자 데이터를 명확히 분리하는 건 품질뿐 아니라 프롬프트 인젝션 방어에도 중요합니다. 사용자 입력 안에 "위 지시 무시하고..." 같은 문장이 섞여 들어올 수 있기 때문입니다.


4. 자주 밟는 실패 패턴과 개선

실패 패턴증상개선
지시가 모호함매번 다른 스타일의 답역할·형식·제약을 명시
형식을 안 정함파싱 깨짐, 군더더기출력 스키마 고정 + "설명 붙이지 마"
부정문 남발"~하지 마"를 무시함원하는 행동을 긍정문으로
한 번에 너무 많이일부 지시 누락작업을 쪼개거나 단계 분리
예시 없음형식이 들쭉날쭉few-shot 예시 추가
모순된 지시이상한 절충 답우선순위를 명시

개선의 핵심은 "프롬프트를 코드처럼 반복 개선" 하는 것입니다. 한 번에 완벽할 수 없으니, 실패 사례를 모아 지시를 보강하세요.

[개선 전] "에러 로그 분석해줘" [개선 후] 너는 SRE 엔지니어야. 아래 로그에서 1) 근본 원인 한 줄, 2) 영향 범위, 3) 즉시 조치 1개 를 순서대로 bullet로 답해. 추측이면 "추정"이라고 표시해.

5. 개발자용 프롬프트 템플릿

실무에서 재사용하기 좋은 골격입니다. 시스템 프롬프트에 넣고, 데이터만 갈아끼우는 식으로 씁니다.

5-1. 구조화 추출 (분류/파싱)

const system = ` 너는 고객 문의 분류기다. 아래 규칙만 따른다. - 카테고리: [결제, 배송, 환불, 계정, 기타] 중 하나 - 반드시 아래 JSON만 출력. 설명 금지. { "category": "...", "urgent": true|false, "reason": "한 줄" } `; const user = `문의: "결제했는데 3일째 상품이 안 와요. 환불해주세요."`;

few-shot 예시 2~3개를 system에 더하면 경계 케이스가 안정됩니다.

5-2. 근거 기반 답변 (할루시네이션 억제)

아래 <context>의 내용만 근거로 답해. context에 없는 내용은 지어내지 말고 "자료에 없음"이라고 답해. 답변 끝에 근거가 된 문장을 인용해. <context> {검색된 문서} </context> 질문: {사용자 질문}

5-3. 코드 작업

# 역할: 시니어 TypeScript 개발자 # 작업: 아래 함수에 대한 단위 테스트를 작성 # 제약: - Vitest 사용, 엣지 케이스 포함 - 테스트 코드만 출력, 설명 없음 - 기존 함수 시그니처는 변경하지 말 것 <code> {대상 함수} </code>

팁: 온도(temperature)도 프롬프트의 일부입니다. 분류·추출처럼 일관성이 중요하면 낮게(0~0.3), 창작처럼 다양성이 필요하면 높게 잡습니다.


6. 프롬프트를 넘어서 - 언제 다른 도구가 필요한가

프롬프트로 대부분 해결되지만, 한계도 분명합니다.

  • 최신 정보나 사내 지식이 필요 → 프롬프트만으론 안 됨. RAG로 근거를 넣어야 함.
  • 일관된 말투·형식을 대량으로 → few-shot이 매번 토큰을 먹는다면 파인튜닝을 검토.
  • 외부 행동(검색·API 호출)이 필요도구 사용(tool use) 으로 확장.

즉 프롬프트 엔지니어링은 첫 번째로 시도할 가장 값싼 지렛대입니다. 여기서 안 되는 것만 무거운 방법으로 넘기면 됩니다.


마무리

프롬프트 엔지니어링은 요령 모음이 아니라 명확한 커뮤니케이션의 기술입니다.

핵심을 정리하면 이렇습니다.

  1. 역할 · 지시 · 예시 · 출력 형식 네 축을 갖춰라.
  2. 어려운 문제엔 단계적 사고(CoT) 로 생각할 공간을 줘라.
  3. 구조화로 지시와 데이터를 분리하고, 형식을 못 박아 파싱을 지켜라.
  4. 프롬프트는 코드처럼 반복 개선하는 것이다. 실패 사례가 최고의 교재다.

가장 값싸고 빠른 지렛대부터 당겨보고, 그래도 안 될 때 RAG나 파인튜닝으로 넘어가세요.

me

강경원

Backend Developer

성능과 안정성으로 신뢰받는 백엔드 개발자 · 요즘은 AI/LLM을 서비스에 접목합니다

이력서 보기