AI 코딩 에이전트에게 제대로 프롬프트를 작성하는 방법

AI 코딩 에이전트에게 제대로 프롬프트를 작성하는 방법

대부분의 개발자가 AI 코딩 에이전트를 쓰는 방식은 이렇다. 채팅 창을 열고 "설정 페이지에 다크 모드 토글을 추가해 줘" 같은 문장을 입력한다. 에이전트는 뭔가를 내놓는다. 어느 정도 작동한다. 하지만 거친 부분이 남는다. 개발자는 다음 이십 분 동안 오가며 이것저것 고쳐 댄다.

그리고 나서 모델이 별로라는 결론을 내린다.

모델은 괜찮다. 문제는 프롬프트다.

모호한 프롬프트의 불편한 현실

프롬프트의 모호함 하나하나가 모델이 당신 몰래 내리는 결정이다. 다크 모드 설정은 세션을 넘어 유지되어야 할까. 운영체제 수준의 설정을 따라야 할까. 설정은 어디에 저장될까. localStorage, 데이터베이스의 사용자 프로필, 쿠키 중 어디인가. 어떤 컴포넌트 라이브러리를 쓰고 있으며 그 안에서 테마는 어떻게 동작하는가.

당신은 말하지 않았다. 그래서 모델이 추측한다. 맞힐 때도 있다. 아닐 때가 더 많다. 그러면 한 환경에서는 돌아가고 다른 환경에서는 깨지는 코드, 또는 사용자가 이미 정한 설정을 무시하는 컴포넌트가 나온다.

이건 정보의 문제다.

테크닉: 에이전트가 자신의 프롬프트를 만들게 하라

진지하게 AI 지원 개발 워크플로우를 만드는 팀들이 깨달은 것은 이렇다. 모델은 대부분의 개발자가 어떻게 요청해야 할지를 아는 것보다, 작업을 잘 해내기 위해 무엇이 필요한지를 더 잘 안다.

모델은 잘 명세된 엔지니어링 작업을 엄청나게 많이 처리해 왔다. 그래서 완전한 기능 요청이 어떤 모습인지, 모호한 버그 리포트에 대개 무엇이 빠져 있는지를 안다. 요령은 뭔가를 시키기 전에 무엇이 빠졌는지 말하게 하는 것이다.

흐름은 이렇게 된다.

  1. 목표를 대략 설명한다 에이전트가 문제의 영역을 파악할 만큼만
  2. 제대로 하려면 무엇이 필요한지 묻는다 "이 작업을 잘 마치려면 어떤 정보가 필요해? 어떤 모호한 점을 명확히 해야 할까? 아직 지정하지 않은 것은?"
  3. 빈틈을 채운다 질문에 답하고 요청한 맥락을 넘겨준다
  4. 그제야 작업을 준다 질문을 프롬프트에 넣거나, 원래 요청을 완전한 명세로 다시 쓰게 한 뒤 승인하고 실행한다

마지막 단계는 선택 사항이지만 할 가치가 있다. 에이전트에게 "내 답변을 바탕으로 원래 요청을 완전한 작업 명세로 다시 써 줘"라고 부탁할 수 있다. 돌아오는 것은 모델 스스로 실행하기에 충분하다고 판단한 프롬프트다. 그 프롬프트를 실제 작업으로 제출하면 된다.

이를 작업 실행을 위한 역방향 프롬프트 엔지니어링이라고 부르는 사람도 있다. 처음부터 완벽한 프롬프트를 쓰는 것이 아니라, 모델이 완벽한 프롬프트에 무엇이 들어갈지 끄집어내고 그걸로 진행하는 방식이다.

예시 1: 기능을 추가할 때

설정 페이지에 다크 모드 토글을 추가하고 싶다고 하자. 두 접근 방식이 어떻게 다른지 보자.

단순한 방식:

"설정 페이지에 다크 모드 토글을 추가해 줘."

에이전트는 하드코딩된 토글이 달린 컴포넌트를 만들고, 설정을 컴포넌트 상태에 저장해 새로고침하면 사라지게 하며, 기존 테마 시스템을 무시하고, 이미 있는 CSS 변수나 테마 토큰 대신 인라인 스타일을 쓴다.

다음 한 시간은 고치느라 보낸다.

역방향 프롬프트 방식:

같은 문장으로 시작해 이렇게 묻는다. "시작하기 전에, 제대로 구현하려면 무엇을 알아야 해? 무엇을 명확히 해야 할까?"

에이전트는 대략 이런 답을 준다.

이 질문들에 답한다. 앱이 next-themes를 쓰고, 설정은 기존 PATCH /users/me 엔드포인트를 통해 사용자 프로필에 저장되며, 설정 페이지에는 특정 컴포넌트 패턴을 따르는 "외관" 섹션이 이미 있다고 알려준다.

이제 에이전트는 필요한 것을 갖췄다. 만들어낸 구현은 올바른 테마 제공자에 연결되고, 기존 API를 쓰고, 기존 UI 패턴에 맞으며, OS 설정 폴백도 처리한다. 고칠 것이 없다.

예시 2: 버그를 고칠 때

버그 리포트는 모호한 프롬프트가 가장 큰 피해를 내는 곳이다. 맥락이 부족한 모델은 형편없는 코드를 내놓는 데 그치지 않고, 자신만만하면서 틀린 코드를 내놓는다.

누군가 "로그인 버튼이 가끔 작동하지 않는다"고 버그를 제기했다고 하자.

단순한 방식: 그대로 에이전트에 붙여 넣는다. 에이전트는 인증 코드를 훑기 시작하고, 수상한 async/await 패턴을 발견해 아마 이게 원인일 거라 짐작하고, 함수를 다시 쓰고, PR을 연다. 버그는 그대로다. 고친 함수는 무관했다.

역방향 프롬프트 방식:

에이전트에 버그 리포트를 주고 이렇게 묻는다. "이걸 효과적으로 진단하려면 무엇을 알아야 해? 코드를 만지기 전에 시니어 엔지니어는 어떤 질문을 할까?"

에이전트는 이렇게 답한다.

버그를 제기한 사람에게 돌아가 답을 받는다. 간헐적이고, 사용자가 페이지에 십 분 이상 머문 뒤에만 나타난다. 콘솔 오류는 없지만 네트워크 요청은 아예 발화되지 않는다. 이건 완전히 다른 버그다. 원인은 토큰 만료 문제이거나 이벤트 핸들러 안의 낡은 클로저일 가능성이 크다.

그 정보를 에이전트에 넘기면 이제 올바른 곳으로 간다. 초기 렌더링에서 인증 토큰을 포착하는, 의존성이 낡은 useCallback을 찾아낸다. 수정은 딱 하나의 겨냥한 변경이다.

왜 효과가 있는가

AI 지원 코딩이 협상처럼 느껴지는 이유는, 첫 프롬프트가 모델에 너무 많은 결정을 맡기기 때문이다. 여러 라운드에 걸쳐 출력을 다듬으며 오가게 된다. 라운드마다 하는 수정은, 당신이 지정하지 않아서 모델이 내린 추측을 바로잡는 일이다.

역방향 프롬프트는 그 라운드 대부분을 처음의 한 번의 대화로 압축한다. 모델의 질문은 스스로라면 어떤 결정을 내렸을지를 정확히 알려준다. 그 결정을 당신이 대신 내린다. 완전한 정보가 있었으므로 출력은 처음부터 제대로 나온다.

부수적인 이점도 하나 있다. 모델이 던지는 질문은 체크리스트가 된다. 새 설정 추가나 인증 버그 수정처럼 비슷한 작업에 같은 테크닉을 꾸준히 쓰면, 질문이 점점 익숙해진다. 시간이 지나면 물어보지 않아도 그 세부 사항들을 프롬프트에 넣게 되고, 기본적인 프롬프트 품질이 좋아진다.

실용적인 참고 사항

이 테크닉은 도구와 파일 접근이 있는 에이전트, 즉 Cursor나 에이전트 모드의 GitHub Copilot 같은 것에서 가장 잘 작동한다. 코드베이스를 읽을 수 있는 에이전트는 아무것도 보지 못하고 작업하는 에이전트보다 훨씬 구체적인 질문을 한다.

두 번 왕복하는 흐름(무엇이 필요한지 -> 여기 있다 -> 이제 작업을)은 분명 단계를 하나 더한다. 작고 명확한 작업에는 과하다. 하지만 여러 파일을 건드리거나 기존 시스템과 통합되는 작업은, 구현으로 바로 가는 것보다 일관되게 더 나은 결과를 낸다.

3단계에서 생성된 명세는 저장할 가치가 있다. 재사용할 수 있는 템플릿이다. 다음에 누군가 사용자 프로필에 저장되는 설정을 추가해야 한다면, 이미 잘 명세된 프롬프트를 갖고 있다.

더 큰 요점

대부분의 개발자가 에이전트에 프롬프트를 쓰는 방식은 품질을 희생하고 속도에 최적화되어 있다. 문장 하나를 재빨리 넣고, 평범한 출력을 받고, 십 분간 정리한다. 이게 하루에 수십 번 반복된다.

역방향 프롬프트 접근은 이 트레이드오프를 뒤집는다. 처음에 조금 더 시간을 써서 모델이 필요한 것을 갖추도록 한다. 그 대가로 출력은 실제로 원했던 것에 가까워지고, 고치는 시간은 줄어든다.

어떤 작업에 가장 좋은 프롬프트는 모델이 자신에게 필요하다고 알려주는 것이다.

© Melvin Laplanche - All rights reserved.