Page Router
여기서 정리한 설명과 코드는 Page Router 기반으로 작성되어 있다.
App Router 방식을 이해하기 앞서 어떤 점이 보완되었고 차이가 무엇인지 알기 위해 Pager Route를 간략하게 공부하였다.
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** 으로 페이지 이동!
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)
위 사진에서 query 에 내 이름이 적혀있는데 localhost:3000/search?=김하영 을 적어주었기 때문이다.
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
값을 받는다.
[…id]
로 만들어주면 여러개 url id URLparameter(ex. ~~~/book/12/223/333) 를 받아올 수 있다. 이는 배열형태로 구성되어있다.[[...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>
<Link href={"/search"}>search</Link>
<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
방식이라는 것도 알아두자!
: 웹페이지에서 링크, 버튼이 존재해서 이 부분과 연결된 모든 페이지들에 자바스크립트 코드를 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를 볼 수 있다.
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>
<Link href={"/search"} prefetch={false}>
search
</Link>
<Link href={"/book/1"}>book</Link>
<div>
<button onClick={onClickButton}>/test 페이지로 이동</button>
</div>
</header>
<Component {...pageProps} />
</>
);
}
useEffect
같은 방식을 사용해서 useRouter
메소드 중 prefetch
를 사용한다.prefetch={false}
: 기본적으로 적용되는 pre-fatching을 막아줌렌더링 되는 방식은 SSG, SSR, ISR, CSR 이렇게 4가지 가 있는데 자세한 내용은 코드를 통해 정리해보기로!
🫨 정리 🫨
프리패칭은 페이지 전환 시 빈 화면을 방지하기 위한 데이터 미리 불러오기를 의미하고,
데이터 패칭은 서버나 API로부터 데이터를 가져오는 작업을 말한다.
각 상황에 맞게 SSG, SSR, ISR, CSR을 선택해 효율적으로 데이터를 패칭하는 것이 중요하다.
출처 : 한 입 크기로 잘라먹는 Next.js(15+)
https://www.udemy.com/course/onebite-next/