Skip to main content
Summary

앱은 로컬 서버가 아니라 실제 URL에서 완성된다

초보자가 앱을 만들 때 가장 자주 하는 착각이 있습니다. npm run dev로 브라우저에 화면이 뜨면 앱이 완성됐다고 생각하는 것입니다. 물론 그 순간은 뿌듯합니다. 내 컴퓨터에서 버튼이 눌리고, 목록이 저장되고, 로그인 화면이 움직이면 "드디어 만들었다"는 느낌이 듭니다.

하지만 앱 개발의 마지막 문장은 로컬 주소가 아닙니다.

http://localhost:3000

진짜 마지막 문장은 이런 주소입니다.

https://my-first-saas.vercel.app
https://todo-dashboard.netlify.app
https://weather-app.pages.dev
https://my-api.onrender.com

즉, 다른 사람이 자기 휴대폰이나 노트북에서 열 수 있는 URL이 생겨야 앱 만들기가 끝납니다. 이 장에서는 Codex가 만든 앱을 로컬 프로젝트에서 꺼내 실제 배포 가능한 상태로 정리하는 방법을 다룹니다. 목표는 단순히 "어딘가에 올리기"가 아닙니다. 빌드가 통과하고, 환경 변수가 분리되고, 배포 로그를 읽을 수 있으며, 실제 URL에서 핵심 기능을 검수할 수 있는 상태까지 가는 것입니다.

Codex는 이 마지막 구간에서 특히 강합니다. OpenAI의 Codex 배포 유스케이스에서도 저장소, 스크린샷, 디자인, 대략적인 앱 아이디어를 실제 미리보기 배포로 연결하는 흐름을 강조합니다.1 이제 우리는 Codex에게 코드를 쓰게 하는 단계를 넘어, "이 앱을 출시 가능한 형태로 정리해줘"라고 맡기는 단계로 들어갑니다.

배포 가능한 앱으로 마무리하기

배포 전에 먼저 저장소를 차갑게 점검하기

배포는 축제처럼 느껴지지만, 사실은 시험장에 가깝습니다. 내 컴퓨터에서는 대충 돌아가던 코드도 배포 서버에서는 조금만 허술해도 바로 실패합니다. Node 버전이 다르거나, 환경 변수가 없거나, 빌드 출력 폴더가 틀리거나, 타입 오류가 숨어 있으면 배포 로그가 빨갛게 변합니다.

그래서 첫 단계는 플랫폼 선택이 아닙니다. 저장소 점검입니다. Codex에게 바로 "Vercel에 배포해줘"라고 하기 전에, 먼저 "이 저장소가 배포 가능한 상태인지 점검해줘"라고 요청해야 합니다.

다음 프롬프트를 그대로 사용해도 좋습니다.

이 저장소를 배포 가능한 상태로 점검해줘.

다음을 순서대로 확인해줘.
1. 프레임워크와 패키지 매니저를 감지한다.
2. package.json의 scripts를 확인한다.
3. 설치, 린트, 타입체크, 테스트, 빌드 명령을 찾아 실행 가능한 형태로 정리한다.
4. .env, .env.local, .env.example, .gitignore 상태를 확인한다.
5. 배포 전에 필요한 환경 변수 목록을 추출한다.
6. README에 설치, 실행, 테스트, 빌드, 배포 방법이 충분히 적혀 있는지 확인한다.
7. 의존성 보안 점검 명령을 제안한다.
8. 문제가 있으면 파일을 바로 수정하지 말고 먼저 보고서로 정리해줘.

최종 출력은 다음 형식으로 해줘.
- 감지한 기술 스택
- 로컬 검증 명령
- 배포에 필요한 환경 변수
- 수정이 필요한 파일
- 배포 전 위험 요소
- 추천 배포 플랫폼

여기서 중요한 것은 "바로 수정하지 말고 먼저 보고서로 정리해줘"라는 문장입니다. 배포 직전에는 작은 수정도 예상치 못한 결과를 낳을 수 있습니다. Codex가 마음대로 설정 파일을 바꾸기 전에, 사람이 먼저 방향을 확인해야 합니다.

일반적인 JavaScript 또는 TypeScript 앱이라면 배포 전 검증 명령은 대략 다음 흐름이 됩니다.

npm install
npm run lint
npm run typecheck
npm test
npm run build
npm audit

프로젝트가 pnpm을 쓴다면 이렇게 바뀝니다.

pnpm install
pnpm lint
pnpm typecheck
pnpm test
pnpm build
pnpm audit

모든 프로젝트에 lint, typecheck, test 스크립트가 있는 것은 아닙니다. 초보자 프로젝트라면 build만 있는 경우도 많습니다. 이때 Codex에게 없는 명령을 억지로 만들라고 하기보다, 먼저 현재 상태를 파악하게 해야 합니다.

package.json을 확인해서 현재 존재하는 검증 명령만 실행해줘.
없는 스크립트는 실패로 처리하지 말고, 어떤 스크립트가 없으며 추가하면 좋은지 제안해줘.

배포 전 저장소 점검에서 가장 중요한 파일은 .env.local과 .env.example입니다. .env.local에는 내 컴퓨터에서만 쓰는 진짜 비밀값이 들어갑니다. 반면 .env.example에는 값 없이 이름만 적습니다.

# .env.example
DATABASE_URL=
NEXTAUTH_SECRET=
NEXT_PUBLIC_APP_URL=
OPENAI_API_KEY=

이렇게 해두면 Codex도, 미래의 나도, 팀원도 "이 앱을 실행하려면 어떤 환경 변수가 필요한지" 알 수 있습니다. 단, 실제 비밀번호나 API 키는 절대 .env.example에 넣지 않습니다.

Codex에게 플랫폼별 배포 설정을 먼저 비교하게 하기

배포 플랫폼마다 좋아하는 형식이 조금씩 다릅니다. Vercel은 Next.js와 프론트엔드 프레임워크에 강하고, Netlify는 정적 사이트와 Jamstack 흐름에 익숙합니다. Cloudflare Pages는 전 세계 엣지 네트워크와 Pages/Workers 조합이 강점이고, Render는 백엔드 서버, 워커, 데이터베이스가 있는 앱을 배포하기 좋습니다.

초보자에게 어려운 부분은 "내 앱에는 무엇을 골라야 하지?"입니다. 이때 Codex에게 플랫폼 결정을 도와달라고 할 수 있습니다.

이 저장소의 프레임워크와 패키지 매니저를 감지해서
Vercel, Netlify, Cloudflare Pages, Render에 배포할 때 필요한 설정을 비교해줘.

각 플랫폼별로 다음 항목을 표로 정리해줘.
- install command
- build command
- output directory
- start command가 필요한지 여부
- Node.js 버전
- 필요한 설정 파일
- 환경 변수 등록 위치
- 이 프로젝트에 추천하는 정도

추측하지 말고 package.json, lockfile, 설정 파일을 근거로 판단해줘.

Codex가 만들어줄 표는 프로젝트마다 다르지만, 전형적인 Vite 앱이라면 대략 이런 결론이 나옵니다.

플랫폼Install commandBuild commandOutput directory적합한 경우
Vercelnpm installnpm run builddist프론트엔드 앱, 빠른 미리보기 배포
Netlifynpm installnpm run builddist정적 사이트, 폼, 함수 조합
Cloudflare Pagesnpm installnpm run builddist빠른 CDN, Pages Functions, Workers 연동
Rendernpm installnpm run build정적 사이트면 dist, 서버면 start command백엔드 서버, API, 장기 실행 서비스

Next.js 앱이라면 상황이 달라집니다. Vercel에서는 대부분 자동 감지가 잘 되지만, Netlify나 Cloudflare에서는 런타임 어댑터, 정적 export 여부, 서버리스 함수 경로를 확인해야 합니다. Express API 서버라면 Vercel이나 Netlify의 정적 사이트 설정이 아니라 Render의 Web Service가 더 자연스러울 수 있습니다.

여기서 핵심은 "플랫폼을 먼저 정하고 앱을 끼워 맞추는 것"이 아니라 "앱의 구조를 보고 플랫폼을 고르는 것"입니다. Codex에게 이 판단을 맡기면 빌드 명령 불일치, 출력 폴더 오류, Node 버전 차이 같은 초보자 실수를 크게 줄일 수 있습니다.

환경 변수는 로컬용과 배포용을 반드시 분리한다

배포 실패의 절반은 환경 변수에서 시작됩니다. 로컬에서는 .env.local에 값이 있어서 잘 돌아갔는데, 배포 서버에는 그 값이 없어서 로그인, API 호출, 데이터베이스 연결이 모두 실패하는 식입니다.

환경 변수는 크게 세 종류로 나누면 이해하기 쉽습니다.

종류예시브라우저 노출 여부저장 위치
서버 비밀값DATABASE_URL, OPENAI_API_KEY, JWT_SECRET노출되면 안 됨플랫폼 환경 변수/Secrets
공개 설정값NEXT_PUBLIC_APP_URL, VITE_API_BASE_URL노출 가능플랫폼 환경 변수
로컬 개발값테스트 DB URL, 로컬 API 주소로컬에서만 사용.env.local

프레임워크마다 브라우저에 노출되는 환경 변수 접두사가 다릅니다. Next.js는 NEXT_PUBLIC_, Vite는 VITE_, Astro는 PUBLIC_ 같은 접두사를 사용합니다. 이 접두사가 붙은 값은 최종 JavaScript 번들에 포함될 수 있으므로, 비밀키를 넣으면 안 됩니다.

# 안전한 예: 브라우저에 공개되어도 되는 API base URL
VITE_API_BASE_URL=https://api.example.com

# 위험한 예: 브라우저에 공개되면 안 되는 비밀키
VITE_OPENAI_API_KEY=sk-...

위험한 예가 왜 위험할까요? VITE_가 붙은 값은 프론트엔드 코드에서 접근할 수 있게 번들링됩니다. 사용자가 개발자 도구를 열면 값을 볼 수 있습니다. OpenAI API 키, Stripe secret key, 데이터베이스 URL 같은 값은 반드시 서버에서만 사용해야 합니다.

Netlify의 공식 문서도 빌드 환경 변수는 UI, CLI, API, 설정 파일 등으로 만들 수 있고, 민감한 값은 저장소에 커밋하지 않는 방식으로 관리해야 한다고 설명합니다. 또한 Netlify에서 빌드할 때는 로컬 .env 파일을 자동으로 읽는 방식이 아니므로, 필요한 값은 Netlify 환경 변수로 가져와야 합니다.2

Codex에게 환경 변수를 점검시킬 때는 다음처럼 요청하세요.

이 프로젝트의 환경 변수 사용을 점검해줘.

다음을 확인해줘.
1. 코드에서 process.env, import.meta.env로 읽는 변수를 모두 찾아줘.
2. 브라우저에 노출되는 변수와 서버 전용 변수를 분리해줘.
3. .env.example에 추가해야 할 변수 목록을 만들어줘.
4. .env.local이 .gitignore에 포함되어 있는지 확인해줘.
5. Vercel, Netlify, Cloudflare Pages, Render에 각각 어떤 이름으로 등록해야 하는지 정리해줘.
6. 비밀값이 클라이언트 번들에 노출될 위험이 있으면 경고해줘.

실전에서는 .env.local 파일의 실제 값을 Codex에게 그대로 보여주지 않는 편이 안전합니다. 필요한 경우 변수 이름만 공유하세요.

실제 값은 보지 말고 변수 이름만 기준으로 점검해줘.
.env.local의 값은 읽지 말고, 코드에서 참조하는 환경 변수 이름만 찾아줘.

이 습관은 보안 장에서 다시 다루겠지만, 배포 단계에서도 매우 중요합니다.

Vercel 배포: 먼저 Preview로 올리고 나중에 Production으로 승격하기

Vercel은 Codex와 가장 자연스럽게 연결되는 배포 플랫폼 중 하나입니다. 2026년 3월 Vercel은 Vercel Plugin이 OpenAI Codex와 Codex CLI를 지원한다고 발표했고, 이 플러그인을 통해 플랫폼 스킬, 전문 에이전트, 실시간 코드 검증을 Codex 워크플로 안에서 활용할 수 있게 했습니다.3

Vercel 배포에서 초보자가 꼭 기억해야 할 원칙은 하나입니다.

처음부터 production으로 배포하지 않습니다.

먼저 preview deployment를 만듭니다. 미리보기 URL에서 직접 눌러보고, 로그인해보고, 모바일 화면을 확인한 뒤 문제가 없을 때 production으로 승격합니다. Vercel 배포 스킬도 사용자가 명시적으로 production을 요청하지 않는 한 preview로 배포하는 흐름을 기본으로 둡니다.4

Codex App이나 CLI에서 Vercel 플러그인 또는 스킬을 사용할 수 있다면 이렇게 요청할 수 있습니다.

Vercel preview deployment를 만들어줘.

조건:
- production 배포는 하지 마.
- 먼저 npm run build가 통과하는지 확인해줘.
- 필요한 환경 변수 목록을 알려줘.
- Vercel 프로젝트 설정에서 build command, output directory, install command가 맞는지 확인해줘.
- 배포가 끝나면 preview URL만 알려줘.
- preview URL 검수 체크리스트도 함께 작성해줘.

CLI로 직접 배포한다면 일반적으로 다음 흐름이 됩니다.

vercel deploy -y

production 배포는 명시적으로 다음 명령을 사용할 때만 진행합니다.

vercel deploy --prod -y

초보자에게는 --prod가 생각보다 무거운 버튼입니다. 특히 로그인, 결제, 데이터베이스 쓰기 기능이 있는 앱이라면 preview 환경에서 충분히 확인한 뒤 production으로 넘어가야 합니다.

Vercel 배포 전에 Codex에게 설정 파일도 확인하게 하세요.

Vercel 배포 기준으로 이 저장소를 점검해줘.

다음을 확인해줘.
- Next.js/Vite/React/Astro 등 프레임워크 감지 결과
- vercel.json이 필요한지 여부
- build command
- output directory
- Node.js 버전 고정 필요 여부
- 서버리스 함수 또는 API route가 Vercel에서 정상 동작할지 여부
- preview와 production에 다르게 설정해야 할 환경 변수

만약 앱이 Next.js라면 Vercel은 대부분 자동으로 설정을 감지합니다. 반면 Vite 앱에서 출력 폴더가 dist가 아닌 커스텀 폴더라면 vercel.json 또는 프로젝트 설정에서 명확히 지정해야 할 수 있습니다.

{
  "buildCommand": "npm run build",
  "outputDirectory": "dist"
}

Codex가 이런 파일을 제안하더라도 바로 커밋하지 말고, 실제 플랫폼 설정과 중복되지는 않는지 확인하세요. 플랫폼 UI에서 이미 설정한 값과 저장소 설정 파일의 값이 충돌하면 나중에 헷갈릴 수 있습니다.

Netlify 배포: build command와 publish directory를 정확히 맞추기

Netlify는 정적 프론트엔드 앱, Jamstack 사이트, 간단한 서버리스 함수가 있는 프로젝트에 잘 맞습니다. Netlify에서 가장 자주 틀리는 설정은 publish directory입니다. Vite는 보통 dist, Create React App은 build, 정적 export한 Next.js는 out을 사용합니다.

Netlify용 설정 파일은 보통 netlify.toml입니다.

[build]
  command = "npm run build"
  publish = "dist"

[build.environment]
  NODE_VERSION = "20"

여기서 NODE_VERSION처럼 공개되어도 되는 설정값은 파일에 넣을 수 있습니다. 하지만 API 키, 데이터베이스 URL, OAuth secret 같은 민감한 값은 netlify.toml에 넣지 말고 Netlify 대시보드의 Environment variables에 등록해야 합니다.

Codex에게 Netlify 설정을 부탁할 때는 이렇게 말하세요.

이 프로젝트를 Netlify에 배포할 수 있도록 설정을 점검해줘.

다음을 확인해줘.
- netlify.toml이 필요한지 여부
- build command와 publish directory
- Node.js 버전
- Netlify Functions가 있다면 함수 경로
- 환경 변수 중 Builds scope가 필요한 것과 Functions scope가 필요한 것
- production, deploy-preview, branch-deploy에서 값이 달라야 하는 변수

필요하면 netlify.toml 초안을 제안하되, secrets는 절대 파일에 쓰지 마.

Netlify에서 환경 변수를 추가했는데도 앱이 계속 이전 값을 쓰는 경우가 있습니다. 이때는 새 배포를 트리거해야 합니다. 빌드 시점에 주입되는 값은 배포를 다시 해야 반영되기 때문입니다. Codex에게 로그와 설정을 함께 보게 하면 원인을 빠르게 좁힐 수 있습니다.

Netlify 배포에서 환경 변수가 반영되지 않는 문제를 디버깅해줘.

다음을 기준으로 원인을 분류해줘.
- 변수 이름 오타
- 프레임워크 접두사 누락
- Builds/Functions scope 설정 오류
- deploy context 오류
- 환경 변수 추가 후 재배포하지 않음
- netlify.toml 값이 UI 값을 덮어씀
- 클라이언트에 노출하면 안 되는 secret을 잘못 사용함

Netlify는 deploy preview와 branch deploy 개념이 잘 잡혀 있으므로, GitHub PR과 연결해 두면 기능 브랜치마다 자동으로 미리보기 URL을 받을 수 있습니다. 이 흐름은 Codex가 만든 PR을 실제 URL에서 확인하기에 좋습니다.

Cloudflare Pages와 Workers: 프론트엔드와 엣지 백엔드를 함께 생각하기

Cloudflare는 Pages와 Workers를 함께 사용할 때 강력합니다. 정적 프론트엔드는 Cloudflare Pages에 올리고, API나 엣지 로직은 Workers 또는 Pages Functions로 처리할 수 있습니다. Cloudflare의 Codex 에이전트 설정 문서는 Codex CLI를 프로젝트 루트에서 실행하고, /plugins에서 Cloudflare 플러그인을 설치해 Skills와 MCP 서버를 연결하는 흐름을 안내합니다.5

Cloudflare 배포에서는 먼저 내 앱이 Pages에 맞는지 Workers에 맞는지 구분해야 합니다. Vite, Astro, 정적 React 앱은 Pages로 시작하기 좋습니다. API 서버, 인증 미들웨어, 엣지 캐시, KV, D1, R2 같은 Cloudflare 리소스를 써야 한다면 Workers까지 고려합니다.

Cloudflare Pages의 전형적인 설정은 다음과 같습니다.

프레임워크Build commandOutput directory
Vitenpm run builddist
React CRAnpm run buildbuild
Astronpm run builddist
정적 HTML없음 또는 커스텀.

Codex에게는 이렇게 요청할 수 있습니다.

이 프로젝트를 Cloudflare Pages에 배포할 수 있는지 점검해줘.

다음을 확인해줘.
- Pages로 충분한지, Workers가 필요한지
- build command와 output directory
- wrangler 설정 파일이 필요한지
- Pages Functions 경로가 올바른지
- 환경 변수와 secrets 등록 방법
- Preview branch와 Production branch를 어떻게 나누면 좋은지
- 배포 후 라우팅 새로고침 문제가 생길 가능성

Cloudflare Workers를 쓴다면 wrangler가 중요합니다. 로컬 인증 상태를 확인할 때는 다음 명령을 사용합니다.

npx wrangler whoami

배포는 프로젝트 구조에 따라 달라지지만, Workers 프로젝트에서는 보통 다음 흐름을 사용합니다.

npx wrangler deploy

Cloudflare 쪽에서 많이 만나는 오류는 출력 폴더 문제와 SPA 라우팅 문제입니다. 예를 들어 React Router를 쓰는 앱에서 /dashboard로 직접 접속했을 때 404가 뜬다면, 정적 파일 서버가 해당 경로의 실제 파일을 찾으려 하기 때문입니다. 이 경우 Cloudflare Pages의 리다이렉트 규칙이나 _redirects 파일을 검토해야 합니다.

Cloudflare Pages 배포 후 새로고침하면 404가 발생해.
React Router를 사용하는 SPA인지 확인하고,
필요한 리다이렉트 설정 파일을 제안해줘.
단, 기존 라우팅 구조를 바꾸지 말고 배포 설정만 수정해줘.

Render 배포: 백엔드 서버와 데이터베이스가 있을 때

Render는 Express, Fastify, NestJS, Django, Rails 같은 백엔드 서버를 배포할 때 초보자에게 비교적 이해하기 쉬운 선택지입니다. 정적 사이트도 배포할 수 있지만, 특히 "계속 실행되는 서버"가 필요할 때 자연스럽습니다.

2026년 Render는 Codex Plugin을 소개하며 Codex가 Render 배포, 실패한 배포 디버깅, 서비스 상태 확인을 단계적으로 수행할 수 있다고 설명했습니다. 이 플러그인은 서비스 생성, render.yaml 검증, 배포 로그 읽기, 일반적인 실패 원인 진단 같은 스킬을 포함합니다.6

Express API 서버의 package.json이 다음과 같다고 해봅시다.

{
  "scripts": {
    "dev": "tsx watch src/server.ts",
    "build": "tsc",
    "start": "node dist/server.js"
  }
}

Render에서는 보통 다음 설정이 필요합니다.

항목값
Build Commandnpm install && npm run build
Start Commandnpm start
Node Version프로젝트에 맞게 20 또는 22
Environment VariablesDATABASE_URL, JWT_SECRET, CORS_ORIGIN 등

Codex에게 Render 설정을 부탁하는 프롬프트는 다음과 같습니다.

이 백엔드 프로젝트를 Render Web Service로 배포하려고 해.

다음을 확인해줘.
- build command
- start command
- 서버가 process.env.PORT를 사용하는지
- Node.js 버전
- 필요한 환경 변수
- render.yaml을 사용할지, 대시보드 설정으로 충분한지
- health check endpoint가 있는지
- 배포 후 CORS_ORIGIN에 프론트엔드 도메인을 넣어야 하는지

Render에서 초보자가 자주 놓치는 부분은 PORT입니다. 로컬에서는 3000번 포트를 고정해서 쓰더라도, 배포 플랫폼에서는 플랫폼이 지정한 포트를 사용해야 합니다.

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

Codex에게 다음처럼 점검을 시키면 좋습니다.

이 서버 코드가 Render 같은 호스팅 플랫폼에서 동작할 수 있는지 확인해줘.
특히 PORT를 하드코딩하고 있는지, 0.0.0.0 바인딩이 필요한지,
start script가 빌드 결과물을 실행하는지 점검해줘.

배포 로그를 Codex와 함께 읽는 법

배포가 실패하면 로그가 나옵니다. 초보자에게 로그는 무섭습니다. 영어이고, 길고, 빨간 줄이 많습니다. 하지만 대부분의 배포 실패는 몇 가지 패턴으로 분류됩니다.

로그에서 보이는 증상흔한 원인확인할 것
command not found패키지 매니저 또는 스크립트 불일치package.json, lockfile
Cannot find module의존성 누락dependencies/devDependencies
Missing environment variable환경 변수 미등록플랫폼 env 설정
No such file or directory: distoutput directory 오류빌드 결과 폴더
Unsupported engineNode 버전 차이engines, 플랫폼 Node 설정
Build exceeded memory빌드 메모리 부족의존성, 빌드 최적화
Function not found서버리스 함수 경로 오류API/functions 디렉터리

Codex에게 로그를 줄 때는 전체를 던져도 되지만, 더 좋은 방법은 "분류해서 읽어달라"고 요청하는 것입니다.

아래 배포 로그를 분석해줘.

원인을 다음 범주 중 하나로 분류해줘.
- install 단계 실패
- build command 오류
- output directory 오류
- 환경 변수 누락
- Node.js 버전 차이
- 타입스크립트/린트 오류
- 서버리스 함수 경로 문제
- 런타임 시작 실패

각 원인에 대해:
1. 로그에서 근거가 되는 줄
2. 가장 가능성 높은 원인
3. 수정할 파일 또는 플랫폼 설정
4. 재배포 전에 로컬에서 실행할 명령
을 정리해줘.

로그:
```txt
여기에 배포 로그 붙여넣기

여기서 중요한 점은 Codex가 로그를 보고 바로 코드를 고치게 하지 않는 것입니다. 먼저 원인을 분류하게 한 뒤, 수정 범위를 좁혀야 합니다.

예를 들어 이런 로그가 있다고 해봅시다.

```txt
sh: 1: vite: not found
Error: Command "npm run build" exited with 127

가능한 원인은 vite가 devDependencies에 있는데 배포 환경에서 devDependencies를 설치하지 않았거나, 의존성이 아예 누락된 경우입니다. Codex는 package.json과 플랫폼의 install 설정을 함께 봐야 정확히 판단할 수 있습니다.

또 다른 예입니다.

Error: Cannot find module '/opt/render/project/src/dist/server.js'

이 경우에는 npm run build가 실제로 dist/server.js를 만들지 않았거나, start 명령이 잘못된 파일을 가리키는 것입니다. 이때 Codex에게 tsconfig.json, package.json, 실제 빌드 결과 폴더를 함께 확인하게 하면 해결이 빠릅니다.

데이터베이스가 있는 앱은 배포 순서가 중요하다

프론트엔드만 있는 앱은 빌드해서 올리면 끝나는 경우가 많습니다. 하지만 로그인, CRUD, 결제, 파일 업로드, 관리자 페이지가 있는 앱은 이야기가 달라집니다. 데이터베이스와 백엔드 설정이 함께 움직여야 합니다.

배포 전후에 꼭 확인해야 할 항목은 다음과 같습니다.

항목확인 질문
DATABASE_URLproduction DB 주소가 플랫폼 환경 변수에 등록되어 있는가?
마이그레이션배포 전에 실행할지, 배포 후에 실행할지 정했는가?
API 키서버 전용 secret으로 등록되어 있는가?
OAuth redirect URL실제 배포 URL이 등록되어 있는가?
CORS프론트엔드 production 도메인을 허용하는가?
쿠키 설정HTTPS 환경에서 secure, sameSite가 올바른가?
API base URL프론트엔드가 localhost가 아니라 production API를 호출하는가?

Prisma를 쓰는 앱이라면 마이그레이션 흐름이 특히 중요합니다.

npx prisma migrate deploy

이 명령은 production 환경에서 이미 만들어 둔 migration 파일을 적용할 때 주로 사용합니다. 반대로 prisma migrate dev는 개발용 명령에 가깝습니다. Codex에게 이 차이를 확인하게 하세요.

이 프로젝트의 데이터베이스 배포 절차를 점검해줘.

다음을 확인해줘.
- ORM 또는 DB 클라이언트가 무엇인지
- production에서 실행해야 할 migration 명령
- seed 명령이 production에서 안전한지
- DATABASE_URL이 어디에서 필요한지
- 배포 플랫폼의 build 단계에서 DB 접속이 필요한지
- 배포 후 수동으로 실행해야 하는 명령이 있는지
- 롤백이 필요한 경우 어떤 파일과 테이블이 영향을 받는지

OAuth 로그인이 있는 앱은 redirect URL을 반드시 실제 배포 주소로 바꿔야 합니다. 로컬에서는 다음 주소를 썼을 수 있습니다.

http://localhost:3000/api/auth/callback/google

배포 후에는 이런 주소가 필요합니다.

https://my-saas.vercel.app/api/auth/callback/google

이 설정은 코드만 바꾼다고 해결되지 않습니다. Google Cloud Console, GitHub OAuth App, Supabase Auth, Clerk, Auth0 같은 외부 서비스 대시보드에서도 허용 URL을 추가해야 합니다.

쿠키도 조심해야 합니다. 로컬 HTTP에서는 되던 쿠키가 production HTTPS에서 안 되거나, 반대로 secure 설정이 없어서 브라우저가 막는 일이 생깁니다.

배포 환경에서 인증 쿠키 설정을 점검해줘.

다음을 확인해줘.
- secure 설정이 production에서 true가 되는지
- sameSite 값이 OAuth 흐름에 적합한지
- domain/path 설정이 실제 도메인과 충돌하지 않는지
- 프론트엔드와 백엔드 도메인이 다를 때 credentials 설정이 맞는지
- CORS에서 origin과 credentials가 함께 설정되어 있는지

초보자에게는 이 부분이 가장 어렵지만, Codex에게 체크리스트로 나눠 맡기면 충분히 따라갈 수 있습니다.

실전 예제 1: Vite 할 일 앱을 Netlify에 배포하기

이전에 만든 할 일 관리 앱이 Vite 기반이라고 가정해봅시다. 로컬에서는 다음 명령으로 실행됩니다.

npm run dev

배포 전 Codex에게 먼저 확인시킵니다.

이 Vite 할 일 앱을 Netlify에 배포하려고 해.
package.json과 vite.config 파일을 확인해서
build command와 publish directory를 알려줘.
필요하면 netlify.toml을 만들어줘.

Codex가 확인한 결과가 다음과 같다고 합시다.

Build command: npm run build
Publish directory: dist

그러면 netlify.toml은 이렇게 단순할 수 있습니다.

[build]
  command = "npm run build"
  publish = "dist"

환경 변수가 없는 순수 프론트엔드 앱이라면 여기서 거의 끝입니다. GitHub 저장소를 Netlify에 연결하고, build command와 publish directory를 입력한 뒤 배포하면 됩니다.

배포 후에는 Codex에게 실제 URL 기준으로 검수 목록을 만들게 합니다.

배포된 할 일 앱 URL은 https://example-todo.netlify.app 이야.
사용자 관점에서 검수 체크리스트를 만들어줘.

확인할 기능:
- 첫 화면 로딩
- 할 일 추가
- 완료 체크
- 삭제
- 새로고침 후 데이터 유지 여부
- 모바일 화면
- 존재하지 않는 경로 접근 시 동작

만약 앱이 localStorage를 사용한다면 "새로고침 후 데이터 유지"는 통과해야 하지만, 다른 기기에서는 데이터가 공유되지 않는 것이 정상입니다. 이런 기대 동작까지 README에 적어두면 좋습니다.

실전 예제 2: Next.js 미니 SaaS를 Vercel Preview로 배포하기

이번에는 로그인과 CRUD가 있는 Next.js 미니 SaaS를 생각해봅시다. 이 앱에는 데이터베이스, 인증 secret, 공개 앱 URL이 필요합니다.

.env.example은 대략 이렇게 생겼을 수 있습니다.

DATABASE_URL=
NEXTAUTH_SECRET=
NEXTAUTH_URL=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
NEXT_PUBLIC_APP_URL=

Codex에게 먼저 배포 준비를 맡깁니다.

이 Next.js 미니 SaaS를 Vercel preview로 배포할 준비를 해줘.

다음을 점검해줘.
- npm run build 통과 여부
- Prisma migration 필요 여부
- Vercel에 등록해야 할 환경 변수 목록
- preview와 production에서 다르게 설정해야 할 URL
- OAuth redirect URL 목록
- 쿠키와 CORS 설정
- 배포 후 확인해야 할 핵심 사용자 시나리오

production 배포는 아직 하지 마.

이때 NEXTAUTH_URL이나 NEXT_PUBLIC_APP_URL은 preview URL이 매번 달라질 수 있으므로 주의해야 합니다. 인증 라이브러리나 OAuth 제공자에 따라 preview URL을 모두 허용하기 어렵다면, staging 도메인을 따로 두는 편이 안정적입니다.

배포 후 검수 프롬프트는 이렇게 작성할 수 있습니다.

아래 Vercel preview URL을 기준으로 앱을 검수해줘.

URL: https://my-saas-git-feature-login.vercel.app

사용자 시나리오:
1. 첫 화면이 3초 안에 로딩되는지 확인
2. 회원가입 또는 OAuth 로그인 진입 가능 여부 확인
3. 로그인 후 대시보드 접근 확인
4. 프로젝트 생성, 조회, 수정, 삭제 확인
5. 로그아웃 후 보호 페이지 접근 차단 확인
6. 모바일 375px 폭에서 주요 화면 확인
7. 새로고침했을 때 라우팅 오류가 없는지 확인

결과는 통과/실패/수정 제안 표로 정리해줘.

Codex가 Browser Use나 Playwright MCP와 연결되어 있다면 실제 브라우저 검증까지 맡길 수 있습니다. 그렇지 않더라도 이 체크리스트를 사람이 따라가면 충분히 유용합니다.

실전 예제 3: Express API를 Render에, 프론트엔드를 Vercel에 배포하기

풀스택 앱은 프론트엔드와 백엔드가 따로 배포될 수 있습니다. 예를 들어 프론트엔드는 Vercel, 백엔드 API는 Render에 올리는 구조입니다.

이때 핵심은 URL 연결입니다.

Frontend: https://my-app.vercel.app
Backend: https://my-api.onrender.com

프론트엔드에는 다음 환경 변수가 필요할 수 있습니다.

VITE_API_BASE_URL=https://my-api.onrender.com

백엔드에는 다음 환경 변수가 필요할 수 있습니다.

DATABASE_URL=postgresql://...
JWT_SECRET=...
CORS_ORIGIN=https://my-app.vercel.app

Codex에게 전체 연결을 점검하게 하세요.

프론트엔드는 Vercel, 백엔드는 Render에 배포하는 구조야.
두 프로젝트의 환경 변수와 CORS 설정을 함께 점검해줘.

확인할 것:
- 프론트엔드 API base URL이 localhost를 가리키지 않는지
- 백엔드 CORS_ORIGIN에 Vercel 도메인이 들어가는지
- 쿠키 인증을 쓴다면 credentials 설정이 양쪽에 맞는지
- Render 서버가 process.env.PORT를 사용하는지
- 헬스체크 엔드포인트가 있는지
- 배포 후 로그인과 CRUD 요청이 어느 URL로 가는지

Express 서버의 CORS 설정은 대략 이런 형태가 됩니다.

app.use(cors({
  origin: process.env.CORS_ORIGIN,
  credentials: true,
}));

프론트엔드 요청도 쿠키를 포함해야 한다면 다음처럼 설정해야 합니다.

fetch(`${import.meta.env.VITE_API_BASE_URL}/api/projects`, {
  credentials: 'include',
});

이 두 줄이 서로 맞지 않으면 로그인은 된 것처럼 보이는데 API 요청은 계속 401이 되는 이상한 상황이 생깁니다. 배포 후 인증 문제는 대부분 이런 작은 불일치에서 시작됩니다.

README는 배포 가능한 앱의 사용 설명서다

앱을 배포했다면 README도 함께 정리해야 합니다. README는 남에게 보여주기 위한 문서이기도 하지만, 한 달 뒤의 나를 구해주는 구조대이기도 합니다.

Codex에게 README 정리를 맡길 때는 다음 항목을 포함시키세요.

README를 배포 가능한 프로젝트 기준으로 업데이트해줘.

포함할 내용:
- 프로젝트 소개
- 기술 스택
- 로컬 설치 방법
- 개발 서버 실행 명령
- 테스트/린트/타입체크/빌드 명령
- 필요한 환경 변수와 .env.example 설명
- 배포 플랫폼과 배포 명령
- 데이터베이스 migration 방법
- 주요 기능 수동 테스트 시나리오
- 라이선스
- 알려진 제한 사항

README에 실제 secret 값을 넣으면 안 됩니다. 대신 다음처럼 설명합니다.

## Environment Variables

Create `.env.local` based on `.env.example`.

| Name | Required | Description |
| --- | --- | --- |
| DATABASE_URL | Yes | PostgreSQL connection string |
| NEXTAUTH_SECRET | Yes | Secret used by auth session signing |
| NEXT_PUBLIC_APP_URL | Yes | Public application URL |

초보자 프로젝트라도 라이선스는 적어두는 편이 좋습니다. 공개 저장소라면 다른 사람이 이 코드를 사용해도 되는지 명확해야 합니다. 개인 학습용이면 "학습용 프로젝트"라고 밝혀도 좋고, 오픈소스로 공유하려면 MIT 같은 라이선스를 선택할 수 있습니다.

배포 후 사용자 관점 검수 프롬프트

배포가 성공했다고 끝난 것이 아닙니다. 배포 플랫폼은 "빌드가 성공했다"고 말해줄 뿐, 사용자가 앱을 편하게 쓸 수 있는지는 말해주지 않습니다. 그래서 실제 URL 기준 검수가 필요합니다.

아래 프롬프트는 거의 모든 앱에 사용할 수 있는 배포 후 검수 템플릿입니다.

다음 배포 URL을 사용자 관점에서 검수해줘.

URL: https://your-app.example.com

검수 범위:
- 첫 화면 로딩
- 주요 내비게이션
- 회원가입/로그인/로그아웃
- 주요 CRUD 기능
- 검색, 필터, 정렬 같은 핵심 상호작용
- 파일 업로드 또는 결제 기능이 있다면 해당 흐름
- 모바일 반응형 화면
- 404 페이지
- 500 오류 상황 처리
- 새로고침 시 라우팅 문제
- 브라우저 콘솔 오류
- 네트워크 요청 실패

출력 형식:
| 구분 | 결과 | 재현 방법 | 심각도 | 수정 제안 |

심각도는 Blocker, High, Medium, Low로 나눠줘.

이 프롬프트의 핵심은 "수정 이슈 목록"을 얻는 것입니다. 배포 직후 모든 것을 완벽하게 고치려고 하면 지칩니다. 먼저 치명도별로 나누세요.

Blocker는 앱 사용을 막는 문제입니다. 로그인 불가, 첫 화면 흰 화면, 결제 실패, 데이터 저장 불가가 여기에 들어갑니다. High는 주요 기능은 되지만 신뢰를 떨어뜨리는 문제입니다. 모바일에서 버튼이 가려지거나, 에러 메시지가 이상하거나, 특정 CRUD만 실패하는 경우입니다. Medium과 Low는 이후 개선할 수 있는 문제입니다.

Codex에게 바로 수정까지 맡기고 싶다면 한 번에 모든 이슈를 주지 말고, Blocker부터 하나씩 맡기세요.

배포 후 검수에서 발견된 Blocker 이슈만 먼저 수정해줘.

수정 범위:
- 로그인 후 대시보드가 500 오류를 내는 문제

조건:
- 관련 파일만 수정
- 원인을 먼저 설명
- 수정 후 npm run build 실행
- 재발 방지를 위한 테스트가 가능하면 추가
- 다른 Medium/Low 이슈는 건드리지 말 것

이렇게 해야 Codex가 작은 성공을 반복하면서 앱을 안정화할 수 있습니다.

production 배포 버튼을 누르기 전 마지막 체크리스트

Preview에서 충분히 확인했다면 이제 production 배포를 생각할 수 있습니다. 하지만 마지막으로 한 번 더 멈춰야 합니다. production은 사용자에게 보이는 공간입니다. 실험실이 아닙니다.

아래 체크리스트를 Codex에게 그대로 검토하게 하세요.

production 배포 전 최종 체크리스트를 점검해줘.

확인 항목:
- main 브랜치가 최신인지
- 작업 중인 변경 사항이 남아 있지 않은지
- npm run build가 통과하는지
- 테스트/린트/타입체크가 가능한 범위에서 통과하는지
- production 환경 변수가 모두 등록되어 있는지
- preview용 API 키가 production에 들어가지 않았는지
- DATABASE_URL이 production DB를 가리키는지
- migration 실행 순서가 정리되어 있는지
- OAuth redirect URL에 production 도메인이 등록되어 있는지
- CORS 허용 도메인이 production 프론트엔드와 일치하는지
- 쿠키 secure/sameSite 설정이 production에 맞는지
- README와 .env.example이 최신인지
- 배포 후 롤백 방법을 알고 있는지

문제가 있으면 production 배포를 보류해야 하는 항목과
배포 후 수정해도 되는 항목을 나눠줘.

이 체크리스트를 통과하면 production 배포를 진행합니다.

Vercel이라면 다음 명령이 될 수 있습니다.

vercel deploy --prod -y

Netlify라면 GitHub의 production branch에 merge하거나, 대시보드에서 production deploy를 트리거할 수 있습니다. Cloudflare Pages도 production branch에 merge하면 production 배포가 실행되도록 설정할 수 있습니다. Render는 main branch push 또는 수동 deploy로 production 서비스를 갱신할 수 있습니다.

중요한 것은 명령 자체가 아닙니다. 어떤 브랜치가 production으로 연결되어 있는지, 어떤 환경 변수가 production에 들어가는지, 실패했을 때 어떻게 되돌릴지 알고 있어야 합니다.

배포는 끝이 아니라 운영의 시작이다

이 장에서 우리는 Codex가 만든 앱을 실제 URL로 배포하는 흐름을 배웠습니다. 처음에는 복잡해 보였지만, 구조는 단순합니다. 먼저 저장소를 점검하고, 플랫폼별 설정을 비교하고, 환경 변수를 분리하고, preview로 배포한 뒤, 실제 URL에서 검수하고, 마지막에 production으로 승격합니다.

Codex는 이 과정에서 손발이 되어줍니다. 빌드 로그를 읽고, 설정 파일을 제안하고, 환경 변수 목록을 추출하고, README를 정리하고, 검수 체크리스트를 만들어줍니다. 하지만 최종 판단은 여전히 사람의 몫입니다. 특히 production 배포, secret 등록, 데이터베이스 migration, OAuth 설정, 결제 기능은 반드시 사람이 확인해야 합니다.

앱 만들기의 완성은 "내 컴퓨터에서 된다"가 아닙니다.

"다른 사람이 실제 URL로 접속해서 쓸 수 있다"입니다.

이제 여러분의 앱은 로컬 폴더 안에 갇힌 실습물이 아니라, 세상 밖으로 나온 서비스가 될 준비를 마쳤습니다. 다음 장에서는 이렇게 세상 밖으로 나온 앱을 더 안전하게 만들기 위해 보안, 개인정보, 저작권을 점검합니다. 배포가 문을 여는 일이라면, 보안 검토는 그 문에 자물쇠와 안내문을 다는 일입니다.

참고

1Deploy an app or website | Codex use cases

2Build environment variables | Netlify Docs

3Vercel plugin now supported on OpenAI Codex and Codex CLI

4Vercel Deploy Skill

5Codex + Cloudflare · Agent setup docs

6Ship directly from Codex with the Render Plugin

책 목록

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

전체 목차 보기

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

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

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

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

참여하기