한땀한땀

Next.js 설정 파일에서 process.env.NODE_ENV 사용할 때 주의할 점 본문

FrontEnd Dev

Next.js 설정 파일에서 process.env.NODE_ENV 사용할 때 주의할 점

junfromkorea 2025. 8. 7. 10:00

Node.js 환경에서 개발을 해본 사람이라면 대부분 알고 있을 법한 기본 중 하나는,

 process.env.NODE_ENV와 같은 환경 변수를 직접 사용하는 것에 대한 이해이다.

 

하지만 나는 그 기본을 잠시 망각했고, 그로 인해 꽤 많은 시간을 디버깅에 허비하게 되었고, 그 과정에서 중요한 교훈을 얻었다.

 

당시 나는 Module Federation을 적용해 마이크로 프론트엔드 구조를 구성하고 있었고,
개발 환경에서는 Hot Reload 이후 변경 사항 반영이 느려지는 문제가 있었다.
그래서 로컬 환경에서는 Module Federation이 아예 동작하지 않도록 조건 분기를 만들고자 했다.

 

문제는 그 조건 분기에서 비롯되었다.
process.env.NODE_ENV === 'development' 같은 구문을 프로젝트 전역에서 반복해서 사용하고 있었기에,

// 상수 파일
const isLocal = process.env.NODE_ENV === 'development'


위와 같이 따로 상수화한 뒤,

import { isLocal } from '@/constants/env'


필요한 곳에서 위와 같이 가져다 썼다.

 

그중 하나가 바로 next.config였고, 그 순간부터 문제가 시작됐다.

이 글은 그때 겪었던 빌드 실패의 원인과,
환경 변수는 단순히 “무엇”이 아니라 “언제 평가되느냐”가 더 중요하다는 사실을 공유하기 위한 기록이다.


문제 상황

Module Federation을 설정한 상태였고,
로컬 개발 환경에서는 해당 플러그인이 아예 동작하지 않도록 조건문으로 분기하는 구조였다.

 

당시 next.config.js 내부 구조:

// next.config.js

import { isLocal } from './env'; // const isLocal = process.env.NODE_ENV === 'development'

module.exports = {
  webpack(config, options) {
    const isServer = options.isServer;

    // 문제의 조건문
    if (!isServer && !isLocal) {
      // Module Federation 관련 설정
      config.plugins.push(
        new NextFederationPlugin({
          // ...name, remotes, shared 등
        })
      );
    }

    return config;
  },
};

 

코드 내용은 대략 위와 같았고, 내부적으로는 원격 모듈을 promise로 로드하는 커스텀 설정과,
공통 패키지 공유 설정 등이 포함돼 있었지만, 보안을 위해 상세 구현은 생략한다.

 

처음에는 문제없이 동작할 거라 생각했지만, 빌드 시 다음과 같은 에러가 발생했다:

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '패키지명' imported from 경로/next.config.js

 

단순한 설정 실수로 보였지만, 원인은 예상외로 단순하면서도 치명적인 부분에 있었다.


원인 분석: 환경 변수의 "평가 타이밍"

이 문제의 핵심은 process.env.NODE_ENV의 평가 시점이었다.

Webpack이나 Next.js의 설정 파일은 Node.js 환경에서 빌드 타임에 실행되고,

Webpack은 조건문을 정적으로 분석해, 필요한 모듈만 트리쉐이킹하고 초기화한다.

 

이 때 다음 두 코드의 차이가 문제를 만들었다:

// ❌ 실패
import { isLocal } from './env';
if (!isServer && !isLocal) {
  // Module Federation 초기화
}

// ✅ 성공
if (!isServer && process.env.NODE_ENV === 'production') {
  // Module Federation 초기화
}

 

왜 이렇게 다른 걸까?

Next.js는 process.env.NODE_ENV처럼 직접 접근한 환경 변수
빌드 시점에 정적으로 문자열로 치환한다고 한다. 예를 들어:

if (process.env.NODE_ENV === 'production')
// → if ('production' === 'production')

와 같이 말이다.

 

이렇게 되면 Webpack이 조건문을 빌드 시점에 바로 평가할 수 있고,
관련 모듈도 정상적으로 불러올 수 있게 된다.

 

하지만 isLocal과 같이 별도로 추출된 상수는,
외부 파일에서 import 되면서 언제 평가되는지 보장할 수 없는 런타임 값이 되어버린다.
이로 인해 Webpack은 해당 분기를 정적으로 분석할 수 없고,
require()로 모듈을 불러오기 전에 조건이 평가되지 않아 undefined 오류가 발생하게 된 것이다.


해결 방법

해결 방법은 생각보다 너무도 단순하고, 어찌 보면 너무 기초적인 부분에 있었고,
그래서 더 허탈하기도 했다.

 

조건문에서 상수를 사용하지 않고, 다시 process.env.NODE_ENV를 직접 사용하는 방식으로 고쳐주었을 뿐인데,
그렇게 하자 빌드는 아무 일 없었다는 듯이 정상적으로 통과됐고, Module Federation도 의도한 대로 잘 작동했다.

if (!isServer && process.env.NODE_ENV === 'production') {
  config.plugins.push(
    new NextFederationPlugin({
      // ...
    })
  );
}

 


마무리

환경 변수는 단순한 문자열이 아니고,

언제 어디서 평가되는지가 전체 빌드 결과에 큰 영향을 미칠 수 있다.

 

이번 경험을 통해 "기본"이라 생각했던 개념도 실제로 부딪혀봐야 진짜 이해하 된다는 사시을 다시금 느꼈다.

 

혹시나 비슷한 상황을 겪고 있는 사람이 있다면, 

"이 환경 변수는 빌드 타임에 평가되어야 하는가?"를 한 번쯤 생각해 보시길 추천합니다.