#15일차: Next.js - 라우팅

min0._.9·2026년 1월 25일

우리FISA 일일 회고

목록 보기
12/15

Next.js

React/Vite만 가지고 개발한 결과물의 특징

  1. Gmail과 같은 CSR(Client Side Rendering)을 진행한다.

  2. 빌드한 결과물이 단일 html, css, js 파일이다. 배포하려면 별도의 웹서버(ex. Nginx)를 통해 배포해야 한다.

  3. 페이지 라우팅에 대한 별도의 방법이 필요하다. (React router를 주로 불러온다.)

  4. 이미지, 폰트 등에 대한 최적화가 필요하다.

  5. 렌더링 관점에서 봤을 때, SEO가 떨어진다.

  6. CSR은 초기 페이지 렌더링이 느리다.

추후 프로젝트에,

React/Vite만 가지고 CSR로 서비스를 구현할지,

Next.js의 다양한 특징들을 통해 조금 더 편하고, 다양한 렌더링 기법을 활용할지 정해야 한다.

Next.js가 React보다 더 무겁게 동작할 수 있기 때문이다!

Next.js

서버 측 코드를 실행시킬 수 있다.

Next.js 특징

Routing

라우팅이란, 사용자가 현재 페이지에서 다른 페이지로 이동할 수 있도록 제공하는메커니즘을 의미한다.

Next.js는 파일 기반 방식의 직관적인 라우팅 기능을 제공한다.

다음과 같이 폴더명이 url의 세그먼트로 바로 연결되어 편하다.

라우팅과 관련된 파일은 ‘app/ ‘ 내부에 작성해야 한다.

렌더링 될 파일 이름은 page.js로 해야 한다!

app > {라우팅 이름} > page.js

동적 라우팅

localhost:3000/products/{:id}

→ 특정 id에 해당하는 특정 상품의 상세 페이지(detail)로 이동하도록 하기 위해서는 어떻게 해야 할까?

폴더명을 [이름] 으로 설정한 후 다음과 같이 params를 이용한다.


export default async function Page({ params }) {
    
    const { productId } = await params; 
    
    return (
        <div>
            상품 { productId }번 디테일 페이지입니다.
        </div>
    );
}

404 페이지 처리하기

Next.js는 잘못된 경로로 접근하면 기본적으로 404 페이지를 응답한다.

not-found.js 로 생성 가능하다. 각 엔드포인트마다 만들어주면 된다.

// app/not-found.js
// lh:3000/{존재하지 않는 경로}

// nafe
const NotFound = () => {
    return (
        <div className="flex justify-center">
            <h2 className="italic font-bold text-red-500 underline text-7xl">404 Not Found!</h2>
        </div>
    );
}

export default NotFound;

notFound

notFound() 를 직접 호출하면 정의한 not-found.js 파일을 불러올 수 있다. 다음 코드는 조건 분기를 적용해, reviewId가 10을 초과할 시, notFound()를 호출해 404 에러를 일으키는 not-found.js 파일을 불러온다.


import { notFound } from 'next/navigation'
export default async function ReviewDetailPage({ params }) {
    
    const {productId, reviewId } = await params; 

    if(reviewId > 10){
        notFound()
    }
    else{
        return (
            <div>
                상품 {productId}{reviewId} 번째 리뷰 페이지
            </div>
        );

    }
    
}

Component 이용

.jsx 로 된 컴포넌트를 생성해 불러와 사용할 수도 있다. 특정 라우팅 경로(app/dashboard)에서 사용될 컴포넌트들은 별도의 폴더(ex. components/dashboard)에 분리하여 관리하자.

layout.js

dashboard에 layout.js 파일을 작성하면, 동등한 위치인 page.js 파일과, 하위 폴더 settings 아래에 있는 page.js 파일에 레이아웃이 적용된다.

하위 페이지들을 렌더링할 때 사용되어야 하기 때문에 꼭 children props를 받게 해야 한다.

import "./globals.css";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body >
        <header className="p-2 bg-lime-200"> Header </header>
        {children}
        <footer className="c-1 bg-orange-50">Footer</footer>
      </body>
    </html>
  );
}
  • a tag
    <a href='/blog'>블로그</a>
    보통 a tag는 외부 페이지로 나갈 때 사용하기 때문에 최적화가 덜 되어있다.
  • Link tag
    <Link href='/blog'>블로그</Link>
    next.js에서 제공하는 Link를 이용할 시 페이지를 미리 로드하기 때문에(prefetch) 최적화 되어있다.

loading.js

React18의 Suspense, error-boundary 를 이용했다.

다음과 같이 페이지에서 의도적으로 시간지연을 주면, 로딩 중 메시지를 확인할 수 있다.

page.js

// lh:3000/blog main page

export default async function Page() {

    await new Promise(resolve => setTimeout(resolve, 2000)); 
    return (
        <div>blog main 페이지</div>
    );
}

loading.js

export default function Loading() {
    return (
        <div>
            Loading...
        </div>
    );
}

spinner

loading.js

// nalo - 로딩UI 스니펫

// loading.js의 메커니즘
// React18의 Suspense, error-boundary
export default function Loading() {
    return (
        <div role="status">
            <svg aria-hidden="true" class="w-8 h-8 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor" />
                <path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill" />
            </svg>
        </div>
    );
}

skeleton

loading.js

export default function Loading() {
    return (
            <div role="status" class="max-w-sm animate-pulse">
            <div class="h-2.5 bg-gray-200 rounded-full dark:bg-gray-700 w-48 mb-4"></div>
            <div class="h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[360px] mb-2.5"></div>
            <div class="h-2 bg-gray-200 rounded-full dark:bg-gray-700 mb-2.5"></div>
            <div class="h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[330px] mb-2.5"></div>
            <div class="h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[300px] mb-2.5"></div>
            <div class="h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[360px]"></div>
            <span class="sr-only">Loading...</span>

        </div>
    );
}

Rendering

SPA 기반의 CSR 렌더링 방식의 단점을 해소시켜주는 다양한 렌더링 기법(SSR, SSG, ISR), Streaming 등을 제공한다.

Data Fetching

서버 컴포넌트에서의 data fetching 작업을 단순화한다.


dashboard 만들면서 next.js 를 익혔다. next.js에서 제공하는 공식 문서이다.

https://nextjs.org/learn?utm_source=next-site&utm_medium=homepage-cta&utm_campaign=home

0개의 댓글