문서
App Router 사용하기
headers

headers

헤더를 사용하면 주어진 경로에 대한 들어오는 요청에 대한 응답에 사용자 정의 HTTP 헤더를 설정할 수 있습니다.

사용자 정의 HTTP 헤더를 설정하려면 next.config.js에서 headers 키를 사용할 수 있습니다:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: "/about",
        headers: [
          {
            key: "x-custom-header",
            value: "my custom header value",
          },
          {
            key: "x-another-custom-header",
            value: "my other custom header value",
          },
        ],
      },
    ];
  },
};

headerssourceheaders 속성을 가진 객체들의 배열을 반환할 것으로 예상되는 비동기 함수입니다:

  • source는 수신 요청 경로 패턴입니다.
  • headerskeyvalue 속성을 가진 응답 헤더 객체의 배열입니다.
  • basePath: false 또는 undefined. false인 경우 매칭 시 basePath가 포함되지 않으며, 외부 URL 재작성에만 사용할 수 있습니다.
  • locale: false 또는 undefined. 매칭 시 로케일을 포함해야 하는지 여부입니다.
  • hastype, key, value 속성을 가진 has 객체의 배열입니다.
  • missingtype, key, value 속성을 가진 missing 객체의 배열입니다.

헤더는 페이지와 /public 파일을 포함한 파일 시스템보다 먼저 확인됩니다.

헤더 오버라이딩 동작

두 개의 헤더가 동일한 경로와 일치하고 동일한 헤더 키를 설정하는 경우, 마지막 헤더 키가 첫 번째 것을 오버라이드합니다. 아래의 헤더를 사용하면 /hello 경로에 대해 x-hello 헤더가 world가 됩니다. 마지막으로 설정된 헤더 값이 world이기 때문입니다.

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: "/:path*",
        headers: [
          {
            key: "x-hello",
            value: "there",
          },
        ],
      },
      {
        source: "/hello",
        headers: [
          {
            key: "x-hello",
            value: "world",
          },
        ],
      },
    ];
  },
};

경로 매칭

경로 매칭이 허용됩니다. 예를 들어, /blog/:slug/blog/hello-world와 일치합니다 (중첩 경로는 제외):

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: "/blog/:slug",
        headers: [
          {
            key: "x-slug",
            value: ":slug", // 일치하는 매개변수를 값에 사용할 수 있습니다
          },
          {
            key: "x-slug-:slug", // 일치하는 매개변수를 키에 사용할 수 있습니다
            value: "my other custom header value",
          },
        ],
      },
    ];
  },
};

와일드카드 경로 매칭

와일드카드 경로를 매칭하려면 매개변수 뒤에 *를 사용할 수 있습니다. 예를 들어, /blog/:slug*/blog/a/b/c/d/hello-world와 일치합니다:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: "/blog/:slug*",
        headers: [
          {
            key: "x-slug",
            value: ":slug*", // 일치하는 매개변수를 값에 사용할 수 있습니다
          },
          {
            key: "x-slug-:slug*", // 일치하는 매개변수를 키에 사용할 수 있습니다
            value: "my other custom header value",
          },
        ],
      },
    ];
  },
};

정규식 경로 매칭

정규식 경로를 매칭하려면 매개변수 뒤에 괄호로 정규식을 감싸면 됩니다. 예를 들어, /blog/:slug(\\d{1,})/blog/123과 일치하지만 /blog/abc와는 일치하지 않습니다:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: "/blog/:post(\\d{1,})",
        headers: [
          {
            key: "x-post",
            value: ":post",
          },
        ],
      },
    ];
  },
};

다음 문자 (, ), {, }, :, *, +, ?는 정규식 경로 매칭에 사용되므로, source에서 특수하지 않은 값으로 사용될 때는 \\를 앞에 추가하여 이스케이프해야 합니다:

next.config.js
module.exports = {
  async headers() {
    return [
      {
        // 이것은 요청된 '/english(default)/something'과 일치합니다
        source: "/english\\(default\\)/:slug",
        headers: [
          {
            key: "x-header",
            value: "value",
          },
        ],
      },
    ];
  },
};

헤더, 쿠키, 쿼리 매칭

헤더, 쿠키 또는 쿼리 값이 has 필드와 일치하거나 missing 필드와 일치하지 않을 때만 헤더를 적용하려면 has 필드를 사용할 수 있습니다. source와 모든 has 항목이 일치해야 하고 모든 missing 항목이 일치하지 않아야 헤더가 적용됩니다.

hasmissing 항목은 다음 필드를 가질 수 있습니다:

  • type: String. header, cookie, host, 또는 query 중 하나여야 합니다.
  • key: String. 선택된 유형에서 일치시킬 키입니다.
  • value: String 또는 undefined. 확인할 값입니다. undefined인 경우 모든 값이 일치합니다. 정규식과 같은 문자열을 사용하여 값의 특정 부분을 캡처할 수 있습니다. 예를 들어, first-(?<paramName>.*)라는 값을 first-second에 사용하면 second:paramName으로 목적지에서 사용할 수 있습니다.
next.config.js
module.exports = {
  async headers() {
    return [
      // 'x-add-header' 헤더가 있는 경우,
      // 'x-another-header' 헤더가 적용됩니다
      {
        source: "/:path*",
        has: [
          {
            type: "header",
            key: "x-add-header",
          },
        ],
        headers: [
          {
            key: "x-another-header",
            value: "hello",
          },
        ],
      },
      // 'x-no-header' 헤더가 없는 경우,
      // 'x-another-header' 헤더가 적용됩니다
      {
        source: "/:path*",
        missing: [
          {
            type: "header",
            key: "x-no-header",
          },
        ],
        headers: [
          {
            key: "x-another-header",
            value: "hello",
          },
        ],
      },
      // 소스, 쿼리 및 쿠키가 일치하는 경우,
      // 'x-authorized' 헤더가 적용됩니다
      {
        source: "/specific/:path*",
        has: [
          {
            type: "query",
            key: "page",
            // 값이 제공되고 명명된 캡처 그룹을 사용하지 않으므로
            // (예: (?<page>home)) 페이지 값은 헤더 키/값에서 사용할 수 없습니다
            value: "home",
          },
          {
            type: "cookie",
            key: "authorized",
            value: "true",
          },
        ],
        headers: [
          {
            key: "x-authorized",
            value: ":authorized",
          },
        ],
      },
      // 'x-authorized' 헤더가 있고
      // 일치하는 값을 포함하는 경우, 'x-another-header'가 적용됩니다
      {
        source: "/:path*",
        has: [
          {
            type: "header",
            key: "x-authorized",
            value: "(?<authorized>yes|true)",
          },
        ],
        headers: [
          {
            key: "x-another-header",
            value: ":authorized",
          },
        ],
      },
      // 호스트가 'example.com'인 경우,
      // 이 헤더가 적용됩니다
      {
        source: "/:path*",
        has: [
          {
            type: "host",
            value: "example.com",
          },
        ],
        headers: [
          {
            key: "x-another-header",
            value: ":authorized",
          },
        ],
      },
    ];
  },
};

basePath 지원이 있는 헤더

basePath 지원을 헤더와 함께 사용할 때, 각 sourcebasePath: false를 헤더에 추가하지 않는 한 자동으로 basePath로 접두사가 붙습니다:

next.config.js
module.exports = {
  basePath: "/docs",
 
  async headers() {
    return [
      {
        source: "/with-basePath", // /docs/with-basePath가 됩니다
        headers: [
          {
            key: "x-hello",
            value: "world",
          },
        ],
      },
      {
        source: "/without-basePath", // basePath: false가 설정되어 있으므로 수정되지 않습니다
        headers: [
          {
            key: "x-hello",
            value: "world",
          },
        ],
        basePath: false,
      },
    ];
  },
};

i18n 지원이 있는 헤더

i18n 지원을 헤더와 함께 사용할 때, 각 sourcelocale: false를 헤더에 추가하지 않는 한 구성된 locales를 처리하기 위해 자동으로 접두사가 붙습니다. locale: false를 사용하는 경우 올바르게 일치하도록 source에 로케일을 접두사로 붙여야 합니다.

next.config.js
module.exports = {
  i18n: {
    locales: ["en", "fr", "de"],
    defaultLocale: "en",
  },
 
  async headers() {
    return [
      {
        source: "/with-locale", // 모든 로케일을 자동으로 처리합니다
        headers: [
          {
            key: "x-hello",
            value: "world",
          },
        ],
      },
      {
        // locale: false가 설정되어 있으므로 로케일을 자동으로 처리하지 않습니다
        source: "/nl/with-locale-manual",
        locale: false,
        headers: [
          {
            key: "x-hello",
            value: "world",
          },
        ],
      },
      {
        // 이것은 'en'이 defaultLocale이므로 '/'와 일치합니다
        source: "/en",
        locale: false,
        headers: [
          {
            key: "x-hello",
            value: "world",
          },
        ],
      },
      {
        // 이것은 /(en|fr|de)/(.*) 로 변환되므로 /:path*가 할 것처럼
        // 최상위 '/' 또는 '/fr' 경로와 일치하지 않습니다
        source: "/(.*)",
        headers: [
          {
            key: "x-hello",
            value: "world",
          },
        ],
      },
    ];
  },
};

Cache-Control

Next.js는 변경되지 않는 리소스에 대해 Cache-Control 헤더를 public, max-age=31536000, immutable로 설정합니다. 이는 오버라이드할 수 없습니다. 이러한 불변 파일에는 파일 이름에 SHA-해시가 포함되어 있어 안전하게 무기한 캐시할 수 있습니다. 예를 들어, 정적 이미지 가져오기가 있습니다. 이러한 자산에 대해서는 next.config.js에서 Cache-Control 헤더를 설정할 수 없습니다.

그러나 다른 응답이나 데이터에 대해서는 Cache-Control 헤더를 설정할 수 있습니다.

App Router를 사용한 캐싱에 대해 자세히 알아보세요.

옵션

CORS

교차 출처 리소스 공유(CORS)는 어떤 사이트가 귀하의 리소스에 접근할 수 있는지를 제어할 수 있게 해주는 보안 기능입니다. 특정 출처가 귀하의 Route Handler에 접근할 수 있도록 Access-Control-Allow-Origin 헤더를 설정할 수 있습니다.

async headers() {
    return [
      {
        source: "/api/:path*",
        headers: [
          {
            key: "Access-Control-Allow-Origin",
            value: "*", // 귀하의 출처를 설정하세요
          },
          {
            key: "Access-Control-Allow-Methods",
            value: "GET, POST, PUT, DELETE, OPTIONS",
          },
          {
            key: "Access-Control-Allow-Headers",
            value: "Content-Type, Authorization",
          },
        ],
      },
    ];
  },

X-DNS-Prefetch-Control

이 헤더는 DNS 프리페치를 제어하여 브라우저가 외부 링크, 이미지, CSS, JavaScript 등에 대한 도메인 이름 확인을 사전에 수행할 수 있게 합니다. 이 프리페치는 백그라운드에서 수행되므로, 참조된 항목이 필요할 때까지 DNS 확인이 완료될 가능성이 더 높습니다. 이는 사용자가 링크를 클릭할 때의 지연 시간을 줄입니다.

{
  key: 'X-DNS-Prefetch-Control',
  value: 'on'
}

Strict-Transport-Security

이 헤더는 브라우저에게 HTTP 대신 HTTPS를 사용해서만 접근해야 한다고 알려줍니다. 아래 구성을 사용하면, 현재와 미래의 모든 서브도메인이 2년의 max-age동안 HTTPS를 사용합니다. 이는 HTTP로만 서비스될 수 있는 페이지나 서브도메인에 대한 접근을 차단합니다.

Vercel에 배포하는 경우, next.config.js에서 headers를 선언하지 않는 한 이 헤더는 모든 배포에 자동으로 추가되므로 필요하지 않습니다.

{
  key: 'Strict-Transport-Security',
  value: 'max-age=63072000; includeSubDomains; preload'
}

X-Frame-Options

이 헤더는 사이트가 iframe 내에 표시될 수 있는지 여부를 나타냅니다. 이는 클릭재킹(Clickjacking) 공격을 방지할 수 있습니다.

이 헤더는 CSP의 frame-ancestors 옵션으로 대체되었으며, 최신 브라우저에서 더 나은 지원을 제공합니다(구성 세부 사항은 콘텐츠 보안 정책 참조).

{
  key: 'X-Frame-Options',
  value: 'SAMEORIGIN'
}

Permissions-Policy

이 헤더를 사용하면 브라우저에서 어떤 기능과 API를 사용할 수 있는지 제어할 수 있습니다. 이전에는 Feature-Policy라고 불렸습니다.

{
  key: 'Permissions-Policy',
  value: 'camera=(), microphone=(), geolocation=(), browsing-topics=()'
}

X-Content-Type-Options

이 헤더Content-Type 헤더가 명시적으로 설정되지 않은 경우 브라우저가 콘텐츠 유형을 추측하려는 시도를 방지합니다. 이는 사용자가 파일을 업로드하고 공유할 수 있는 웹사이트의 XSS 공격을 방지할 수 있습니다.

예를 들어, 사용자가 이미지를 다운로드하려고 하지만 실행 파일과 같은 다른 Content-Type으로 취급되어 악의적일 수 있는 경우입니다. 이 헤더는 브라우저 확장 프로그램 다운로드에도 적용됩니다. 이 헤더의 유일한 유효한 값은 nosniff입니다.

{
  key: 'X-Content-Type-Options',
  value: 'nosniff'
}

Referrer-Policy

이 헤더는 현재 웹사이트(출처)에서 다른 웹사이트로 이동할 때 브라우저가 포함하는 정보의 양을 제어합니다.

{
  key: 'Referrer-Policy',
  value: 'origin-when-cross-origin'
}

Content-Security-Policy

애플리케이션에 콘텐츠 보안 정책을 추가하는 방법에 대해 자세히 알아보세요.

버전 기록

버전변경 사항
v13.3.0missing 추가됨.
v10.2.0has 추가됨.
v9.5.0Headers 추가됨.