← 전체 글로 돌아가기

Next.js

배포용 환경 변수 이름을 바꾸기 전에 확인한 Next.js 공개 범위 비교

NEXT_PUBLIC_ 접두사와 서버 전용 환경 변수의 차이를 배포 환경에서 검증한 비교 메모.

이름 하나가 브라우저 번들에 들어갔다

결제 API 키를 NEXT_PUBLIC_PAYMENT_KEY라는 이름으로 올린 적이 있다. 테스트 키라서 당장 사고는 없었지만, 빌드된 JavaScript에서 문자열 검색을 해 보니 그대로 발견됐다. 공개 키와 비밀 키를 이름만 보고 섞어 둔 것이 문제였다.

두 범위를 표로 먼저 구분했다

종류사용 위치브라우저에 노출
NEXT_PUBLIC_*클라이언트 컴포넌트 가능
접두사 없는 변수서버 컴포넌트, Route Handler아니오

클라이언트에서 꼭 필요한 값은 공개 식별자나 공개 URL뿐이다. 서명 키, DB URL, 외부 API 비밀값은 서버에서만 사용한다.

확인은 코드 검색과 프로덕션 빌드로 했다

npm run build
rg 'NEXT_PUBLIC_|SECRET|DATABASE_URL' app src
rg 'test-secret-value' .next/static

마지막 명령은 개발 환경에서만 쓰는 임시 문자열을 넣고 확인할 때 유용했다. .next/static에서 값이 보이면 이미 클라이언트 번들에 포함된 것이다. 단, 실제 비밀값을 검색 명령 인수나 CI 로그에 적지 않도록 임시 값으로만 검사했다.

배포 시점도 다르다

Next.js에서 NEXT_PUBLIC_ 값은 대개 빌드 시점에 치환된다. 이미 만든 이미지를 staging과 production에 똑같이 배포하면서 공개 API URL만 런타임에 바꾸려다 기대와 다르게 동작한 이유도 이것이었다. 서버 전용 변수는 실행 컨테이너의 환경에서 읽는지, 정적 페이지에 박히는지 렌더링 방식까지 확인해야 한다.

적용 전 점검표

  • 이 값이 브라우저 개발자 도구에 보여도 되는가?
  • 키 이름이 역할을 설명하는가? (PAYMENT_PUBLIC_KEY처럼)
  • 빌드 산출물에 테스트 비밀 문자열이 없는가?
  • 환경별로 값이 달라질 때 빌드와 실행 중 어느 시점에 읽는가?

접두사는 보안 기능이 아니라 노출 의사를 표시하는 스위치다. 변수 이름을 정할 때부터 공개 여부를 결정하는 편이 가장 안전했다.