Next14 주요 특징과 Vue3 비교

Dae-Hee·2024년 5월 22일
post-thumbnail

Vue3를 Next14로 마이그레이션 하는 업무가 생겨서 정리하는 Next14 주요 특징과 Vue3 비교

Next14 주요 특징

  • File-based Routing:
    Next.js의 파일 기반 라우팅이 더욱 강력해졌습니다.
    동적 라우트와 API 라우트를 더욱 쉽게 설정할 수 있습니다.
  • React 18 Support:
    Next.js 14는 React 18의 새로운 기능을 완벽하게 지원합니다.
    특히, Concurrent ModeSuspense를 활용한 성능 최적화가 가능해졌습니다.
  • Middleware:
    Next.js 14는 경로 기반 미들웨어 기능을 도입하여, 요청에 대한 중간 처리가 가능해졌습니다.
  • Improved Image Optimization:
    새로운 이미지 최적화 기능으로, 더욱 효율적인 이미지 로딩과 품질 관리가 가능합니다.
  • Built-in Analytics:
    사용자 행동과 성능을 추적할 수 있는 내장 분석 도구가 추가되었습니다.
  • ES Modules Support:
    ES Modules를 지원하여, 더 나은 트리 쉐이킹(tree-shaking)과 모듈 로딩을 제공합니다.
  • Server-side Rendering Enhancements:
    서버사이드 렌더링이 더욱 효율적으로 개선되었습니다.

Concurrent Mode, Suspense, Middleware, Built-in Analytics
더 자세하게 알아보자


Concurrent Mode

React 18에서 도입된 기능으로, 여러 버전의 UI를 동시에 준비할 수 있게 합니다. 이를 통해 애플리케이션이 더욱 반응성 있게 동작하며, 사용자의 장치 성능과 네트워크 속도에 맞게 유연하게 조정됩니다. Concurrent Mode는 단일 기능이 아니라, React 앱이 반응성을 유지하고 사용자의 장치 성능에 맞게 조정될 수 있도록 돕는 여러 기능의 집합입니다.

주요 특징

  1. Interruptible Rendering (중단 가능한 렌더링): React는 렌더링 작업을 일시 중지, 중단 또는 다시 시작할 수 있습니다.
  2. Concurrent Rendering (동시 렌더링): React는 여러 작업을 동시에 수행할 수 있습니다.
  3. Transitions (전환): 특정 상태 업데이트를 전환으로 표시하여, 상태 업데이트 동안 UI를 반응성 있게 유지할 수 있습니다.

예시:
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는 코드 로드 및 데이터 로드를 기다리게 하고, 대기 중인 컴포넌트 트리에 대한 로딩 상태를 선언적으로 지정할 수 있게 합니다. 이는 코드 분할 및 데이터 페칭에 특히 유용합니다.

주요 특징

  1. Code Splitting (코드 분할): 컴포넌트를 지연 로딩할 수 있습니다.
  2. Data Fetching (데이터 페칭): 비동기 데이터를 기다리게 합니다.

예시:
데이터 페칭 컴포넌트와 함께 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>)를 지정합니다.


Concurrent Mode와 Suspense 결합

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가 반응성을 유지하게 하고, SuspenseDataComponent가 로딩되는 동안 로딩 상태를 처리합니다.

동시 다발적으로 API 요청을 처리할 수 있고, Concurrent ModeSuspense를 결합하여 반응성을 유지 한채 여러 개의 API 요청을 동시에 처리하고, 결과를 한꺼번에 렌더링할 수 있다.


Vue3 Suspense 비교

Vue3의 Suspense는 주로 비동기 컴포넌트 로딩에 중점을 두고 있으며,
Next.js14의 Suspense는 Concurrent Mode와 결합하여 더 나은 성능 최적화 중점을 둔다.

중단 가능한 렌더링 (Interruptible Rendering)

  • React18 Concurrent Mode:
    Concurrent Mode는 렌더링 작업을 중단하고 더 중요한 업데이트를 우선 처리할 수 있는 기능을 제공합니다. 이를 통해 긴 렌더링 작업이 진행되는 동안에도 사용자 인터페이스가 반응성을 유지할 수 있습니다.
  • Vue3:
    Vue 3는 이러한 중단 가능한 렌더링 기능을 기본적으로 제공하지 않습니다. Vue 3의 렌더링은 단일 스레드에서 동기적으로 수행되며, 긴 렌더링 작업이 진행되는 동안 UI가 응답하지 않을 수 있습니다. Vue 3의 Suspense는 비동기 컴포넌트 로딩 및 데이터 페칭 동안의 로딩 상태를 관리하지만, Concurrent Mode와 같은 중단 가능한 렌더링 기능은 포함되지 않습니다.

사용자 경험 향상 (Improved User Experience)

  • React18 Concurrent Mode:
    Concurrent Mode는 긴 작업이 진행되는 동안에도 사용자가 인터랙션을 할 수 있도록 하여 사용자 경험을 크게 향상시킵니다. 이는 React가 UI 업데이트를 최적의 시점에 처리하고, 백그라운드에서 긴 작업을 계속 수행할 수 있도록 합니다.
  • Vue3:
    Vue 3의 Suspense는 비동기 컴포넌트 로딩과 데이터 페칭 동안 로딩 상태를 제공하여 사용자 경험을 개선할 수 있습니다. 그러나 Concurrent Mode가 제공하는 수준의 반응성 향상 기능은 제공하지 않습니다. Vue 3에서는 긴 작업이 진행되는 동안 UI가 차단될 수 있습니다.

Middleware

// 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의 미들웨어 기능을 사용하면 특정 경로에 대해 다양한 중간 처리를 수행할 수 있습니다. 인증, 로깅, 리다이렉션 등 다양한 용도로 활용할 수 있다.

파일 기반 라우팅을 제공하다보니 이런 기능이 있는 것 같다.


Built-in Analytics

Next.js 14는 사용자 행동과 성능을 추적할 수 있는 내장 분석 도구를 제공합니다.
이를 통해 애플리케이션에서 사용자 인터랙션을 분석하고 성능 문제를 식별하여 최적화할 수 있습니다.

주요 기능

  1. 자동 페이지 조회 추적: 추가 설정 없이 페이지 조회를 자동으로 추적합니다.
  2. 커스텀 이벤트: 특정 사용자 인터랙션을 추적하기 위해 커스텀 이벤트를 로깅할 수 있습니다.
  3. 성능 지표: 페이지 로드 시간, 인터랙션 지연 시간 등 중요한 성능 지표를 측정합니다.
  4. 대시보드: 사용자 행동과 성능 데이터를 시각화할 수 있는 대시보드를 제공합니다.

커스텀 이벤트 로깅:
커스텀 이벤트를 로깅하려면, 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 비교

  • 성능 최적화: Next.js 14는 자동 코드 스플리팅, 이미지 최적화, 빠른 페이지 로드를 위한 최적화 기능을 내장하고 있습니다.
  • 개발 편의성: Next.js는 파일 기반 라우팅을 제공하여, 개발자가 라우트를 설정하기 훨씬 쉽게 만들었습니다. Vue3의 경우 Vue Router를 통해 라우트를 설정해야 합니다.
  • 서버사이드 렌더링(SSR): Next.js는 SSR을 기본적으로 지원하며, 서버사이드에서 데이터를 미리 가져와 렌더링하는 기능이 강력합니다. Vue3도 Nuxt.js를 통해 SSR을 지원하지만, Next.js가 더 널리 사용됩니다.

둘다 사용해보니...

아직은 Vue3가 더 익숙해서 그런지 Vue3가 생산성이 더 좋다고 판단 되지만,
압도적으로 커뮤니티, 정보, 유용한 라이브러리가 next14(react)가 더 많은 것 같다.

next14는 규모가 크고 다양한 기능을 가진 슈퍼앱에 더 적합한 프레임워크로 느껴졌다.

0개의 댓글