Vercel 자주 하는 실수 10가지

카페인코더·2026년 6월 22일

AI 웹앱 보안 점검

목록 보기
8/11
post-thumbnail

AI 개발 도구를 이용해 만든 웹앱을 배포할 때 Vercel을 사용하는 경우가 많습니다.

GitHub 저장소를 연결하면 자동으로 빌드되고 URL까지 생성되기 때문에 배포 과정은 간단하게 느껴집니다.

하지만 배포에 성공했다는 것과 안전하게 운영할 준비가 끝났다는 것은 다릅니다.

Vercel은 컴퓨팅, 네트워크 같은 플랫폼 인프라를 보호하지만 애플리케이션 코드, 사용자 인증, 데이터 접근 권한, 환경변수 사용은 개발자가 관리해야 합니다.

이번 글에서는 Vercel로 웹앱을 배포할 때 자주 하는 실수 10가지와 확인 방법을 정리해보겠습니다.

이 글은 2026년 6월 22일 기준 Vercel, Next.js, OWASP 공식 문서를 바탕으로 작성했습니다. 요금제와 플랫폼 기능은 변경될 수 있으므로 글 하단의 공식 문서도 함께 확인해주세요.


1. 환경변수에 넣으면 무조건 비밀이라고 생각한다

Vercel에 등록한 환경변수는 저장 시 암호화됩니다.

일반 환경변수는 프로젝트 접근 권한이 있는 사용자가 확인할 수 있으며, Production과 Preview에서는 값을 다시 읽을 수 없도록 Sensitive 옵션을 사용할 수도 있습니다.

하지만 환경변수를 안전하게 저장했다는 사실이 애플리케이션에서의 노출까지 막아주지는 않습니다.

다음과 같은 경우에는 값이 외부로 노출될 수 있습니다.

  • 브라우저용 JavaScript에 포함한 경우
  • API 응답에 값을 넣은 경우
  • console.log로 출력한 경우
  • 오류 메시지에 환경변수를 포함한 경우
  • URL이나 쿼리 파라미터에 넣은 경우

환경변수는 비밀을 저장하는 방법이지, 어디에서 사용해도 안전하게 만들어주는 기능은 아닙니다.

이렇게 확인해보세요

  • 환경변수를 서버 코드에서만 사용하는가
  • 프로젝트 접근 권한을 가진 사람이 누구인지 알고 있는가
  • 중요한 값에 Sensitive 옵션을 적용했는가
  • 환경변수를 응답이나 로그에 출력하고 있지 않은가

Vercel 환경변수 공식 문서


2. Secret을 NEXT_PUBLIC_ 변수에 넣는다

Next.js는 NEXT_PUBLIC_ 접두사가 붙은 환경변수를 브라우저에서 사용할 수 있도록 빌드 결과에 포함합니다.

NEXT_PUBLIC_ANALYTICS_ID=public-value

위와 같이 브라우저에서 사용하도록 만들어진 공개 값에는 사용할 수 있습니다.

하지만 다음과 같은 값에는 사용하면 안 됩니다.

NEXT_PUBLIC_DATABASE_URL=...
NEXT_PUBLIC_SERVICE_ROLE_KEY=...
NEXT_PUBLIC_STRIPE_SECRET_KEY=...
NEXT_PUBLIC_JWT_SECRET=...

NEXT_PUBLIC_ 변수의 값은 빌드 시 브라우저에 전달되는 JavaScript에 포함될 수 있습니다. 사용자가 개발자 도구나 빌드 파일을 통해 값을 확인할 수 있다는 뜻입니다.

프로젝트에서 검색할 항목

NEXT_PUBLIC_
DATABASE_URL
SERVICE_ROLE
SECRET_KEY
PRIVATE_KEY
JWT_SECRET

공개되어도 되는 값과 서버에서만 사용해야 하는 값을 구분해야 합니다.

Next.js 환경변수 공식 문서


3. 환경변수를 변경하고 다시 배포하지 않는다

Vercel에서 환경변수를 수정해도 이전에 생성된 배포에는 새로운 값이 적용되지 않습니다.

변경된 환경변수는 이후 만들어지는 새로운 배포부터 적용됩니다.

예를 들어 노출된 API Key를 교체하기 위해 Vercel 설정만 변경하고 다시 배포하지 않았다면 현재 실행 중인 배포는 기존 값을 계속 사용할 수 있습니다.

환경변수를 변경했다면 확인할 항목

  1. 어떤 환경에 적용했는지 확인한다.
  2. 해당 환경을 다시 배포한다.
  3. 새 배포가 변경된 값으로 동작하는지 확인한다.
  4. 필요한 경우 기존 키를 폐기한다.
  5. Preview 배포도 교체가 필요한지 확인한다.

Secret을 교체할 때는 새 값을 적용할 배포와 기존 키의 폐기 시점을 함께 계획해야 서비스 중단을 줄일 수 있습니다.


4. Production과 Preview 환경을 구분하지 않는다

Vercel은 기본적으로 다음 환경을 구분합니다.

  • Production
  • Preview
  • Development

Production이 아닌 Git 브랜치를 배포하면 일반적으로 Preview 배포가 생성됩니다. Preview 환경변수는 전체 비운영 브랜치 또는 특정 브랜치에 적용할 수 있습니다.

문제는 Preview가 운영 환경과 같은 비밀 값과 데이터베이스를 사용할 때 발생합니다.

발생할 수 있는 문제

  • 테스트 코드가 운영 데이터를 수정함
  • 개발 중인 화면에서 실제 개인정보가 노출됨
  • 외부에 공유된 Preview가 운영 DB에 접근함
  • 테스트 요청이 실제 결제·메일·문자 발송으로 이어짐

이렇게 구분해보세요

환경연결 대상 예시
Development로컬 또는 개발용 DB
Preview테스트 DB, 테스트 API Key
Production운영 DB, 운영 API Key

모든 서비스에서 반드시 별도의 DB를 사용해야 하는 것은 아닙니다. 하지만 Preview가 운영 데이터에 접근한다면 접근 권한과 테스트 데이터 처리 방식을 명확히 정해야 합니다.

Vercel 환경 구분 공식 문서


5. Preview 배포의 접근 설정을 확인하지 않는다

Vercel은 브랜치나 커밋마다 고유한 Preview URL을 생성할 수 있습니다.

Preview 응답에는 검색엔진 수집을 막기 위한 x-robots-tag: noindex가 자동으로 추가될 수 있지만, 검색되지 않는 것과 비공개인 것은 다릅니다.

Deployment Protection이 적용되지 않은 배포는 URL을 가진 사람이 접근할 수 있습니다.

Deployment Protection에서 확인할 항목

  • 현재 프로젝트에 보호 기능이 활성화되어 있는가
  • Preview와 생성된 배포 URL이 보호 대상인가
  • 외부 협업자에게 어떤 방식으로 접근을 허용하는가
  • 공유 링크가 필요한 사람에게만 전달되었는가
  • Preview에서 실제 개인정보를 사용하고 있지 않은가

Vercel의 Standard Protection은 Production 도메인을 제외한 배포를 보호하는 용도로 사용할 수 있습니다. 적용 가능한 보호 방식과 범위는 요금제 및 프로젝트 설정에 따라 달라질 수 있습니다.

Preview URL을 추측하기 어렵게 만드는 것보다 접근 권한을 설정하는 것이 중요합니다.

Vercel Deployment Protection 공식 문서


6. API Route에 인증과 권한 검사를 넣지 않는다

Vercel에 배포된 Next.js Route Handler와 API Route는 외부에서 요청할 수 있는 HTTP 엔드포인트입니다.

Vercel이 서버를 실행해준다고 해서 애플리케이션의 API에 사용자 인증과 권한 검사가 자동으로 추가되는 것은 아닙니다.

다음 두 가지를 구분해야 합니다.

  • 인증: 요청한 사용자가 누구인지 확인
  • 인가: 해당 사용자가 이 데이터에 접근할 수 있는지 확인

예를 들어 로그인한 사용자라 하더라도 URL의 예약 ID만 변경해서 다른 사용자의 예약을 조회할 수 있다면 권한 검사가 부족한 것입니다.

API마다 확인할 항목

  • 유효한 세션이 있는가
  • 해당 데이터의 소유자가 요청한 사용자인가
  • 일반 사용자와 관리자의 권한을 구분했는가
  • 등록·조회·수정·삭제 작업마다 권한을 확인하는가
  • 화면에서 버튼을 숨기는 것에만 의존하지 않는가

Next.js의 Server Action도 데이터 변경 작업을 수행한다면 호출 사용자의 권한을 확인해야 합니다.

Vercel의 공식 공동 책임 모델에서도 애플리케이션의 인증과 사용자 접근 관리는 고객 책임으로 구분합니다.

Vercel 공동 책임 모델

Next.js Backend for Frontend 공식 문서


7. 프론트엔드의 입력값 검사만 믿는다

브라우저 화면에서 필수 항목과 글자 수를 검사해도 사용자는 API를 직접 호출할 수 있습니다.

따라서 프론트엔드 검사는 사용자 편의를 위한 기능으로 보고, 서버에서 입력값을 다시 검증해야 합니다.

서버에서 확인할 항목

  • 필수 값이 존재하는가
  • 문자열의 최소·최대 길이가 적절한가
  • 숫자의 범위가 유효한가
  • 날짜의 순서가 올바른가
  • 정해진 선택지 중 하나인지 확인했는가
  • 요청한 사용자가 해당 값을 변경할 권한이 있는가
  • 예상하지 않은 필드가 포함되지 않았는가

예를 들어 화면에서 예약 인원을 1명 이상으로 제한했더라도 API에 -100을 직접 전달할 수 있습니다.

클라이언트와 서버 검증은 목적이 다릅니다.

  • 클라이언트 검증: 빠른 안내와 사용자 경험
  • 서버 검증: 신뢰할 수 없는 요청 차단

OWASP도 클라이언트 검증은 우회할 수 있으므로 서버 측 검증을 함께 구현하도록 안내합니다.

OWASP Input Validation Cheat Sheet


8. 로그에 개인정보와 Secret을 남긴다

Vercel Functions에서 console.log, console.error 등으로 출력한 값은 Runtime Logs에서 확인할 수 있습니다.

Runtime Logs에는 Preview와 Production 함수에서 출력한 내용이 포함될 수 있으며, 프로젝트에서 로그를 볼 수 있는 권한을 가진 사용자에게 노출될 수 있습니다.

디버깅을 위해 요청 전체를 출력하면 다음 정보가 함께 기록될 수 있습니다.

  • 비밀번호
  • Access Token
  • Session ID
  • Cookie
  • Authorization 헤더
  • 데이터베이스 연결 문자열
  • API Secret
  • 이메일, 전화번호, 주소
  • 문의와 상담 내용

피해야 할 코드

console.log(request.headers);
console.log(await request.json());
console.log(process.env);
console.log(user);

객체 전체를 출력하기보다 문제 확인에 필요한 값만 선택해서 기록해야 합니다.

console.log({
  event: "reservation_created",
  requestId,
  userId,
  success: true,
});

사용자 ID도 서비스 상황에 따라 마스킹하거나 내부 식별자로 대체할 수 있습니다.

Vercel Runtime Logs 공식 문서

OWASP Logging Cheat Sheet


9. 보안 헤더가 모두 자동 설정된다고 생각한다

Vercel은 배포 응답에 HSTS와 같은 일부 헤더를 기본으로 제공합니다.

하지만 다음과 같은 보안 정책까지 모든 서비스에 맞게 자동으로 만들어주는 것은 아닙니다.

  • Content-Security-Policy
  • Referrer-Policy
  • X-Content-Type-Options
  • iframe 삽입 제한
  • 서비스별 Cache-Control

특히 CSP는 서비스가 사용하는 스크립트, 이미지, API, 외부 서비스에 따라 허용 범위가 달라지므로 애플리케이션에 맞춰 구성해야 합니다.

Vercel에서는 프레임워크 설정이나 vercel.json을 이용해 응답 헤더를 추가할 수 있습니다.

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "Referrer-Policy",
          "value": "strict-origin-when-cross-origin"
        }
      ]
    }
  ]
}

보안 헤더는 무조건 많이 넣는 것이 목적이 아닙니다. 서비스 기능을 깨뜨리지 않는지 Preview에서 테스트한 뒤 적용해야 합니다.

Vercel Response Headers 공식 문서

Vercel 프로젝트 설정 공식 문서

OWASP HTTP Headers Cheat Sheet


10. 사용량과 비용 제한을 확인하지 않는다

Vercel은 요청, 데이터 전송, 빌드, Functions 실행 등 여러 자원의 사용량을 측정합니다.

기능 오류, 반복 요청, 자동화된 공격 또는 갑작스러운 트래픽으로 사용량이 증가할 수 있습니다.

Vercel Dashboard의 Usage에서 프로젝트별 사용량과 예상 비용을 확인할 수 있습니다.

Pro 요금제의 Spend Management

Pro 팀은 Spend Management를 이용해 설정 금액에 도달했을 때 다음 작업을 구성할 수 있습니다.

  • 알림 전송
  • Webhook 호출
  • Production 프로젝트 일시 중지

주의할 점은 금액을 설정하는 것만으로 프로젝트가 자동 중지되는 것은 아니라는 것입니다.

프로젝트 중지를 원한다면 해당 옵션을 별도로 활성화해야 합니다. 중지되면 정상 사용자도 서비스에 접근할 수 없으므로 운영 영향을 함께 고려해야 합니다.

함께 확인할 항목

  • 최근 30일간 프로젝트별 사용량
  • 예상보다 많이 호출되는 API
  • 반복 요청을 제한할 필요가 있는 기능
  • 이미지 최적화와 데이터 전송 사용량
  • Functions 실행 시간과 오류
  • 비용 알림 수신자
  • 사용량 급증 시 대응 방법

플랫폼 비용 설정만 믿기보다 로그인, 문의, 예약, AI API처럼 반복 호출될 수 있는 기능에도 적절한 요청 제한을 두는 것이 좋습니다.

Vercel Usage 공식 문서

Vercel Spend Management 공식 문서


배포 전 체크리스트

  • Secret을 브라우저 코드에서 사용하지 않는다
  • NEXT_PUBLIC_ 변수에는 공개 가능한 값만 넣었다
  • .env 파일이 Git 저장소에 포함되지 않았다
  • 환경변수 변경 후 해당 환경을 다시 배포했다
  • Production과 Preview 환경변수를 구분했다
  • Preview가 운영 데이터에 접근하는지 확인했다
  • Deployment Protection 설정을 확인했다
  • API마다 인증과 데이터 권한을 검사한다
  • 서버에서도 입력값을 검증한다
  • 로그에 Token, Cookie, 개인정보를 남기지 않는다
  • 실제 응답의 보안 헤더를 확인했다
  • Usage와 비용 알림을 확인했다
  • 반복 호출이 가능한 기능에 요청 제한을 검토했다

마무리

Vercel은 웹앱을 빠르게 배포하고 운영할 수 있게 도와주는 플랫폼입니다.

하지만 플랫폼에 배포했다는 이유만으로 애플리케이션의 인증, 권한, 입력값, 환경변수까지 자동으로 보호되는 것은 아닙니다.

처음부터 모든 항목을 확인하기 어렵다면 다음 세 가지부터 점검해보세요.

  1. 프론트엔드에 Secret이 포함되어 있지 않은가
  2. Preview 배포가 누구에게 공개되어 있는가
  3. API가 사용자 인증과 데이터 권한을 확인하는가

이 세 가지는 소스코드와 Vercel 프로젝트 설정에서 바로 확인할 수 있습니다.

배포 성공 화면을 확인한 뒤에는 실제 사용자가 접근하는 경로와 권한도 함께 점검해야 합니다.


참고한 공식 문서

profile
꾸준히 기록 중 입니다.

0개의 댓글