안녕하세요. Next.js 팀은 최근 약 1년 주기로 메이저 업데이트를 진행하고 있는데요. 최근에도 Next.js 14가 출시된 지 1년 만인 2023년 10월 21일에 Next.js 15가 발표 되었습니다. Next.js 14는 App Router의 안정성에 중점을 두어 큰 변경사항이 없었던 반면, Next.js 15는 주목할 만한 변화가 많이 포함되어 있습니다. 따라서 오늘은 Next.js 15의 주요 변경사항 5가지를 살펴보려고 합니다.

 

Next.js 15의 전체 업데이트 내용은 해당 링크에서 확인하실 수 있습니다.

 

1. `@next/codemod` CLI

가장 먼저 주목할 만한 변화는 `@next/codemod` CLI의 도입입니다. `@next/codemod`는 코드베이스를 최신 안정 버전이나 사전 릴리스 버전으로 업그레이드할 수 있게 해주며, 주요 릴리즈에 맞춰 기존 코드를 자동으로 변환해주는 도구입니다.

 

예를 들어, 이번 Next.js 15의 주요 업데이트인 Async Request APIs로의 마이그레이션을 할 때, 개발자가 일일이 코드를 찾아 수정할 필요 없이 아래와 같은 간단한 커맨드 하나로 마이그레이션이 가능합니다.

npx @next/codemod@latest next-async-request-api .

Next.js는 새로운 버전이 매우 빠르게 릴리즈되어 개발자들이 마이그레이션 과정에서 피로감을 많이 느꼈는데요. `@next/codemod`의 도입으로 이러한 문제를 해결하고 Next 생태계를 더욱 견고하게 만들고자 한 것으로 보입니다. 그 과정에서 휴면 에러도 줄일 수 있어서 많은 개발자들과 팀이 환영할 만한 기능이네요!

 

다만, 일부 커뮤니티에서는 대규모 프로젝트, 특히 모노레포 환경에서 호환성과 의존성 문제가 보고되고 있어 안정화에 시간이 더 필요해 보입니다. Vercel은 Turborepo 프로젝트가 있는 만큼 모노레포 환경에서도 호환이 얼른 이뤄졌으면 합니다.

 

 

2. Async Request APIs (Breaking Change)

두 번째로 주목할 만한 변화는 기존의 몇몇 API들이 비동기 API로 전환된 것입니다. 변경된 API는 `cookies`, `headers`, `params`, `searchParams`, `draftMode` 입니다.

 

변경 이유로는 향후 서버 사이드 렌더링의 효율성과 성능을 개선하기 위함이라고 하네요. 변경된 API들은 대부분 개인화와 관련된 요소들인데요. 이러한 API를 사용하는 컴포넌트는 매 요청마다 새로 렌더링이 필요합니다. 반면, 개인화가 필요 없는 컴포넌트는 리렌더링이 불필요하죠. 따라서 이번 변경으로 요청 전에 준비할 수 있는 부분과 요청 후에 처리해야 하는 부분을 명확하게 구분하여 최적화하는 것이 목표로 보입니다. 변경된 코드를 보면 이 이유가 더 명확히 들어나는데요.

 

Next.js 14에서 cookies API 사용할 때:

import { cookies } from 'next/headers'
 
export default function Page() {
  const cookieStore = cookies()
  const theme = cookieStore.get('theme')
  return '...'
}

변경 후:

import { cookies } from 'next/headers';
 
export async function AdminPanel() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
 
  // ...
}

기존에는 cookies API가 동기식이어서 요청 전에 해당 컴포넌트를 준비할 수 있는지 알 수 없었는데요. 이제는 cookies API가 비동기로 변경되어 요청 전에 준비할 수 있는 부분과 요청 후에 처리해야 하는 부분을 async를 통해 명확하게 구분할 수 있게 되었습니다!

 

개인적인 생각

Next.js는 Partial Prerendering(PPR)을 미래 웹 애플리케이션 개발의 기본 모델로 제시하며 꾸준히 실험을 진행해왔습니다. PPR은 동적 렌더링과 정적 렌더링을 페이지가 아닌 컴포넌트 단위로 전환하는 것이 핵심인데요. 이번 변경사항은 더욱 정교한 PPR 구현을 위한 로드맵의 일환으로 보입니다.

 

사실 이번에 변경된 API에 문제가 있긴 했습니다. 실제로 제가 직접 경험한 바로는, cookies API를 사용할 때 해당 API가 비동기 API가 아님에도 불구하고, 이를 사용하는 함수가 비동기 함수가 아니면 에러가 발생했던 경험이 있습니다. 따라서 아래와 같이 API를 사용하는 모든 함수는 반드시 비동기 함수로 선언해야 했습니다.

 import { cookies } from 'next/headers'
 
async function delete(data) {
  cookies().set('name', '') // Next.js 14에서 비동기 API가 아님에도 비동기 함수에서만 사용이 가능하다.
}

JavaScript 문법적으로도 어색했고, Next.js 문서를 읽지 않으면 알기 어려운 부분이었기에 문제가 있다고 생각했는데, 이번 변경으로 API 사용이 더 일관되고 명확해져서 다행이네요.

 

 

3. Caching Semantics(Breaking Change)

Next.js 15에서 기존의 캐시 휴리스틱도 변경되었습니다. 기존에는 성능 최적화를 위해 기본적으로 캐싱이 설정되어 있었지만, 이로 인해 의도한 대로 동작하지 않는 경우가 있어 개발자들의 불만이 있었고, 결과적으로 GET Route Handlers와 Client Router Cache의 기본 설정이 '캐싱됨'에서 '캐싱되지 않음'으로 변경되었다고 합니다.

 

사실 저는 이 부분에서 큰 이슈를 겪지 않았지만, fetch를 사용할 때 기본적으로 캐시가 되지 않을 것이라고 예상하며 사용하기 때문에 이번 변경이 더 자연스럽게 느껴지네요. Next.js가 이렇게 커뮤니티의 피드백을 적극적으로 수용하고 변경하는 것은 매우 좋은 점인 것 같습니다.

 

 

4. React 19 Support

Next.js 15는 React 19를 지원한다고 합니다. 사실 이 부분은 매우 놀라운 소식인데요. React 19가 아직 RC(Release Candidate) 버전만 제공하고 있기 때문입니다. Next.js팀은 실제 애플리케이션에 대한 광범위한 테스트와 React 팀과의 긴밀한 협력을 통해 안정성(?)에 대한 확신을 얻었다고 합니다. App router는 자동으로 React 19 RC를 사용하며 Pages Router를 사용하는 경우 준비가 되면 React 19로 업그레이드 할 수 있다고 하네요.

 

React19의 가장 큰 변화는 새로운 컴파일러의 도입일텐데요. 새로운 컴파일러는 useCallback, useMemo, memo와 같은 코드 최적화 수단 없이도 자동으로 최적화를 수행합니다. 덕분에 성능 최적화에 대한 부담이 줄어들어 코드 가독성이 향상될 것으로 보입니다. 인스타그램은 이미 이 컴파일러를 사용 중이며, Next 15에서는 실험적 기능으로 제공됩니다. 다만 새로운 컴파일러는 현재 Babel 플러그인으로만 사용 가능해서 개발 및 빌드 시간이 더 오래 걸린다는 점을 참고하시기 바랍니다.

 

다음으로 떠오르는 React19 기능으로는 useActionState와 같은 Form을 더욱 선언적으로 관리할 수 있는 훅과 비동기를 새롭게 다루는 use 훅이 있습니다. 안정성에 대해서는 아직 확신할 수 없지만, 이러한 시도는 매우 인상적이네요. 다만 이러한 기능들은 충분히 안정화된 후에 프로덕션에 도입하시기를 권장드립니다.

 

React 19의 주요 변화에 대해 더 자세히 알고 싶으시다면 What's New in React 19? 글을 참고하셔도 좋을 듯 합니다.

 

 

5. Turbopack Dev

제가 가장 기다려왔던 내용입니다. Turbopack을 사용한 개발 환경 빌드가 드디어 stable 단계에 도달했다고 합니다. Next.js로 개발하다 보면 첫 페이지 로딩이나 수정 후 반영에 시간이 꽤 오래 걸리는데요. 처음에는 괜찮지만 시간이 지날수록 이러한 지연이 피로감으로 쌓이게 됩니다. Next.js도 이 문제를 인지하고 Turbopack 오픈소스 프로젝트를 통해 해결하고자 노력해왔습니다. 그리고 마침내 stable 단계에 진입했네요.

 

Next.js가 발표한 내용에 따르면 아래와 같은 성능 개선이 이루어졌다고 합니다.

  • 로컬 서버 시작이 최대 76.7% 더 빠른 속도를 보입니다.
  • Fast Refresh를 통한 코드 업데이트가 최대 96.3% 더 빠른 속도를 보입니다.
  • 캐싱 없이도 초기 라우트 컴파일이 최대 45.8% 더 빠른 속도를 보입니다 (Turbopack은 아직 디스크 캐싱을 지원하지 않습니다)

 

방금 진행하는 프로젝트에서 간단하게 마이그레이션하고 `next dev --turbo`를 적용해보니 정말 신세계네요. 개발이 10배는 재미있어지는 기분입니다. 공식 발표된 수치만큼의 개선인지는 정확히 알 수 없지만, 성능 향상을 확실히 체감할 수 있었습니다.

 

다만, 일부 커뮤니티에서 Turbopack 활성화 시 빌드 실패 에러를 보고하고 있어서, 사이드 프로젝트 외의 중요한 프로젝트에 적용하기까지는 조금 더 시간이 필요해 보입니다.

 

 

마무리하며

지금까지 Next.js 15의 주요 변경사항 5가지와 이에 대한 개인적인 의견을 살펴보았습니다. Next.js 15에 대한 평가는 크게 두 가지로 나뉘는 것 같습니다. 대다수는 Turbopack과 React 19 지원으로 인한 성능 향상과 개발자 경험 개선을 긍정적으로 평가하고 있지만, 반면 일부에서는 React 19가 아직 RC 상태이고 codemod의 호환성 문제가 있다는 점을 들어 다소 급진적인 업데이트라는 의견을 제시하시는 분들도 있습니다.

 

개인적으로 저도 App Router 초기에 잦은 버그로 고생한 경험이 있어서 Next.js를 무조건적으로 지지할 수는 없습니다. 하지만 이전의 문제들을 지속적으로 해결하고 개선해나가면서 프론트엔드 개발 생태계를 발전시키는 모습은 인상적이라고 생각합니다. 다만 Next.js 15가 더 성숙해지고 서드파티 라이브러리들이 Next.js 15와 React 19에 적응하는 데 시간이 필요하므로, 프로덕션 환경에 도입하기까지는 시간이 걸릴 것 같습니다.

 

앞으로도 계속 이슈를 모니터링하면서 안정성이 확보되면 얼른 Next.js 15로 마이그레이션하고 싶네요! 긴 글 읽어주셔서 감사합니다.