AI 코딩 에이전트에게 일 잘 시키는 법 — 프롬프트 엔지니어링 실전 가이드
AI 코딩 도구를 처음 쓰기 시작했을 때 솔직히 실망했다. “이게 뭐야, 내가 원하는 걸 전혀 못 알아듣네.” 그러고서 한참을 기본 기능만 쓰다가 어느 날 문득 깨달았다. 문제는 AI가 아니라 내가 일을 시키는 방식이었다.
Claude Code를 쓰면서 같은 작업을 두 가지 방식으로 요청했을 때 결과 차이가 하늘과 땅이었다. 프롬프트 한 줄 바꿨을 뿐인데 한쪽은 2시간이 걸릴 쓸모없는 코드, 다른 쪽은 바로 쓸 수 있는 완성품. 그 차이가 뭔지 이 글에서 전부 털어놓겠다.
왜 AI는 내 말을 못 알아듣는 걸까?
먼저 한 가지 오해를 풀고 가자. AI 코딩 에이전트는 독심술사가 아니다. 우리가 머릿속으로 상상하는 맥락, 제약 조건, 최종 목표를 AI는 알 수 없다. 우리가 말하는 것만 안다.
“로그인 기능 만들어줘” 라고 하면 AI는 나름대로 최선을 다해 만들어준다. JWT를 쓸 수도 있고, 세션 기반일 수도 있고, 소셜 로그인이 들어갈 수도 있다. 내가 이미 JWT를 쓰고 있다는 걸, 기존 DB 스키마가 있다는 걸, 회사 보안 정책이 있다는 걸 — AI는 모른다.
이게 컨텍스트 부재 문제다. 좋은 프롬프트는 이 컨텍스트를 충분히 제공하는 것에서 시작한다.
AI가 실제로 처리하는 방식
AI는 프롬프트를 받으면 다음 순서로 처리한다:
- 뭘 만들어야 하는가 (What)
- 어떤 맥락인가 (Context)
- 어떤 제약이 있는가 (Constraints)
- 어떤 형식으로 출력해야 하는가 (Format)
이 네 가지 중 하나라도 빠지면 AI는 빈칸을 자신의 “기본값”으로 채운다. 그 기본값이 내가 원하는 것과 다를 때 “AI가 내 말을 못 알아들었다”는 느낌이 드는 거다.
실전 프롬프트 작성의 7가지 원칙
1. 역할을 명확히 지정하라 (Role Prompting)
AI에게 어떤 역할을 맡길지 먼저 설정하면 출력 품질이 달라진다.
나쁜 예:
리액트 컴포넌트 만들어줘
좋은 예:
시니어 프론트엔드 개발자 입장에서 리액트 컴포넌트를 만들어줘.
- TypeScript 사용
- 접근성(a11y) 고려
- 성능 최적화 (불필요한 리렌더링 방지)
- 프로젝트 컨벤션: 함수형 컴포넌트, 커스텀 훅 분리
역할 지정을 하면 AI가 단순히 동작하는 코드가 아니라 그 역할에 걸맞는 품질 기준을 스스로 적용한다. “시니어 개발자”라고 하면 에러 처리, 타입 안전성, 코드 가독성을 더 신경 쓴다.
2. 기술 스택과 버전을 명시하라
Next.js 15 App Router (서버 컴포넌트 기반)
TypeScript 5.x
Tailwind CSS v4
Prisma ORM + PostgreSQL
버전 명시가 왜 중요하냐면, AI는 다양한 버전의 코드로 학습했기 때문에 그냥 “Next.js”라고 하면 Pages Router 방식으로 짤 수도 있다. 실제로 나는 이 실수로 App Router 프로젝트에 getServerSideProps가 들어간 코드를 받은 적이 있다. 😅
3. 기존 코드 컨텍스트를 제공하라
AI에게 백지에서 짜달라고 하는 게 아니라, 기존 코드베이스에 맞게 짜달라고 해야 한다.
현재 프로젝트의 API 호출 방식은 아래와 같아:
// 기존 패턴
const { data, error } = await supabase
.from('users')
.select('*')
.eq('id', userId)
이 패턴에 맞춰서 posts 테이블 CRUD를 만들어줘.
이렇게 하면 AI가 내 스타일을 학습해서 일관된 코드를 만들어준다. 코드 리뷰할 때 “이건 우리 스타일이랑 다른데?” 같은 소리 안 들어도 된다.
4. 원하지 않는 것도 명시하라 (Negative Prompting)
이게 처음엔 좀 이상하게 느껴질 수 있는데, AI에게 하지 말 것을 알려주는 게 매우 효과적이다.
사용자 인증 미들웨어 작성해줘.
제약 사항:
- 외부 라이브러리 추가 금지 (passport.js 같은 거 쓰지 마)
- express-session 대신 JWT 방식으로
- 복잡한 추상화 레이어 만들지 말고 단순하게
- 지금 당장 필요 없는 기능(OAuth, 2FA 등)은 포함하지 마
“단순하게 만들어줘”만 하면 AI는 자기 기준의 단순함으로 만든다. 근데 AI의 단순함과 내 단순함이 다를 때가 많다. 명시적으로 “이건 하지 마”를 적어줘야 내가 원하는 방향이 나온다.
5. 단계별로 쪼개서 요청하라 (Incremental Prompting)
한 번에 “풀스택 앱 만들어줘”라고 하지 말고 단계별로 나눠서 요청하는 게 훨씬 낫다.
나의 실제 작업 패턴:
# Step 1: DB 스키마 먼저
Prisma 스키마 파일 작성해줘.
요구사항: 블로그 포스트 시스템
- 유저, 포스트, 댓글, 태그 관계
- soft delete 지원
- 타임스탬프 자동 관리
# Step 2: 스키마 확인 후 API 레이어
방금 만든 스키마 기반으로 posts CRUD API 작성해줘 (Next.js Route Handlers)
# Step 3: 프론트엔드
위 API를 호출하는 리액트 훅과 컴포넌트 만들어줘
이렇게 하면 각 단계에서 검토하고 수정할 수 있어서 나중에 뒤엎는 상황이 줄어든다. 한 번에 다 만들어달라고 하면 중간에 방향이 틀렸어도 너무 많이 만들어버린 후에 알게 된다.
6. 예상 출력 형식을 지정하라
아래 형식으로 코드 작성해줘:
1. 먼저 어떻게 구현할지 간단히 설명 (2-3줄)
2. 완성된 코드
3. 사용 예시 (간단한 스니펫)
4. 주의사항이나 한계점 있으면 마지막에 추가
이 방식이 좋은 이유는 AI가 자기가 뭘 만들려는지 먼저 설명하게 하면, 그 설명이 틀렸을 때 코드 보기 전에 잡을 수 있어서다. “아 그 방향 아니야, 이렇게 해줘” 하고 바로잡을 수 있다.
7. 테스트 케이스를 함께 요청하라
다음 함수 만들어줘:
- 기능: 이메일 유효성 검사
- 반환: { valid: boolean, reason?: string }
함수랑 같이 Jest 테스트 케이스도 작성해줘.
엣지케이스 포함: 빈 문자열, null, 특수문자, 국제 도메인, 매우 긴 이메일 등
테스트를 같이 요청하면 두 가지 이점이 있다. 첫째, AI가 엣지케이스를 미리 고려하게 된다. 둘째, 만들어진 함수가 실제로 제대로 동작하는지 테스트로 확인할 수 있다.
CLAUDE.md / .cursorrules — 프롬프트를 파일로 저장하기
매번 같은 컨텍스트를 적어주는 게 귀찮다면 이걸 파일로 저장해서 자동화할 수 있다. Claude Code에서는 CLAUDE.md, Cursor에서는 .cursorrules, GitHub Copilot에서는 .github/copilot-instructions.md 파일을 쓴다.
내가 현재 사용하는 CLAUDE.md의 핵심 구성:
# 프로젝트 컨텍스트
이 프로젝트는 Next.js 15 기반 SaaS 앱입니다.
## 기술 스택
- Framework: Next.js 15 (App Router)
- Language: TypeScript 5.x (strict mode)
- Styling: Tailwind CSS v4
- DB: Supabase (PostgreSQL)
- State: Zustand + React Query v5
## 코드 컨벤션
- 함수형 컴포넌트만 사용 (클래스 컴포넌트 금지)
- 비동기: async/await (Promise.then 체이닝 금지)
- 에러 처리: try-catch with 구조화된 에러 객체
- 임포트: 절대 경로 (@/components/...)
## 하지 말 것
- console.log 프로덕션 코드에 남기지 않기
- any 타입 사용 금지
- useEffect 남용 금지 (서버 컴포넌트로 해결 가능한 건 서버에서)
이 파일 하나로 매번 길게 적던 컨텍스트를 대신할 수 있다. AI가 프로젝트를 열 때마다 이 파일을 읽고 맥락을 파악한다.
상황별 프롬프트 템플릿
버그 수정 요청 시
[버그 상황]
환경: Next.js 15, Node 20
증상: 특정 페이지에서 hydration 에러 발생
에러 메시지: "Warning: Expected server HTML to contain..."
[관련 코드]
(코드 붙여넣기)
[이미 시도한 것]
- useEffect로 클라이언트 체크 추가해봤는데 안 됨
- Suspense로 감싸봤는데 안 됨
[원하는 것]
근본 원인 분석 + 수정 방법
버그 리포트할 때 이미 시도한 것을 같이 알려주면 AI가 이미 실패한 방법을 다시 제안하는 시간 낭비를 막을 수 있다.
코드 리뷰 요청 시
아래 코드 리뷰해줘. 시니어 개발자 관점에서 아래 기준으로:
1. 버그 가능성 (특히 엣지케이스)
2. 성능 문제
3. 보안 이슈
4. 코드 가독성
5. 테스트 용이성
각 문제마다 왜 문제인지 + 수정 방법 알려줘.
심각도는 [Critical / Warning / Suggestion] 으로 분류해서.
(코드 붙여넣기)
“리뷰해줘” 한 마디 vs 위 프롬프트 — 결과물의 깊이가 완전히 다르다.
리팩토링 요청 시
아래 함수 리팩토링해줘.
목표:
- 가독성 향상
- 단일 책임 원칙 적용
- 테스트하기 쉬운 구조로
주의사항:
- 외부 API 인터페이스는 변경하지 마 (하위 호환성 유지)
- 성능이 나빠지면 안 됨
- 리팩토링 전후 동작이 완전히 동일해야 함
리팩토링 전 코드:
(코드 붙여넣기)
흔히 하는 실수들
실수 1: 너무 짧은 요청
“간단한 CRUD 만들어줘”는 사실 간단하지 않다. CRUD의 복잡도는 엄청나게 다양하다. 유효성 검사는? 페이지네이션은? 소프트 딜리트는? 동시성 처리는?
“간단하다”는 건 주관적이다. 구체적으로 무엇이 필요하고 무엇이 필요하지 않은지를 명시해야 한다.
실수 2: 한 번에 너무 많이 요청
“회원가입, 로그인, 비밀번호 찾기, 소셜 로그인, 2FA 인증 다 만들어줘” — 이런 요청은 AI가 각 기능을 대충 만들거나 서로 일관성 없이 만들 가능성이 높다.
큰 기능은 반드시 잘게 쪼개서 하나씩 완성하고 검토한 뒤 다음으로 넘어가야 한다.
실수 3: 피드백 없이 계속 새로 요청
AI가 잘못된 방향으로 가고 있을 때 “그냥 다시 해줘”보다는 구체적으로 뭐가 틀렸는지 알려줘야 한다.
# 나쁜 피드백
"다시 만들어줘, 이건 아닌 것 같아"
# 좋은 피드백
"방금 만든 코드에서 두 가지 문제가 있어:
1. state 업데이트가 비동기인데 동기처럼 처리함 → useEffect 의존성 배열 수정 필요
2. 에러 발생 시 UI 피드백이 없음 → toast 알림 추가해줘"
실수 4: 맥락 없이 “고쳐줘”
AI에게 코드를 보여주면서 “이거 왜 안 돼?”라고 하면, AI는 코드는 보지만 실제 실행 환경은 모른다. 에러 메시지, 스택 트레이스, 어떤 상황에서 발생하는지를 함께 제공해야 한다.
고급 기법: 체인 오브 쏘트(CoT) 활용
복잡한 아키텍처 결정을 할 때는 AI에게 단순히 해답을 달라고 하지 말고 사고 과정을 보여달라고 하면 더 좋은 결과가 나온다.
실시간 채팅 기능을 구현해야 하는데, 기술 선택에 도움이 필요해.
옵션들:
A. WebSocket (직접 구현)
B. Socket.io
C. Supabase Realtime
D. Firebase Realtime DB
각 옵션에 대해:
1. 장점
2. 단점
3. 어떤 상황에서 적합한지
4. 우리 상황 (Next.js + Supabase 스택, MAU 1만 명 목표)에서의 추천
결론 내리기 전에 각 옵션 분석을 충분히 해줘.
“뭐가 좋아?” 한 마디 vs 위 프롬프트 — AI가 주는 답의 신뢰도와 깊이가 완전히 다르다.
AI와 협업하는 마인드셋
프롬프트 엔지니어링을 배우면서 가장 크게 바뀐 건 AI를 보는 시각이다.
처음엔 AI를 “명령을 받아서 실행하는 도구”로 봤다. 지금은 “컨텍스트를 받아서 생각하는 협업자”로 본다.
좋은 동료에게 일을 맡길 때를 생각해보면 — “이거 해줘”라고만 하지 않는다. 배경을 설명하고, 제약 조건을 알려주고, 기대하는 결과물을 공유하고, 진행 중에 피드백을 주고받는다. AI와의 협업도 마찬가지다.
그리고 중요한 점 하나 더: AI가 틀릴 수 있다는 걸 항상 인지하자. AI가 만들어준 코드는 반드시 이해하고 검토한 후에 쓰는 습관이 중요하다. AI는 자신 있게 틀린 코드를 짜기도 한다. 최종 판단은 항상 개발자인 내가 해야 한다.
정리: 좋은 프롬프트의 공식
경험상 잘 동작하는 프롬프트의 공식을 정리하면 이렇다:
[역할] + [기술 스택/버전] + [해야 할 것] + [하지 말 것] + [출력 형식]
예시:
시니어 백엔드 개발자로서,
Node.js 20 + Express 5 + TypeScript 환경에서,
JWT 기반 인증 미들웨어를 만들어줘.
포함: 토큰 발급, 검증, 갱신, 블랙리스트 처리
제외: OAuth, 소셜 로그인, 이메일 인증
출력 형식:
1. 구현 방법 설명 (3줄)
2. 전체 코드
3. 사용 예시
4. 보안 고려사항
이 공식대로만 해도 프롬프트 품질이 확연히 올라간다.
AI 코딩 도구를 쓰는 개발자 중에서 진짜 생산성을 끌어올리는 사람들은 AI가 뛰어나서가 아니라, AI에게 일 잘 시키는 방법을 알기 때문에 차이가 난다. 프롬프트 엔지니어링은 이 시대 개발자에게 필수 스킬이 됐다.
도구가 좋아도 잘 쓸 줄 모르면 의미가 없다. 이 가이드를 참고해서 여러분도 AI와의 협업 효율을 한 단계 올려보시길.