Blog

NEXT_PUBLIC_ 환경변수는 왜 env인데 클라이언트에 노출될까


env인데 왜 노출되나요?#

환경변수(env)는 보통 "비밀값"이라는 인식이 강하다.
그래서 NEXT_PUBLIC_ 환경변수가 클라이언트에서 보인다는 사실을 처음 접하면,
"env가 노출되면 보안 사고 아닌가?"라는 의문이 자연스럽게 든다.

하지만 이 의문은 env의 역할과 Next.js의 실행 구조를 분리해서 보지 않았기 때문에 생긴다.
환경변수는 본질적으로 "비밀"이 아니라, 실행 환경에 따라 값을 분기하기 위한 설정값이다.

Next.js는 이 설정값 중 일부를 의도적으로 클라이언트에 공개할 수 있게 설계했고,
그 선언이 바로 NEXT_PUBLIC_ 접두사다.

환경변수는 언제, 어디서 값이 결정되는가#

Next.js에서 NEXT_PUBLIC_ 환경변수는
클라이언트 기준으로 런타임에 읽히는 값이 아니라,
빌드 시점에 코드에 직접 치환된다.

process.env.NEXT_PUBLIC_API_URL;

이 코드는 브라우저에서 process.env를 실제로 읽는 것이 아니라,
next build 시점에 문자열 값으로 대체되어 번들에 포함된다.

즉, 클라이언트 번들에 포함된 env는 "나중에 가져오는 값"이 아니라,
이미 코드의 일부가 된 상수다.

NEXT_PUBLIC_만 클라이언트 번들에 들어갈까#

Next.js는 서버 코드와 클라이언트 코드를 명확히 분리한다.
그리고 이 경계에서 중요한 원칙 하나를 강제한다.

개발자가 명시적으로 공개를 선언한 env만 클라이언트에 포함한다.

그 선언이 바로 NEXT_PUBLIC_다.

  • NEXT_PUBLIC_가 붙은 env > 클라이언트 코드에서 사용 가능
  • 붙지 않은 env > 서버 전용

이는 단순한 네이밍 규칙이 아니라,
보안 경계를 개발자에게 명확히 인식시키기 위한 장치다.

NEXT_PUBLIC_이 없는 env는 왜 번들에 포함되지 않는가#

NEXT_PUBLIC_이 없는 env는 클라이언트 코드에서 접근할 수 없다.
접근할 수 없다는 말은, 번들에 포함될 이유가 없다는 뜻이다.

Next.js는 빌드 과정에서:

  • 클라이언트 코드에서 사용되지 않는 env를 제거하고
  • 서버에서만 사용 가능한 값은 서버에만 남긴다.

이 덕분에,

  • API Secret
  • DB 접근 키
  • JWT Secret

같은 값이 실수로 클라이언트 번들에 들어가는 구조 자체를 차단한다.

번들에 포함된 env != 비밀키#

여기서 가장 큰 오해가 발생한다.

"번들에 포함되면, 그건 이미 털린 거 아닌가?"

이 질문은 값의 노출과 위험성을 동일시하고 있다.
하지만 보안에서 중요한 건 "보였는가"가 아니라 "그 값만으로 무엇을 할 수 있는가"이다.

비유를 들면 이렇다.

  • NEXT_PUBLIC_ env를 공개했다는 것은 길을 가다가 누군가에게 집 열쇠를 하나 건네준 상황이다.

  • 하지만 그 사람은:

    • 집 주소, 위치를 모르고 열쇠가 어디에 쓰이는지도 모른다.

열쇠는 손에 있지만, 공격 가능한 맥락이 없다.

중요한 점은, 그 열쇠는
서버 검증 없이는 어떤 문도 열 수 없도록 설계된 열쇠라는 점이다.

진짜 비밀키와의 차이#

진짜 비밀키는 다르다.

  • API Secret
  • Service Role Key
  • JWT Secret

이 값들은 그 자체만으로 권한을 가진다.
주소, 경로를 몰라도, 열쇠만 있으면 바로 문을 열 수 있는 구조다.

그래서 이 값들은:

  • 절대 클라이언트로 내려가면 안 되고
  • env라는 이유만으로 안전하다고 착각해서도 안 된다.

보안의 기준은 단순하다.

값 하나로 단독 행동이 가능한가?

이 질문에 "예"라면, 그건 비밀키에 해당한다.

NEXT_PUBLIC_ env의 올바른 사용 기준#

NEXT_PUBLIC_ env는 다음 조건을 만족할 때만 사용해야 한다.

  • 공개되어도 무방한 값일 것
  • 단독으로 의미를 가지지 않을 것
  • 반드시 서버 검증을 거쳐야만 동작할 것

대표적인 예시는:

  • 공개 API 엔드포인트
  • 서비스 식별자
  • 클라이언트 설정용 플래그

반대로,

  • 권한을 직접 부여하는 값
  • 서버 자원을 직접 조작할 수 있는 값

이런 것들은 env 여부와 상관없이 절대 클라이언트로 가면 안 된다.

정리#

NEXT_PUBLIC_는 보안을 제공하는 기능이 아니다.
"이 값은 공개해도 괜찮다"라고 개발자가 선언하는 장치일 뿐이다.

5