Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

프롬프트

1개요

프롬프트 엔지니어링(Prompt Engineering)은 대규모 언어 모델(LLM)이 원하는 출력을 내도록 입력 프롬프트를 설계·최적화하는 기술입니다. Liu et al. (2021) 모델의 가중치를 바꾸는 사전 훈련이나 미세 조정과 달리, 모델은 그대로 둔 채 무엇을 어떻게 입력하느냐만으로 동작을 바꿉니다. 추가 훈련이 없으므로 비용이 낮고, 같은 모델로 요약·분석·번역 등 여러 작업을 프롬프트만 바꿔 즉시 전환할 수 있습니다.

프롬프트는 컨텍스트 엔지니어링의 가장 기초가 되는 조정 방법입니다. 뒤에서 다룰 문서(RAG)·도구(MCP)·스킬도 결국 모델의 컨텍스트 창에 들어가는 텍스트를 잘 설계하는 일이므로, 프롬프트 설계가 그 토대가 됩니다.

2좋은 프롬프트의 원칙

기법에 앞서, 작업 종류와 무관하게 통하는 기본 원칙이 있습니다.

  1. 명확하고 구체적으로: 모호한 지시 대신 무엇을, 어떤 형식으로, 어떤 제약으로 답할지 분명히 적습니다. "요약해줘"보다 "세 문장으로, 핵심만 요약해줘"가 낫습니다.

  2. 맥락을 제공: 역할(누구로서), 배경, 대상 독자, 목적을 알려 주면 출력의 톤과 수준이 맞춰집니다.

  3. 지시와 데이터를 구분: 처리할 입력은 따옴표나 구분선 등으로 지시와 분리합니다. 가독성이 좋아지고, 입력 속 문장이 지시로 오인되는 프롬프트 주입도 줄입니다.

  4. 출력 형식을 지정: 길이·형식(목록·표·JSON)·예시를 명시하면 후속 처리가 안정적입니다.

  5. 반복 정제: 한 번에 완성되지 않습니다. 결과를 보고 프롬프트를 다듬는 과정을 전제로 설계합니다.

3핵심 기법

대표적인 기법들입니다. Sahoo et al. (2024)

4실습: Ollama로 기법 비교

각 기법이 실제로 출력을 어떻게 바꾸는지 로컬 모델로 직접 확인해 봅니다.

!uv pip install httpx

Ollama /api/chat을 호출하는 간단한 도우미를 만듭니다.

import os
import httpx

# Ollama 주소(localhost가 아니면 OLLAMA_HOST로 지정). 도구 호출 불필요하므로 일반 모델도 가능.
OLLAMA_API_URL = f"{os.getenv('OLLAMA_HOST', 'http://localhost:11434')}/api/chat"
MODEL_NAME = "qwen3:latest"

def ask(user, system=None, temperature=0.2):
    messages = ([{"role": "system", "content": system}] if system else []) + \
               [{"role": "user", "content": user}]
    payload = {"model": MODEL_NAME, "messages": messages, "stream": False,
               "think": False, "options": {"temperature": temperature}}
    response = httpx.post(OLLAMA_API_URL, json=payload, timeout=120)
    response.raise_for_status()
    return response.json()["message"]["content"].strip()

4.1역할 지정

같은 질문도 시스템 메시지로 역할을 주면 톤과 수준이 달라집니다.

question = "물은 왜 파랗게 보여?"

print("[역할 없음]\n", ask(question))
print("\n[5세 아이에게 설명하는 선생님]\n",
      ask(question, system="너는 5세 아이에게 설명하는 친절한 선생님이다. 두 문장 이내, 쉬운 말로만."))

역할이 없으면 빛의 산란·물의 흡수 같은 길고 기술적인 설명이 나오지만, 역할을 주면 *“물은 파란빛을 반사해서 파랗게 보여요. 해가 빛나면 더 잘 보여요!”*처럼 짧고 쉬운 답으로 바뀝니다.

4.2Few-shot: 예시로 형식 고정

예시 몇 개를 보여 주면 모델이 그 형식·라벨 집합을 그대로 따릅니다.

few_shot = (
    "아래 예시처럼 문장의 감정을 이모지 하나로만 답하라.\n"
    "예) 최고예요! → 😀\n"
    "예) 그냥 그래요 → 😐\n"
    "예) 최악이에요 → 😞\n"
    "문장: 생각보다 별로네요"
)
print(ask(few_shot))   # → 😞 (정의한 세 이모지 중 하나로만)

강력한 모델은 단순 작업이면 zero-shot으로도 잘하지만, 출력 형식이 정해져 있거나 라벨·관례가 임의적일수록, 그리고 작은 모델일수록 few-shot의 효과가 큽니다.

4.3추론 유도 (Chain-of-Thought)

여러 단계를 거쳐야 하는 문제는 "단계적으로 풀라"고 지시하면 정확도가 올라갑니다.

problem = "한 반 학생 30명 중 60%가 안경을 쓴다. 안경 쓴 학생의 1/3이 여학생이다. 안경 쓴 남학생은 몇 명인가?"

print(ask(problem + " 단계적으로 풀고 마지막 줄에 '답: N명' 형식으로 제시하라."))

모델이 "30 × 60% = 18명 → 1/3인 6명이 여학생 → 18 − 6 = 12명"처럼 과정을 적은 뒤 답: 12명을 내놓습니다. 중간 단계를 강제하면 곧바로 답을 던질 때보다 산술·논리 오류가 줄어듭니다.

4.4출력 형식 제어 (구조화 출력)

출력을 JSON으로 강제하면 결과를 프로그램에서 바로 다룰 수 있습니다.

import json

review = "배송은 빨랐지만 포장이 부실했어요."
out = ask(
    '다음 후기를 분석해 JSON으로만 출력하라(설명 금지): '
    '{"sentiment": "긍정|부정|중립", "keywords": ["..."]}\n'
    f"후기: {review}"
)
data = json.loads(out[out.find("{"): out.rfind("}") + 1])
print(data)   # {'sentiment': '중립', 'keywords': ['배송', '포장']}

5한계 및 고려 사항

6결론

프롬프트 엔지니어링은 모델을 바꾸지 않고도 그 잠재력을 끌어내는, 가장 빠르고 유연한 방법입니다. 그리고 이는 컨텍스트 엔지니어링의 토대입니다 — 이어지는 문서(RAG)·도구(MCP)·스킬은 모두 "무엇을 어떻게 컨텍스트에 넣을지"를 다루며, 그 안에서 결국 잘 설계된 프롬프트 위에 쌓입니다.

References
  1. Liu, P., Yuan, W., Fu, J., Jiang, Z., Hayashi, H., & Neubig, G. (2021). Pre-train, Prompt, and Predict: A Systematic Survey of Prompting Methods in Natural Language Processing. https://arxiv.org/abs/2107.13586
  2. Sahoo, P., Singh, A. K., Saha, S., Jain, V., Mondal, S., & Chadha, A. (2024). A Systematic Survey of Prompt Engineering in Large Language Models: Techniques and Applications. https://arxiv.org/abs/2402.07927