내 AI 이력서 검사기를 실제로 신뢰할 수 있게 만든 5가지 프롬프트 엔지니어링 (Prompt Engineering) 기술
요약
Gemini를 활용한 AI 이력서 검사기의 신뢰도를 높이기 위한 5가지 프롬프트 엔지니어링 기술을 소개합니다. 루브릭 활용, JSON 스키마 강제, 예시 제공 등을 통해 결과의 일관성과 구조적 안정성을 확보하는 방법을 다룹니다.
핵심 포인트
- 주관적 점수 대신 구조화된 루브릭(Rubric)을 먼저 요구하여 결정론적 결과 유도
- JSON 스키마를 명시하고 API 파라미터를 활용해 출력 형식의 안정성 확보
- 단순 정의를 넘어 구체적인 Before/After 예시를 제공하여 품질 향상
처음 Gemini를 이력서 채점용으로 연결했을 때, 결과물은 형편없었습니다.
Gemini가 나빠서가 아닙니다. 제가 Gemini를 마치 챗봇(Chatbot)처럼 프롬프팅(Prompting)했기 때문입니다.
그 이후 저는 이 앱을 Google Play에 출시했고, 이제 분석 결과는 사용자들이 신뢰할 수 있을 만큼 충분히 일관적입니다. 제가 "가끔 맞히는 수준"에서 "비즈니스를 구축할 수 있을 만큼 신뢰할 수 있는 수준"으로 올라올 수 있게 해준 5가지 프롬프트 엔지니어링 (Prompt Engineering) 기술을 소개합니다.
1. 점수를 요구하지 마세요. 루브릭 (Rubric)을 먼저 요구한 다음, 점수를 요구하세요.
나쁜 프롬프트:
"이 이력서를 0점에서 100점 사이로 평가해줘."
결과: 60. 65. 70. 항상 그 범위 내에 머뭅니다. 의미가 없습니다. 동일한 이력서임에도 호출할 때마다 점수가 달라집니다.
좋은 프롬프트:
"다음 루브릭 (Rubric)에 따라 이 이력서를 채점하세요. 각 기준에 대해 기준 정의를 바탕으로 0-25 사이의 정수를 출력하세요. 네 가지 기준을 합산하여 최종 점수를 계산하세요."
연락처 정보 (0-25): 0 = 누락됨/손상됨; 12 = 존재하지만 ATS 파싱에 어색한 형식임; 25 = 깔끔한 3줄 헤더.
경력 사항 (0-25): 0 = 날짜 또는 역할 누락; 12 = 일반적인 불렛 포인트, 지표 없음; 25 = 모든 불렛 포인트에 숫자와 구체적인 결과가 포함됨.
(기타 등등)
결과: 결정론적 (Deterministic) 점수. 동일한 이력서 → 매번 동일한 점수. 모델에게 느낌적인 느낌(Vibe check)이 아니라 수학 문제를 주었기 때문입니다.
통찰 (Insight): LLM (Large Language Models)은 주관적인 판단을 내리고 단일 숫자를 반환하는 데 매우 서툽니다. 하지만 주관적인 입력값에 구조화된 루브릭 (Rubric)을 적용하는 데는 매우 뛰어납니다. 루브릭 (Rubric) 단계를 절대 건너뛰지 마세요.
2. 단순한 요청이 아니라, 스키마 (Schema)를 사용하여 JSON 출력을 강제하세요.
나쁜 프롬프트:
"응답을 JSON으로 반환해줘."
결과: 때로는 유효한 JSON. 때로는 마크다운 (Markdown)으로 감싸진 JSON. 때로는 JSON 앞에 사과하는 설명이 붙은 JSON. 때로는 요청하지 않은 추가 "reasoning" 필드가 포함된 유효한 JSON.
좋은 프롬프트:
"주변 텍스트, 마크다운 (Markdown) 펜스, 설명 없이 정확히 다음 스키마 (Schema)와 일치하는 유효한 JSON으로 응답을 반환하세요:"
{ "overallScore": number, "sectionScores": {
...
결과: 신뢰할 수 있는 JSON. 응답을 `try/catch` 문 내의 `JSON.parse()`로 감싸고 Zod로 검증하세요. 이제 호출 실패율이 15%에서 1% 미만으로 줄어들 것입니다.
**보너스:** Gemini는 특히 `responseSchema` 파라미터를 가지고 있습니다. 스키마를 일급 API 인자 (first-class API argument)로 전달하면 프롬프팅만 사용할 때보다 훨씬 더 안정적으로 스키마를 강제합니다.
## 3. 정의만 주지 말고, 예시를 제공하세요.
**나쁜 프롬프트:**
> "각 개선 사항에 대해 '이전 (before)' 불렛 포인트와 '이후 (after)' 불렛 포인트를 제공하세요."
결과: '이후' 불렛 포인트가 '이전'과 거의 차이가 없는 경우가 많습니다. 또는 '이후'가 훨씬 좋아지긴 했지만, 구체적으로 어떤 변화가 일어났는지 알 수 없습니다.
**좋은 프롬프트:**
> "각 개선 사항에 대해 '이전 (before)' 불렛 포인트와 '이후 (after)' 불렛 포인트를 제공하세요. 기대되는 변환 품질을 위해 다음 예시를 따르세요:"
>
> **예시 1:**
> 이전: "엔지니어 팀 관리 책임"
> 이후: "6명의 엔지니어 팀 리드; 2분기 동안 4개의 주요 기능을 출시하고 배포 시간을 40% 단축함"
> 변경 사항 설명: 모호한 책임 중심의 표현을 구체적인 팀 규모 + 측정 가능한 결과로 교체함.
>
> **예시 2:**
> 이전: "백엔드 인프라 작업 수행"
> 이후: "Go를 사용하여 결제 백엔드 재구축; p95 지연 시간을 320ms에서 45ms로 줄이고 연간 인프라 비용을 $60K 절감함"
> 변경 사항 설명: 특정 기술 명시 + 전/후 지표 + 비즈니스 임팩트 포함.
결과: 모델이 '품질 높은 변환'이 무엇을 의미하는지 실제로 이해합니다. 출력 결과가 패턴과 일치하게 됩니다.
**통찰 (Insight):** LLM은 지침 (instructions)보다 프롬프트 내의 패턴으로부터 더 많이 학습합니다. 좋은 예시 하나가 세 단락의 가이드라인보다 낫습니다.
## 4. 추론을 위해 "생각의 사슬 (chain-of-thought)"을 사용한 뒤, 이를 버리세요.
특히 ATS 키워드 매칭 기능을 위해:
**나쁜 프롬프트:**
> "직무 기술서 (job description)의 키워드 중 이력서에 누락된 것은 무엇인가요?"
결과: 가끔은 맞지만, 명백한 것을 놓치거나 직무 기술서에 없는 키워드를 지어내는 경우가 많습니다.
**좋은 프롬프트:**
> "다음 단계들을 순서대로 수행하세요:
1. 직무 기술서 (JOB DESCRIPTION)에서 모든 명사구와 기술 용어를 추출하세요. 이를 'jdKeywords' 아래의 리스트로 출력하세요.
2. 이력서 (RESUME)에서 모든 명사구와 기술 용어를 추출하세요. 이를 'resumeKeywords' 아래의 리스트로 출력하세요.
3. 두 리스트를 비교하세요. 각 JD 키워드에 대해, 해당 키워드가 이력서에 나타나는지 표시하세요 (퍼지 매칭 (fuzzy match) 적용 — 'PostgreSQL'은 'Postgres'와 일치함).
4. 최종 결과를 'present'와 'missing' 배열을 포함하는 JSON 형식으로 출력하세요.
1~3단계의 작업 과정을 '_reasoning'이라는 필드에 보여주세요. 실제 서비스 (production) 환경에서는 사용자에게 보여주기 전에 이 필드들을 제거하겠지만, 모델이 이를 통해 사고 과정을 거쳐야 합니다."
결과: 훨씬 더 정확합니다. 모델이 비교하기 전에 실제로 항목을 열거하도록 강제됩니다.
그다음 파서 (parser)에서: 클라이언트에게 반환하기 전에 `_reasoning` 필드를 삭제하세요. 당신은 토큰 비용을 지불했고 모델은 사고를 위해 토큰이 필요했지만, 사용자는 이를 볼 필요가 없습니다.
## 5. "크게 실패하라 (fail loudly)" 지침을 추가하세요.
**나쁜 접근 방식:**
> 모델이 항상 좋은 출력을 반환할 것이라고 믿으세요.
결과: 때때로 입력값이 손상된 PDF, 빈 이력서, 또는 장난스러운 이력서("주요 책임: Call of Duty 정복")인 경우가 있습니다. 모델은 이를 어떻게든 채점하려고 시도하다가 터무니없는 결과를 반환합니다.
**좋은 접근 방식:**
> "만약 입력값이 실제 이력서로 보이지 않는다면 (예: 빈 문서, 손상된 문서, 또는 명백히 이력서가 아닌 문서), 채점을 시도하지 마세요. 대신 정확히 다음과 같이 반환하세요:"
>
> ```
> { "error": "not_a_resume", "reason": "<한 문장으로 된 설명>" }
> ```
결과: 모델이 쓰레기 입력값을 우아하게 거부하며, 당신은 사용자에게 가짜 점수(예: 43/100) 대신 도움이 되는 에러 메시지를 보여줄 수 있습니다.
## 신뢰성의 복리 효과
개별적으로 이 기술들은 각각 5~15%의 신뢰도 향상을 가져다줍니다. 이 기술들을 함께 사용했을 때, 저의 분석 도구는 "멋진 데모"에서 "출시 가능한 제품"으로 변모했습니다.
만약 여러분이 출력 구조(output structure)가 중요한 그 어떤 것이라도 LLM(Large Language Model)으로 구축하고 있다면 — 가격 책정 엔진(pricing engine), 채점 도구(grading tool), 분류기(classifier), 추출기(extractor) 등 — 이 기술들을 적용해 보세요. 이 기술들은 Gemini에만 국한된 것이 아닙니다. GPT-4, Claude, Llama에서도 동일한 트릭이 작동합니다.
## 제가 이를 적용한 곳
저의 앱은 Crux로, Google Play에서 제공되는 무료 Android AI 이력서 검사기입니다. 위에 언급된 모든 것들이 실제 점수 산출이 사용자들에게 신뢰할 수 있게 느껴지도록 만드는 요소들입니다.
실제로 작동하는 모습을 보고 싶다면, 여기에서 확인하실 수 있습니다: [https://play.google.com/store/apps/details?id=com.crux.ai.resume](https://play.google.com/store/apps/details?id=com.crux.ai.resume)
만약 여러분이 유사한 것을 구축하고 있고, 이 중 어떤 것에 대해 더 깊이 있는 내용을 알고 싶다면 — 후속 글을 기꺼이 작성하겠습니다. 질문은 댓글로 남겨주세요.
제가 계속해서 결과물을 출시(shipping)할 예정이니, 이와 같은 포스트를 더 보고 싶다면 팔로우해 주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기