Next.js Page Router와 프리패칭, 데이터패칭

하영·2024년 9월 30일
1

Next.js

목록 보기
5/19

Page Router

여기서 정리한 설명과 코드는 Page Router 기반으로 작성되어 있다.

App Router 방식을 이해하기 앞서 어떤 점이 보완되었고 차이가 무엇인지 알기 위해 Pager Route를 간략하게 공부하였다.

01. Page Router의 폴더 및 파일 구조

App Router 와 비슷하지만 조금 다른 점은 Page폴더 안에 폴더를 만드는 구조이다.

📦src
 ┣ 📂**pages**
 ┃ ┣ 📂api
 ┃ ┃ ┗ hello.ts
 ┃ ┣ 📂**book**
 ┃ ┃ ┗ [[...id]].tsx
 ┃ ┣ 📂**search**
 ┃ ┃ ┗ index.tsx
 ┃ ┣ 404.tsx
 ┃ ┣ _app.tsx
 ┃ ┣ _document.tsx
 ┃ ┣ index.tsx
 ┃ ┗ test.js
 ┗ 📂styles
 ┃ ┗ globals.css

Page라는 폴더에는 book, search 라는 폴더가 있고 그 안에 각각 index.tsx 파일이 있다.

💡http://localhost:3000**/search** 혹은 http://localhost:3000**/book** 으로 페이지 이동!

02. useRouter hook 사용하기

쿼리스트링 👩🏻‍💻

import React from "react";
import { useRouter } from "next/router";

const Search = () => {
  const router = useRouter();

  const { q } = router.query;

  return <div>Search {q}</div>;
};

export default Search;

쿼리스트링은 경로에 직접적인 영향을 주지 않기 때문에 폴더나 파일을 추가 생성하지 않아도 된다.

대신 useRouter hook 을 활용해서 그 안에 있는 다양한 메소드 를 활용한다. (쿼리스트링은 query)


👩🏻‍💻 useRouter 메소드

위 사진에서 query 에 내 이름이 적혀있는데 localhost:3000/search?=김하영 을 적어주었기 때문이다.

👩🏻‍💻 URLparameter 동적 경로로 만들기

import { useRouter } from "next/router";

export default function Page() {
  const router = useRouter();
  // const { id } = router;
  const { id } = router.query;

  return <h1>Book {id}</h1>;
}

URLparameter 동적 경로로 만들기 - id 값을 받는다.

  • Catch All Segment : 모든 구간에 대응하는 페이지를 만든다! 만드는 방법: […id]로 만들어주면 여러개 url id URLparameter(ex. ~~~/book/12/223/333) 를 받아올 수 있다. 이는 배열형태로 구성되어있다.
  • Optional Catch All Segment : id 값을 주지 않는 경우의 페이지도 404 에러를 띄우지 않고 페이지를 보여준다! 만드는 방법 : [[...id]].tsx 로 파일 생성해준다.

🫨정리🫨

[id] : 1개의 동적 id 받음
[…id] : 여러 개의 동적 id 받음
[[…id]] : id 값 뒤에 아무것도 쓰지 않은 페이지까지 출력


import "@/styles/globals.css";
import type { AppProps } from "next/app";
import Link from "next/link";
import { useRouter } from "next/router";

export default function App({ Component, pageProps }: AppProps) {
  const router = useRouter();

  const onClickButton = () => {
    router.push("/test");

    // 컴포넌트 내에서 특정 조건이 만족했다거나 useEffect에서 상황을 가정한다고 했을 때
    // 함수 내부에서도 CSR 방식으로 페이지를 이동시킬 수 있다.
    // push 말고도 다양한 메소드 있으니 콘솔 찍어서 확인해보고 사용
  };

  return (
    <>
      <header>
        <Link href={"/"}>index</Link>
        &nbsp;
        <Link href={"/search"}>search</Link>
        &nbsp;
        <Link href={"/book/1"}>book</Link>
        <div>
          <button onClick={onClickButton}>/test 페이지로 이동</button>
        </div>
      </header>

      <Component {...pageProps} />
    </>
  );
}

Link 태그로 페이지를 이동시킬 수 있는데 import 할 때 "next/link" 에서 불러와지는 걸 꼭 확인하자!

Link 태그를 사용하지 않고 버튼을 눌렀을 때 페이지를 이동 시키고 싶다 → 함수형태로 만들어주면 된다.

useRouter를 사용했을 때 봤던 다양한 메소드를 활용하면 앞으로 가기, 뒤로 가기 등을 구현할 수 있다.

이 방식은 Client Side Rendering 방식이라는 것도 알아두자!


04. Pre-fetching

: 웹페이지에서 링크, 버튼이 존재해서 이 부분과 연결된 모든 페이지들에 자바스크립트 코드를 JS Bundle로 미리 불러와 놓는 과정이다.

page router에서는 사실 이런 방식으로 되어있다. search 페이지에서의 데이터는 search 폴더 내에 있는 컴포넌트 파일들(js파일들)을 불러오는 것인데

처음에 사용자가 브라우저를 열면 빈 껍데기만 보여주고, 버튼을 누른다거나 글을 쓰는 등의 상호작용을 할 수 있는 자바스크립트는 해당 page 에 있는 스크립트가 Bundle 형태로 가져와진다.

이렇게 Hydration이 되면 그제서야 사용자는 상호작용이 가능하게 된다.

이 과정의 시간을 TTI(Time To Interactive)라고 하고 이걸 줄이는 것이 중요하다.

pre-fetching 과정까지 합쳐진 전체 흐름은 위 사진과 같다.

페이지를 이동하면 그 페이지에서 또 빈 화면을 보여준다거나 Hydration 시간이 길어지면 좋지 않으므로 미리 불러와놓는 것이다.

👩🏻‍💻 터미널에서 확인해보기

yarn build로 프로덕션 모드로 가동해주기!!

page별로 출력된 build 결과를 볼 수 있다.

네트워크 탭으로 들어가서 새로고침을 해보면 어떤 page가 pre-fetching 되는지 확인할 수 있다.

👩🏻‍💻 search page pre-fetching

👩🏻‍💻 book page pre-fetching

yarn start까지 해주고 다시 브라우저로 돌아가서 보면 이렇게 pre-fetching 된 page를 볼 수 있다.


04-1. pre-fetching이 적용되지 않은 경우

pre-fetching은 기본적으로 Link 태그에 적용되어있는데, 버튼에 함수형태로 페이지 이동을 준 경우에는 pre-fetching이 적용되어있지 않다.

→ 이럴 때는 아래 코드처럼 작성해주면 pre-fetching을 할 수 있다.

import "@/styles/globals.css";
import type { AppProps } from "next/app";
import Link from "next/link";
import { useRouter } from "next/router";
import { useEffect } from "react";

export default function App({ Component, pageProps }: AppProps) {
  const router = useRouter();

  // 버튼을 클릭하면 test page로 이동하는 함수 로직
  const onClickButton = () => {
    router.push("/test");
  };

  // ✅ Pre-fetch 하는 방법
  useEffect(() => {
    router.prefetch("/test");
  }, []);

  return (
    <>
      <header>
        <Link href={"/"}>index</Link>
        &nbsp;
        <Link href={"/search"} prefetch={false}>
          search
        </Link>
        &nbsp;
        <Link href={"/book/1"}>book</Link>
        <div>
          <button onClick={onClickButton}>/test 페이지로 이동</button>
        </div>
      </header>

      <Component {...pageProps} />
    </>
  );
}
  • useEffect 같은 방식을 사용해서 useRouter 메소드 중 prefetch 를 사용한다.
  • prefetch={false}: 기본적으로 적용되는 pre-fatching을 막아줌

05. 데이터 패칭

👩🏻‍💻 React App 데이터 패칭

  • 컴포넌트 마운트 이후에 발생함
  • 데이터 요청 시점이 느려지게 되는 단점 발생

👩🏻‍💻 Next App 데이터 패칭

  • 사전 렌더링 중 발생함 (컴포넌트 마운트 이후에도 발생 가능)
  • 데이터 요청 시점이 매우 빨라지는 장점 있음

렌더링 되는 방식은 SSG, SSR, ISR, CSR 이렇게 4가지 가 있는데 자세한 내용은 코드를 통해 정리해보기로!

🫨 정리 🫨

프리패칭은 페이지 전환 시 빈 화면을 방지하기 위한 데이터 미리 불러오기를 의미하고,
데이터 패칭서버나 API로부터 데이터를 가져오는 작업을 말한다.
각 상황에 맞게 SSG, SSR, ISR, CSR을 선택해 효율적으로 데이터를 패칭하는 것이 중요하다.


출처 : 한 입 크기로 잘라먹는 Next.js(15+)
https://www.udemy.com/course/onebite-next/

profile
왕쪼랩 탈출 목표자의 코딩 공부기록

0개의 댓글