Skip to main content
Summary

Codex에게 일을 맡긴다는 것

Codex를 처음 쓰면 누구나 한 번쯤 이렇게 말하고 싶어진다.

"이 앱 좀 예쁘게 만들어줘."

놀랍게도 Codex는 이 말만 듣고도 무언가를 해낸다. 색을 바꾸고, 여백을 조정하고, 버튼을 둥글게 만들고, 어쩌면 애니메이션까지 넣어 줄 수도 있다. 문제는 그 결과가 내가 원한 앱인지 알기 어렵다는 데 있다. Codex가 틀렸다기보다, 우리가 일을 너무 넓게 맡긴 것이다.

앱 개발에서 프롬프트는 "질문"이라기보다 "작업 지시서"에 가깝다. Codex는 단순히 대답만 하는 도구가 아니라 프로젝트 폴더 안으로 들어가 파일을 읽고, 코드를 고치고, 명령을 실행하고, 변경 diff를 보여주는 에이전트다. 그래서 프롬프트가 모호하면 Codex는 빈칸을 스스로 채운다. 때로는 그 빈칸이 멋진 아이디어가 되지만, 때로는 엉뚱한 파일 수정, 불필요한 라이브러리 추가, 기대와 다른 UI로 이어진다.

이 장의 핵심은 단순하다. Codex 실력의 절반은 모델 성능이 아니라 사용자가 일을 잘 맡기는 능력에서 나온다. 좋은 프롬프트는 긴 문장이 아니다. Codex가 헷갈리지 않도록 목표, 맥락, 제약, 완료 기준을 또렷하게 알려주는 문장이다. OpenAI의 Codex 관련 가이드에서도 자율성, 코드베이스 탐색, 도구 사용, 프론트엔드 품질 같은 요소를 프롬프트에 명확히 담는 습관을 강조한다.1

이제부터는 "잘 부탁해" 수준의 요청을 실제 앱 개발에 쓸 수 있는 작업 지시서로 바꾸는 법을 배워 보자.

초보자를 위한 프롬프트 기본기

나쁜 프롬프트는 왜 나쁜 결과를 부를까

나쁜 프롬프트는 보통 짧아서 나쁜 것이 아니다. 판단 기준이 없어서 나쁘다. 예를 들어 쇼핑몰 앱의 상품 카드 화면을 개선한다고 해 보자.

상품 카드 예쁘게 해줘.

이 문장은 사람에게도 어렵다. 어떤 사용자를 위한 상품 카드인지, 어떤 화면에서 보이는지, 무엇이 예쁘다는 뜻인지, 모바일 기준인지 데스크톱 기준인지 알 수 없다. Codex는 결국 추측해야 한다. 카드 그림자를 강하게 넣을 수도 있고, 버튼 색을 바꿀 수도 있고, 레이아웃을 완전히 갈아엎을 수도 있다.

이 프롬프트를 앱 작업 지시서답게 바꾸면 다음처럼 된다.

Goal:
모바일 쇼핑몰의 상품 카드 UI를 더 읽기 쉽고 구매 행동이 잘 보이도록 개선해줘.

Context:
- 대상 사용자: 20~30대 모바일 쇼핑 사용자
- 관련 화면: `src/pages/Home.tsx`
- 관련 컴포넌트: `src/components/ProductCard.tsx`
- 현재 문제: 상품명과 가격은 보이지만 할인율, 평점, 장바구니 버튼의 우선순위가 약함

Requirements:
- 카드에는 상품 이미지, 상품명, 할인율, 최종 가격, 평점, 장바구니 버튼이 보여야 함
- 모바일 375px 너비에서 한 줄에 카드 2개가 자연스럽게 보여야 함
- 버튼은 엄지손가락으로 누르기 쉬운 크기여야 함
- 기존 브랜드 색상은 `src/styles/theme.css`의 CSS 변수를 사용할 것

Constraints:
- 새 UI 라이브러리를 추가하지 말 것
- API 응답 구조는 바꾸지 말 것
- `ProductCard.tsx`와 관련 CSS 파일만 수정할 것

Completion:
- `npm run lint`를 실행하고 결과를 알려줘
- 변경한 파일 목록과 핵심 변경 내용을 요약해줘
- 테스트하지 못한 부분이 있으면 이유를 알려줘

두 프롬프트의 차이는 분명하다. 첫 번째는 Codex에게 "알아서 감각적으로 해 봐"라고 말한다. 두 번째는 "누구를 위해, 어느 파일에서, 어떤 기준으로, 어디까지 바꾸고, 어떻게 확인할지"를 알려준다.

좋은 프롬프트는 Codex를 답답하게 묶는 문서가 아니다. 오히려 Codex가 자유롭게 움직일 수 있는 안전한 울타리다. 울타리가 있어야 Codex는 어디까지 탐색해도 되는지, 어디서 멈춰야 하는지 알 수 있다.

초보자를 위한 기본 공식: 목표, 맥락, 제약, 완료 기준

처음부터 완벽한 프롬프트를 쓰려고 하면 부담스럽다. 그래서 이 책에서는 가장 먼저 다음 네 가지 칸만 기억하자.

  • 목표: 무엇을 만들거나 고칠 것인가

  • 맥락: Codex가 참고해야 할 파일, 화면, 오류, 사용자 상황은 무엇인가

  • 제약: 바꾸면 안 되는 것과 지켜야 할 규칙은 무엇인가

  • 완료 기준: 어떤 상태가 되면 끝났다고 볼 것인가

이 구조는 여러 Codex 실무 가이드에서 반복해서 등장하는 기본형이다. 목표, 컨텍스트, 제약, 완료 조건을 나누면 Codex가 코드베이스를 탐색하고 수정 범위를 정하고 검증하는 방식이 훨씬 안정된다.2

예를 들어 로그인 화면에 "비밀번호 보기" 버튼을 추가한다고 해 보자. 초보자는 이렇게 요청할 수 있다.

로그인 화면에 비밀번호 보기 기능 추가해줘.

나쁜 요청은 아니다. 하지만 Codex가 어떤 파일을 찾아야 하는지, 기존 디자인을 유지해야 하는지, 테스트는 어떻게 해야 하는지 모른다. 같은 요청을 기본 공식에 맞추면 이렇게 바뀐다.

Goal:
로그인 화면의 비밀번호 입력칸 오른쪽에 비밀번호 보기/숨기기 토글 버튼을 추가해줘.

Context:
- 로그인 화면은 `src/pages/Login.tsx`에 있음
- 공통 입력 컴포넌트는 `src/components/TextField.tsx`를 사용함
- 기존 버튼 스타일은 `src/components/Button.tsx`를 참고해줘

Constraints:
- 로그인 API 요청 방식은 변경하지 말 것
- 새 패키지는 설치하지 말 것
- 기존 TextField를 크게 리팩터링하지 말고 필요한 최소 변경만 할 것
- 접근성을 위해 버튼에 `aria-label`을 넣을 것

Completion:
- 비밀번호가 기본적으로 가려져 있어야 함
- 토글 버튼을 누르면 보이고, 다시 누르면 가려져야 함
- `npm run lint`를 실행하고 결과를 보고할 것
- 변경 파일과 수동 확인 방법을 요약할 것

여기서 중요한 것은 영어로 써야만 좋은 프롬프트가 되는 것은 아니라는 점이다. Codex는 한국어 요청도 잘 이해한다. 다만 코드, 라이브러리, 오류 메시지, 명령어는 대부분 영어이므로 파일명과 명령어는 그대로 적는 편이 좋다. 영어가 부담된다면 한국어 문장 안에 코드 관련 단어만 정확히 넣어도 충분하다.

"예쁘게"를 앱 요구사항으로 번역하기

초보자가 가장 자주 쓰는 말 중 하나가 "예쁘게"다. 이 말은 틀리지 않다. 실제 앱 개발에서도 우리는 "좀 더 깔끔하게", "더 현대적으로", "사용하기 쉽게" 같은 말을 자주 한다. 하지만 Codex에게는 이 감각적인 표현을 작업 가능한 요구사항으로 바꿔 줘야 한다.

"예쁘게 해줘"를 구체화할 때는 다음 질문을 떠올리면 된다.

  • 이 화면을 보는 사용자는 누구인가

  • 사용자가 이 화면에서 가장 먼저 해야 할 행동은 무엇인가

  • 화면에는 어떤 정보가 반드시 보여야 하는가

  • 어떤 디자인 분위기를 원하는가

  • 모바일과 데스크톱에서 각각 어떻게 보여야 하는가

  • 키보드 조작, 색 대비, 대체 텍스트 같은 접근성 요구가 있는가

  • 완료 후 무엇을 확인하면 성공이라고 볼 수 있는가

이 질문들을 모두 거창하게 답할 필요는 없다. 하지만 최소한 두세 개만 넣어도 결과가 크게 달라진다.

예를 들어 "날씨 앱 메인 화면 예쁘게 해줘"는 다음처럼 바꿀 수 있다.

Goal:
날씨 대시보드의 메인 화면을 초보 사용자도 한눈에 현재 날씨와 오늘의 변화를 이해할 수 있게 개선해줘.

User scenario:
사용자는 출근 전에 모바일로 앱을 열고, 현재 기온과 강수 가능성, 시간대별 날씨를 10초 안에 확인하고 싶어 함.

Screen requirements:
- 상단에는 현재 위치, 현재 기온, 날씨 상태 아이콘을 크게 표시
- 중간에는 체감 온도, 습도, 풍속, 강수 확률을 카드 형태로 표시
- 하단에는 시간대별 예보를 가로 스크롤 목록으로 표시

Design tone:
- 밝고 깨끗한 느낌
- 과한 그림자나 애니메이션은 피함
- 기존 색상 변수와 폰트 스타일을 유지

Responsive:
- 360px 모바일 화면에서 가로 스크롤 없이 주요 정보가 보여야 함
- 768px 이상에서는 카드가 2열로 배치되어도 좋음

Accessibility:
- 날씨 아이콘에 의미 있는 `aria-label` 또는 대체 텍스트 제공
- 텍스트와 배경의 대비가 낮아지지 않게 할 것

Completion:
- 관련 컴포넌트와 CSS만 수정
- `npm run lint` 실행
- 변경 파일, 확인한 화면 크기, 남은 위험을 보고

이 정도로 적으면 Codex는 디자인을 "취향"이 아니라 "사용자 행동을 돕는 구조"로 이해한다. 특히 프론트엔드 작업에서는 화면 캡처나 디자인 이미지가 있다면 함께 주는 것이 좋다. Codex App이나 IDE 환경에서는 이미지와 파일을 맥락으로 제공할 수 있으므로, "여기 여백이 너무 넓다", "이 버튼이 눈에 띄지 않는다"처럼 구체적인 지점을 짚어 주면 더 안정적인 결과를 얻을 수 있다.3

앱 작업 프롬프트에 꼭 넣어야 할 것들

Codex가 앱 프로젝트에서 제대로 일하려면 단지 "무엇을 만들지"만 알아서는 부족하다. 실제 개발자는 프로젝트 구조, 기술 스택, 테스트 명령, 건드리면 안 되는 파일을 함께 본다. Codex도 마찬가지다.

앱 작업을 맡길 때는 다음 정보가 있으면 좋다.

  • 사용자 시나리오: 사용자가 어떤 상황에서 어떤 행동을 하는가

  • 기술 스택: React, Next.js, Express, Prisma, Tailwind CSS처럼 사용 중인 도구

  • 참고 파일과 폴더: Codex가 먼저 읽어야 할 컴포넌트, API 라우트, 스타일 파일

  • 수정 가능한 범위: 이번 작업에서 바꿔도 되는 파일이나 폴더

  • 금지 영역: DB 스키마, 공개 API 응답 형태, 인증 로직, 결제 코드처럼 건드리면 안 되는 부분

  • 실행과 테스트 명령: npm run dev, npm test, pnpm lint, npm run typecheck 등

  • 기대 출력 형식: 마지막에 무엇을 보고해야 하는지

예를 들어 할 일 관리 앱에 필터 기능을 추가한다고 해 보자.

Goal:
할 일 목록 앱에 전체/진행 중/완료 필터를 추가해줘.

User scenario:
사용자는 할 일이 많을 때 완료된 항목을 숨기고 아직 해야 할 일만 빠르게 보고 싶어 함.

Tech stack:
- React + TypeScript
- Vite
- 상태 관리는 현재 `useState`만 사용 중

Context:
- 앱 진입점: `src/App.tsx`
- 할 일 목록 컴포넌트: `src/components/TodoList.tsx`
- 할 일 아이템 컴포넌트: `src/components/TodoItem.tsx`
- 스타일: `src/App.css`

Scope:
- 수정 가능: `src/App.tsx`, `src/components/*`, `src/App.css`
- 수정 금지: `package.json`, `vite.config.ts`, 테스트 설정 파일

Requirements:
- 필터 버튼은 `All`, `Active`, `Completed` 3개
- 현재 선택된 필터가 시각적으로 구분되어야 함
- 완료된 항목은 Completed 필터에서만 보이고, Active에서는 숨김
- 기존 할 일 추가/삭제/완료 토글 기능은 유지

Verification:
- `npm run lint` 실행
- 가능하면 `npm run build` 실행
- 수동 확인 시나리오를 마지막에 알려줘

Report:
- 변경 파일 목록
- 핵심 변경 내용
- 실행한 명령과 결과
- 테스트하지 못한 부분
- 남은 위험 또는 후속 작업

이 프롬프트는 길어 보이지만, 실제로는 Codex의 시행착오를 줄여 준다. Codex가 package.json에 새 라이브러리를 추가하거나, 상태 관리를 갑자기 Redux로 바꾸거나, 테스트 설정을 고치는 일을 막을 수 있다.

초보자에게 특히 중요한 부분은 수정 금지 영역이다. "건드리지 마"라고 말하는 것은 Codex를 불신하는 행동이 아니다. 좋은 동료에게도 "이번 배포에서는 DB 스키마는 바꾸지 말자", "결제 쪽은 손대지 말자"라고 말한다. Codex에게도 같은 방식으로 범위를 알려주는 것이다.

바로 구현하지 말고, 먼저 계획을 요청하라

작은 버튼 하나를 추가하는 일이라면 바로 구현을 맡겨도 괜찮다. 하지만 인증, 결제, 데이터베이스, 대규모 리팩터링, 여러 화면이 얽힌 기능은 다르다. 이런 작업에서 Codex가 처음부터 코드를 고치기 시작하면, 나중에 방향이 틀렸다는 것을 발견했을 때 되돌리기 어렵다.

이럴 때는 먼저 계획을 요청한다. Codex CLI에는 /plan 같은 계획 모드가 있고, Codex App에서도 복잡한 작업은 구현 전에 접근 방식을 정리하게 만들 수 있다. 계획 모드는 파일을 바로 수정하기보다 요구사항을 이해하고, 영향 범위와 작업 순서, 위험 요소를 먼저 드러내는 데 유용하다.4

예를 들어 미니 SaaS 앱에 팀 초대 기능을 추가한다고 해 보자. 바로 이렇게 말하면 위험하다.

팀 초대 기능 만들어줘.

팀 초대 기능은 생각보다 크다. 초대 링크, 이메일 발송, 권한, 만료 시간, 중복 초대, 가입 전 사용자 처리, 보안 검증이 얽힌다. 먼저 이렇게 요청하는 편이 안전하다.

/plan 팀 초대 기능을 추가하기 위한 구현 계획을 먼저 세워줘. 아직 파일은 수정하지 마.

Goal:
워크스페이스 관리자가 이메일로 팀원을 초대하고, 초대받은 사용자가 링크를 통해 가입 또는 로그인 후 워크스페이스에 합류할 수 있게 만들고 싶어.

Context:
- Next.js App Router 프로젝트
- 인증은 이미 구현되어 있음
- Prisma와 PostgreSQL 사용
- 관련 폴더: `app/(dashboard)`, `app/api`, `prisma`, `lib/auth.ts`

Return:
- Codex가 이해한 요구사항 요약
- 변경이 필요할 가능성이 있는 파일 목록
- 새로 필요한 데이터 모델 또는 API 후보
- 구현 순서
- 보안상 주의할 점
- 먼저 확인해야 할 질문
- 테스트 계획

Constraints:
- 아직 코드는 수정하지 말 것
- 기존 로그인 흐름을 깨지 말 것
- 결제/구독 관련 코드는 건드리지 말 것

이렇게 하면 Codex가 먼저 설계도를 가져온다. 우리는 그 설계도를 보고 "이번 버전에서는 이메일 발송은 빼고 초대 링크 생성까지만 하자", "워크스페이스 소유자만 초대할 수 있어야 한다", "초대 만료 시간은 7일로 하자"처럼 범위를 줄이거나 조건을 추가할 수 있다.

계획 요청에서 꼭 봐야 할 것은 세 가지다. 첫째, Codex가 요구사항을 제대로 이해했는가. 둘째, 건드릴 파일 범위가 너무 넓지 않은가. 셋째, 빠진 질문이 없는가. 이 세 가지만 확인해도 큰 사고를 줄일 수 있다.

Codex가 스스로 찾아보게 하되, 위험한 일은 묻게 하라

좋은 프롬프트는 Codex를 지나치게 손발 묶지 않는다. "이 파일만 보고 이 줄만 고쳐"라고 하면 안전할 수는 있지만, Codex가 프로젝트 전체 패턴을 이해하지 못해 어색한 코드를 만들 수 있다. 반대로 "알아서 다 해"라고 하면 위험하다.

그래서 프롬프트에는 자율성과 지속성의 한계를 함께 적는 것이 좋다. 즉, Codex가 스스로 탐색해도 되는 부분과 사용자 승인이 필요한 부분을 나누는 것이다.

예를 들어 다음처럼 쓸 수 있다.

Autonomy:
- 필요한 관련 파일은 직접 찾아보고 읽어도 됨
- 기존 UI 패턴과 테스트 패턴을 참고해도 됨
- 작은 타입 오류나 린트 오류는 직접 수정해도 됨

Ask before:
- 새 npm 패키지를 설치해야 할 때
- DB 스키마를 변경해야 할 때
- 외부 API 요청 방식이 바뀔 때
- 인증, 결제, 데이터 삭제 로직을 수정해야 할 때
- 5개 이상의 파일을 크게 리팩터링해야 할 때

이런 지시는 초보자에게 특히 중요하다. 아직 코드베이스를 완전히 이해하지 못해도 "위험한 일은 먼저 물어봐"라고 정해 두면 Codex를 더 안심하고 사용할 수 있다. Codex의 샌드박스와 승인 모드도 이런 생각과 연결된다. 샌드박스는 Codex가 실제로 어디까지 파일을 읽고 쓰고 명령을 실행할 수 있는지 제한하는 안전 울타리이고, 승인 정책은 경계를 넘을 때 사용자에게 물어보게 하는 규칙이다.5

프롬프트는 논리적인 안전장치이고, 샌드박스와 승인 모드는 기술적인 안전장치다. 둘을 함께 쓰면 훨씬 좋다. 프롬프트로 "DB 삭제는 하지 마"라고 말하고, 권한 설정으로도 위험한 명령을 바로 실행하지 못하게 막는 식이다.

중간에 방향이 틀어졌을 때 바로잡는 법

Codex가 작업 중인데 무언가 이상하다는 느낌이 들 때가 있다. 예를 들어 단순한 UI 수정이라고 생각했는데 갑자기 상태 관리 구조를 바꾸고 있거나, 기존 컴포넌트를 재사용하지 않고 새 컴포넌트를 잔뜩 만들고 있을 수 있다. 이때 초보자는 긴 설명을 덧붙이려 한다.

아니 그게 아니라 내가 원한 건 기존 구조를 최대한 유지하면서 조금만 바꾸는 거였고, 이 화면은 다른 페이지랑 스타일이 맞아야 하고, 지금 네가 만든 방식은 좀 과한 것 같고...

사람과 대화할 때는 이런 설명이 자연스럽지만, 작업 중인 Codex에게는 짧고 명확한 수정 지시가 더 잘 먹힌다. 진행 방향을 바로잡을 때는 다음처럼 말하자.

현재 접근을 중단해줘.
`src/store` 구조는 수정하지 마.
기존 `ProductCard` 컴포넌트를 유지한 채 CSS와 props 처리만 최소 수정해줘.
먼저 현재 diff에서 불필요한 새 파일을 되돌릴 계획을 제안해줘.

또는 테스트가 실패하고 있다면 이렇게 말할 수 있다.

새 기능 추가는 잠시 멈춰줘.
먼저 `npm test -- auth` 실패부터 해결해줘.
공개 API 응답 형태는 바꾸지 말고, 실패 원인과 최소 수정안을 설명한 뒤 패치해줘.

디자인 방향이 어긋났다면 이렇게 짚는다.

현재 UI 방향은 너무 화려해.
기존 대시보드의 카드 패턴을 유지해줘.
그라데이션과 큰 그림자는 제거하고, `DashboardCard`의 spacing과 border 스타일을 맞춰줘.

수정 지시의 핵심은 "왜 마음에 안 드는지"보다 "지금부터 무엇을 하지 말고, 무엇을 먼저 해야 하는지"를 분명히 말하는 것이다. Codex App의 실행 중 개입 기능이나 CLI 대화 흐름에서도 이런 짧은 방향 전환 지시가 효과적이다. 여러 실무 가이드에서도 같은 실수를 반복할 때는 장황한 새 요구사항보다 구체적인 중단, 제한, 우선순위 지시가 더 낫다고 설명한다.6

좋은 프롬프트 예제 1: 버그 수정

버그 수정 프롬프트에서 가장 중요한 것은 재현 방법이다. "저장 안 됨"보다 "어떤 버튼을 어떤 순서로 눌렀을 때 어떤 결과가 나오는지"를 알려줘야 한다.

Goal:
설정 화면에서 알림 토글을 저장해도 새로고침 후 값이 원래대로 돌아가는 버그를 고쳐줘.

Bug:
`/settings` 화면에서 `Enable notifications` 토글을 켠 뒤 Save를 누르면 `Saved` 메시지는 보이지만, 새로고침하면 토글이 다시 꺼져 있음.

Reproduction:
1. `npm run dev`로 앱 실행
2. 브라우저에서 `/settings` 이동
3. `Enable notifications` 토글 켜기
4. Save 클릭
5. 페이지 새로고침
6. 토글 상태가 유지되어야 하지만 꺼져 있음

Context:
- 설정 화면: `src/pages/Settings.tsx`
- 설정 API: `src/api/settings.ts`
- 관련 테스트: `tests/settings.test.ts`

Constraints:
- API 응답 형태는 바꾸지 말 것
- 설정 저장 로직 전체를 재작성하지 말 것
- 가능한 최소 수정으로 해결할 것

Verification:
- 먼저 버그 원인을 설명해줘
- 가능하면 회귀 테스트를 추가해줘
- `npm test -- settings`를 실행해줘

Report:
- 원인
- 변경 파일
- 수정 방식
- 실행한 테스트와 결과
- 남은 위험

여기서 "회귀 테스트"는 한 번 고친 버그가 다시 생기지 않도록 막는 테스트다. 초보자라면 이 단어를 몰라도 괜찮다. 프롬프트에 "같은 문제가 다시 생기지 않도록 테스트를 추가해줘"라고 써도 된다.

좋은 프롬프트 예제 2: 기능 추가

기능 추가는 버그 수정보다 범위가 넓어지기 쉽다. 그래서 사용자 시나리오와 완료 기준을 더 신경 써야 한다.

Goal:
날씨 대시보드에 도시 검색 기능을 추가해줘.

User scenario:
사용자는 현재 위치가 아닌 다른 도시의 날씨를 보고 싶어 함. 검색창에 도시 이름을 입력하고 Enter를 누르면 해당 도시의 날씨 카드가 갱신되어야 함.

Tech stack:
- React + TypeScript
- 날씨 데이터는 이미 `src/lib/weatherApi.ts`에서 가져옴
- 스타일은 CSS Modules 사용

Context:
- 메인 화면: `src/pages/WeatherDashboard.tsx`
- API 함수: `src/lib/weatherApi.ts`
- 기존 날씨 카드: `src/components/WeatherCard.tsx`

Requirements:
- 검색창은 대시보드 상단에 배치
- 빈 문자열로 검색하면 요청하지 않고 안내 문구 표시
- 로딩 중에는 버튼이 비활성화되고 `Loading...` 표시
- 도시를 찾지 못하면 사용자에게 이해하기 쉬운 오류 메시지 표시

Constraints:
- 외부 자동완성 라이브러리는 추가하지 말 것
- 기존 `getCurrentWeather` 함수의 공개 인터페이스는 가능한 유지
- 전체 레이아웃을 새로 만들지 말고 기존 카드 디자인을 유지

Verification:
- `npm run lint`
- `npm run build`
- 수동 확인: Seoul 검색, 빈 검색, 존재하지 않는 도시 검색

Report:
- 변경 파일
- 새로 추가한 상태와 이벤트 처리 설명
- 실행한 검증 명령과 결과
- 수동 확인 방법

이 프롬프트는 Codex에게 "도시 검색"이라는 기능뿐 아니라 사용자가 실패했을 때의 경험까지 알려준다. 실제 앱은 성공 상황보다 실패 상황에서 품질이 드러난다. 빈 입력, 로딩, 오류 메시지 같은 조건을 미리 적어 두면 Codex가 더 완성도 높은 기능을 만든다.

좋은 프롬프트 예제 3: 리팩터링

리팩터링은 코드를 정리하는 작업이다. 겉으로 보이는 기능은 그대로 두고 내부 구조를 읽기 쉽고 유지보수하기 좋게 바꾸는 일이다. 문제는 Codex가 "정리"를 너무 적극적으로 해석하면 동작까지 바뀔 수 있다는 점이다.

그래서 리팩터링 프롬프트에는 반드시 "동작은 바꾸지 말 것"을 넣어야 한다.

Goal:
`src/utils/price.ts` 파일의 중복 로직을 줄이고 읽기 쉽게 리팩터링해줘.

Context:
- 이 파일은 상품 가격, 할인율, 배송비 표시 문자열을 만드는 유틸 함수들을 포함함
- 관련 테스트는 `tests/price.test.ts`에 있음

Scope:
- 수정 가능: `src/utils/price.ts`, `tests/price.test.ts`
- 수정 금지: 상품 API, 결제 로직, UI 컴포넌트

Constraints:
- 기존 함수 이름과 export 형태는 유지
- 기존 테스트가 기대하는 출력 문자열은 바꾸지 말 것
- 새 의존성 추가 금지
- 큰 구조 변경보다 작은 helper 함수 추출을 선호

Verification:
- 리팩터링 전 현재 테스트 의도를 먼저 파악
- 수정 후 `npm test -- price` 실행
- 동작이 바뀌지 않았음을 설명

Report:
- 어떤 중복을 제거했는지
- 동작을 유지하기 위해 확인한 부분
- 테스트 결과

리팩터링은 Codex에게 잘 맞는 작업이지만, 범위가 넓어지면 위험하다. "전체 프로젝트 리팩터링해줘"보다는 "이 파일의 중복을 줄여줘", "이 컴포넌트의 조건문을 읽기 쉽게 바꿔줘"처럼 작게 맡기는 편이 좋다.

좋은 프롬프트 예제 4: 테스트 작성

테스트를 작성할 때는 입력, 출력, 예외 상황을 알려줘야 한다. 테스트란 코드가 약속대로 동작하는지 확인하는 장치다. 초보자는 테스트를 어렵게 느끼지만, Codex에게 테스트 초안을 맡기면 기능의 계약을 더 잘 이해할 수 있다.

Goal:
회원가입 폼 검증 함수에 대한 단위 테스트를 추가해줘.

Context:
- 검증 함수: `src/lib/validateSignup.ts`
- 테스트 폴더: `tests/lib`
- 테스트 도구: Vitest

Cases:
- 올바른 이메일과 8자 이상의 비밀번호면 통과
- 이메일 형식이 아니면 에러
- 비밀번호가 8자 미만이면 에러
- 비밀번호 확인 값이 다르면 에러
- 이름이 비어 있으면 에러

Constraints:
- 검증 함수의 public API는 바꾸지 말 것
- 테스트를 통과시키기 위해 에러 메시지를 임의로 바꾸지 말 것
- 먼저 테스트 케이스 표를 제안하고, 그다음 테스트 파일을 작성해줘

Verification:
- `npm test -- validateSignup` 실행

Report:
- 추가한 테스트 파일
- 다룬 케이스
- 실행 결과
- 빠진 케이스가 있다면 이유

여기서 "먼저 테스트 케이스 표를 제안"하게 하는 부분이 중요하다. Codex가 곧바로 테스트 코드를 쓰기 전에 우리가 빠진 조건을 볼 수 있기 때문이다. 큰 기능을 만들 때도 마찬가지다. 구현 전에 테스트 관점으로 요구사항을 정리하면 결과가 훨씬 안정된다.

원하는 최종 응답 형식을 지정하라

Codex가 작업을 끝냈을 때 "완료했습니다"라고만 말하면 초보자는 무엇을 확인해야 할지 모른다. 그래서 프롬프트 끝에 반드시 최종 보고 형식을 넣는 습관을 들이자.

다음 템플릿을 그대로 복사해 써도 좋다.

Final response format:
1. 변경 파일 목록
2. 핵심 변경 내용
3. 실행 방법
4. 수행한 테스트와 결과
5. 테스트하지 못한 부분과 이유
6. 남은 위험 또는 후속 작업

조금 더 엄격하게 하려면 이렇게 쓸 수 있다.

작업 완료 후에는 아래 형식으로만 보고해줘.

## Changed files
- 파일별 변경 요약

## What changed
- 사용자 관점에서 달라진 점
- 코드 구조 관점에서 달라진 점

## How to run
- 로컬 실행 명령
- 확인할 URL 또는 화면

## Verification
- 실행한 명령
- 통과/실패 결과
- 실패했다면 원인 또는 추정 이유

## Not tested
- 실행하지 못한 테스트
- 실행하지 못한 이유

## Risks / Next steps
- 남은 위험
- 추천 후속 작업

이 형식은 초보자에게 매우 유용하다. 변경 파일 목록을 보면 Codex가 엉뚱한 곳을 건드렸는지 확인할 수 있다. 테스트 결과를 보면 최소한의 검증이 되었는지 알 수 있다. "테스트하지 못한 부분"을 요구하면 Codex가 조용히 넘어가는 일을 줄일 수 있다.

특히 "수행한 테스트와 결과"는 꼭 넣자. Codex가 npm run lint를 실행했는지, 실행하려 했지만 환경 문제로 실패했는지, 아예 실행하지 않았는지는 큰 차이가 있다. 실행하지 못했다면 왜 못했는지 보고하게 해야 다음 판단을 할 수 있다.

프롬프트를 한 번에 길게 쓰지 않아도 된다

여기까지 보면 "매번 이렇게 길게 써야 하나?"라는 생각이 들 수 있다. 답은 아니다. 모든 작업에 긴 프롬프트가 필요한 것은 아니다. 간단한 문구 수정이나 버튼 색 변경은 짧게 요청해도 된다.

`src/components/Header.tsx`의 로그인 버튼 문구를 `Sign in`에서 `Log in`으로 바꿔줘. 다른 파일은 수정하지 마.

이 정도면 충분하다. 중요한 것은 작업의 위험도에 맞게 프롬프트의 밀도를 조절하는 것이다. 작은 작업은 짧게, 큰 작업은 계획부터, 위험한 작업은 제약과 승인 조건을 자세히 적는다.

처음에는 다음 기준으로 판단하면 쉽다. 한 파일의 작은 수정이면 짧은 프롬프트로 시작한다. 여러 파일을 건드릴 가능성이 있으면 목표, 맥락, 제약, 완료 기준을 넣는다. 데이터베이스, 인증, 결제, 배포, 대규모 리팩터링이 포함되면 먼저 계획을 요청한다.

바로 복사해서 쓰는 만능 템플릿

아래 템플릿은 앱 개발에서 가장 자주 쓰는 형태다. 처음에는 이 형식을 복사해 빈칸만 채워도 충분하다.

Goal:
[무엇을 만들거나 고칠지 한 문장으로 적기]

User scenario:
[사용자가 어떤 상황에서 어떤 행동을 하는지 적기]

Tech stack:
[React, Next.js, Node.js, Prisma, Tailwind CSS 등]

Context:
- 관련 파일: [파일 경로]
- 참고할 기존 구현: [파일 경로]
- 현재 문제 또는 요구사항: [설명]

Scope:
- 수정 가능: [파일/폴더]
- 수정 금지: [파일/폴더/기능]

Requirements:
- [필수 요구사항 1]
- [필수 요구사항 2]
- [필수 요구사항 3]

Constraints:
- [새 패키지 금지 여부]
- [API 응답 형태 유지 여부]
- [기존 UI 패턴 유지 여부]
- [성능, 보안, 접근성 조건]

Autonomy:
- 필요한 관련 파일은 직접 찾아봐도 됨
- 작은 린트/타입 오류는 직접 고쳐도 됨

Ask before:
- DB 스키마 변경
- 외부 API 변경
- 새 의존성 추가
- 대규모 리팩터링
- 데이터 삭제 또는 위험한 명령 실행

Verification:
- [실행할 명령: npm run lint 등]
- [수동 확인 시나리오]

Final response format:
1. 변경 파일 목록
2. 핵심 변경 내용
3. 실행 방법
4. 수행한 테스트와 결과
5. 테스트하지 못한 부분과 이유
6. 남은 위험 또는 후속 작업

이 템플릿은 길어 보이지만 실제로 매번 모든 칸을 채울 필요는 없다. 모르는 부분은 비워도 된다. 예를 들어 테스트 명령을 모른다면 이렇게 쓰면 된다.

Verification:
프로젝트에서 적절한 lint/test/build 명령을 찾아보고 실행해줘. 명령을 찾지 못하면 어떤 파일을 확인했는지와 함께 이유를 보고해줘.

이렇게 적으면 Codex가 package.json을 읽고 가능한 명령을 찾을 수 있다. 단, 명령 실행이 위험하거나 시간이 오래 걸릴 수 있다면 먼저 확인을 요청하도록 제약을 넣는 편이 좋다.

프롬프트 실전 연습: 나쁜 요청 바꾸기

마지막으로 짧은 요청을 좋은 요청으로 바꾸는 연습을 해 보자.

첫 번째 요청이다.

게시판 검색 좀 고쳐줘.

이 요청은 무엇이 고장 났는지 알 수 없다. 다음처럼 바꾸면 훨씬 좋다.

Goal:
게시판 목록에서 검색어를 입력해도 결과가 필터링되지 않는 문제를 고쳐줘.

Reproduction:
1. `npm run dev` 실행
2. `/posts`로 이동
3. 검색창에 `react` 입력
4. Enter 또는 Search 버튼 클릭
5. URL은 바뀌지만 목록이 전체 글 그대로 남아 있음

Context:
- 게시판 화면: `src/pages/Posts.tsx`
- 검색 API: `src/api/posts.ts`
- 관련 훅: `src/hooks/usePosts.ts`

Constraints:
- API 응답 형태는 바꾸지 말 것
- 페이지네이션 동작은 유지할 것
- 검색과 무관한 UI 리팩터링은 하지 말 것

Verification:
- `npm test -- posts` 실행
- 수동 확인: 검색어 있음/없음, 결과 없음 상태

Report:
원인, 변경 파일, 테스트 결과, 남은 위험을 알려줘.

두 번째 요청이다.

대시보드 좀 멋있게 만들어줘.

이 요청은 디자인 방향이 없다. 다음처럼 바꾸자.

Goal:
SaaS 관리자 대시보드 첫 화면을 더 전문적이고 읽기 쉽게 개선해줘.

User scenario:
관리자는 로그인 직후 오늘의 매출, 신규 가입자, 활성 사용자, 오류 알림을 빠르게 확인하고 싶어 함.

Requirements:
- 상단에 핵심 지표 카드 4개 표시
- 각 카드에는 제목, 숫자, 전일 대비 변화율 표시
- 아래에는 최근 활동 목록과 오류 알림 영역 배치
- 데이터가 없을 때 빈 상태 메시지 표시

Design tone:
- B2B SaaS 느낌의 차분한 디자인
- 과한 색상보다 회색 계열과 브랜드 포인트 색 사용
- 기존 `Card`와 `Button` 컴포넌트 패턴 유지

Responsive:
- 모바일에서는 지표 카드가 1열
- 태블릿 이상에서는 2열 또는 4열

Constraints:
- 새 차트 라이브러리 추가 금지
- 백엔드 API 변경 금지
- `src/pages/Dashboard.tsx`와 관련 스타일 중심으로 수정

Completion:
- `npm run lint` 실행
- 변경 파일과 확인 방법 보고

세 번째 요청이다.

코드 정리해줘.

이 요청은 너무 넓다. 다음처럼 바꾸면 안전하다.

Goal:
`src/components/CheckoutSummary.tsx`의 조건문과 중복 렌더링을 정리해서 읽기 쉽게 만들어줘.

Constraints:
- 화면에 표시되는 문구와 금액 계산 결과는 바꾸지 말 것
- public props 타입은 바꾸지 말 것
- 결제 API 호출 로직은 수정하지 말 것
- 새 파일을 만들기보다 작은 helper 함수 추출을 우선 고려

Verification:
- 기존 테스트가 있으면 관련 테스트 실행
- 테스트가 없으면 어떤 수동 확인이 필요한지 알려줘

Report:
- 정리한 부분
- 동작 유지 확인 방법
- 변경 파일

이 연습의 핵심은 "내 머릿속 기대"를 Codex가 볼 수 있는 문장으로 꺼내는 것이다.

이번 장의 정리

Codex에게 좋은 결과를 얻는 가장 빠른 방법은 더 어려운 기술 용어를 쓰는 것이 아니다. 일을 잘게 나누고, 기준을 분명히 하고, 끝났는지 확인할 방법을 알려주는 것이다.

프롬프트에는 최소한 목표, 맥락, 제약, 완료 기준을 넣자. 앱 작업이라면 사용자 시나리오, 기술 스택, 참고 파일, 수정 가능 범위, 금지 영역, 실행 명령, 최종 보고 형식을 함께 주면 좋다. 큰 작업은 바로 구현시키지 말고 먼저 계획을 요청하자. Codex가 잘못된 방향으로 가면 장황하게 설명하기보다 "중단", "수정 금지", "먼저 해결할 테스트", "유지할 UI 패턴"을 짧고 명확하게 지시하자.

좋은 프롬프트는 Codex를 통제하기 위한 족쇄가 아니다. Codex가 더 빠르고 안전하게 움직일 수 있게 해 주는 지도다. 이제 우리는 Codex에게 일을 맡기는 기본 언어를 배웠다. 다음 장에서는 이 지시가 실제로 어디까지 실행될 수 있는지, 즉 권한, 샌드박스, 승인 모드를 안전하게 다루는 법을 살펴본다.

참고

1Codex Prompting Guide

2Best practices - Codex | OpenAI Developers

3Codex App Beginner Guide: Installation, Sandbox, Parallel Tasks, Skills, and MCP

4Codex CLI Cheatsheet: config, commands, AGENTS.md, + best practices

5Practical Codex 03. How to Write Your First Codex Task Request

610 Codex Prompts Every Developer Should Save

책 목록

Codex로 앱 만들기 완벽 가이드: 초보자를 위한 AI 코딩 에이전트 실전 입문

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기