3강

프롬프트 엔지니어링 실험실

왜 실험이 필요한가

2강에서 배운 프롬프트 원칙들이 실제로 결과 품질을 얼마나 바꾸는지 눈으로 직접 확인하는 강입니다. 같은 데이터, 같은 모델, 프롬프트만 다르게 두어 나쁜 프롬프트와 좋은 프롬프트의 결과물을 나란히 비교합니다.

💡
실무에서 프롬프트 튜닝을 할 때 이 대조군 구조 를 그대로 재사용할 수 있습니다. 프롬프트 A / B / C 를 병렬로 연결해두고 같은 입력을 흘려보내 결과를 비교.

데이터 세팅 — Code 노드로 대체

외부 시트·DB 없이 Code 노드 하나만으로 테스트 데이터를 만듭니다. 실험 목적에는 이게 가장 빠릅니다.

Manual Trigger → Code 노드

Code 노드 안에서 이번 실험에 쓸 필드를 직접 넣습니다.

shop_name / delay_reason / delay_days / situation / normal_schedule 을 하드코딩
Code 노드 (테스트 데이터) javascript
return [{
  json: {
    shop_name: "달콤마켓",
    delay_reason: "주문량 급증",
    delay_days: "2~3일",
    situation: "현재 일부 주문의 배송이 평소보다 늦어지고 있습니다.",
    normal_schedule: "순차적으로 출고가 진행되고 있습니다."
  }
}];
💡
이렇게 하면 시트/API 상관없이 순수 프롬프트 자체만 비교할 수 있습니다.

Basic LLM Chain 노드

OpenAI 노드 말고 Basic LLM Chain 을 씁니다. LangChain 계열 노드라 모델을 하위 슬롯으로 붙이고 프롬프트만 관리할 수 있어 실험에 유리합니다.

Code 노드 뒤에 Basic LLM Chain 배치, 하위에 OpenAI Chat Model 연결

대조군 — LLM Chain 2개 병렬

같은 Code 노드 출력에 Basic LLM Chain 2개를 병렬로 걸어둡니다. 하나는 나쁜 프롬프트, 하나는 좋은 프롬프트. 실행 한 번에 두 결과를 비교.

① Basic LLM Chain (나쁜 프롬프트) / ② Basic LLM Chain1 (좋은 프롬프트)

흔한 오류 — chatInput 을 참조하는 기본값

LLM Chain 을 처음 배치하면 Prompt (User Message) 필드의 기본값이 {{ $json.chatInput }} 으로 되어있습니다. 이건 Chat Trigger 노드에서 오는 값 을 참조하는 표현식이라, 지금처럼 Manual Trigger + Code 노드 구성에서는 chatInput 필드가 없어 "No prompt specified" 오류가 납니다.

Source: Connected Chat Trigger Node → No prompt specified 오류

해결: Source for Prompt 를 Define below 로 바꿉니다. 그러면 프롬프트를 직접 텍스트로 입력할 수 있어 chatInput 을 안 써도 됩니다.

Source for Prompt → Define below 선택
💡
이 오류는 처음 LLM Chain 을 다루는 사람이 제일 자주 걸리는 함정입니다. Chat Trigger 없이 쓸 땐 반드시 Define below.

프롬프트 A — 모호한 요청 (윗 노드)

첫 번째 LLM Chain 에 아래 프롬프트를 넣습니다. 요청은 담겨있지만 기준이 모호합니다.

기준·순서·금지사항이 모호한 요청
프롬프트 A — 모호한 요청 text
{{$json.shop_name}}에서 현재 배송 문제가 발생했어.

현재 상황은 {{$json.situation}}
원인은 {{$json.delay_reason}}이고
배송이 {{$json.delay_days}} 정도 늦어지고 있어.

고객에게 보낼 배송 지연 안내문을 작성해줘.

고객이 화나지 않도록 최대한 친절하고 센스 있게 작성해줘.
우리 쇼핑몰 이미지가 나빠지지 않도록 긍정적으로 표현하고,
배송이 정상화되고 있다는 느낌도 줘.

너무 딱딱하지 않고 자연스럽게 작성하고,
내용도 너무 길지 않게 적당히 작성해줘.
  • "최대한 친절하게", "센스 있게", "적당히" 같은 주관적·모호한 기준
  • "정상화되고 있다는 느낌" — 사실 확인 없이 뉘앙스만 요구
  • 몇 문장, 어떤 순서, 어떤 표현 금지인지 구체 규칙 없음
  • 결과: 매번 다른 결과 가 나올 가능성 큼 (사람의 취향에 맡긴 격)

프롬프트 B — 원하는 결과를 명확히 (아랫 노드)

두 번째 LLM Chain 에는 원하는 결과의 조건을 하나하나 못박은 프롬프트를 넣습니다. 목적·사실·규칙·금지·형식이 분리되어 있어요.

역할·사실·규칙·금지·형식이 분리된 구조
프롬프트 B — 원하는 결과를 명확히 text
당신은 {{$json.shop_name}}의 고객지원 담당자입니다.

아래 사실만을 이용하여
배송 지연 고객에게 실제로 발송할 안내 메시지를 작성하세요.

[확인된 사실]

쇼핑몰:
{{$json.shop_name}}

배송 지연 원인:
{{$json.delay_reason}}

예상 지연:
{{$json.delay_days}}

현재 상황:
{{$json.situation}}

현재 출고 상태:
{{$json.normal_schedule}}

[목적]

고객에게 배송 지연 사실을 정확하게 전달하고
현재 확인되지 않은 정보를 약속하지 않으면서
고객의 불편에 대해 정중하게 안내하는 것이 목적입니다.

[작성 규칙]

1. 정확히 3문장으로 작성하세요.

2. 첫 번째 문장:
고객의 배송이 지연되고 있다는 사실과
불편을 드린 것에 대한 사과를 작성하세요.

3. 두 번째 문장:
배송 지연 원인이 {{$json.delay_reason}}이며
예상 지연 기간이 {{$json.delay_days}}이라는 사실을 반드시 포함하세요.

4. 세 번째 문장:
{{$json.normal_schedule}}라는 현재 상황만 안내하고
고객의 양해를 요청하세요.

[금지사항]

다음 내용은 절대 작성하지 마세요.

- "곧 정상화됩니다"
- "오늘 발송됩니다"
- "내일 도착합니다"
- "빠른 시일 내 정상화됩니다"
- 정확한 배송 완료일
- 보상 또는 환불 약속
- 입력 데이터에서 확인할 수 없는 내용

"최대한", "곧", "빠르게", "조만간"처럼
기준이 불명확한 표현도 사용하지 마세요.

[출력 형식]

제목이나 설명을 붙이지 말고
고객에게 실제로 발송할 안내문 3문장만 출력하세요.
  • 역할·목적·사실·규칙·금지·형식을 구획으로 분리
  • 문장 수, 각 문장의 역할까지 지정 (1문장=사과 / 2문장=사실 / 3문장=양해)
  • "확인되지 않은 정보를 약속하지 마세요" — 안 할 것을 구체적으로 나열
  • "최대한", "곧" 같은 모호한 표현 자체를 금지
  • 결과: 매번 거의 같은 형태로 나옴 (자동화에 안심하고 붙일 수 있음)

결과 비교 — 무엇이 '좋은' 프롬프트인가

두 노드를 나란히 실행해 결과를 봅니다.

프롬프트 A 결과
프롬프트 B 결과
💡
사실 A의 답변에도 문장 자체가 '틀린' 건 없습니다. 문장은 그럴싸하고 문법도 맞습니다. 프롬프트 자체에는 절대적인 잘잘못이 없습니다.

그렇다면 왜 굳이 B처럼 길게 쓰는 걸까요? 이유는 하나입니다.

💡
🎯 좋은 프롬프트란 — 내가 원하는 결과가 정확히 나오도록 유도하는 프롬프트입니다. A는 AI에게 '알아서 잘 해줘'라고 넘긴 것이고, B는 '이런 결과가 나와야 한다'를 모든 조건으로 못박은 것입니다.

다시 말해 프롬프트의 품질은 결과물 자체의 문법·문장력이 아니라, 내 의도와 얼마나 일치하는가 · 매번 같은 품질로 재현되는가 로 판단합니다.

  • 다른 쇼핑몰 데이터를 넣어도 같은 형식으로 나오는가
  • "곧 정상화됩니다" 같은 내가 금지한 표현이 안 나오는가
  • 매번 실행할 때마다 결과가 비슷한 톤·구조인가
  • 다음 노드(이메일 발송 등)에 그대로 넘겨도 안전한가
💡
정리하면 — 모호하게 던지면 AI가 알아서 채우고, 명확하게 던지면 AI가 그대로 따라옵니다. 자동화에 붙일 프롬프트일수록 내가 원하는 결과의 조건을 얼마나 세밀하게 명시했는가 가 유일한 기준입니다.