← posts/b.log()

blog92@web:~$ cat posts/ai-06-prompt-engineering-for-coding.md

AI4 min read

AI 완전 정복 6편 — 코딩을 위한 프롬프트 엔지니어링

좋은 프롬프트는 화려한 문장이 아니라, 새로 들어온 유능한 동료에게 주는 업무 지시서다. 목표, 맥락, 제약, 완료 기준, 출력 형식 다섯 가지를 구분해 쓰면 대부분의 품질 문제가 해결된다.

한 줄 요약: 좋은 프롬프트는 화려한 문장이 아니라, 새로 들어온 유능한 동료에게 주는 업무 지시서다. 목표, 맥락, 제약, 완료 기준, 출력 형식 다섯 가지를 구분해 쓰면 대부분의 품질 문제가 해결된다.

먼저 테스트 하나: "입사 첫날 동료" 테스트

프롬프트를 보내기 전에 이렇게 자문해 보세요. "이 프로젝트를 처음 본 실력 있는 개발자가 이 메시지만 보고 내가 원하는 결과를 낼 수 있을까?" 1편에서 본 것처럼 모델은 입력 밖의 정보를 모릅니다. 내 머릿속에만 있는 전제는 모델에게도 없습니다.

좋은 코딩 프롬프트의 다섯 요소

요소질문예시
목표무엇을, 왜 하려는가?페이지당 50건으로 고정된 목록 API에 커서 페이지네이션을 추가한다. 모바일 무한 스크롤용이다.
맥락어떤 코드, 환경, 에러가 관련되는가?Next.js 15 App Router, Prisma, PostgreSQL. 관련 파일과 현재 에러 전문
제약무엇을 지켜야 하는가?기존 응답 필드는 바꾸지 않는다. 새 라이브러리는 추가하지 않는다.
완료 기준무엇이 되면 끝인가?기존 테스트 통과 + 커서 경계값 테스트 3개 추가
출력 형식결과를 어떻게 받고 싶은가?변경 파일별 diff, 마지막에 마이그레이션 필요 여부 한 줄

비교: 같은 요청, 다른 결과

나쁜 프롬프트:

text
목록 API에 페이지네이션 넣어줘

모델은 오프셋 방식을 고를지, 커서 방식을 고를지, 어떤 ORM을 쓸지 모두 추측해야 합니다. 추측이 하나라도 틀리면 다시 물어야 합니다.

좋은 프롬프트:

text
<goal>
/api/posts 목록 API에 커서 기반 페이지네이션을 추가해줘.
모바일 무한 스크롤에서 쓸 거라서 오프셋 방식은 안 돼(중간에 데이터가 추가되면 중복이 생김).
</goal>
 
<context>
- Next.js 15 App Router, Prisma 6, PostgreSQL
- 정렬 기준: updatedAt DESC, 동일값일 때 id DESC
- 현재 코드: (route.ts 내용 붙여넣기)
</context>
 
<constraints>
- 기존 응답의 items 배열 형식은 유지하고 nextCursor만 추가
- 새 의존성 추가 금지
</constraints>
 
<done_when>
- limit 기본값 20, 최대 100
- 마지막 페이지에서 nextCursor는 null
- 위 두 조건과 "동일한 updatedAt" 케이스에 대한 테스트 추가
</done_when>
 
코드를 쓰기 전에 커서를 어떻게 인코딩할지 2~3줄로 먼저 설명해줘.

두 번째 프롬프트는 길지만, 재작업 한 번을 아끼면 타이핑 시간은 금방 회수됩니다.

알아두면 효과가 큰 기법 7가지

  1. XML 태그로 구역 나누기. <context>, <code>, <error>처럼 감싸면 모델이 지시와 자료를 헷갈리지 않습니다. 태그 이름은 자유롭게 정해도 됩니다.
  2. 이유를 함께 쓰기. "오프셋 금지"보다 "중복이 생기므로 오프셋 금지"가 낫습니다. 이유를 알면 모델이 비슷한 상황에서도 올바른 판단을 합니다.
  3. 하지 말 것보다 할 것. "마크다운 쓰지 마"보다 "평문 문단으로 써"가 더 잘 통합니다.
  4. 예시는 강력하다(few-shot). 커밋 메시지, 테스트 이름 규칙처럼 형식이 중요한 작업은 예시 2~3개가 긴 설명보다 효과적입니다. 단, 모델은 예시를 강하게 따라하므로 서로 다른 예시를 주세요.
  5. 계획 먼저, 코드 나중. "코드는 아직 쓰지 말고 접근 방법과 예상 리스크를 먼저"라고 요청하면, 틀린 방향을 저렴하게 조기에 잡을 수 있습니다(9편).
  6. 질문하게 허용하기. "요구사항이 모호하면 추측하지 말고 먼저 질문해"를 붙이면 잘못된 가정 위에 코드가 쌓이는 것을 막습니다.
  7. 자기 검토 요청. 답을 받은 뒤 "이 코드를 시니어 리뷰어 관점에서 검토하고, 엣지 케이스와 보안 문제를 찾아줘"라고 한 번 더 물으면 상당수의 실수가 드러납니다. 새 대화에서 물으면 더 객관적입니다.

최신 모델은 지시를 문자 그대로 따르는 경향이 강합니다. "대시보드 만들어줘"라고만 하면 딱 최소한만 만들 수 있으므로, 기대하는 수준("필터, 정렬, 빈 상태, 로딩 상태까지")을 명시하는 편이 좋습니다. 반대로 예전 모델을 위해 쓰던 "반드시!!!", "CRITICAL" 같은 강조는 요즘 모델에서는 오히려 과잉 반응을 부를 수 있습니다.

바로 쓰는 템플릿 4종

버그 수정

text
<symptom>어떤 입력에서 어떤 결과가 나오는데, 기대는 무엇인지</symptom>
<error>에러 메시지와 스택 트레이스 전문</error>
<code>관련 함수와 호출부</code>
<tried>이미 해 본 것</tried>
원인 후보를 가능성 순으로 제시하고, 가장 유력한 원인을 확인할 방법부터 알려줘. 수정은 그다음에.

코드 리뷰

text
아래 diff를 리뷰해줘. 우선순위: 버그 > 보안 > 성능 > 가독성.
각 지적은 [파일:줄] 심각도(high/med/low) 한 줄 설명 형식으로.
스타일 취향 문제는 제외해줘.
<diff>...</diff>

테스트 생성

text
아래 함수의 단위 테스트를 Vitest로 작성해줘.
정상 케이스보다 경계값, 빈 입력, 예외 경로를 우선해줘.
구현을 보고 기대값을 역산하지 말고, 함수 이름과 주석에 드러난 의도를 기준으로 작성해줘.

마지막 문장이 중요합니다. 구현에서 기대값을 베끼면 버그까지 "정답"으로 박제하는 테스트가 됩니다.

리팩터링

text
동작을 바꾸지 않는 리팩터링만 해줘. 목표: (예: 중복 제거, 함수 분리).
공개 API(export된 함수 시그니처)는 유지.
먼저 바꿀 지점 목록을 보여 주고, 내가 고른 것만 적용해줘.

코딩 실습 (30분)

이번 주 실제 작업 하나를 골라 "나쁜 프롬프트"와 "다섯 요소 프롬프트"로 각각 요청하고, 다음 세 가지를 기록하세요. (1) 원하는 결과까지 몇 번 주고받았는지 (2) 결과물을 고치는 데 몇 분이 걸렸는지 (3) 다섯 요소 중 어느 것이 가장 큰 차이를 만들었는지. 위 템플릿 중 자주 쓸 것은 에디터 스니펫이나 도구의 커맨드로 저장해 두세요.

정리

  • 프롬프트 = 업무 지시서. 목표, 맥락, 제약, 완료 기준, 출력 형식.
  • XML 태그로 구분하고, 이유를 쓰고, 예시를 주고, 계획부터 받는다.
  • 테스트는 구현이 아니라 의도를 기준으로 쓰게 한다.

다음 편: 프롬프트가 "무엇을 말할지"라면, 컨텍스트 엔지니어링은 "모델이 무엇을 보게 할지"입니다.

COMMENTS (…)

댓글을 불러오는 중이에요.

NEW COMMENT0 / 1000
⌘↵ 전송

blog92@web:~$ cd ..