카테고리 없음

[next.js] Next.js 설정 파일(next.config.js 정리)

solutionMan 2025. 1. 5. 15:53
반응형

Next.js에서 설정 파일인 next.config.js는 웹사이트의 동작을 최적화하고 보안을 강화하며 개발 환경과 실제 배포 환경 간의 차이를 관리할 수 있는 중요한 역할을 합니다. 이 문서에서는 설정 파일을 구성하는 방법과 각 기능의 사용 이유, 장점, 단점, 그리고 코드 예제를 통해 자세히 설명하겠습니다


목차

  1. 리다이렉션 설정하기
  2. 환경 변수
  3. 외부 이미지 도메인 허용
  4. 커스터마이징
  5.  국제화 설정
  6. 보안 헤더 설정하기

1. 리다이렉션 설정하기

사용 이유

  • 오래된 URL을 새로운 URL로 연결할 때 유용합니다.
  • SEO를 유지하고 사용자 경험을 개선할 수 있습니다.

장점

  • 사용자가 잘못된 URL로 접속해도 자동으로 올바른 페이지로 이동합니다.
  • 검색 엔진 크롤러가 새로운 URL을 쉽게 인식합니다.

단점

  • 많은 리다이렉션 규칙이 있을 경우 관리가 복잡해질 수 있습니다.

코드 예시

module.exports = {
  async redirects() {
    return [
      {
        source: '/old-page',
        destination: '/new-page',
        permanent: true, // 301 리다이렉션
      },
    ];
  },
};

비유

리다이렉션은 오래된 주소를 새로운 집 주소로 안내하는 우편 서비스와 같습니다. 이를 통해 검색 엔진은 웹사이트의 구조 변화에도 혼란을 겪지 않으며, 올바른 페이지를 색인할 수 있습니다. 특히, 301 리다이렉션은 기존 페이지의 SEO 점수를 새로운 페이지로 이전시켜 검색 순위를 유지하는 데 중요한 역할을 합니다.


2. 환경 변수 설정하기

사용 이유

  • 개발 환경과 배포 환경에서 다른 설정값을 사용할 수 있습니다.
  • 민감한 정보를 코드에 직접 포함하지 않도록 보호합니다. 예를 들어, API 키, 데이터베이스 URL, 인증 토큰과 같은 민감한 정보는 노출될 경우 보안 사고로 이어질 수 있으므로 환경 변수로 관리해야 합니다.

장점

  • 환경별로 다른 설정을 쉽게 관리할 수 있습니다.
  • 민감한 데이터를 안전하게 처리할 수 있습니다.

단점

  • 환경 변수가 올바르게 설정되지 않으면 예상치 못한 동작이 발생할 수 있습니다.

코드 예시

module.exports = {
  env: {
    CUSTOM_API_ENDPOINT: process.env.CUSTOM_API_ENDPOINT,
  },
};

비유

환경 변수는 다양한 재료를 저장하는 찬장처럼, 필요할 때 필요한 재료(API, 키 등)를 꺼내 쓸 수 있게 합니다.

 


3. 외부 이미지 도메인 허용하기

사용 이유

  • 외부 이미지 리소스를 활용하여 웹사이트 성능을 최적화할 수 있습니다.

장점

  • CDN을 활용한 빠른 이미지 로딩이 가능합니다.
  • 다양한 출처의 이미지를 사용할 수 있습니다.

단점

  • 도메인을 추가로 관리해야 합니다.

코드 예시

module.exports = {
  images: {
    domains: ['example.com', 'images.unsplash.com'],
  },
};

비유

이미지 도메인 허용은 특정 친구만 파티에 초대하는 것과 같습니다.

 


4. Webpack 설정 커스터마이징

사용 이유

  • 빌드 과정을 세부적으로 제어하여 프로젝트 요구 사항에 맞출 수 있습니다.

장점

  • 프로젝트에 특화된 플러그인을 추가할 수 있습니다.
  • 빌드 성능을 최적화할 수 있습니다.

단점

  • 복잡한 설정은 유지보수를 어렵게 만들 수 있습니다.

코드 예시

module.exports = {
  webpack: (config, { webpack }) => {
    config.plugins.push(new webpack.DefinePlugin({
      'process.env.VERSION': JSON.stringify('1.0.0'),
    }));
    return config;
  },
};

비유

Webpack 커스터마이징은 레고 조립에서 자신만의 특별한 부품을 추가하는 것과 같습니다. 이를 통해 개발자는 빌드 프로세스를 보다 효율적으로 디버깅할 수 있습니다. 특히, 소스맵(source map)을 활성화하면 원본 코드를 기반으로 오류를 추적할 수 있어 디버깅 과정이 훨씬 간단해집니다. 하지만 복잡한 설정으로 인해 디버깅 시 불필요한 변수가 생길 수 있으므로 적절한 테스트와 검토가 필요합니다.

 

 


5. 국제화 설정

사용 이유

  • 다국어 사용자 경험을 제공합니다. 이를 위해 i18next와 같은 번역 도구나 서비스를 활용하면 실무에서 더욱 효과적으로 다국어 지원을 구현할 수 있습니다. i18next는 다양한 언어 파일 관리 및 번역 작업을 단순화하며, Next.js와의 통합도 용이합니다.

장점

  • 전 세계 사용자를 대상으로 서비스를 확장할 수 있습니다.
  • 기본 언어 설정을 통해 접근성을 높입니다.

단점

  • 번역 및 언어 파일 관리가 필요합니다.

코드 예시

module.exports = {
  i18n: {
    locales: ['en', 'ko', 'ja'],
    defaultLocale: 'en',
  },
};

비유

국제화 설정은 전 세계 여행자를 위한 다국어 표지판을 설치하는 것과 같습니다.


6. 보안 헤더 설정하기

사용 이유

  • 다양한 보안 위협(클릭재킹, XSS 등)으로부터 보호합니다.

장점

  • 보안이 강화됩니다.
  • 사용자의 데이터를 안전하게 보호할 수 있습니다.

단점

  • 잘못된 설정은 정상적인 동작을 방해할 수 있습니다.

주요 보안 헤더 기능

  1. X-Content-Type-Options
  2. X-Frame-Options
  3. X-XSS-Protection
  4. Strict-Transport-Security (HSTS)
  5. Content-Security-Policy (CSP)
    • 사용 목적: 허용된 리소스 출처를 명시하여 XSS 및 데이터 삽입 공격 방지.
    • 설정값: default-src 'self'; 등.
    • 예: Content-Security-Policy: default-src 'self'; script-src 'self';
    • https://developer.mozilla.org/ko/docs/Web/HTTP/CSP.

코드 예시

module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          { key: 'X-Content-Type-Options', value: 'nosniff' },
          { key: 'X-Frame-Options', value: 'DENY' },
          { key: 'X-XSS-Protection', value: '1; mode=block' },
          { key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' },
          { key: 'Content-Security-Policy', value: "default-src 'self'; script-src 'self';" },
        ],
      },
    ];
  },
};

 

보안 헤더 설정은 집에 잠금장치, 경보 시스템, 그리고 감시 카메라를 설치하는 것과 같습니다.

이 문서를 통해 next.config.js의 다양한 기능과 설정을 이해하고, 필요에 맞게 프로젝트를 최적화할 수 있기를 바랍니다!

 

/** @type {import('next').NextConfig} */

const nextConfig = {
  // 보안 헤더를 설정하는 비동기 함수
  async headers() {
    // 현재 환경이 개발 환경인지 확인
    const isDevelopment = process.env.NODE_ENV === "development";

    // 기본적인 보안 헤더 설정 배열
    const securityHeaders = [
      {
        // MIME 타입 스니핑 방지
        key: "X-Content-Type-Options",
        value: "nosniff",
      },
      {
        // iframe으로 페이지가 로드되는 것을 방지
        key: "X-Frame-Options",
        value: "DENY",
      },
      {
        // XSS 공격 방지를 위한 브라우저 내장 필터 활성화
        key: "X-XSS-Protection",
        value: "1; mode=block",
      },
      {
        // HTTPS 강제 적용 (HSTS)
        key: "Strict-Transport-Security",
        value: "max-age=31536000; includeSubDomains",
      },
    ];

    // Content Security Policy(CSP) 헤더 설정
    const cspHeader = {
      key: "Content-Security-Policy",
      value: [
        // 기본적으로 같은 출처의 리소스만 허용
        "default-src 'self'",
        // 스크립트 실행 정책 (개발/프로덕션 환경 분리)
        isDevelopment
          ? "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://vercel.live"
          : "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
        // 스타일 로딩 정책
        "style-src 'self' 'unsafe-inline'",
        // 이미지 로딩 정책
        "img-src 'self' data: blob:",
        // 폰트 로딩 정책
        "font-src 'self'",
        // iframe 관련 정책
        "frame-ancestors 'none'",
        // 폼 제출 정책
        "form-action 'self'",
        // iframe 소스 정책
        "frame-src 'self'",
        // 미디어 파일 정책
        "media-src 'self'",
        // 매니페스트 파일 정책
        "manifest-src 'self'",
      ].join("; "),
    };

    // 모든 경로에 보안 헤더 적용
    return [
      {
        source: "/:path*",
        headers: [...securityHeaders, cspHeader],
      },
    ];
  },
};

module.exports = nextConfig;
반응형