본문 바로가기

개발 지식

Next.js Standalone 으로 빌드하기

1. Standalone 이란?

- Next.js에서 웹 어플리케이션을 실행하는데 필요한 최소한의 코드만 추출하겠다는 의미로 사용
- 배포에 필요한 파일만 복사하는 폴더를 자동으로 생성할 수 있으며, 선택한 파일이 포함됨

// next.config.js
module.exports = {
  output: 'standalone',
};

 

사실 별거 없다. 그냥 next.config.js 파일에 이렇게 output으로 standalone 만 추가하면 끝이다.

 

그러나 빌드 후 .next/standalone 이 생기지 않았다..

 

2. 문제 해결

빌드 캐쉬도 제거해보고, 

.node_modules 제거 후 다시 인스톨해보고,

.next 도 제거후 다시 빌드해봐도 .. 생기지 않았다.

빌드 로그를 살펴봐도 standalone 에 대한 내용은 1도 없었다.

 

그러다 문득 next.config.cjs 확장자 때문인가 ? 

싶어서 cjs -> js 로 바꿔주고 문법도 바꿔주었다.

// 수정전 next.config.cjs

/** @type {import('next').NextConfig} */
import withTMOriginal from 'next-transpile-modules';
const withTM = withTMOriginal();

const nextConfig = withTM({
	output: 'standalone',
  	compress: true, // : Gzip 압축을 활성화하여 페이지 로딩 속도를 개선
    webpack: (config) => {
    config.module.rules = config.module.rules || [];

    config.module.rules.push({
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            postcssOptions:{
              plugins: ['tailwindcss', 'autoprefixer']
            },
          },
        },
      ],
    });

    return config;
  },
  images: {
    domains: ['isomorphic-furyroad.s3.amazonaws.com', 'randomuser.me'],
  },
  reactStrictMode: false,
  experimental: {
  	optimizeCss: true, // CSS 최적화
    serverActions: true,
  },
  swcMinify: true,
  compiler: {
    removeConsole: process.env.NODE_ENV === 'production', // 프로덕션모드 - 콘솔로그 미출력
  },
});

module.exports = nextConfig;
// 수정후 next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
  compress: true, // : Gzip 압축을 활성화하여 페이지 로딩 속도를 개선
  images: {
    domains: ['isomorphic-furyroad.s3.amazonaws.com', 'randomuser.me'],
  },
  reactStrictMode: false,
  experimental: {
    optimizeCss: true, // CSS 최적화
    scrollRestoration: true,
    serverActions: true,
  },
  swcMinify: true,
  compiler: {
    removeConsole: process.env.NODE_ENV === 'production', // 프로덕션모드 - 콘솔로그 미출력
  },
};

module.exports = nextConfig;

 

그리고 .next를 삭제후 재빌드 했더니 .. 

이렇게 .next/standalone 으로 잘 생기는것을 확인했고 도커에서 문제없이 실행되었다 :)

 

3. 이유는 ? 

우선 .cjs 와 .js 의 차이를 알아보자. Next.js의 next.config.cjs와 next.config.js의 차이를 이해하려면 CommonJSESModules의 차이와 Next.js가 이 파일들을 처리하는 방식을 알아야 한다. 

 

CommonJS(.cjs)와 ESModules(.js)의 차이

  • CommonJS (.cjs): Node.js에서 기본적으로 사용되는 모듈 시스템으로, module.exports와 require()로 모듈을 가져오고 내보냅니다. CommonJS는 동기적으로 모듈을 로드하며, 이 방식은 파일 확장자가 .cjs일 때 강제됩니다.
  • ESModules (.js): ECMAScript 모듈 시스템으로, 최신 JavaScript 표준입니다. export와 import 구문을 사용하여 모듈을 내보내고 가져옵니다. ESModules는 비동기적이며, 확장자가 .js일 경우 ESM 방식으로 실행될 수 있습니다. 하지만, Node.js 환경에서 ESModules를 사용하는 경우에는 package.json에 "type": "module" 설정을 추가해야 합니다.

 

왜 .cjs와 .js의 차이가 빌드에 영향을 주었을까?

Next.js는 ESModulesCommonJS 모듈 시스템을 모두 지원한다. 

하지만 .cjs 파일은 CommonJS 방식으로 동작하는 반면, .js 파일은 ESModules 방식으로 동작한다.

  1. Next.js의 기본 모듈 시스템 설정
    - Next.js는 기본적으로 ESModules 방식을 동작하기 때문에, .js 파일을 ESM 방식으로 읽고 처리하는 것이 더 자연스럽다고 한다.
    - 만약 next.config.cjs 파일이 있다면 Next.js는 CommonJS로 처리하는데, 이 과정에서 Next.js가 일부 설정이나 파일 경로 처리를 제대로 처리하지 못했을 가능성이 있다.
    - 특히 output: 'standalone' 옵션이 Next.js 의 빌드 방식에 영향을 미치는데, CommonJS 방식으로 처리할 때 해당 옵션이 제대로 적용되지 않은 것이다
  2. .cjs 파일 내의 설정 인식 문제
    - Next.js가 ESModules와 CommonJS의 설정을 다르게 처리하는 경우가 종종 있다
    - .js 파일로 전환하면서 Next.js가 설정을 올바르게 읽고 standalone 출력을 생성할 수 있었던 것
    - ESModules 방식이 Next.js의 설정 및 빌드 프로세스에 더 잘 맞았다고 볼 수 있다
  3. 빌드 시스템이나 패키지 문제
    - 일부 패키지나 설정이 ESModules로 작성된 환경에서 더 잘 동작할 수 있다
    - 특히 Next.js의 최신 기능이나 실험적 옵션(예: experimental.optimizeCss, output: 'standalone')은 ESModules 환경에서 최적화된 방식으로 작동할 수 있다

 

라고 지피티 교수님은 말씀하셨다 .

지금 보니 next.config.cjs 설정파일의 문법이 좀 잘못된것 같기도 .. ;; 

처음에 모노레포 때문에 .cjs 로 기본설정을 했었던 건데 그게 발목을 잡을줄 몰랐다 

아무튼 안전하게 .js를 쓰도록 하자!

'개발 지식' 카테고리의 다른 글

AWS Amplify 슬랙 연동하기  (0) 2024.11.18
스토리북 사용기  (1) 2024.07.18
AWS amplify 배포해보기  (0) 2024.07.04
[FE] 웹뷰(WebView) 란?  (1) 2024.06.17
[FE] 쿠키, 세션, 로컬 스토리지와 세션 스토리지  (0) 2024.02.07