Vue3를 Next14로 마이그레이션 하는 업무가 생겨서 정리하는 Next14 주요 특징과 Vue3 비교
Concurrent Mode, Suspense, Middleware, Built-in Analytics
더 자세하게 알아보자
React 18에서 도입된 기능으로, 여러 버전의 UI를 동시에 준비할 수 있게 합니다. 이를 통해 애플리케이션이 더욱 반응성 있게 동작하며, 사용자의 장치 성능과 네트워크 속도에 맞게 유연하게 조정됩니다. Concurrent Mode는 단일 기능이 아니라, React 앱이 반응성을 유지하고 사용자의 장치 성능에 맞게 조정될 수 있도록 돕는 여러 기능의 집합입니다.
주요 특징
예시:
Concurrent Mode를 사용하여 무거운 컴포넌트를 렌더링하는 동안 메인 스레드를 차단하지 않는 Next.js 컴포넌트
import { useState, useTransition } from 'react';
function HeavyComponent() {
// 무거운 연산을 시뮬레이션
let now = performance.now();
while (performance.now() - now < 1000) {
// 인위적인 지연
}
return <div>Heavy Component Rendered</div>;
}
export default function HomePage() {
const [isPending, startTransition] = useTransition();
const [showHeavy, setShowHeavy] = useState(false);
const handleClick = () => {
startTransition(() => {
setShowHeavy((prev) => !prev);
});
};
return (
<div>
<button onClick={handleClick}>Toggle Heavy Component</button>
{isPending ? <div>Loading...</div> : showHeavy && <HeavyComponent />}
</div>
);
}
이 예시에서 useTransition을 사용하여 상태 업데이트를 연기하고, 무거운 컴포넌트를 준비하는 동안 UI가 반응성을 유지하도록 합니다.
Suspense는 코드 로드 및 데이터 로드를 기다리게 하고, 대기 중인 컴포넌트 트리에 대한 로딩 상태를 선언적으로 지정할 수 있게 합니다. 이는 코드 분할 및 데이터 페칭에 특히 유용합니다.
예시:
데이터 페칭 컴포넌트와 함께 Suspense를 사용하는 Next.js
import React, { Suspense } from 'react';
// 데이터 페칭 지연을 시뮬레이션
const fetchData = () => new Promise((resolve) => setTimeout(() => resolve('Data loaded'), 2000));
const DataComponent = React.lazy(() =>
fetchData().then((data) => ({
default: () => <div>{data}</div>,
}))
);
export default function HomePage() {
return (
<div>
<h1>Next.js 14 with React 18</h1>
<Suspense fallback={<div>Loading...</div>}>
<DataComponent />
</Suspense>
</div>
);
}
이 예시에서 React.lazy를 사용하여 동적으로 DataComponent를 가져오며, Suspense 컴포넌트는 DataComponent가 로딩되는 동안 로딩 상태 (<div>Loading...</div>)를 지정합니다.
Next.js 14는 이러한 기능들을 활용하여 매끄러운 사용자 경험을 제공합니다.
Concurrent Mode와 Suspense를 결합한 예시는 다음과 같습니다:
import React, { Suspense, useState, useTransition } from 'react';
const fetchData = () => new Promise((resolve) => setTimeout(() => resolve('Data loaded'), 2000));
const DataComponent = React.lazy(() =>
fetchData().then((data) => ({
default: () => <div>{data}</div>,
}))
);
export default function HomePage() {
const [isPending, startTransition] = useTransition();
const [showData, setShowData] = useState(false);
const handleClick = () => {
startTransition(() => {
setShowData((prev) => !prev);
});
};
return (
<div>
<h1>Next.js 14 with React 18</h1>
<button onClick={handleClick}>
{isPending ? 'Loading...' : 'Toggle Data Component'}
</button>
<Suspense fallback={<div>Loading...</div>}>
{showData && <DataComponent />}
</Suspense>
</div>
);
}
이 예시에서 버튼을 클릭하면 DataComponent의 로딩이 토글됩니다. useTransition 훅은 상태 업데이트를 연기하여 UI가 반응성을 유지하게 하고, Suspense는 DataComponent가 로딩되는 동안 로딩 상태를 처리합니다.
동시 다발적으로 API 요청을 처리할 수 있고, Concurrent Mode와 Suspense를 결합하여 반응성을 유지 한채 여러 개의 API 요청을 동시에 처리하고, 결과를 한꺼번에 렌더링할 수 있다.
Vue3의 Suspense는 주로 비동기 컴포넌트 로딩에 중점을 두고 있으며,
Next.js14의 Suspense는 Concurrent Mode와 결합하여 더 나은 성능 최적화 중점을 둔다.
중단 가능한 렌더링 (Interruptible Rendering)
사용자 경험 향상 (Improved User Experience)
// middleware.js
import { NextResponse } from 'next/server';
export function middleware(req) {
const { pathname } = req.nextUrl;
const token = req.cookies.get('token'); // 쿠키에서 인증 토큰을 가져옴
// 인증이 필요한 경로 설정
const protectedPaths = ['/dashboard', '/settings'];
// 인증이 필요한 경로에 대한 요청인지 확인
if (protectedPaths.includes(pathname)) {
// 토큰이 없으면 로그인 페이지로 리다이렉트
if (!token) {
return NextResponse.redirect('/login');
}
}
// 요청을 그대로 전달
return NextResponse.next();
}
// next.config.js
module.exports = {
async middleware() {
return ['/dashboard', '/settings']; // 미들웨어를 적용할 경로
},
};
Next.js 14의 미들웨어 기능을 사용하면 특정 경로에 대해 다양한 중간 처리를 수행할 수 있습니다. 인증, 로깅, 리다이렉션 등 다양한 용도로 활용할 수 있다.
파일 기반 라우팅을 제공하다보니 이런 기능이 있는 것 같다.
Next.js 14는 사용자 행동과 성능을 추적할 수 있는 내장 분석 도구를 제공합니다.
이를 통해 애플리케이션에서 사용자 인터랙션을 분석하고 성능 문제를 식별하여 최적화할 수 있습니다.
커스텀 이벤트 로깅:
커스텀 이벤트를 로깅하려면, useAnalytics 훅을 사용하여 특정 이벤트를 로깅할 수 있습니다.
// components/ExampleComponent.js
import { useAnalytics } from 'next/analytics';
export default function ExampleComponent() {
const analytics = useAnalytics();
const handleClick = () => {
analytics.logEvent('button_click', { label: 'example_button' });
};
return <button onClick={handleClick}>Click me</button>;
}
이 예시에서, 버튼이 클릭될 때 button_click이라는 커스텀 이벤트가 로깅됩니다. 이벤트에는 label이라는 추가 메타데이터가 포함됩니다.
Next.js는 수집된 분석 데이터를 시각화할 수 있는 대시보드를 제공합니다.
이 대시보드에서는 다음과 같은 정보를 확인할 수 있다.
아직은 Vue3가 더 익숙해서 그런지 Vue3가 생산성이 더 좋다고 판단 되지만,
압도적으로 커뮤니티, 정보, 유용한 라이브러리가 next14(react)가 더 많은 것 같다.
next14는 규모가 크고 다양한 기능을 가진 슈퍼앱에 더 적합한 프레임워크로 느껴졌다.