5장. 배포와 운영

학습 목표

  • 미리보기 배포와 프로덕션 배포가 만들어지는 조건과 쓰임을 설명한다.
  • 환경별로 환경 변수를 설정하고, 변경이 언제 반영되는지 안다.
  • 배포 전 점검과 배포 직후 확인을 내 앱에 맞게 만들어 쓴다.
  • 장애가 나면 로그로 시점과 위치를 좁히고, 직전 정상 버전으로 먼저 복구한다.
  • 롤백 뒤에 달라지는 점과, 롤백으로 되돌아가지 않는 것(데이터, 설정)을 구분한다.

들어가며

금요일 저녁 7시, 혼자 운영하는 예약 앱에 새 기능을 배포한 개발자가 10분 뒤 "로그인이 안 돼요"라는 메시지를 받습니다. 이때 할 수 있는 일은 두 가지입니다. 원인을 찾을 때까지 운영 화면을 붙잡고 고치거나, 1분 안에 어제의 정상 버전으로 되돌린 뒤 차분히 원인을 찾거나. 앞의 길은 사용자가 장애를 겪는 시간을 늘리고, 급하게 고친 코드가 두 번째 장애를 부르기도 합니다.

배포는 운영의 시작입니다. 내놓는 순간부터 실제 사용자, 데이터, 비용이 얽히므로 세 가지 준비가 따라야 합니다. 내놓기 전에 사용자와 같은 조건에서 확인하는 방법, 문제가 생겼을 때 알아차리는 방법, 그리고 되돌아갈 방법입니다.

이 장은 개인 개발자가 많이 쓰는 Vercel을 예로 들어 이 세 가지를 다룹니다. 미리보기와 프로덕션의 차이, 환경 변수, 배포 전후 점검, 로그와 모니터링, 롤백과 장애 대응을 차례로 보고, 깊이 읽기에서는 데이터 변경, 점진적 배포, 무료 플랜의 운영 제약을 살핍니다. 플랫폼이 달라도 원리는 같습니다.

핵심 개념

배포가 하는 일

배포(deployment)는 내 컴퓨터에서 돌던 앱을 인터넷에 올려 누구나 쓰게 하는 일입니다. 손님을 받는 진짜 가게가 프로덕션(production, 운영 환경)이고, 개업 전에 지인만 불러 둘러보게 하는 리허설 무대가 미리보기(preview)입니다. 리허설에서 문제를 찾으면 손님은 그 문제를 겪지 않습니다.

Vercel 문서는 배포를 '프로젝트를 성공적으로 빌드한 결과'로 정의하고, 배포할 때마다 고유한 URL이 생긴다고 설명합니다. 배포는 Git 푸시, CLI, 배포 훅, REST API로 만들 수 있습니다. 중요한 성질은 배포 하나하나가 따로 보관된다는 점입니다. 새 배포를 만들어도 이전 배포는 보존 정책에 따라 지워지기 전까지 그대로 남아 있고, 도메인이 어느 배포를 가리킬지만 바뀝니다. 롤백이 빠를 수 있는 이유가 여기에 있습니다.

미리보기와 프로덕션

Vercel 문서로 확인한 기본 동작은 다음과 같습니다.

상황 결과
프로덕션 브랜치(보통 main)가 아닌 브랜치에 푸시 미리보기 배포
풀 리퀘스트 생성 미리보기 배포
CLI에서 vercel (--prod 없이) 미리보기 배포
프로덕션 브랜치에 푸시·병합, 또는 vercel --prod 프로덕션 배포
새 프로젝트의 첫 배포 어느 브랜치에서 하든, --prod가 없어도 항상 프로덕션 배포

첫 배포 규칙은 의외의 결과를 낳습니다. 기능 브랜치에서 처음 연결해 배포해도 그 배포가 프로덕션이 됩니다. 새 프로젝트가 곧바로 프로덕션 도메인을 받을 수 있게 하려는 설계입니다.

미리보기 URL은 두 종류입니다. 브랜치 URL은 그 브랜치의 최신 배포를 계속 가리키고, 커밋 URL은 특정 커밋의 배포를 고정해서 가리킵니다. "늘 최신 작업"을 보여 줄 때는 브랜치 URL을, 특정 시점을 비교하거나 기록할 때는 커밋 URL을 씁니다. Pro와 Enterprise 플랜에서는 staging 같은 사용자 지정 환경을 따로 만들 수도 있습니다.

미리보기를 공유할 때

미리보기는 리허설 무대지만 인터넷에 열려 있는 무대입니다. URL을 아는 사람이 들어올 수 있다면, 미리보기에 보이는 데이터와 기능이 그대로 노출됩니다. Vercel의 Deployment Protection은 누가 배포 URL에 접근할지 정합니다. 문서에 따르면 권장 범위인 Standard Protection은 프로덕션 도메인을 뺀 모든 배포를 보호하고 모든 플랜에서 쓸 수 있습니다. 보호 방법 중 Vercel Authentication은 적절한 권한이 있는 Vercel 사용자만 들어오게 하고, 비밀번호 보호는 Hobby 플랜에서는 쓸 수 없습니다.

미리보기에서 지켜야 할 원칙은 세 가지입니다.

  1. 미리보기에는 테스트용 키와 테스트 데이터베이스를 쓴다. 실제 결제나 실제 메일이 나가지 않게 한다.
  2. 외부 사람에게 보여 줄 때는 보호를 끄는 대신, 플랫폼이 제공하는 접근 방법을 쓴다.
  3. 미리보기 화면에 실제 개인정보가 보이지 않는지 공유 전에 확인한다.

환경마다 다른 환경 변수

Vercel은 환경 변수를 Production, Preview, Development(로컬), 그리고 사용자 지정 환경마다 따로 둡니다. 같은 이름의 변수라도 환경마다 다른 값을 줄 수 있어, 미리보기에는 테스트 결제 키를, 운영에는 실제 결제 키를 넣는 식으로 씁니다. Preview 변수는 특정 브랜치에만 다른 값을 줄 수도 있고, 브랜치별 값이 같은 이름의 일반 Preview 값을 덮습니다. 로컬 개발용 값은 vercel env pull로 내려받되, 받은 env 파일이 .gitignore에 들어 있는지 먼저 확인합니다. 변수마다 Config(권한 있는 구성원이 읽을 수 있음)와 Secret(저장 뒤에는 쓰기만 가능) 유형을 고를 수도 있습니다.

주의

Vercel 문서에 따르면 환경 변수 변경은 이전 배포에 적용되지 않고 새 배포에만 반영됩니다. 변수를 고친 뒤에는 반드시 다시 배포해야 합니다. "값을 바꿨는데 왜 그대로지?"의 가장 흔한 원인입니다. 4장의 공개 접두사 변수처럼 빌드 때 코드에 박히는 값은 특히 새로 빌드해야만 바뀝니다.

새 기능이 새 환경 변수를 쓴다면, 그 변수가 모든 필요한 환경에 들어 있는지 확인합니다. Preview에만 넣고 Production을 잊으면 미리보기에서는 되던 기능이 운영에서 실패하고, 반대로 하면 미리보기에서 실패합니다.

개발 서버와 빌드는 다르다

개발 서버(npm run dev)에서 잘 돌던 앱이 배포에서 실패하는 일은 흔합니다. 배포는 개발 서버가 아니라 빌드(npm run build)를 거치고, 빌드 단계에서만 드러나는 오류가 있기 때문입니다. 타입 오류로 빌드가 멈추거나, 빌드 중에 미리 그리는 페이지가 아직 없는 데이터를 읽거나, 빌드 때 필요한 환경 변수가 빠진 경우입니다. 배포 전에는 로컬에서도 빌드 명령을 한 번 돌립니다.

Vercel에서 빌드 로그는 배포 화면에서, 런타임 로그(앱이 실행되며 남기는 기록)는 Logs 화면에서 봅니다. 빌드는 성공했는데 특정 기능만 500을 낸다면 런타임 로그를 봅니다.

배포 전 점검

점검 질문
검사 테스트, 타입 검사, 빌드가 모두 통과했는가
미리보기 미리보기 URL에서 핵심 흐름(가입, 결제, 저장)을 직접 해 봤는가
환경 변수 새로 쓰는 변수가 Production에도 들어 있는가
데이터 데이터베이스 구조를 바꿨다면 이전 코드와도 호환되는가
외부 연동 결제·메일·웹훅이 운영 주소와 운영 키를 가리키는가
복구 문제가 생기면 돌아갈 직전 정상 배포가 무엇인지 아는가

점검표에는 체크 표시만이 아니라 확인한 것과 확인하지 못한 것을 함께 적습니다(2장).

배포 직후 확인

배포가 성공했다는 표시는 빌드가 끝났다는 뜻일 뿐, 사용자가 쓸 수 있다는 뜻은 아닙니다. 배포 직후 몇 분 안에 핵심 흐름을 빠르게 확인하는 것을 스모크 테스트(smoke test)라 합니다. 새 기계를 켰을 때 연기부터 나지 않는지 보는 데서 온 말입니다. 운영 주소로 접속하고, 로그인하고, 핵심 기능을 한 번 실행하고, 저장 결과를 새로고침해 확인하고, 콘솔과 런타임 로그에 새 오류가 없는지 봅니다.

운영 설정으로 만든 배포를 사용자 앞에 내놓기 전에 확인하고 싶다면 Vercel의 단계적 프로덕션 배포를 씁니다. 문서에 따르면 Environments 설정의 Production에서 Branch Tracking을 열고 Auto-assign Custom Production Domains를 끄면, 프로덕션 브랜치의 배포가 만들어져도 프로덕션 도메인에 바로 연결되지 않고 수동 승격을 기다립니다. 생성된 배포 URL에서 확인한 뒤 승격(promote)하면 다시 빌드하지 않고 도메인만 그 배포로 옮겨집니다. 다만 이 배포는 운영 환경 변수를 쓰므로 운영 서비스와 데이터에 실제로 닿는다는 점을 기억합니다.

로그와 모니터링

로그는 앱이 실행되며 남기는 기록이고, 모니터링은 오류율이나 응답 시간 같은 지표를 꾸준히 지켜보는 일입니다. 둘은 역할이 다릅니다. 모니터링은 "뭔가 잘못됐다"를 알려 주고, 로그는 "무엇이 어디서 잘못됐는가"를 알려 줍니다.

Vercel 런타임 로그에는 함수 호출 기록과 console.log 출력이 요청 단위로 묶여 나옵니다. 문서에 따르면 상태 코드 400번대 요청은 경고, 500번대 요청은 오류로 표시되고, 경로, 상태 코드, 환경, 브랜치, 배포 등으로 걸러 볼 수 있습니다. CLI의 vercel logs는 기본적으로 최근 30분의 최신 100개 항목을 보여 주므로, 더 이전을 보려면 --since로 범위를 넓히고, 특정 배포만 보려면 --deployment로 지정합니다.

장애가 나면 추측으로 고치기 전에 로그에서 세 가지를 확인합니다. 언제부터, 어떤 요청에서, 어떤 오류가 났는가. 오류가 늘어난 시각이 배포 시각과 겹치면 그 배포가 가장 유력한 원인입니다.

로그에는 보관 기간이 있어 늦게 보면 사라져 있을 수 있습니다. 그래서 핵심 주소를 주기적으로 확인하는 외부 점검, 오류율이 오르면 오는 알림, 오래 남길 기록을 보낼 외부 저장소를 둡니다. 알림이 왔을 때 누가 무엇을 할지까지 정해야 모니터링이 완성됩니다.

롤백: 직전 정상 버전으로 돌아가기

롤백(rollback)은 문제가 생긴 배포 대신 이전의 정상 배포로 되돌리는 일입니다. Vercel의 Instant Rollback은 다시 빌드하지 않고 도메인을 이전 프로덕션 배포로 즉시 돌립니다. 공식 문서로 확인한 주의점은 다음과 같습니다.

  • 롤백한 배포는 당시의 설정으로 돌아간다. 프로젝트 설정에서 바꾼 환경 변수는 반영되지 않고, 크론 작업 정의도 그 배포의 것으로 돌아간다.
  • 롤백 뒤에는 프로덕션 도메인 자동 연결이 꺼진다. 프로덕션 브랜치에 새 커밋이 들어와도 운영 도메인은 롤백한 배포에 머문다. 평소 흐름으로 돌아오려면 대시보드의 Undo Rollback이나 vercel promote로 다른 배포를 승격한다.
  • Hobby 플랜은 바로 이전 배포로만, Pro와 Enterprise는 프로덕션 도메인에 연결된 적 있는 배포 어디로든 롤백할 수 있다. 프로덕션에 연결된 적 없는 미리보기 배포는 대상이 아니다.
  • 롤백 확인 단계는 외부 API와 데이터베이스의 동작 변화를 상기시킨다. 롤백은 코드를 되돌릴 뿐 데이터를 되돌리지 않는다.

롤백은 플랫폼의 배포를 되돌릴 뿐 Git 기록은 그대로입니다. 문제 커밋은 여전히 main에 남아 있으므로, 다음 배포가 같은 문제를 다시 내놓지 않도록 수정 커밋을 올리거나 문제 커밋을 revert합니다(3장).

장애 대응 순서

장애가 났을 때의 순서는 응급실의 순서와 같습니다. 원인을 밝히기 전에 출혈부터 막습니다.

  1. 영향을 확인한다. 어떤 기능이, 언제부터, 얼마나 많은 사용자에게 실패하는가.
  2. 복구한다. 최근 배포가 유력한 원인이고 데이터 구조 변경이 없었다면, 직전 정상 배포로 롤백한다.
  3. 원인을 찾는다. 런타임 로그와 diff로 원인을 좁힌다. 운영 화면이 아니라 브랜치에서 일한다.
  4. 수정하고 검증한다. 수정을 미리보기에서 확인한다.
  5. 정상 흐름으로 돌아온다. 수정한 배포를 승격해 자동 연결을 되살리고, 스모크 테스트를 한다.
  6. 기록한다. 무엇이 왜 일어났고 무엇을 바꿔 재발을 막을지 적는다. 점검표에 한 줄을 더하는 것도 좋은 결과다.

깊이 읽기

코드는 돌아가도 데이터는 돌아가지 않는다

롤백이 마법처럼 느껴지는 것은 코드에 대해서뿐입니다. 새 배포가 데이터베이스의 열 이름을 바꾸거나 열을 지웠다면, 롤백한 옛 코드는 사라진 열을 찾다가 실패합니다. 새 코드가 새 형식으로 써 넣은 데이터를 옛 코드가 읽지 못할 수도 있습니다. 시계를 되돌려도 그사이 쌓인 택배는 그대로 있는 것과 같습니다.

그래서 데이터 구조 변경은 어느 시점에 롤백해도 앱이 깨지지 않게 여러 번의 배포로 나눕니다. 흔히 확장–축소(expand–contract) 방식이라 부릅니다.

  1. 확장: 새 열을 추가한다. 옛 열은 그대로 둔다.
  2. 양쪽 쓰기: 새 코드가 옛 열과 새 열에 모두 쓰고, 읽기는 새 열을 우선하되 없으면 옛 열을 읽는다.
  3. 옮기기: 기존 데이터를 새 열로 복사한다.
  4. 전환: 새 열만 읽고 쓰는 코드로 바꾼다.
  5. 축소: 옛 열을 아무 코드도 쓰지 않는 것을 확인한 뒤 지운다.

각 단계는 직전 단계의 코드와 함께 돌아갈 수 있으므로, 어느 배포에서 롤백해도 데이터와 코드가 맞습니다. 지우는 작업은 맨 마지막에, 되돌릴 필요가 없다는 확신이 선 뒤에 합니다. 데이터를 지우거나 덮어쓰는 배포 앞에는 백업과 복원 확인이 따로 있어야 합니다. 미리보기와 운영이 같은 데이터베이스를 쓴다면, 빌드 단계에서 마이그레이션을 돌리는 설정은 미리보기 빌드만으로 운영 데이터를 바꿀 수 있으니 피합니다.

조금씩 내보내기

모든 사용자에게 한꺼번에 새 버전을 내놓지 않는 방법도 있습니다.

기능 플래그(feature flag)는 코드에는 기능을 넣되, 켜고 끄는 스위치로 사용자에게 보일지를 정하는 방법입니다. 미완성 기능도 꺼 둔 채로 main에 자주 합칠 수 있어 긴 기능 브랜치의 병합 충돌을 줄이고, 문제가 생기면 배포 없이 스위치만 끕니다.

기능 하나가 아니라 앱 전체가 함께 바뀌는 배포는 사용자를 나눠 내보냅니다. Vercel의 Rolling Releases(Pro와 Enterprise)는 새 배포를 처음에는 방문자의 일부(예: 10%)에게만 보내고 나머지는 이전 배포에 남겨 두며, 두 배포의 지표를 나란히 비교하게 해 줍니다. 단계를 높여 100%까지 승격하거나, 문제가 보이면 Instant Rollback으로 되돌립니다.

배포가 바뀌는 순간에는 버전 어긋남(version skew)도 생깁니다. 사용자의 브라우저는 옛 버전의 화면 코드를 들고 있는데 서버는 새 버전인 상태입니다. Vercel 문서는 이것을 클라이언트와 서버가 서로 다른 버전으로 돌아 오류가 나는 현상이라 설명하고, Skew Protection(Pro와 Enterprise)이 같은 배포의 클라이언트와 서버끼리 통신하게 해 준다고 안내합니다. 이 고정은 프레임워크가 관리하는 요청(정적 파일, 화면 전환, Server Actions 등)에 적용되고, 직접 쓴 fetch() 요청에는 배포 ID를 따로 붙여야 합니다. 이 플랜에서 2024년 11월 19일 이후 지원 프레임워크로 만든 프로젝트는 기본으로 켜져 있고, Rolling Releases를 쓸 때는 함께 켜라고 권합니다.

작은 앱의 운영 제약

무료 플랜으로 시작하는 앱은 운영 도구에도 제약이 있습니다. 제약을 모르면 장애가 난 뒤에야 알게 됩니다. 확인 당시 Vercel 문서 기준으로 대표적인 것은 다음과 같습니다.

항목 Hobby Pro
런타임 로그 보관 1시간 1일(Observability Plus로 30일)
Instant Rollback 범위 바로 이전 배포 프로덕션에 연결된 적 있는 배포
크론 작업 최소 간격 하루 한 번 1분
크론 실행 시각의 정밀도 지정한 시의 59분 안 어딘가 분 단위

보관 기간이 짧은 플랜일수록 알림과 외부 기록이 중요해지고, Hobby의 크론은 정해 둔 시의 59분 안 어딘가에 돌므로 정확한 시각이 필요한 일에는 맞지 않습니다. 수치는 바뀔 수 있으니 외우기보다, 플랜을 고를 때 내 앱의 운영 요구와 제약을 공식 문서로 맞춰 봅니다.

실무 장면

별빛 천문대: 도메인을 붙이기 전에

관측 체험을 예약받는 '별빛 천문대'의 운영자 지수는 예약금 결제 기능을 처음 붙이며 출시일을 정했다. 미리보기에서는 테스트 결제가 잘 됐고, 테스트와 빌드도 통과했다. 지수는 그대로 main에 병합하려다 멈췄다. 미리보기는 테스트 키로 돌았지만 운영은 처음 쓰는 실제 결제 키와 실제 문자 발송 키로 돈다. 그 조합은 아직 아무도 확인하지 않았다.

지수가 따진 선택지는 세 가지였다.

  • 바로 병합: 미리보기가 통과했으니 운영도 될 것이라는 기대다. 하지만 환경 변수와 외부 연동이 환경마다 다르다. 첫 실제 손님이 시험 대상이 된다. 기각했다.
  • 운영 도메인에서 시험하고 문제가 있으면 롤백: 확인은 되지만, 시험하는 동안 손님도 같은 화면을 쓴다. 기각했다.
  • 단계적 프로덕션 배포: 운영 설정으로 배포하되 도메인 연결은 미룬다. 이것을 골랐다.

지수는 Production 환경의 Branch Tracking에서 Auto-assign Custom Production Domains를 끄고 main에 병합했다. 프로덕션 배포가 만들어졌지만 운영 도메인은 여전히 이전 배포를 가리켰다. 생성된 배포 URL에서 소액 실결제로 예약해 보니, 결제와 예약은 되는데 손님에게 가야 할 예약 확정 문자가 오지 않았다. 런타임 로그에는 문자 발송 단계에서 API 키가 없다는 오류가 찍혀 있었다. SMS_API_KEY를 Preview 환경에만 넣어 둔 것이다.

지수는 Production에 값을 넣고, 변경은 새 배포에만 반영된다는 점을 떠올려 다시 배포했다. 새 배포 URL에서 결제, 예약, 확정 문자까지 본 뒤 그 배포를 승격했다. 다시 빌드하지 않고 도메인만 옮겨졌다. 마지막으로 시험 결제를 환불하고, 자동 연결을 다시 켰다. 점검표의 환경 변수 줄은 "새 변수가 Production에 있는가"에서 "새 변수가 쓰이는 모든 환경에 있는가, 운영 배포 URL에서 확인했는가"로 바뀌었다.

물결 수영장: 토요일 아침의 500

강습 신청 앱을 운영하는 '물결 수영장'의 개발자 현우는 토요일 오전 9시에 '대기 신청' 기능을 배포했다. 9시 12분, 알림이 왔다. /api/lessons 경로의 500 오류가 평소의 수십 배로 늘었다.

현우는 먼저 영향을 확인했다. 런타임 로그를 상태 코드 500과 해당 경로로 거르자 9시 2분부터 같은 오류가 반복되고 있었다. 배포 시각과 겹쳤다. 강습 목록이 아예 열리지 않아 대부분의 회원이 영향을 받고 있었다. 배포 내용에 데이터베이스 표를 바꾸는 작업은 들어 있지 않았다.

현우는 원인을 따지기 전에 대시보드에서 바로 앞의 정상 배포로 Instant Rollback을 실행했고, 1분 안에 목록이 다시 열렸다. 그는 롤백 뒤 자동 연결이 꺼진다는 것을 알고 있었기에, 점검표의 '롤백 중' 칸에 표시를 해 두었다.

그다음에야 원인을 봤다. 오류는 Cannot read properties of undefined (reading 'length')였고, 새 코드가 강습마다 대기자 명단을 읽는 줄이었다. 명단은 선택 항목이었는데 새 코드는 늘 있다고 가정했다. 대기 신청 기능 이전에 만들어진 강습에는 명단 자체가 없었다. 미리보기의 테스트 데이터에는 새로 만든 강습만 있어서 드러나지 않았던 것이다.

현우는 기능 브랜치에서 명단이 없으면 빈 목록으로 다루도록 고치고, 오래된 강습을 흉내 낸 테스트 데이터를 추가해 테스트를 썼다. 미리보기에서 옛 강습과 새 강습을 모두 열어 본 뒤 병합했다. 운영 화면은 예상대로 여전히 롤백된 버전이었다. 현우는 새 프로덕션 배포를 승격해 롤백 상태를 풀었고, 스모크 테스트를 한 뒤 점검표의 표시를 지웠다.

장애 기록에는 세 줄이 남았다. 무엇이 일어났는가(기존 데이터에 없는 필드를 읽음), 왜 미리보기에서 놓쳤는가(테스트 데이터가 새 데이터뿐), 무엇을 바꾸는가(미리보기 데이터에 오래된 형식의 표본 포함). 장애는 12분, 복구는 1분, 수정은 한 시간이 걸렸다. 순서가 반대였다면 장애가 한 시간이었을 것이다.

자주 틀리는 지점

  1. "미리보기에서 됐으니 운영에서도 된다." 같은 코드이니 같을 것 같습니다. 하지만 환경 변수, 외부 연동, 데이터가 환경마다 다릅니다. 미리보기 통과는 필요조건일 뿐입니다.
  2. "환경 변수를 고치면 바로 반영된다." 설정 화면에서 저장했으니 끝난 것 같습니다. 하지만 변경은 새 배포에만 적용됩니다. 고친 뒤에는 다시 배포합니다.
  3. "롤백하면 데이터도 예전으로 돌아간다." 이름이 '되돌리기'이니 전부 돌아갈 것 같습니다. 하지만 롤백은 코드와 배포 당시 설정을 되돌릴 뿐입니다. 데이터 구조 변경이 있었다면 호환성부터 확인합니다.
  4. "장애가 나면 운영에서 바로 고친다." 원인만 찾으면 빨리 끝날 것 같습니다. 하지만 원인을 모른 채 고치면 장애가 길어지고, 급한 수정이 새 장애를 부릅니다. 직전 정상 배포로 먼저 복구하고 원인은 브랜치에서 찾습니다.
  5. "롤백 뒤에는 고친 코드를 main에 올리기만 하면 된다." 평소처럼 푸시하면 반영될 것 같습니다. 하지만 롤백 뒤에는 자동 연결이 꺼져 있습니다. 고친 배포를 승격해야 평소 흐름으로 돌아옵니다.
  6. "빌드가 성공했으니 배포는 성공이다." 초록색 표시는 안심을 줍니다. 하지만 빌드 성공은 실행 중 오류를 보증하지 않습니다. 배포 직후 스모크 테스트와 런타임 로그 확인이 따로 필요합니다.

한눈에 정리

주제 기억할 것
배포 성공한 빌드의 결과, 배포마다 고유 URL. 도메인이 가리키는 배포만 바뀐다
미리보기 조건 프로덕션 브랜치 외 푸시, PR, --prod 없는 CLI. 새 프로젝트의 첫 배포는 항상 프로덕션
URL 브랜치 URL은 최신을, 커밋 URL은 그 시점을 가리킨다
보호 Standard Protection은 프로덕션 도메인 외 전부 보호. 미리보기는 테스트 키·데이터로
환경 변수 환경별로 따로. 변경은 새 배포에만. 새 변수는 필요한 모든 환경에
빌드와 로그 배포 전 로컬 빌드. 빌드 실패는 빌드 로그, 실행 중 오류는 런타임 로그
배포 전후 점검표에 확인한 것과 못 한 것. 직후 스모크 테스트. 단계적 배포 후 승격
롤백 재빌드 없이 즉시. 설정은 당시 것, 데이터는 그대로, 자동 연결 꺼짐 → 승격으로 복귀
장애 순서 영향 확인 → 롤백 → 원인 → 수정·미리보기 → 승격 → 기록
데이터 변경 확장–축소로 나눠 어느 시점에 롤백해도 깨지지 않게

공식 문서로 확인하기

셀프 체크

5-1. 새 프로젝트를 Vercel에 처음 연결하면서 기능 브랜치에서 vercel을 --prod 없이 실행했다. 이 첫 배포는 미리보기인가, 프로덕션인가? 그 뒤의 배포에는 어떤 규칙이 적용되는가?

5-2. 외주 디자이너에게 작업 중인 화면을 보여 주려 한다. 디자이너는 며칠 동안 수시로 들어와 "늘 최신 상태"를 보고 싶어 한다. 브랜치 URL과 커밋 URL 중 무엇을 공유하는가? 다른 하나는 언제 쓰는가?

5-3. 지난주 배포로 롤백한 뒤, 오늘 프로젝트 설정에서 환경 변수 값 하나를 바꿨다. 이 새 값은 지금 운영 중인 롤백된 배포에 적용되는가? 새 값을 운영에 반영하려면 어떻게 하는가?

5-4. Hobby 플랜과 Pro 플랜에서 Instant Rollback으로 고를 수 있는 배포는 각각 어디까지인가?

5-5. 두 시간 전에 난 오류를 확인하려고 터미널에서 vercel logs --environment production을 실행했는데 그 시각의 기록이 보이지 않는다. 명령의 기본 조회 범위는 어떻게 되며, 더 이전 기록을 보려면 무엇을 덧붙이는가?

5-6. 운영 환경 변수로 빌드된 배포를, 프로덕션 도메인에 연결하기 전에 직접 확인하고 싶다. Vercel에서 어떤 설정을 바꾸고 어떤 순서로 진행하는가? 확인이 끝난 뒤 승격하면 다시 빌드되는가?

5-7. 내 앱(또는 연습용 앱)에 맞는 배포 전 점검표를 여섯 줄로 만들어 보라. 검사, 미리보기 흐름, 환경 변수, 데이터, 외부 연동, 복구 지점을 각각 한 줄씩, 내 앱의 실제 기능 이름을 넣어 쓴다.

실습 과제

실습

미리보기, 환경별 변수, 롤백과 승격 (60분)

  1. 연습용 앱을 Vercel에 연결해 첫 프로덕션 배포를 만든다.
  2. 화면에 환경 변수 값(비밀이 아닌 값, 예: APP_LABEL)을 보여 주는 기능을 넣고, Preview와 Production에 서로 다른 값을 넣는다.
  3. 기능 브랜치를 푸시해 미리보기 URL에서 Preview 값이 보이는지 확인하고, main에 병합해 운영에서 Production 값이 보이는지 확인한다.
  4. Production 값을 바꾼 뒤, 다시 배포하기 전과 후에 화면 값이 어떻게 다른지 본다.
  5. 직전 배포로 Instant Rollback을 한 뒤 main에 작은 변경을 푸시해 운영에 자동 반영되지 않는 것을 확인하고, 새 배포를 승격해 평소 흐름으로 돌아온다.

완료 기준: 단계마다 화면 값과 배포 상태를 캡처한 기록이 있고, 4단계에서 재배포 전후의 값 차이와 5단계에서 자동 반영이 멈췄다가 승격 뒤 돌아온 것을 캡처로 보여 줄 수 있다.

실습

로그로 장애 한 번 따라가기 (40분)

  1. 연습용 앱에 특정 조건(예: 주소에 ?fail=1)에서만 서버 오류를 내고 로그를 남기는 경로를 만든다.
  2. 미리보기 배포를 만들고, 정상 요청 몇 번과 실패 요청 몇 번을 보낸다.
  3. 런타임 로그에서 상태 코드 500과 해당 경로로 걸러, 첫 오류 시각과 오류 문구를 찾는다.
  4. 같은 내용을 CLI의 vercel logs로도 찾아본다. 기본 범위로 안 보이면 --since를 쓴다.
  5. 찾은 내용으로 장애 기록 세 줄(무엇이, 왜, 무엇을 바꾸는가)을 쓴다.

완료 기준: 대시보드와 CLI 양쪽에서 찾은 첫 오류 시각이 일치하고, 장애 기록 세 줄이 로그의 실제 내용을 근거로 작성되어 있다.