Post

Next.js Blog - Next.js 15 RC (2024.05.23) 번역

본 포스팅은 Next.js의 공식 블로그에 포스팅된 내용을 번역한 것입니다.

Next.js 15 RC

이제 Next.js 15 릴리스 후보를 사용할 수 있습니다. 이 초기 버전을 사용하면 곧 출시될 안정 버전에 앞서 최신 기능을 테스트 할 수 있습니다.

  • React : React 19 RC, React Compiler (Experimental) 및 하이드레이션 오류 개선 지원
  • Caching : fetch requests, GET Route Handlers 및 client navigations가 더 이상 기본적으로 캐시되지 않습니다.
  • Partial Prerendering (Experimental) : 점진적 적용을 위한 새로운 레이아웃 및 페이지 구성 옵션
  • next/after (Experimental) : 응답 스트리밍이 완료된 후 코드를 실행하는 새로운 API
  • create-next-app : 로컬 개발에서 터보팩을 사용할 수 있도록 디자인 업데이트되고 새로운 플래그가 추가되었습니다.
  • Bundling external packages (Stable) : 앱 및 페이지 라우터를 위한 새로운 구성 옵션

지금 바로 Next.js 15 RC를 사용해 보세요.

1
npm install next@rc react@rc react-dom@rc

Note
Next.js 15 RC 문서는 Next.js 15 GA까지 rc.nextjs.org/docs에서 볼 수 있습니다.

React 19 RC

Next.js 앱 라우터는 프레임워크용 React 카나리아 채널을 기반으로 구축되었기 때문에 개발자는 v19 릴리스 전에 이 새로운 React API를 사용하고 피드백을 제공할 수 있습니다. Next.js 15 RC는 이제 액션과 같은 클라이언트와 서버를 위한 새로운 기능을 포함하는 React 19 RC를 지원합니다.

자세한 내용은 Next.js 15 업그레이드 가이드React 19 업그레이드 가이드를 읽고 React Conf 키노트를 시청하세요.

Note
일부 서드 파티 라이브러리는 아직 React 19와 호환되지 않을 수 있습니다.

React Compiler (Experimental)

React Compiler는 Meta의 React 팀에서 만든 새로운 실험적인 컴파일러입니다. 이 컴파일러는 일반 JavaScript 의미론과 React 규칙을 이해함으로써 코드를 심층적으로 이해하여 코드에 자동 최적화를 추가할 수 있습니다. 컴파일러는 useMemouseCallback과 같은 API를 통해 개발자가 수동으로 메모이제이션해야하는 양을 줄여 코드를 더 간단하고 유지 관리하기 쉽게 합니다.

Next.js 15에서는 React Compiler에 대한 지원이 추가되었습니다.

babel-plugin-react-compiler를 설치합니다.

1
npm install babel-plugin-react-compiler

그런 다음 next.config.jsexperimental.reactCompiler 옵션을 추가합니다.

1
2
3
4
5
6
7
8
9
// next.config.ts

const nextConfig = {
  experimental: {
    reactCompiler: true,
  },
};
 
module.exports = nextConfig;

선택적으로 다음과 같이 컴파일러가 ‘opt-in’ 모드에서 실행되도록 구성할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
// next.config.ts

const nextConfig = {
  experimental: {
    reactCompiler: {
      compilationMode: 'annotation',
    },
  },
};
 
module.exports = nextConfig;

Note
React Compiler는 현재 Babel 플러그인을 통해서만 Next.js에서 사용할 수 있으며, 이로 인해 빌드 시간이 느려질 수 있습니다.

React Compiler와 사용 가능한 Next.js 구성 옵션에 대해 자세히 알아보세요.

Hydration error improvements

Next.js 14.1에서는 오류 메시지와 하이드레이션 오류가 개선했습니다. Next.js 15에서는 개선된 하이드레이션 오류 보기를 추가하여 이러한 기능을 계속 개선하고 있습니다. 이제 하이드레이션 오류에는 오류의 소스 코드와 함께 문제 해결 방법에 대한 제안이 표시됩니다.

예를 들어 이것을 Next.js 14.1의 이전 하이드레이션 오류 메시지였습니다.

Desktop View

Next.js 15 RC에서는 다음과 같이 개선했습니다.

Desktop View

Caching updates

Next.js 앱 라우터에서 의견에 따른 캐싱 기본값이 출시되었습니다. 이는 기본적으로 성능이 좋은 옵션을 제공하고 필요한 경우 opt-out할 수 있는 기능을 제공하도록 설계되었습니다.

여러분의 피드백을 바탕으로 caching heuristics과 Partial Prerendering(PPR)과 같은 프로젝트 및 fetch를 사용하는 타사 라이브러리와의 상호 작용 방식을 재평가했습니다.

Next.js 15에서는 fetch requests, GET Route Handlers, Client Router Cache에 대한 캐싱 기본값을 캐시됨에서 캐시되지 않음으로 변경합니다. 이전 동작을 유지하려면 캐싱을 계속 사용하도록 opt-in할 수 있습니다.

앞으로 몇 달 동안 Next.js의 캐싱을 지속적으로 개선할 예정이며, 자세한 내용은 Next.js 15 GA 발표에서 공유할 예정입니다.

fetch Requests are no longer cached by default

Next.js는 Web fetch API 캐시 옵션을 사용하여 서버 측 가져오기 요청이 프레임워크의 영구 HTTP 캐시와 상호 작용하는 방식을 구성합니다.

1
fetch('https://...', { cache: 'force-cache' | 'no-store' });
  • force-cache : 캐시(존재하는 경우) 또는 원격 서버에서 리소스를 가져와서 캐시를 업데이트합니다.
  • no-store : 요청할 때마다 원격 서버에서 리소스를 가져오고 캐시를 업데이트 하지 않습니다.

Next.js 14에서는 동적 함수 또는 동적 구성 옵션을 사용하지 않는 한 cache 옵션이 제공되지 않으면 기본적으로 force-cache가 사용되었습니다. Next.js 15에서는 cache 옵션이 제공되지 않으면 기본적으로 no-store가 사용됩니다. 즉, 기본적으로 fetch requests가 캐시되지 않습니다.

다음과 같은 방법으로 여전히 fetch requests 캐싱을 선택할 수 있습니다.

  • Single fetch call에서 cache optionforce-cache로 설정하기
  • Single route에서 dynamic route config optionforce-static으로 설정하기
  • 레이아웃 또는 페이지의 모든 가져오기 요청이 명시적으로 자체 cache option을 지정하지 않는 한 force-cache를 사용하도록 재정의하려면 fetchCache route config optiondefault-cache로 설정합니다.

GET Route Handlers are no longer cached by default

Next.js 14에서는 동적 함수 또는 동적 구성 옵션을 사용하지 않는 한 GET HTTP 메서드를 사용하는 라우트 핸들러가 기본적으로 캐시되었습니다. Next.js 15에서는 GET 함수가 기본적으로 캐시되지 않습니다. export dynamic = 'force-static'과 같은 정적 경로 구성 옵션을 사용하여 캐싱을 선택할 수 있습니다. sitemap.ts, opengraph-image.tsx, icon.tsx와 같은 특수 경로 핸들러와 기타 metadata files는 동적 함수 또는 동적 구성 옵션을 사용하지 않는 한 기본적으로 정적으로 유지됩니다.

Client Router Cache no longer caches Page components by default

Next.js 14.2에서는 라우터 캐시의 사용자 지정 구성을 허용하기 위해 실험적인 staleTimes 플래그를 도입했습니다. Next.js 15에서도 이 플래그는 여전히 액세스할 수 있지만 페이지 세그먼트에 대한 기본 동작으로 staleTime0이 되도록 변경되었습니다. 즉, 앱을 탐색할 때 클라이언트는 탐색의 일부로 활성화되는 페이지 컴포넌트의 최신 데이터를 항상 반영합니다. 그러나 변경되지 않는 중요한 동작이 있습니다.

  • Partial rendering을 계속 지원하기 위해 공유 레이아웃 데이터는 서버에서 다시 가져오지 않습니다.
  • 브라우저에서 스크롤 위치를 복원할 수 있도록 캐시에서 Back/forward로 이동이 계속 복원됩니다.
  • Loading.js는 5분 동안 캐시된 상태로 유지됩니다(또는 staleTimes.static 구성의 값).

다음 구성을 설정하여 이전 클라이언트 라우터 캐시 동작을 선택할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
// next.config.ts

const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
    },
  },
};
 
module.exports = nextConfig;

Incremental adoption of Partial Prerendering (Experimental)

Next.js 14에서는 동일한 페이지에서 정적 렌더링과 동적 렌더링을 결합하는 최적화 기능인 Partial Prerendering(PPR)을 도입했습니다.

cookies(), headers(), uncached data requests과 같은 동적 함수를 사용하지 않는 한 현재 Next.js는 기본적으로 정적 렌더링으로 설정되어 있습니다. 이러한 API는 전체 경로를 동적 렌더링으로 선택합니다. PPR을 사용하면 모든 동적 UI를 서스펜스 경계로 래핑할 수 있습니다. 새 요청이 들어오면 Next.js는 즉시 정적 HTML 셸을 제공한 다음 동일한 HTTP 요청에서 동적 부분을 렌더링하고 스트리밍합니다.

점진적인 적용을 위해 특정 레이아웃과 페이지를 PPR로 선택하기 위한 experimental_ppr 경로 구성 옵션을 추가했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// app/page.jsx

import { Suspense } from "react"
import { StaticComponent, DynamicComponent } from "@/app/ui"
 
export const experimental_ppr = true
 
export default function Page() {
  return {
     <>
	     <StaticComponent />
	     <Suspense fallback={...}>
		     <DynamicComponent />
	     </Suspense>
     </>
  };
}

새 옵션을 사용하려면 next.config.js 파일에서 experimental.ppr 구성을 'incremental'으로 설정해야 합니다.

1
2
3
4
5
6
7
8
9
// next.config.ts

const nextConfig = {
  experimental: {
    ppr: 'incremental',
  },
};
 
module.exports = nextConfig;

모든 세그먼트에 PPR이 활성화되면 ppr 값을 true로 설정하고 전체 앱과 향후 모든 경로에 대해 활성화하는 것이 안전하다고 간주합니다. PPR 로드맵에 대한 자세한 내용은 Next.js 15 GA 블로그 게시물에서 확인할 수 있습니다. Partial Prerendering에 대해 자세히 알아보세요.

Executing code after a response with next/after (Experimental)

사용자 요청을 처리할 때 서버는 일반적으로 응답을 계산하는 것과 직접 관련된 작업을 수행합니다. 하지만 logging, analytics 및 external system synchronization과 같은 작업을 수행해야 할 수도 있습니다. 이러한 작업은 응답과 직접 관련이 없으므로 사용자가 완료될 때까지 기다릴 필요가 없습니다. 서버리스 함수는 응답이 종료되는 즉시 계산을 중지하기 때문에 사용자에게 응답한 후 작업을 연기하는 것은 어려운 문제입니다.

after()는 응답 스트리밍이 완료된 후 처리할 작업을 예약하여 기본 응답을 차단하지 않고 보조 작업을 실행할 수 있도록 함으로써 이 문제를 해결하는 새로운 실험적 API입니다. 이를 사용하려면 next.config.jsexperimental.after를 추가하세요.

1
2
3
4
5
6
7
8
9
// next.config.ts

const nextConfig = {
  experimental: {
    after: true,
  },
};
 
module.exports = nextConfig;

그런 다음 Server Components, Server Actions, Route Handlers 또는 Middleware에서 함수를 가져옵니다.

1
2
3
4
5
6
7
8
9
10
11
12
import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // Secondary task
  after(() => {
    log();
  });
 
  // Primary task
  return <>{children}</>;
}

next/after에 대해 자세히 알아보세요.

create-next-app updates

Next.js 15에서는 create-next-app을 새로운 디자인으로 업데이트했습니다.

Desktop View

create-next-app을 실행하면 로컬 개발을 위해 Turbopack을 활성화할지 묻는 새 프롬프트가 표시됩니다. 디폴트는 No입니다.

1
✔ Would you like to use Turbopack for next dev? … No / Yes

--turbo 플래그를 사용하여 터보팩을 활성화할 수도 있습니다.

1
npx create-next-app@rc --turbo

새 프로젝트를 더욱 쉽게 시작할 수 있도록 CLI에 새로운 --empty 플래그가 추가되었습니다. 이렇게하면 불필요한 파일과 스타일이 모두 제거되어 최소한의 “hello world” 페이지가 생성됩니다.

1
npx create-next-app@rc --empty

Optimizing bundling of external packages (Stable)

외부 패키지를 번들로 제공하면 애플리케이션의 콜드 스타트 성능을 향상시킬 수 있습니다. 앱 라우터에서 외부 패키지는 기본적으로 번들로 제공되며, 새로운 serverExternalPackages 구성 옵션을 사용하여 특정 패키지를 선택 해제할 수 있습니다. 페이지 라우터에서는 외부 패키지가 기본적으로 번들로 제공되지 않지만 기존 transpilePackages 옵션을 사용하여 번들할 패키지 목록을 제공할 수 있습니다. 이 구성 옵션을 사용하면 각 패키지를 지정해야 합니다. 앱과 페이지 라우터 간의 구성을 통합하기 위해 앱 라우터의 기본 자동 번들링과 일치하는 새로운 옵션인 bundlePagesRouterDependencies를 도입합니다. 그런 다음 필요한 경우 serverExternalPackages를 사용하여 특정 패키지를 선택 해제할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
// next.config.ts

const nextConfig = {
  // Automatically bundle external packages in the Pages Router:
  bundlePagesRouterDependencies: true,
  // Opt specific packages out of bundling for both App and Pages Router:
  serverExternalPackages: ['package-name'],
};
 
module.exports = nextConfig;

optimizing external packages에 대해 자세히 알아보세요.

Other Changes

  • [Breaking] 이제 최소 React 버전은 19 RC입니다.
  • [Breaking] next/image: 선택적 종속성으로서 sharp를 위해 squoosh를 제거했습니다.
  • [Breaking] next/image: 기본 Content-Dispositionattachment로 변경.
  • [Breaking] next/image: src에 선행 또는 후행 공백이 있을 때 오류 발생
  • [Breaking] Middleware: 권장되지 않는 리액트 API 가져오기를 제한하기 위해 react-server 조건 적용
  • [Breaking] next/font: 외부 @next/font 패키지에 대한 지원 제거.
  • [Breaking] next/font: font-family 해싱 제거
  • [Breaking] Caching: force-dynamic은 이제 가져오기 캐시에 no-store 기본값을 설정합니다.
  • [Breaking] Config: swcMinify, missingSuspenseWithCSRBailoutoutputFileTracing 동작을 기본적으로 활성화하고 더 이상 사용되지 않는 옵션을 제거합니다.
  • [Breaking] 속도 인사이트에 대한 자동 계측 제거(이제 전용 @vercel/speed-insights 패키지를 사용해야 함).
  • [Improvement] development 및 production에서 사이트맵 URL 정렬하기
  • [Improvement] Metadata: Vercel에서 호스팅할 때 metadataBase에 대한 환경 변수 폴백 업데이트 (PR)
  • [Improvement] optimizePackageImports에서 네임스페이스와 네임 임포트가 혼합된 트리 흔들림 수정
  • [Improvement] Parallel Routes: 알려진 모든 파라미터로 타의 추종을 불허하는 캐치올 경로 제공
  • [Improvement] bundlePagesExternals 구성이 이제 안정적이며 이름이 bundlePagesRouterDependencies으로 변경되었습니다.
  • [Improvement] serverComponentsExternalPackages 구성이 이제 안정적이며 serverExternalPackages로 이름이 변경되었습니다.
  • [Improvement] create-next-app: 새 프로젝트는 기본적으로 모든 .env 파일을 무시합니다.
  • [Docs] 인증 문서 개선
  • [Docs] @next/env 패키지

자세한 내용은 업그레이드 가이드를 확인하세요.

Contributors

Next.js는 3,000명이 넘는 개인 개발자, Google 및 Meta와 같은 업계 파트너, 그리고 Vercel의 핵심 팀이 함께 노력한 결과물입니다. 이 릴리스는 다음에서 제공했습니다.

Huge thanks to @devjiwonchoi, @ijjk, @Ethan-Arrowood, @sokra, @kenji-webdev, @wbinnssmith, @huozhi, @domdomegg, @samcx, @Jaaneek, @evanwinter, @wyattjoh, @kdy1, @balazsorban44, @feedthejim, @ztanner, @ForsakenHarmony, @kwonoj, @delbaoliveira, @stipsan, @leerob, @shuding, @xiaohanyu, @timneutkens, @dvoytenko, @bobaaaaa, @bgw, @gaspar09, @souporserious, @unflxw, @kiner-tang, @Ehren12, @EffectDoplera, @IAmKushagraSharma, @Auxdible, @sean-rallycry, @Jeffrey-Zutt, @eps1lon, @jeanmax1me, @unstubbable, @NilsJacobsen, @PaulAsjes, @adiguno, @ryan-nauman, @zsh77, @KagamiChan, @steveluscher, @MehfoozurRehman, @vkryachko, @chentsulin, @samijaber, @begalinsaf, @FluxCapacitor2, @lukahartwig, @brianshano, @pavelglac, @styfle, @symant233, @HristovCodes, @karlhorky, @jonluca, @jonathan-ingram, @mknichel, @sopranopillow, @Gomah, @imddc, @notrab, @gabrielrolfsen, @remorses, @AbhiShake1, @agadzik, @ryota-murakami, @rishabhpoddar, @rezamauliadi, @IncognitoTGT, @webtinax, @BunsDev, @nisabmohd, @z0n, @bennettdams, @joeshub, @n1ckoates, @srkirkland, @RiskyMH, @coopbri, @okoyecharles, @diogocapela, @dnhn, @typeofweb, @davidsa03, @imranolas, @lubieowoce, @maxhaomh, @mirasayon, @blvdmitry, @hwangstar156, @lforst, @emmerich, @christian-bromann, @Lsnsh, @datner, @hiro0218, @flybayer, @ianmacartney, @ypessoa, @ryohidaka, @icyJoseph, @Arinji2, @lovell, @nsams, @Nayeem-XTREME, @JamBalaya56562, @Arindam200, @gaojude, @qqww08, @todor0v, @coltonehrman, and @wiesson for helping!

This post is licensed under CC BY 4.0 by the author.