IT/IT 독서

AI와 소통하는 코딩의 예술: '프롬프트 엔지니어링' 완벽 가이드 - Beyond Vibe Coding 바이브 코딩을 넘어 (O'reily) - Chapter02. 신속한 의사 소통의 기술: AI와 효과적으로 의사소통하기

카멜필름 2025. 6. 14. 13:53

Beyond Vibe Coding 바이브 코딩을 넘어 (O'reily) - Chapter02. 신속한 의사 소통의 기술: AI와 효과적으로 의사소통하기

안녕하세요, 카멜필름 구독자 여러분! 지난 포스팅에서 AI 시대의 새로운 코딩 패러다임인 바이브 코딩(Vibe Coding)AI 지원 엔지니어링(AI-assisted Engineering)에 대해 심도 있게 다뤄보았습니다. AI가 코드 생성의 영역으로 깊숙이 들어오면서 이제 프롬프트는 단순한 지시를 넘어선 새로운 소스 코드가 되었습니다. 이번 시간에는 '프롬프트 엔지니어링'이라는 예술이자 과학의 영역을 탐구하며 AI 코딩 어시스턴트의 잠재력을 최대한 끌어내는 방법을 함께 알아보겠습니다.


프롬프트, 왜 이렇게 중요할까? 코딩의 새로운 언어

 바이브 코딩을 AI 모델과의 대화라고 비유한다면 프롬프트 엔지니어링(Prompt Engineering)은 바로 그 AI의 언어를 구사하여 최상의 결과물을 얻어내는 기술입니다. 한 줄의 관련 없는 코드나 버그투성이의 제안과 완벽한 솔루션 사이의 차이는 바로 잘 만들어진 프롬프트에서 갈립니다. 프롬프트 엔지니어링을 마스터한다는 것은 AI를 효과적으로 안내하고, 필요한 문맥을 제공하며, 첫 번째 답변이 만족스럽지 않을 때 AI와 반복적으로 소통하는 법을 아는 것을 의미합니다.

 

 AI와 함께 프로그래밍한다는 것은 본질적으로 AI를 통해(through) 자연어를 사용하여 프로그래밍하는 것입니다. 여러분이 제공하는 프롬프트는 AI 인터프리터가 실제 코드로 번역하는 고수준 프로그래밍 언어와 같습니다. 컴파일러의 출력이 원본 코드의 품질에 좌우되듯이, AI의 출력 또한 프롬프트의 품질에 달려 있습니다.

 

프롬프트가 그토록 중요한 몇 가지 이유를 살펴봅시다:

  • AI는 독심술사가 아니다: LLM은 아무리 정교하더라도 당신의 마음을 읽지 못합니다. 그들은 주어진 입력에만 반응하죠. 모호하거나 모호하게 작성된 프롬프트는 관련 없거나 부정확한 코드로 이어질 수 있는 반면, 명확하고 구체적인 프롬프트는 첫 시도에 완벽한 솔루션을 제공할 수 있습니다.
  • 사고의 전환: 전통적인 코딩에서는 알고리즘을 고안하고 코드를 작성하는 데 시간을 보냈습니다. 하지만 바이브 코딩에서는 AI에게 요구사항을 어떻게 전달할지에 대해 고민하는 데 시간을 할애합니다. 이는 '코드를 작성한다'는 의미 자체가 변화하는 것을 뜻합니다. 한 줄의 함수 대신 한 단락의 글을 쓸 수 있지만, 여전히 정밀하고 논리적이어야 합니다.
  • 문서에 적힌 내용만 정확히 실행하는 융통성 없는 주니어 개발자: 프롬프트 작성은 마치 지극히 문자적이고 융통성 없는 주니어 개발자를 위한 문서나 사용자 스토리를 작성하는 것과 같습니다. 이 개발자는 방대한 지식을 가지고 있지만, 패턴 이외의 상식은 전혀 없습니다. 당신의 지시(프롬프트)가 해석의 여지를 남긴다면, AI는 당신이 의도하지 않은 방식으로 빈틈을 채울 것입니다. 따라서 AI와 소통하는 법을 배우는 것은 과거 프로그래밍 언어의 문법을 배우는 것만큼이나 중요합니다.
  • 재현성 및 미래 대비: 특정 패턴이나 작업에 대해 안정적으로 좋은 코드를 생성하는 프롬프트를 발견한다면, 그 프롬프트는 마치 코드 스니펫이나 템플릿처럼 귀중한 지식이 됩니다. 팀 내에서 효과적인 프롬프트 패턴을 공유하는 것은 코딩 모범 사례를 공유하는 것과 유사하죠.
  • 새로운 기능 활용의 열쇠: 모델이 발전하고 더 통합될수록 더 복잡한 상호작용이 가능해질 것입니다. 프롬프트에 능숙해지는 것은 이러한 새로운 기능을 빠르게 활용하는 데 필수적입니다. 예를 들어, 일부 고급 시스템은 모델의 문맥으로 광범위한 지침이나 전체 참조 문서를 첨부할 수 있습니다. 이러한 입력을 구조화하는 방법을 아는 것이 강력한 기능을 활용하는 핵심입니다.

프롬프트 작성은 새로운 필수 기술입니다. 여러 면에서 프롬프트 자체가 프로그래밍입니다. 단지 AI가 코드로 변환할 언어(예: 영어)로 작성한다는 점이 다를 뿐이죠. 여전히 명확하고 논리적이어야 하며 엣지 케이스를 예측해야 합니다.


명확성과 구체성: 원하는 코드를 얻는 프롬프트 작성 전략

프롬프트 작성의 황금비법 중 하나는 원하는 바를 구체적이고 명확하게 제시하는 것입니다. 인간 협업자와 달 AI는 당신이 제공하는 단어 외에 진정으로 당신의 목표를 이해하지 못합니다. 흔한 실수는 AI에게 "웹사이트를 만들어줘"와 같은 매우 고수준의 프롬프트를 주고 마법을 기대하는 것입니다. AI는 마법사가 아니죠~ AI는 구체적인 세부 정보가 있을 때 훨씬 더 잘 작동합니다. 모호하거나 해석의 여지가 있는 부분은 의도치 않은 결과로 이어질 수 있습니다.

예를 들어, 단순히 "정렬 함수를 작성해줘"라고 하기보다는 다음과 같이 말할 수 있습니다:

고객 레코드(각각 first_name과 last_name 필드가 있음) 목록을 받아 last_name을 기준으로 알파벳순으로 정렬된 목록을 반환하는 Python 함수 sort_by_lastname(customers)를 작성해줘. 간략한 독스트링을 포함하고, last_name이 없는 경우는 빈 문자열로 처리해줘.

이 프롬프트는 언어(Python), 함수 이름과 목적, 입력 구조, 정렬 기준 키, 추가 요구사항(독스트링), 그리고 엣지 케이스까지 명확한 기대치를 설정합니다. 이렇게 하면 여러분이 필요로 하는 것과 정확히 일치하거나 매우 유사한 코드를 얻을 가능성이 높습니다. 본질적으로 명세서 작성자처럼 생각하세요. 작업을 더 정밀하게 명시할수록 AI가 추측할 필요가 줄어들고, 수정해야 할 부분도 적어집니다.

구체성을 높이는 전략들은 다음과 같습니다:

  • 언어 또는 환경 명시: JavaScript로 솔루션을 원한다면 "JavaScript 함수를 작성해줘..."라고 명시하세요. 특정 프레임워크나 버전("React Hooks를 사용하여...", "Python 3에서...")을 원한다면 그것도 포함하세요.
  • 출력 범위 정의: 단일 함수만 필요한가요? 전체 파일이나 모듈이 필요한가요? 테스트를 포함해야 할까요? 예를 들어, "함수 구현만 제공해줘"와 "완전히 실행 가능한 스크립트를 제공해줘"는 다른 응답을 가져옵니다.
  • 요구사항 및 제약 조건 포함: 암호 길이, 시도 제한 등 엣지 케이스나 제약 조건을 프롬프트에 명시하세요. 코드가 성능 최적화되거나 특정 알고리즘을 사용해야 한다면("O(n) 시간 및 O(1) 공간 사용", "이진 탐색 접근 방식 사용") 그렇게 말하세요.
  • 모호한 참조 피하기: '그것(it)'과 같이 명확한 선행사가 없는 단어는 사용하지 마세요. "그것을 처리하고 결과를 반환해줘" 대신 "배열을 처리하고 결과 배열을 반환해줘"라고 명시합니다.
  • 원하는 출력 형식: AI가 코드만 출력하기를 원하거나, 주석을 포함한 코드, 또는 설명을 원한다면 그렇게 지시할 수 있습니다. ("코드만 제공하고 설명은 하지 마", "각 단계에 대한 코드와 간략한 주석을 제공해줘").

명확한 프롬프트는 AI의 성공을 위한 발판입니다. 만약 AI의 답변이 너무 많은 수정이 필요하다면, 당신의 프롬프트가 충분히 구체적이지 않았는지 되돌아보세요.

피해야 할 프롬프트 작성 습관:

  • 장황한 프롬프트: 불필요한 정보가 포함된 장황한 프롬프트는 모델을 혼란시키거나 잘못된 것에 집중하게 할 수 있습니다. 간결하지만 완전하게 설명하세요.
  • AI가 스스로 세부 사항을 정확히 채워줄 것이라는 가정: 스레드 안전성이나 특수 문자 처리 등 중요한 사항은 반드시 언급해야 합니다. 언급되지 않으면 AI가 처리하지 않을 수 있습니다.
  • 확정적 결과를 원할 때 개방형 '창의적' 프롬프트 사용: "데이터를 분석하는 코드를 작성해줘"라고 하면 AI는 어떤 분석을 원하는지 추측할 수밖에 없습니다. 대신 "숫자 목록의 평균과 표준 편차를 계산해줘"와 같이 구체적으로 명시해야 합니다.

요약하자면, 원하는 것을 정확하게 말하세요. AI가 당신이 진정으로 원하는 것을 더 많이 '알수록', 더 나은 결과를 제공할 수 있습니다. AI를 여러 번 수정해야 한다면, "어떻게 하면 내 초기 프롬프트가 더 명확할 수 있었을까?"라고 자문해보세요.


반복적인 개선: AI와의 피드백 루프

아무리 명확한 프롬프트를 사용하더라도 첫 시도에 완벽한 답변을 얻지 못할 수도 있습니다. AI와의 상호작용을 대화반복적인 개발 프로세스로 생각해야 합니다. 이것이 바로 우리가 1장에서 언급했던 피드백 루프입니다.

AI가 코드를 제공하면, 인간 개발자가 작성한 코드처럼 비판적으로 검토하세요. 요구사항을 충족하는지? 아니라면, 무엇이 빠졌거나 잘못되었는지 파악하세요. 그런 다음 피드백이나 개선된 프롬프트를 제공합니다. 이는 대화형 AI에서는 단순히 대화를 이어가는 방식으로 코드 에디터에서는 AI가 반응할 수 있는 추가 주석을 작성하는 방식으로 이루어질 수 있습니다.

그림 2-2. 고급 프롬프트 엔지니어링: AI와의 대화는 끊임없는 피드백 루프입니다.

 

AI에 피드백을 제공함으로써 당신은 원하는 결과에 더 가깝게 AI를 이끌 수 있습니다. 어떤 의미에서는 당신이 특정 문제에 대해 AI를 실시간으로 훈련(training it on the fly)시키고 있는 것입니다. 고급 프롬프트 엔지니어링은 프롬프트 -> AI 출력 -> 검토 -> 프롬프트 개선 -> AI 출력 -> ... 만족할 때까지 반복되는 루프와 같습니다. 각 반복에서 변경 사항을 작게 유지하는 것이 유용합니다. 프롬프트를 너무 많이 수정하면 이전 출력의 좋은 부분을 잃을 수 있기 때문이죠.

 

예를 들어, "정수 목록을 받아 그 합계를 반환하는 함수를 작성해줘"라고 프롬프트했습니다. AI는 함수를 반환했지만, 빈 목록을 제대로 처리하지 못합니다.

이때 다음과 같이 답변할 수 있습니다: "잘했어. 근데 목록이 비어 있으면 0을 반환하도록 수정해줘." 그러면 AI는 함수를 그에 따라 업데이트할 것입니다. 이렇게 하면 처음부터 다시 프롬프트할 필요 없이, AI에게 조정을 지시하는 것만으로 됩니다. AI는 이미 이전에 제공한 코드의 문맥을 가지고 있기 때문이죠.

 

만약 인라인 어시스턴트를 사용한다면 개선은 코드를 편집하고 # TODO: handle empty list와 같은 주석을 작성한 다음 AI가 해당 부분을 수정하는 것을 제안하는 형태로 나타날 수 있습니다.

 

AI가 엉뚱한 방향으로 나아간다면 다시 올바른 방향으로 이끌 수 있습니다. 때로는 매우 부정확한 시도를 살리려고 애쓰기보다 처음부터 프롬프트를 재설정하거나 재구성하는 것이 더 쉬울 때도 있습니다. 판단력을 발휘하세요. AI 출력이 완전히 오해한 것이라면, 프롬프트를 처음부터 명확하게 다시 작성해야 합니다.

 

개선을 거듭하면서 AI가 여러분의 프롬프트를 어떻게 해석했는지도 학습하게 됩니다. 이는 앞으로 프롬프트를 작성하는 방식에 영향을 줄 수 있습니다. "아, '로그인 시스템'을 전체 UI로 이해했구나. 다음에는 백엔드만이라고 명시해야겠다"라고 깨달을 수도 있습니다.

 

 이것을 코드를 디버깅하는 것처럼 생각하세요. AI 출력이 잘못되었다면, '버그'는 AI의 처리 과정에 있는 것이 아니라 당신의 프롬프트에 있을 수 있습니다. 코드가 잘못된 결과를 생성할 때 코드를 검사하고 수정하듯이, AI가 예상치 않거나 잘못된 출력을 생성할 때 프롬프트를 개선해야 합니다. 당신과 AI 간의 대화는 각 상호 작용이 문제를 정확히 찾아내고 수정하는 데 도움이 되는 디버깅 세션과 같습니다.


프롬프트 기법: 효과적인 소통을 위한 도구 상자

이제 프롬프트 작성 기술을 비약적으로 향상시킬 수 있는 구체적인 기법들을 살펴보겠습니다. 이들은 마치 단순한 지시만으로는 부족하거나 AI를 특정 방식으로 안내하고 싶을 때 사용할 수 있는 패턴이나 레시피와 같습니다.

이러한 기법들을 마스터함으로써 당신은 다양한 상황을 다룰 수 있습니다: AI에게 평범한 영어로 지시하고, 예시를 제공하고, AI가 출력을 설명하거나 구조화하도록 만들고, AI를 다른 사고방식이나 역할로 설정하는 등 말이죠. 이 모든 것은 AI가 당신이 필요로 하는 것을 정확히 생성하도록 돕습니다.

프롬프트 기법들은 상호 배타적이지 않으며, 특히 복잡한 작업에서는 최상의 결과를 위해 여러 가지를 함께 사용하는 경우가 많습니다.

 

스타일에 대한 참고: 이러한 기법을 사용할 때는 모델에 맞춰 어조를 조절하세요. 많은 모델은 정중하거나 중립적인 지시에 잘 반응합니다. 옛날 방식이거나 지나치게 형식적인 언어를 사용할 필요는 없습니다. 직접적이지만 정중한 표현이 효과적입니다: "X를 해주세요." 또는 "Y를 해봅시다." 예를 들어, 연쇄적 사고(Chain-of-Thought)에서 인기 있는 문구는 "단계별로 생각해봅시다(Let's think step by step)"입니다. GPT-4와 같은 모델은 이를 추론을 보여주라는 신호로 인식합니다.

1. 제로샷 프롬프팅 (Zero-shot Prompting)

  • 정의: 모델에게 어떤 예시나 추가 지침 없이 단순히 작업을 요청하는 것입니다. 본질적으로 모델은 "제로(zero)" 예시에서 작업을 해결합니다.
  • 사용 시점: 가장 흔한 시나리오입니다. 평범한 언어로 원하는 것을 요청하기만 하면 됩니다. 작업이 일반적이고 프롬프트가 명확하다면, 종종 이것으로 충분합니다.
  • 예시: "숫자가 소수인지 확인하는 Python 함수를 작성해줘." AI는 루프나 시험 나눗셈을 사용하여 소수 판별 함수를 생성할 가능성이 높습니다.
  • 장점: 빠르고 모델이 학습한 지식에 의존합니다. 최신 모델은 특히 일반적인 프로그래밍 작업(소수 판별, 정렬, 문자열 조작 등)에 대해 제로샷 응답에 놀랍도록 능숙합니다.
  • 단점: 작업이 특이하거나 출력 형식이 구체적이지 않은 경우, 제로샷은 첫 시도에서 필요한 것과 정확히 일치하지 않는 결과를 산출할 수 있습니다.

대개 간단한 작업에는 제로샷을 먼저 시도하는 것이 좋습니다. 결과가 만족스럽지 않다면, 그때 개선하거나 다른 기법으로 전환할 수 있습니다.

2. 원샷/퓨샷 프롬프팅 (One-shot and Few-shot Prompting)

  • 정의: 원샷(One-shot) 프롬프팅은 프롬프트의 일부로 원하는 것(입력과 원하는 출력)의 예시를 하나만 제공하는 것을 의미합니다. 퓨샷(Few-shot)은 모델에게 새 입력을 가지고 작업을 수행하도록 요청하기 전에 몇 가지 예시(일반적으로 2~5개)를 제공하는 것을 의미합니다. 이는 모델에게 "내가 한 가지 사례를 이렇게 해결했어. 이제 다음 것도 비슷하게 해봐"라고 보여주는 것과 같습니다.
  • 사용 시점: 모델이 원하는 형식이나 스타일을 정확히 모를 수 있거나, 작업이 다소 특이할 때 사용합니다. 예시를 제공함으로써 모호함을 줄일 수 있습니다.
  • 예시 (원샷): 특정 형식이 필요한 의사 코드(pseudocode)를 원한다고 가정해 봅시다.여기서는 팩토리얼 예시와 원하는 형식을 제공했습니다. 이제 모델은 "가장 큰 숫자" 지침에 대해 유사한 형식(함수, if/else 또는 루프 로직 포함)의 의사 코드를 생성할 가능성이 높습니다.
    다음 영어 지침을 Python과 유사한 의사 코드로 변환해줘.
    예시 지침: "n의 팩토리얼을 계산해라"
    예시 의사 코드:
    function factorial(n):
        if n <= 1:
            return 1
        else:
            return n * factorial(n-1)
    지침: "목록에서 가장 큰 숫자를 찾아라"
    
  • 예시 (퓨샷): 특정 알고리즘을 사용하도록 AI에게 지시하고 싶거나, 여러 정답 중 특정 하나를 선호할 때 예시를 통해 그 방향으로 유도할 수 있습니다.여기서 영어-SQL 변환 예시 두 개를 제공하면, AI는 이 패턴을 따라 세 번째 쿼리를 정확하게 답변할 가능성이 높습니다. 퓨샷 예시는 코딩에도 적용될 수 있습니다. 작은 샘플로 원하는 스타일을 AI에게 보여준 다음 더 많은 것을 요청하는 것이죠. 이는 프롬프트 내에서 AI에게 작은 훈련 데이터 세트를 제공하는 것과 같습니다.
  • 참고: 문맥 창(Context Window)은 언어 모델이 단일 상호 작용에서 처리할 수 있는 최대 텍스트 양(토큰 단위)을 의미하며, 이는 입력 프롬프트와 생성된 응답을 모두 포함합니다. 이는 현재 AI 모델의 한계점입니다. 이 한계에 도달하면 모델은 추가 정보를 처리할 수 없습니다. 프롬프트를 작성할 때 포함하는 모든 것(지침, 예시, 데이터, 응답에 필요한 공간)이 이 고정된 용량 내에 들어와야 합니다.
  • 다음 영어 문장을 SQL 쿼리로 변환해줘.
    1. '2020년 이후 고용된 모든 직원 가져오기' -> SELECT * FROM employees WHERE hire_date > '2020-01-01';
    2. '지난달에 구매한 고객 이름 목록' -> SELECT name FROM customers JOIN purchases ON ... WHERE purchase_date > ...;
    3. '재고가 없는 제품 수' ->
    
  • 장점: 매우 구체적인 스타일로 출력을 얻을 수 있습니다. 또한 이 기술은 모델이 패턴을 따르거나 개념을 반복적으로 적용해야 하는 작업을 처리하는 데 도움이 됩니다.
  • 단점: 퓨샷 프롬프팅은 프롬프트를 길게 만들어 문맥 창(context window)을 소모합니다. 매우 크거나 복잡한 예시의 경우 모델의 용량을 많이 "먹어버릴" 수 있습니다. 하지만 보통 한두 개의 작은 예시는 괜찮습니다.

3. 연쇄적 사고 프롬프팅 (Chain-of-Thought Prompting)

  • 정의: 연쇄적 사고(CoT) 프롬프팅은 모델에게 최종 답변을 주기 전에 단계별로 생각하거나 추론을 보여달라고 요청하는 것을 포함합니다. 즉, 모델에게 문제를 분해하도록 권장하는 것입니다.
  • 사용 시점: 추론, 다단계 계산이 필요한 복잡한 문제, 또는 모델이 바로 답변으로 넘어갈 경우 실수를 할 수 있다고 의심될 때 유용합니다. 출력에 설명이 필요할 때도 유용합니다.
  • 예시: 단순히 "12개 중 4개를 선택하는 경우의 수는?"과 같은 조합 수학 문제를 묻고 답변을 얻는 대신, "12개 중 4개를 선택하는 경우의 수를 단계별로 풀어줘"라고 말할 수 있습니다. 모델은 "12개 중 4개 = 12!/(4!*8!) = ... = 495"와 같이 개요를 설명할 것입니다.
  • 코딩에서 연쇄적 사고는 까다로운 알고리즘 작업에 유용할 수 있습니다. 다음과 같은 프롬프트를 시도할 수 있습니다: "정렬된 두 목록을 병합하는 방법을 단계별로 설명한 다음, Python 코드를 제공해줘." 모델은 먼저 "각 목록의 시작 부분에 두 개의 포인터를 사용하여 요소를 비교하고, 더 작은 요소를 결과 목록에 추가하고, 해당 포인터를 이동하는 방식"과 같은 개요를 설명한 다음 코드를 제공할 것입니다. 이는 코딩하기 전에 솔루션을 올바르게 구조화했는지 확인하는 데 도움이 됩니다.
  • 장점: 추론이 필요한 작업에서 정확성을 향상시킵니다. 모델에게 "소리 내어 생각하도록" 프롬프트하면 수학 및 논리 작업에서 더 나은 결과를 얻을 수 있다는 연구 증거도 있습니다. 또한 모델의 프로세스에 대한 통찰력을 제공하여 학습에 도움이 되거나 답변에 대한 신뢰도를 높일 수 있습니다.
  • 단점: 출력이 길어집니다(최종 코드에서는 원하지 않을 수 있음). 또한 일부 인터페이스(일반적인 코드 완성)는 추론을 코드와 분리하여 표시하도록 설정되어 있지 않습니다. 하지만 모델에게 추론을 코드 내 주석으로 포함하도록 지시할 수 있습니다.

4. 역할 프롬프팅 (Role Prompting)

  • 정의: 역할 프롬프팅은 AI에게 특정 정체성이나 역할을 맡도록 요청하여 응답 방식에 영향을 미치도록 하는 것을 의미합니다.
  • 사용 시점: 답변의 스타일이나 세부 사항에 영향을 미치거나, 특정 관점을 얻고 싶을 때 사용합니다. 예를 들어, "전문가" 역할을 맡은 AI는 더 고급 솔루션이나 더 많은 설명을 제공할 수 있는 반면, "초보자" 역할은 더 기본적인 개념을 설명하게 할 수 있습니다.
  • 예시:
    • "당신은 Python 강사입니다. 다음 코드를 설명하고 더 Pythonic하게 수정해주세요."
    • "보안 분석가 역할을 해주세요. 여기에 코드가 있습니다. 보안 취약점을 식별해주세요."
    • "코드의 스타일 문제를 확인하는 린터(linter)처럼 행동해주세요." AI에게 보안 분석가 역할을 할당하면 데이터 유효성 검사, 보안 코딩 관행 또는 잠재적 취약점과 같이 평소에는 언급하지 않았을 내용에 집중하게 할 수 있습니다. 강사 역할은 더 명확한 설명을 제공하고 사전 지식을 가정하지 않게 할 수 있습니다.
    코딩에서는 "당신은 최적화에 능숙한 C++ 전문가 프로그래머이며, 주니어 개발자에게 지시하고 있습니다"라고 말한 다음 코드를 요청할 수 있습니다. 그 결과는 더 고급 C++ 기능을 사용하면서도 특정 선택을 한 이유에 대한 설명을 포함하여, 기술적 정교함과 교육적 명확성의 균형을 이룰 가능성이 높습니다.
  • 장점: 답변의 어조와 깊이를 조절할 수 있습니다. 이는 특정 복잡성이나 철저함 수준에 맞춰 솔루션을 맞춤화하는 데 유용합니다. 매우 간단한 솔루션(초보자처럼 행동하라고 지시하면 복잡한 트릭을 피할 수 있음)을 원하거나 매우 최적화된 솔루션(성능 전문가처럼 행동하라고 지시)을 원할 때 유용합니다.
  • 단점: 때로는 모델이 필요한 것보다 페르소나에 더 집중할 수 있습니다("강사"는 이미 알고 있는 것을 설명하기 시작할 수 있음). 또한 일부 AI 안전 시스템은 특정 역할 설명에 더 민감할 수 있지만("데이터 분석가" 또는 "소프트웨어 엔지니어"와 같은 직업적 역할은 일반적으로 문제 없이 작동합니다).

5. 문맥 프롬프팅 (Contextual Prompting)

  • 정의: 문맥 프롬프팅은 즉각적인 작업 설명 외에 AI에게 추가적인 문맥이나 정보를 제공하는 것을 의미합니다. AI 모델은 프롬프트에 제공하지 않는 한 전체 프로젝트에 대한 지속적인 기억을 가지고 있지 않습니다. 따라서 기존 코드베이스에 맞는 코드를 작성하도록 AI에게 요청하려면 해당 문맥을 제공해야 합니다. 기본적으로 관련 데이터나 배경 정보를 프롬프트의 일부로 제공하는 것입니다.
  • 사용 시점: 문제를 해결하는 데 모델이 알지 못하거나 훈련 데이터에서 정확하게 기억하지 못할 수 있는 특정 데이터나 정의를 알아야 할 때. 또는 특정 외부 정보(API 사양, 이전 대화 내용)와 일관성을 유지하고 싶을 때 사용합니다.
  • 예시:
    • 특정 데이터 구조와 함께 작동하는 코드를 원한다면, 해당 정의를 붙여넣을 수 있습니다:
      Python
       
      아래 클래스가 주어졌을 때, X 함수를 구현해줘.
      class Node:
          def __init__(self, value, next=None):
              self.value = value
              self.next = next
      # 이제 head에서 시작하는 연결 리스트의 노드 수를 세는 함수를 작성해줘.
      
      클래스 정의를 포함함으로써 AI가 코드에서 Node.value와 Node.next를 적절하게 사용할 가능성이 훨씬 높아집니다.
    • 특정 API를 사용하고 싶다면, 문서 스니펫을 프롬프트에 포함합니다: "requests 라이브러리를 사용하여 API에서 데이터를 가져와. (API는 JSON 형식으로 반환: {...})" API 사용의 짧은 예시라도 포함하면 AI는 이를 모방할 수 있습니다.
    • 모호함을 해소하기 위해: "고등학생을 지칭하는 용어로 '학생'을 사용하여 함수를 작성해줘..." 문맥에서 '학생'이 모호할 수 있다면, 명확히 해주는 것입니다.
  • 장점: AI를 당신이 중요하게 생각하는 문맥에 기반을 둡니다. 사실을 제공하면 AI가 잘못된 가정을 할 가능성이 줄어듭니다. 이는 AI가 당신의 특정 사용 사례 세부 정보를 기억하거나 알지 못할 때 매우 유용합니다.
  • 단점: 프롬프트를 길게 만듭니다. 또한 모델이 제공된 문맥을 답변에 그대로 토해낼 수도 있습니다(조심하지 않으면 문서 스니펫의 줄을 코드에 복사하는 식). 하지만 대개는 적절하게 사용합니다. 팁: 방대한 문맥(큰 스키마나 많은 양의 코드)이 있다면, 모든 것을 그대로 포함하기보다 핵심 요소를 직접 요약하여 모델에 제공하는 것이 더 나을 수 있습니다. 이 접근 방식은 문맥 한도를 유지하면서 모델이 가장 관련성 높은 정보를 받도록 돕습니다. 그러나 내용이 충분히 작다면 위처럼 그대로 포함하세요.
  • 성능 제약 조건("O(n log n) 이상으로 최적화해줘"), 호환성 제약 조건("Python 3.8에서 실행되어야 해"), 또는 라이브러리 선택("표준 라이브러리만 사용하고 외부 종속성은 사용하지 마")과 같은 제약 조건을 언급하는 것도 유용합니다. 이들은 보호 장치 역할을 하여 AI가 허용 가능한 범위를 벗어나는 것을 제안하지 않도록 합니다.

6. 메타 프롬프팅 (Metaprompting)

  • 정의: 메타 프롬프팅은 솔루션이 무엇을 해야 하는지뿐만 아니라 출력 자체에 대한 지침을 제공하는 것입니다. AI에게 결과물의 형식이나 접근 방식을 제어하라고 지시하는 것과 같습니다.
  • 사용 시점: 답변이 특정 형식이나 스타일로 필요하거나, AI가 문제를 처리하는 방식을 제어하고 싶을 때 사용합니다.
  • 예시:
    • "먼저 접근 방식을 두 문장으로 설명한 다음 코드를 제공해줘." (AI가 바로 코드로 넘어가지 않도록 보장합니다.)
    • "솔루션에 어떤 라이브러리도 사용하지 마." (솔루션에 제약을 가합니다.)
    • "출력 형식을 JSON으로 지정해줘." (AI를 사용하여 코드가 아닌 데이터를 생성할 때 유용합니다.)
    • "함수 정의 라인 없이 함수 본문만 제공해줘." (기존 코드에 함수를 삽입할 때 유용합니다.)
    • "입력이 유효하지 않으면 오류 대신 None을 반환해줘." (정확히 출력 형식은 아니지만, 특정 경우에 AI가 어떻게 동작해야 하는지 지시하는 것입니다.)
  • 장점: 추가 편집 없이 필요한 것을 정확하게, 필요한 방식으로 얻을 수 있습니다. 이는 일부 시나리오에서 매우 중요합니다. AI의 출력을 파이프라인에서 자동으로 사용할 계획이라면 일관된 형식이 필수적입니다.
  • 단점: 지침이 모델의 기본 스타일과 충돌하면 때로는 부분적으로만 따르거나 강조해야 할 수 있습니다.

7. 자기 일관성 (Self-consistency) (다중 출력 및 다수결)

  • 정의: 자기 일관성은 프롬프트 스타일이라기보다는 전략에 가깝습니다. 동일한 프롬프트에 대해 여러 출력을 얻은 다음, 가장 좋거나 가장 흔한 것을 선택하는 아이디어입니다. Learn Prompting의 Sander Schulhoff가 언급했듯이 이는 모델에게 여러 번(약간의 무작위성을 부여하여) 요청하고 많은 답변이 일치한다면, 그 합의가 올바를 가능성이 높다는 개념을 활용합니다.
  • 사용 시점: 모델의 첫 번째 답변이 정확한지 확신할 수 없는 복잡한 문제, 특히 스스로 쉽게 검증할 수 없거나 AI로부터 반복적인 답변을 통해 신뢰도를 확인하고 싶을 때 사용합니다.
  • 수동 사용법: 일부 플랫폼(예: ChatGPT)에서는 "답변 재생성"을 클릭할 수 있습니다. 또는 프롬프트를 새 세션에 복사하여 동일한 결과를 제공하는지 확인할 수 있습니다. 3개의 답변을 얻었는데 2개가 같고 1개가 다르다면, 그 2개를 신뢰할 수 있습니다(문제에 단 하나의 정답이 있다고 가정할 때).이 기술은 코딩 외 작업(논리 퍼즐 등)에서 더 강력하지만, 알아둘 가치는 있습니다.
  • 프로그래밍 문맥에서, 결정론적인 것을 위한 코드를 생성하는 경우, 일반적으로 매번 매우 유사한 코드(변수 이름이나 스타일의 작은 변화는 있을 수 있음)를 제공할 것입니다. 하지만 알고리즘 질문("이 코드의 출력은 무엇인가?")이라면 여러 번 실행하여 확인할 수 있습니다.
  • 장점: 여러 번 시도했을 때 솔루션이 수렴하면 신뢰도를 높일 수 있습니다. 또한 다양성을 얻을 수 있습니다(여러 솔루션 중에서 가장 우아한 것을 선택하고 싶을 때 유용함).
  • 단점: 여러 번 호출하고 출력을 비교하는 데 시간이 많이 소요됩니다.

실제로 저도 답변이 불확실할 때 다른 방식으로 질문을 다시 던져 동일한 답변을 얻는지 확인하곤 합니다. 동일한 답변을 얻으면 그 답변이 정확하다고 더 확신합니다.

8. ReAct (Reason + Act) 프롬프팅

  • 정의: ReAct추론(Reasoning)행동(Acting)을 결합하는 고급 프롬프트 기술입니다. 이는 모델이 연쇄적 사고처럼 '생각'하게 할 뿐만 아니라, 계산을 하거나, API를 호출하거나, 도구를 사용하는 등의 '행동'을 취하도록 합니다. 현재 실제로는 LangChain과 같은 프레임워크와 함께 자주 사용되며, AI가 프로그램이 명령으로 해석하는 특별한 형식으로 출력을 내보내고, 그 결과를 다시 AI에게 피드백으로 제공합니다.
  • 사용 시점: 외부 정보나 반복적인 시도가 필요한 문제를 해결할 때 유용합니다.
    • 예시: "Python을 사용하여 파리의 현재 날씨를 확인하고 출력해줘." AI가 브라우징 기능이 없다면 현재 날씨를 실제로 가져올 수 없습니다. ReAct 접근 방식에서는 AI가 먼저 "파리의 현재 날씨 데이터를 얻으려면 날씨 API를 호출해야 한다"고 추론하여 문제를 설명합니다. 그런 다음 AI는 사용 가능한 도구를 사용하여 이 API 호출을 시도합니다. 성공하면 실제 날씨 데이터를 수신하고, 사용 가능한 도구가 없으면 한계를 인정하거나 가상의 데이터로 작업할 것입니다. 마지막으로, AI는 이 추론 및 행동 과정을 통해 얻을 수 있는 모든 데이터를 통합하여 날씨 정보를 표시하는 Python 코드를 작성합니다.AI가 코드를 실행할 수 있는 환경(예: Jupyter 통합 또는 유사 플랫폼)을 사용한다면, 다음과 같이 지시하여 ReAct를 구현할 수 있습니다: "먼저 이 함수에 대한 테스트를 작성하고 실행한 다음, 결과에 따라 코드를 조정해줘." 이는 추론 단계(테스트 작성), 행동 단계(테스트 실행), 그리고 결과에 따른 코드 조정이라는 ReAct 패턴을 보여줍니다. 그러나 순수 프롬프트를 통해 이러한 워크플로우를 오케스트레이션하려면 고급 프롬프트 기술과 적절한 기술 인프라가 필요합니다.
    • 참고: 외부 도구 접근 권한이 없다면 ReAct는 간단한 프롬프트 작업에 특히 관련성이 없을 수 있습니다. 그러나 조직을 위한 AI 도구를 평가할 때, 인터넷에서 현재 정보에 접근할 수 있는지 여부는 중요한 기능 평가 요소입니다. 많은 AI 모델은 지식 마감일(knowledge cutoff)을 가지고 있으며, 이는 훈련 데이터가 특정 날짜까지만 확장됨을 의미하므로 빠르게 변화하는 주제에 대한 정보는 오래될 수 있습니다.

고급 프롬프팅: 기법 결합과 복잡성 다루기

위에서 살펴본 프롬프트 기법들은 서로 결합하여 사용할 수 있습니다. 연쇄적 사고(CoT)를 예시로 보여주는 퓨샷 프롬프트를 사용할 수 있습니다. 또는 역할 프롬프팅과 연쇄적 사고를 결합할 수 있습니다: "시니어 엔지니어로서, 문제에 대해 단계별로 생각한 다음 코드를 제공해줘."

작동하지 않는 함수가 있다고 상상해 봅시다. 역할 프롬프팅과 CoT를 결합하여 다음과 같이 사용할 수 있습니다: "당신은 Python 디버거입니다. 다음 코드에서 버그를 찾기 위해 단계별로 생각해봅시다." 이어서 코드를 제공하면 AI는 각 라인에 대한 분석을 제공하고 버그를 정확히 찾아낼 수 있습니다.

혹은 다소 복잡한 알고리즘을 위한 코드를 생성하고, 주석을 잘 달며, 테스트 케이스까지 얻고 싶다고 해봅시다. 다음과 같은 결합된 프롬프트를 사용할 수 있습니다:

당신은 파이썬 전문가 개발자입니다. 단계별로 문제를 해결해봅시다. 두 개의 정렬된 리스트를 하나의 정렬된 리스트로 병합하는 함수 `merge_sorted_lists(list1, list2)`가 필요합니다. 먼저 접근 방식을 설명하고, 그 다음 주석이 포함된 파이썬 코드를 제공해주세요. 그 후, 작동을 시연하기 위한 2-3개의 예시 테스트를 코드로 제공해주세요.

 

이 단일 프롬프트는 매우 포괄적입니다. 첫 문장은 역할을 설정하고, 두 번째 문장은 단계별 추론을 요청합니다. 세 번째 문장은 주요 작업을 제시하고, 네 번째 문장은 설명 주석이 포함된 코드를, 그리고 마지막 문장은 테스트까지 요청합니다.

AI는 설명과 함께 인라인 주석이 달린 코드를 출력하고, 마지막에 테스트 케이스를 제공할 것입니다. 이는 고급 사용법이지만, AI에게 다면적인 응답을 지시하는 방법을 보여줍니다.

 

모델의 한계를 아는 것이 중요합니다: 프롬프트 엔지니어링은 무엇을 요청하지 말아야 하는지와 함정을 피하는 방법을 아는 것도 포함합니다. 프롬프트가 너무 커지거나 너무 많은 지침을 포함하면, 모델이 혼란스러워하거나 일부 출력을 잘라낼 수 있습니다. 만약 AI가 프롬프트의 일부를 무시하기 시작한다면, 프롬프트를 단순화하거나 여러 부분으로 나누어 요청해야 할 수 있습니다.

 

AI 모델이 때때로 부정확한 사실이나 코드를 생성한다면('환각(hallucinates)'을 일으킨다면), 이를 재확인하고 사실의 근거로 맹목적으로 사용하지 않도록 배워야 합니다. AI가 지나치게 장황한 코드를 제공하는 경향이 있다면, "솔루션을 가능한 한 간결하게 만들어줘"와 같이 미리 지시할 수 있습니다. 존재하지 않는 함수를 사용하는 경향이 있다면, "아래 나열된 API 함수만 사용해줘:"라고 지시하고 목록을 제공할 수 있습니다. AI의 행동을 더 잘 이해할수록, 약점을 우회하기 위해 프롬프트를 더 잘 조정할 수 있습니다.

 

매우 복잡한 작업의 경우, AI에게 작업을 하위 작업으로 분해하여 요청할 수도 있습니다. 예를 들어, 먼저 "간단한 산술 표현식 언어를 위한 기본 컴파일러를 구현하는 단계를 나열해줘"라고 프롬프트할 수 있습니다. AI가 단계를 제시하면, 각 단계를 별도의 프롬프트로 다룰 수 있습니다(예: "이제 1단계: 토큰화를 구현해줘"). 이는 AI와 함께 시스템 설계를 하는 것과 같습니다. 개요를 만든 다음 각 부분을 다듬어 나가는 방식이죠. 이는 코딩뿐만 아니라 계획 수립에도 AI의 도움을 활용하는 것입니다.

 

상태 유지 대화(Stateful Conversation) 대 원샷 프롬프팅(One-shot Prompting): 채팅 설정에서는 '상태(state)'라는 대화 기록이 존재하여 AI와 대화하며 문맥을 구축할 수 있습니다. IDE 완성 설정에서는 문맥이 주로 파일 내용과 주석이 됩니다. 둘 다 다른 방식으로 누적 문맥을 허용합니다. AI가 이전 대화 내용을 기억해야 할 경우(예: 답변을 개선할 때) 대화를 활용하고, 현재 관련 있는 내용에만 집중하기를 원할 경우 새로운 프롬프트나 파일 문맥을 사용하세요. 때로는 문맥을 초기화하는 것이 모델이 잠재적으로 잘못된 이전 가정에 집착하는 것을 방지하는 데 도움이 됩니다.

이러한 기법들을 다양한 예시로 연습함으로써, 어떤 상황에서 어떤 접근 방식을 사용해야 할지 능숙하게 판단할 수 있게 될 것입니다.

  • 출력 형식이 중요하다면, 예시(퓨샷) 또는 명시적인 형식 지정 지침을 제공하세요.
  • 논리가 까다롭다면, 연쇄적 사고(Chain-of-Thought) 또는 단계별 설명을 사용하세요.
  • 솔루션의 품질이 다양할 수 있다면, "숙련된 엔지니어"와 같은 역할을 설정하여 더 나은 스타일을 유도하세요.
  • 모델이 지시를 따르지 않는다면, 프롬프트를 여러 부분으로 나누거나 단순화하거나, 제약 조건에 더 강력한 표현을 사용해 보세요.

프롬프트의 예술은 반복적이고 창의적입니다. 모델이 진화함에 따라 프롬프트 모범 사례는 변할 수 있지만(예: 미래 모델은 더 적은 단어로도 의도를 더 잘 이해할 수 있음), 근본적인 원칙은 변하지 않습니다. 즉, 효과적으로 소통하면 AI가 당신을 더 잘 섬길 것이라는 점입니다.

 

본질적으로, 프롬프트 엔지니어링을 마스터하는 것은 새로운 프로그래밍 언어, 즉 AI를 위한 지시 언어를 마스터하는 것과 같습니다. 이는 기술 글쓰기, 선견지명, 그리고 프롬프트 자체에 대한 상호작용적 디버깅이 융합된 기술입니다. 하지만 일단 이 기술에 능숙해지면, AI는 당신의 마음의 확장처럼 느껴지기 시작할 것입니다. 왜냐하면 당신이 상상하는(또는 아직 완전히 상상하지 못했지만 AI의 도움으로 발견할 수 있는) 솔루션을 최소한의 마찰로 안정적으로 이끌어낼 수 있기 때문입니다. 이 기술은 구글링하는 방법이나 디버거를 사용하는 방법만큼이나 기본적인 것이 될 것이며, 바이브 코딩 시대의 현대 개발자의 필수 역량의 일부가 될 것입니다.


 

다음 장에서는 AI가 문제의 약 70%를 해결할 수 있다면, 코딩의 파트너로서 어떻게 접근해야 할지에 대해 다룹니다. 개발자들이 AI를 '진짜로' 어떻게 사용하는지와 바이브 코딩의 몇 가지 "황금비법"을 제시할 예정이니 많은 기대 부탁드립니다!

 

728x90
LIST