생성형 AI와 대화하며 프롬프트를 다듬는 법
이 글은 「생성형 AI로 시작하는 데이터 분석」 9회 연재 중 6회입니다. 전체 목차 보기
안녕하세요, 헬로데이터사이언스 나성호입니다.
지난 5회차에서 좋은 프롬프트의 9가지 요소를 소개하면서, 한 번에 9가지 요소를 모두 담은 프롬프트를 작성하는 것은 쉽지 않다고 말씀드렸죠. 그래서 이번에 좋은 프롬프트를 작성하는 현실적인 해법을 알려드리겠습니다. 결론부터 말하면, 처음부터 완벽하게 쓰려고 하지 말고, 짧게 대화로 시작하여 단계적으로 개선해나가자입니다.
제약 조건이 부족하면 어떤 일이 벌어질까
먼저 제가 강의 중에 소개하는 강의안에서, 같은 계정과 같은 모델로 “제주도 여행 계획을 세워줘”라는 프롬프트를 실행하여 받은 답변을 캡처해놓은 두 개의 이미지를 보여드리겠습니다. 5회차에서 나쁜 프롬프트의 예로 들었던, 지시 하나만 있고 나머지 여덟 가지 요소는 전부 빠진 바로 그 프롬프트입니다. 한 번은 평소 쓰던 일반 대화창에서 실행했고, 한 번은 이전 대화나 메모리의 영향을 받지 않는 임시 대화창에서 실행했습니다.
예상하시는 것처럼 두 답변이 많이 다릅니다. 일정표의 제목과 출력 형식이 완전히 다르다는 것을 쉽게 확인할 수 있을 겁니다. 그런데 더 눈여겨보실 대목이 있습니다. 저는 여행 기간을 한 번도 말한 적이 없는데, 두 답변 모두 3박 4일 일정을 짜놓고는 “정보가 없어서 3박 4일 기준으로 잡았다”고 스스로 밝히고 있습니다. 5회차에서 조건이 빠지면 “일정을 3박 4일로 잡는다든가, 일정표 형식이 매번 달라진다든가” 하는 일이 생긴다고 말씀드렸는데, 그 두 가지가 한 화면에 그대로 나타난 셈이죠.
정리하면 이렇습니다. 지시만 담은 프롬프트에는 LLM이 답변을 작성할 때 참고할 만한 제약 조건이 없습니다. 그러면 LLM은 그 빈자리를 매번 다르게 추정해서 채우고, 그 결과 답변의 품질이 일정하지 않게 되는 거죠.
여기서 한 가지 짚어둘 것이 있습니다. 2회차에서 살펴본 것처럼 LLM은 다음에 올 조각을 확률적으로 골라 이어붙이기 때문에, 조건을 아무리 꼼꼼하게 채워도 답변이 토씨 하나까지 똑같이 나오지는 않습니다. 조건을 채운다는 것은 답변을 고정시킨다는 뜻이 아니라, 답변이 흔들리는 폭을 줄인다는 뜻입니다. 위 실험에서 굳이 대화창을 둘로 나눈 것도 이 때문입니다. 답변이 달라진 이유가 일반 대화창에 남아 있던 이전 대화의 기억 때문이라고 생각하실 수 있으니까요. 하지만 아무 기억도 없는 임시 대화창에서 실행해도 결과가 흔들린다면, 원인은 기억이 아니라 프롬프트에 조건이 없다는 데 있습니다.
반대로 조건을 명확하게 지정하면 어떨까요? 아래 두 이미지는 5회차 마지막에 보여드렸던 ‘좋은 프롬프트’, 즉 도착 시각과 숙소 위치, 선호하는 여행 스타일, 원하는 출력 형식까지 9가지 요소를 모두 담은 프롬프트를 앞서와 똑같이 두 대화창에서 실행한 결과입니다. 사용자가 요구한 기준과 형식에 딱 맞춰 답변이 나왔고, 서로 다른 대화창에서 실행했는데도 제목(“제주도 2박 3일 효도 여행 일정표”)부터 표의 열 구성까지 상당히 유사하게 작성되었습니다.
좋은 프롬프트는 훈련으로 만들어집니다
좋은 프롬프트는 문장을 길게 쓰는 능력에서 나오는 게 아닙니다. 사용자가 원하는 결과를 분명히 정하고, 그 결과를 얻기 위한 조건을 빠뜨리지 않는 능력에서 나옵니다. 다음 표에서 제시하는 다섯 가지 핵심 질문으로 훈련해보시길 권합니다.
| 문제 정의 | 내가 얻고 싶은 결과는 무엇인가? | 최근 3개월 동안 이탈률이 높아진 고객군을 찾고 싶어 |
| 단계 분해 | 어떤 순서로 처리해야 하는가? | 데이터 확인 → 결측값 확인 → 월별 이탈률 계산 → 연령대별 비교 순서로 진행해줘 |
| 조건 명시 | 반드시 지켜야 할 기준은 무엇인가? | 이탈률은 이탈 고객 수를 월초 활성 고객 수로 나눠서 계산해 |
| 예시 작성 | 원하는 결과물은 어떤 모습인가? | 표의 열 이름, 그래프 제목을 정해줄게 |
| 검토·수정 | 현재 답변에서 무엇이 부족한가? | 작성해준 코드를 실행했더니 에러가 발생했어. 에러 메시지를 알려줄 테니 해당 코드를 수정해줘 |
긴 프롬프트, 직접 다 쓰지 않아도 됩니다
프롬프트를 작성할 때 위에서 언급한 9가지 요소를 다 채우는 건 매우 번거롭습니다. 이럴 때 쓸 수 있는 네 가지 방법을 소개합니다.
| 생성형 AI에게 초안 맡기기 | 하고 싶은 작업을 짧게 설명하고, 프롬프트 초안 작성을 요청 | 가장 빠르지만, 초안을 그대로 쓰지 말고 업무 기준에 맞게 수정해야 함 |
| 이전 대화를 정리시키기 | 짧은 요청으로 시작해 답변을 보고 대화를 통해 개선해나가고, 최종 합의된 내용을 프롬프트로 정리할 것을 생성형 AI에게 요청 | 실제 업무에서는 이 방법이 가장 자연스러움 |
| 공개된 예시 참고하기 | 공개된 프롬프트 예시를 가져와 내 상황에 맞게 수정 | 공개된 프롬프트에는 내 의도와 안 맞는 조건이 섞여 있을 수 있음 (참고: prompts.chat) |
| 템플릿 채우기 | 정해진 템플릿의 골격에 내 상황을 끼워 넣은 뒤 요청 | 반복 업무에는 템플릿 방식이 가장 안정적임 |
핵심은 “단계별 요청”입니다
생성형 AI를 활용한 데이터 분석 과정에서는 좋은 프롬프트의 9가지 요소를 처음부터 빠짐없이 한 번에 담아 완벽한 프롬프트를 쓰기 어렵습니다. 왜냐하면 프롬프트의 어떤 부분이 모호했는지는 결과를 직접 보기 전까지 알기 어렵기 때문입니다.
그래서 처음부터 완벽한 프롬프트를 길게 쓰려는 것보다, 생성형 AI와 대화하며 프롬프트를 단계적으로 다듬는 편이 더 빠르고 정확합니다. 물론 첫 번째 요청은 짧아도 됩니다. 결과를 보고 부족한 부분을 발견하면, 그에 해당하는 요소를 다음 지시에 더하면 됩니다. 이게 바로 분석 작업을 여러 단위로 나누고 중간 결과를 검토하기 위한 실무 전략, 단계별 요청입니다.
실습 데이터로 직접 해볼까요
여기서부터는 실습입니다. customer_churn.csv라는 더미 고객 이탈 데이터로 단계별 요청을 직접 연습해보겠습니다.
현재 데이터는 고객 한 명이 한 행이고, 가입일과 이탈일이 열로 들어 있습니다. 그런데 월별 이탈률은 ‘월’이 기준인 값이라서, 고객 한 명이 한 행인 지금 구조로는 바로 계산할 수 없습니다. 먼저 데이터 기간(2023년 6월 ~ 2026년 5월)을 월 단위로 늘어놓아 기준월 목록을 만들고, 고객과 기준월을 조합해 고객 × 기준월 형태로 데이터를 펼쳐야 합니다.
이렇게 펼치고 나면 기준월마다 두 가지를 판정할 수 있습니다. 기준월 1일 이전에 이미 가입했고 그때까지 이탈하지 않은 고객은 월초 활성 고객, 기준월 안에 이탈일이 들어 있는 고객은 이탈 고객입니다. 예를 들어 기준월이 2024.12라면, 2024년 12월 1일 이전에 가입해서 그때까지 남아 있던 고객이 분모가 되고 그중 12월에 이탈한 고객이 분자가 되는 식이죠. 참고로 이 데이터에서 이탈이 처음 발생하는 달이 2024년 12월입니다. 이제 기준월별로 이탈률(이탈 고객 수 ÷ 월초 활성 고객 수)을 계산할 수 있습니다. 예전에는 이 작업을 Excel 수식이나 Python 코드로 직접 만들어야 했는데 이제는 생성형 AI에게 맡길 수 있습니다.
한 번에 완벽한 프롬프트를 쓰는 대신, 짧은 요청에서 시작해 단계적으로 다듬어가며 필요한 Python 코드를 얻는 과정을 이렇게 실습합니다.
| 1단계 | 짧은 지시로 시작 | (customer_churn.csv 파일을 생성형 AI에게 첨부합니다.) 첨부한 데이터로 월별 고객 이탈률을 확인하는 Python 코드를 작성해줘. [지시] |
| 2단계 | 출력 형식·코딩 스타일 추가 | 답변은 Jupyter Notebook 셀 단위로, 마크다운 형식으로 작성해줘. [출력 형식] 코드는 PEP8 스타일로 작성하고, 코드 위에 자세한 주석을 추가해줘. [제약 조건] |
| 3단계 | 배경·분석 범위 추가 | 1단계 결과를 보니 최근 3개월간 이탈률이 크게 늘었네. [배경] 연령대와 가입채널별 이탈률을 계산하는 Python 코드를 작성해줘. [지시] 연령대는 10세 단위로 구간을 나누고, 출력 형식을 준수해야 해. [제약 조건] |
| 4단계 | 분석 범위 좁히기 | 이탈률이 가장 높은 집단의 특징을 확인하는 Python 코드를 작성해줘. [지시] 이전 대화와 중복되는 코드는 제외하고, 출력 형식을 준수해야 해. [제약 조건] |
| 5단계 | 결과 검토·수정 | 방금 받은 코드를 실행했더니 에러가 발생했어. 에러 메시지를 그대로 붙여줄 테니, 원인을 알려주고 해당 셀만 고쳐줘. [지시·제약 조건] |
1단계는 정말 짧은 지시 하나뿐이었는데, 단계를 진행하면서 출력 형식, 배경, 제약 조건을 하나씩 더해갑니다. 각 프롬프트 뒤에 붙여둔 대괄호가 5회차에서 살펴본 9가지 요소 중 무엇이 추가되었는지를 나타냅니다.
그런데 5단계는 앞의 네 단계와 성격이 다릅니다. 새로운 요소를 더하는 것이 아니라, 받은 결과를 직접 실행해보고 어긋난 부분을 되돌려 고치는 단계죠. 앞에서 말씀드린 다섯 가지 핵심 질문의 마지막 항목인 ‘검토·수정’이 여기에 해당합니다. 사실 이 5단계까지 포함해야 비로소 ‘대화하며 다듬는다’는 말이 완성됩니다. 요소를 순서대로 쌓기만 하는 건 아직 대화가 아니니까요.
3단계에서 “연령대는 10세 단위로 구간을 나누고”라고 덧붙인 것도 눈여겨봐 주세요. 실습 데이터에는 나이 열만 있고 연령대 열은 없습니다. 그래서 구간을 어떻게 나눌지 말해주지 않으면 생성형 AI가 알아서 정하는데, 그러면 실행할 때마다 연령대 구간이 달라질 수 있습니다. 앞에서 본 제주도 사례가 여러분의 실습에서 그대로 재현되는 셈이죠.
매번 같은 말 반복하기 귀찮으시죠 — 시스템 프롬프트
그런데 위 실습을 보면 “출력 형식을 준수해야 해”라는 말을 단계마다 반복해서 붙이고 있습니다. 그리고 “PEP8 스타일로”, “Jupyter Notebook 셀 단위로” 같은 조건은 새 대화창을 열 때마다 처음부터 다시 입력해야 하죠. 상당히 번거롭습니다. 이럴 때 쓰는 게 시스템 프롬프트입니다.
시스템 프롬프트는 생성형 AI에게 매번 반복해서 말할 내용을 미리 적어두는 설정입니다. 그렇다면 5회차에서 살펴본 9가지 요소 중에서 무엇을 고정하고 무엇을 매번 입력해야 할까요? 기준은 간단합니다. 작업이 바뀌어도 그대로인 것은 고정하고, 작업마다 달라지는 것은 그때그때 입력합니다.
| 시스템 프롬프트에 고정 | 출력 형식, 예시, 제약 조건, 어조·문체, 답변 분량, 역할 | 데이터 분석 프로젝트가 바뀌어도 크게 달라지지 않습니다. 한 번 정해두면 새 대화를 열어도 같은 스타일의 답변을 받습니다. |
| 대화창에 매번 입력 | 지시, 목적, 배경 | 이번에 무엇을, 왜, 어떤 상황에서 하는지는 작업마다 달라집니다. 분석 목적, 데이터 설명, 이번 작업 내용이 여기에 해당합니다. |
여기서 ‘예시’는 원하는 결과물의 견본을 뜻합니다. 표의 열 이름이나 코드 작성 방식처럼 매번 같은 형태를 원한다면 시스템 프롬프트에 넣어두시고, 이번 데이터에만 해당하는 견본이라면 대화창에서 그때그때 주시면 됩니다.
ChatGPT의 맞춤형 GPT
ChatGPT에서는 이 시스템 프롬프트 개념을 ‘맞춤형 GPT’라는 기능으로 제공합니다. 같은 역할, 같은 출력 형식, 같은 코딩 스타일을 매번 입력하지 않아도 되는 기능인데, 데이터 분석 실습처럼 반복되는 구조가 있는 작업에서 특히 유용합니다. (참고로 Gemini의 ‘Gem’, Claude의 ‘Project’도 비슷한 목적으로 사용할 수 있는 기능입니다.)
저는 이번 강의를 위해 맞춤형 GPT를 두 가지 작업으로 구분해서 만들었고, 현재 다양한 강의 현장에서 교육생분들에게 사용법을 소개하고 있습니다.
| HelloDataScience | Data Analysis Planner | 데이터 파일을 첨부하면 참고 자료를 바탕으로 도메인별 데이터 분석 프로세스를 반영해, 분석 방향을 자연어 프롬프트로 제시합니다. ‘무엇을, 어떻게 분석할지’를 잡아주는 역할입니다. 바로가기 |
| HelloDataScience | Python Code Assistant | 자연어 프롬프트를 입력받아, Jupyter Notebook 셀 단위, 마크다운 형식으로 코드를 작성합니다. 출력 형식을 지침에 고정했기 때문에, 대화창에 출력 형식을 매번 추가하지 않아도 됩니다. 바로가기 |
이렇게 역할을 두 개로 나누면, 생성형 AI를 더욱 안정적으로 사용할 수 있습니다. 이어지는 실습 편(8~9회)에서는 이 두 GPT를 실제로 사용해서, 분석 데이터를 첨부하고 결과를 얻는 전체 과정을 함께 실습해보겠습니다.
오늘 이야기 정리
오늘은 완벽한 프롬프트를 한 번에 쓰려 하지 말고 단계적으로 다듬어가는 법, 그리고 반복되는 조건을 시스템 프롬프트와 맞춤형 GPT로 고정해두는 법을 알아봤습니다. 여기까지가 프롬프트 엔지니어링 이야기입니다.
다음 7회차부터는 실습에 필요한 최소한의 도구, Python과 Colab 활용법을 소개해드리겠습니다. Python 코딩을 한 번도 해본 적 없는 분들도 걱정하지 마세요. 물론 아는 만큼 보이는 법이라서 Python 코딩 경험이 있는 분이라면 더 쉽게 이해할 수 있을 것입니다. 하지만 누구나 초보일 때가 있으니 지금 딱 필요한 만큼만 쉽게 풀어드리겠습니다. 감사합니다.
Comments