콘텐츠로 이동
Study Note웹 개발 일반

12. 배포 — 코드가 서비스가 되기까지

“어디에 올리지?”는 사실 “내 앱은 언제 실행되는가?”라는 질문이다

이 장에서 처음 나오는 말4개
serverlessServerless
서버 인스턴스를 직접 운영하지 않고 플랫폼이 실행 환경과 확장을 관리하는 모델. 요청 단위 함수뿐 아니라 상태형 제품도 있다.
콜드 스타트Cold Start
유휴 실행 환경을 새로 준비할 때 생길 수 있는 첫 요청 지연. 정도와 발생 조건은 플랫폼마다 다르다.
PaaSPlatform as a Service
"코드를 주면 돌려 준다" 수준의 추상화 (Railway, Fly.io). VM부터 직접 만지는 IaaS(AWS EC2)와의 구분이다.
프리뷰 배포Preview Deployment
PR마다 고유 URL로 자동 배포되는 임시 환경. "머지 전에 실물을 보고" 리뷰하게 만든다.

빌드 결과물(6장의 dist/)이 무엇이냐에 따라 올릴 곳의 형태가 갈린다. 축은 하나 — 내 코드는 언제 실행되는가.

형태실행 시점무엇을 올리나대표 서비스비용 구조
정적 호스팅실행 없음 — 빌드 때 끝HTML/JS/CSS 파일Cloudflare Pages, GitHub Pages거의 무료
serverless 함수요청마다 깨어남함수 코드Vercel, Netlify호출량 과금
컨테이너 / 상시 서버항상 떠 있음Docker 이미지 등Railway, Fly.io시간 과금
IaaS항상 (전부 내 몫)VM부터 직접AWS EC2시간 과금 + 인건비
서버 코드가 없으면 정적 호스팅, 있으면 함수 플랫폼의 한계를 넘는지 보고 넘지 않으면 serverless, 넘으면 인프라를 직접 다루고 싶은지에 따라 PaaS 컨테이너와 IaaS로 갈리는 배포 선택 흐름

한 서비스가 여러 형태를 섞는 게 보통이다 — Next.js를 Vercel에 올리면 정적 자산과 함수로 나뉠 수 있다. 함수의 실행·연결·상태 모델에 맞지 않는 작업만 컨테이너나 상태형 serverless 제품 등 다른 실행 환경으로 분리한다.

git 연결형 배포 — 흔한 워크플로

섹션 제목: “git 연결형 배포 — 흔한 워크플로”

Vercel·Netlify·Cloudflare가 표준으로 만든 흐름이다.

  1. GitHub 저장소를 서비스에 연결한다 — 설정은 처음 한 번

  2. 브랜치를 푸시하고 PR을 열면 프리뷰 배포가 자동으로 생긴다 — 고유 URL에서 실물로 리뷰한다

  3. main에 머지하면 프로덕션 배포가 자동으로 나간다

  4. 문제가 생기면 롤백 — 이전 불변 배포를 보존하는 플랫폼이라면 빠르게 되돌린다

CI(8장)와 잇대면 완성이다 — 검사를 통과해야 머지되고, 머지되면 배포된다. 사람 손이 개입하는 지점이 코드 리뷰뿐인 상태가 목표다.

환경 변수 — 코드에 넣지 않는 것들

섹션 제목: “환경 변수 — 코드에 넣지 않는 것들”

DB 접속 정보, API 키처럼 환경마다 다르거나 비밀인 값은 코드가 아니라 환경 변수로 주입한다.

  • 로컬 비밀은 .env.local 같은 gitignored 파일에 둔다. .env.example에는 키 이름과 빈 값만 커밋한다
  • 배포 환경은 호스팅 서비스의 설정 화면에서 넣는다 — 프리뷰/프로덕션을 다르게 줄 수 있다
  • 접두사 규칙을 조심한다 — NEXT_PUBLIC_(Next.js)이나 VITE_(Vite)가 붙은 변수는 브라우저 번들에 박제된다. 비밀 키에 이 접두사를 붙이는 순간 공개다

같은 Next.js Docker image를 DEV와 PRD에 승격하면서 공개값만 다르게 주입해야 한다면 Next.js 런타임 설정 실전처럼 서버 런타임 설정을 브라우저에 명시적으로 전달한다.

1장의 DNS가 여기서 실전이 된다 — “커스텀 도메인 연결”이란 결국 내 도메인의 DNS 레코드가 호스팅 서비스를 가리키게 하는 것이다.

  • 도메인 등록기관에서 도메인을 사고, 호스팅 서비스가 알려 주는 레코드(A 또는 CNAME)를 넣는다
  • HTTPS 인증서는 요즘 호스팅 서비스가 자동 발급·갱신한다(Let’s Encrypt). 직접 만질 일이 없어진 대표적인 영역이다

DB·소셜 로그인·호스팅·외부 DNS를 함께 쓰면 도메인 하나도 여러 설정의 기준점이 된다. 예를 들어 Google이 Supabase로 돌려보내는 callback, Supabase가 앱으로 돌려보내는 callback, 앱이 OG와 sitemap에 쓰는 canonical URL은 서로 다른 설정이다. 도메인을 붙인 뒤 하나라도 예전 주소에 남으면 “페이지는 열리는데 로그인이나 공유만 실패”한다.

모니터링 — 배포가 끝이 아니다

섹션 제목: “모니터링 — 배포가 끝이 아니다”

깊게는 안 들어가고, 세 겹의 이름만 —

겹질문대표 도구
에러 추적사용자가 겪은 에러가 뭐였나Sentry
실사용 성능실제 사용자의 Core Web Vitals는Vercel Analytics 같은 RUM 도구
실험실 성능통제된 환경에서 무엇이 느린가Lighthouse
로그서버에서 무슨 일이 있었나호스팅 내장 로그

최소한 에러 추적 하나는 붙이고 시작한다 — 없으면 사용자가 겪는 에러를 서비스 주인만 모른다.

  • 형태의 축은 “내 코드는 언제 실행되는가” — 실행 없음(정적) / 요청 시(serverless) / 상시(컨테이너)
  • 한 서비스가 형태를 섞는다 — 정적 자산·함수·상태형 실행 환경을 요구에 맞게 조합한다
  • serverless의 작은 글씨는 제품마다 다르다 — 실행·연결·상태·커넥션 제한을 확인한다
  • 흔한 워크플로는 git 연결형 배포 — 프리뷰로 리뷰하고, 불변 배포로 빠르게 롤백한다
  • 비밀은 환경 변수로 — 단, NEXT_PUBLIC_/VITE_ 접두사는 공개 선언이다
  • 에러 추적 없이 배포하지 않는다