Next.js Conf에서 발표했듯이, Next.js 14는 우리의 가장 집중적인 릴리즈이에요:
- Turbopack: App & Pages Router에 대한 5,000개의 테스트가 통과됨
- 53% 더 빠른 로컬 서버 시작
- Fast Refresh와 함께 94% 더 빠른 코드 업데이트
- Server Actions (안정화): 점진적으로 향상된 변화
- 캐싱 및 재검증과 통합
- 단순한 함수 호출, 또는 폼과 자연스럽게 작동
- Partial Prerendering (미리보기): 빠른 초기 정적 응답 + 동적 콘텐츠 스트리밍
- Next.js Learn (신규): App Router, 인증, 데이터베이스 등을 교육하는 무료 강좌
Next.js Compiler: Turbocharged
Next.js 13부터, 우리는 Next.js의 Pages 및 App Router에서 로컬 개발 성능을 향상시키기 위해 노력해 왔어요.
이전에는 이러한 노력을 지원하기 위해 next dev 및 Next.js의 다른 부분을 다시 작성했지만 우리는 이제 접근 방식을 더 점진적으로 변경했어요. 이는 우리의 Rust 기반 컴파일러가 곧 안정화될 것이며, 우리는 모든 Next.js 기능을 지원하는데 중점을 뒀어요.
Turbopack, 우리의 기본 Rust 엔진을 사용하여 next dev에 대한 5,000개의 통합 테스트가 이제 막 통과됐어요. 이 테스트들은 7년 동안의 버그 수정 및 재현을 포함하고 있어요.
vercel.com에서 큰 Next.js 애플리케이션을 테스트할 때의 결과는 다음과 같아요:
- 최대 53.3% 더 빠른 로컬 서버 시작
- Fast Refresh와 함께 최대 94.7% 더 빠른 코드 업데이트
이 벤치마크는 대규모 응용 프로그램 (및 큰 모듈 그래프)에서 예상할 수 있는 성능 개선의 실질적인 결과예요. next dev --turbo를 사용할 때 이제 90%의 next dev 테스트가 통과하므로, 더 빠르고 신뢰할 수 있는 성능을 일관되게 경험할 수 있어야 해요.
100%의 테스트가 통과되면, 우리는 나중에 마이너 릴리즈에서 Turbopack을 안정 버전으로 전환할 예정이에요. 또한 사용자 지정 구성 및 에코시스템 플러그인을 위한 웹팩 사용도 계속 지원할 예정이에요.
areweturboyet.com에서 테스트 통과 비율을 확인할 수 있어요.
Forms and Mutations
Next.js 9에는 프론트엔드 코드와 함께 백엔드 엔드포인트를 빠르게 빌드하는 방법인 API 경로가 도입됐었죠.
예를 들면, api/ 디렉터리에 새 파일을 만들어야 해요:
// pages/api/submit.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
const data = req.body;
const id = await createItem(data);
res.status(200).json({ id });
}
그런 다음, 클라이언트 측에서는 React와 onSubmit과 같은 이벤트 핸들러를 사용하여 API 라우트에 대한 패치를 만들 수 있어요.
// pages/index.tsx
import { FormEvent } from 'react';
export default function Page() {
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const response = await fetch('/api/submit', {
method: 'POST',
body: formData,
});
const data = await response.json();
// ...
}
return (
<form onSubmit={onSubmit}>
<input type="text" name="name" />
<button type="submit">Submit</button>
</form>
);
}
이제 Next.js 14에서, 우리는 데이터를 변경할 때 개발자 경험을 단순화하려고 해요. 또한, 사용자가 느린 네트워크 연결을 가지고 있거나 저성능의 장치에서 폼을 제출할 때 사용자 경험을 개선하려고 해요.
Server Actions (Stable)
API 라우트를 수동으로 만들 필요가 없다면 어떨까요? 대신 React 컴포넌트에서 직접 호출하는 서버에서 안전하게 실행되는 함수를 정의할 수 있어요.
App Router는 프레임워크가 새로운 기능을 채택하기에 안정적인 React canary 채널을 기반으로 구축되었어요.
v14에서 Next.js는 안정적인 서버 액션을 포함하는 최신 React canary로 업그레이드 됐어요.
이전의 페이지 라우터 예제는 다음과 같이 단순화해보자면:
// app/page.tsx
export default function Page() {
async function create(formData: FormData) {
'use server';
const id = await createItem(formData);
}
return (
<form action={create}>
<input type="text" name="name" />
<button type="submit">Submit</button>
</form>
);
}
서버 액션은 과거에 서버 중심 프레임워크를 사용해 본 적이 있는 개발자라면 누구나 친숙하게 느낄 것이에요. 양식 및 FormData 웹 API와 같은 웹 기본 사항을 기반으로 구축되었어요.
form을 통해 서버 액션을 사용하는 것은 점진적인 향상을 위해 유용하지만, 필수는 아니에요. form 없이 함수로 직접 호출할 수도 있어요. TypeScript를 사용하면 클라이언트와 서버 간에 완전한 end-to-end 타입의 안정성을 확보할 수 있어요.
데이터를 변형하거나 페이지를 다시 렌더링하거나 리디렉션 하는 것은 하나의 네트워크 라운드트립에서 발생할 수 있으며, 업스트리밍 제공자가 느려도 클라이언트에 올바른 데이터가 표시돼요. 또한, 다른 액션을 구성하고 재사용하거나 동일한 라우트에서 여러 다른 액션을 포함할 수 있어요.
Caching, Revalidating, Redirecting, and more 서버 액션은 전체 앱 라우터 모델에 깊게 통합되어 있어요. 다음과 같은 작업을 확인해 볼까요:
- revalidatePath() 또는 revalidateTag()를 사용하여 캐싱된 데이터 재검증
- redirect()를 통한 다른 라우트로의 리디렉션
- cookies()를 통해 쿠키 설정 및 읽기
- useOptimistic()을 사용하여 낙관적인 UI 업데이트 처리
- useFormState()를 사용하여 서버의 오류 포착 및 표시
- useFormStatus()를 사용하여 클라이언트에서의 로딩 상태 표시
Partial Prerendering (Preview)
빠른 초기 정적 응답을 제공하는 동적 콘텐츠용 컴파일러 최적화 기능인 부분 프리렌더링의 미리 보기를 Next.js에 적용하는 작업을 진행 중에 있어요.
부분 사전 렌더링은 서버 사이드 렌더링(SSR), 정적 사이트 생성(SSG), 및 점진적인 정적 재검증(ISR)에 대한 10년간의 연구 및 개발을 기반으로 해요.
Motivation
여러분의 피드백을 들었습니다. 현재 고려해야 할 런타임, 구성 옵션, 렌더링 방법등이 너무 많네요.
정적인 속도와 안정성을 원하면서도 완전히 동적이고 개인화된 응답이 지원되길 원하시는군요.
뛰어난 성능과 개인화는 복잡성의 비용으로 이루어져서는 안 돼요.
우리의 도전은 개발자 경험을 개선하고, 새로운 API를 개발자에게 배우게 하지 않는 기존 모델을 단순화하는 것이었어요. 서버 측 콘텐츠의 부분 캐싱이 이미 존재했지만, 이러한 접근법은 우리가 지향하는 개발자 경험과 구성 가능성 목표를 충족해야 하죠.
부분 사전 렌더링은 새로운 API를 배울 필요가 없어요.
Built on React Suspense
부분 사전 렌더링은 서스펜스 경계에 따라 정의돼요. 작동 방식을 확인해 보죠. 다음 전자상거래 페이지를 생각해 봐요:
// app/page.tsx
export default function Page() {
return (
<main>
<header>
<h1>My Store</h1>
<Suspense fallback={<CartSkeleton />}>
<ShoppingCart />
</Suspense>
</header>
<Banner />
<Suspense fallback={<ProductListSkeleton />}>
<Recommendations />
</Suspense>
<NewProducts />
</main>
);
}
부분 사전 렌더링을 사용하면, 이 페이지는 당신의 <Suspense /> 경계에 따라 정적 쉘을 생성해요. React Suspense의 폴백이 사전 렌더링 되죠.
Suspense 폴백은 쉘에서 동적 컴포넌트로 대체돼요, 즉 쿠키를 읽어 카트를 결정하거나 사용자를 기반으로 배너를 표시해요.
요청이 발생하면 정적 HTML 쉘은 바로 제공돼요.
<main>
<header>
<h1>My Store</h1>
<div class="cart-skeleton">
<!-- Hole -->
</div>
</header>
<div class="banner" />
<div class="product-list-skeleton">
<!-- Hole -->
</div>
<section class="new-products" />
</main>
<ShoppingCart />가 쿠키를 읽어 사용자 세션을 보기 때문에, 이 컴포넌트는 정적 쉘의 동일한 HTTP 요청의 일부로 스트리밍 돼요. 추가 네트워크 라운드트립이 필요하지 않아요.
// app/cart.tsx
import { cookies } from 'next/headers'
export default function ShoppingCart() {
const cookieStore = cookies()
const session = cookieStore.get('session')
return ...
}
가장 세분화된 정적 쉘을 가지려면 Suspense 경계가 추가로 필요할 수 있어요. 근데 요즘 loading.js를 이미 사용하고 있다면, 이것은 암시적 Suspense 경계이므로 정적 쉘을 생성하기 위해 변경할 필요가 없어요.
Coming soon
부분 사전 렌더링은 활발하게 개발 중이에요. 다가오는 마이너 릴리스에서 더 많은 업데이트를 공유할 예정이에요.
MetaData Improvements
페이지 콘텐츠를 서버에서 스트리밍 하기 전에 뷰포트, 색 구성표 및 테마에 대한 중요한 메타데이터를 먼저 브라우저로 보내야 해요.
이러한 메타 태그가 초기 페이지 콘텐츠와 함께 전송되도록 하면 테마 색상을 변경하거나 뷰포트 변경으로 인해 레이아웃이 변경되어 페이지가 깜박이는 것을 방지하여 더 나은 사용자 경험을 제공할 수 있어요.
Next.js 14에서는 블로킹 메타데이터와 비 블로킹 메타데이터를 분리했어요. 일부 메타데이터 옵션만 차단하며, 비차단 메타데이터가 부분적으로 미리 렌더링 된 페이지가 정적 셸을 제공하는 것을 방해하지 않도록 하려고 해요.
다음 메타데이터 옵션은 현재 사용되지 않고 있으며 향후 주요 버전에서 메타데이터에서 제거될 예정이에요:
- viewport: 초기 확대 및 뷰포트의 기타 속성 설정
- colorScheme: 뷰포트의 지원 모드 (밝게/어둡게) 설정
- themeColor: 뷰포트 주변의 크롬이 렌더링해야 할 색상 설정
Next.js 14에서는 이러한 옵션들을 대체하기 위해 새로운 옵션 viewport와 generateViewport가 있어요.
다른 모든 메타데이터 옵션은 동일하게 유지돼요.
'FrontEnd > React' 카테고리의 다른 글
React Todo에서 UX개선 (1) | 2023.04.28 |
---|---|
리액트에서 ...state 와 prev => ...prev 의 차이 (0) | 2023.04.25 |
최초 로그인시 토큰이 null로 보내지는 버그 (0) | 2023.04.16 |
Create-React-App는 무엇을 설치해주나? (0) | 2023.04.12 |
BrowserRouter vs HashRouter ? (0) | 2023.04.12 |