📢 어렵고 정석적인 개념 설명보다는 저같은 초보자도 이해하기 쉽게 정리하는 것을 원칙으로 포스팅하고 있습니다. 😄

[Next.js] 페이지 라우팅하는 방법 (동적 라우팅, useRouter())

pages 폴더 안에 만들기

리액트에서는 react-router-dom을 이용해서 컴포넌트를 <Route>로 제어했었다.

하지만, next.js에서는 pages 폴더 안에 index 파일만 잘 구축해 놓으면 리액트처럼 일일이 Route로 연결할 필요 없이 쉽게 페이지 이동을 할 수 있다. 예를 들어, pages/content/index.js 라고 해당 경로에 파일을 만들어 놓으면 주소입력창에 

www.shawn.com/content 라고 했을 때 content/index.js가 실행되는 것이다.

 

폴더 경로 도메인 주소
pages/index.js www.shawn.com
pages/content/index.js www.shawn.com/content
pages/content/[id].js www.shawn.com/content/1
pages/search.js www.shawn.com/search

 

동적 라우팅은 파일 이름에 대괄호 씌우기

예를 들어, www.shawn.com/content 라는 경로가 있다고 하자. content 페이지는 1번, 2번 등 고유 ID를 가진 각 게시물을 볼 수 있는 페이지라고 한다면 우리는 각 ID 파라미터를 받아올 수 있는 동적 라우팅을 사용해야 한다.

 

동적 라우팅의 방법은 바로 이름에 대괄호를 씌우는 것이다. 위의 예시에서는 content의 ID값을 동적으로 받아와야 하므로, pages/content에 [id].js라는 파일을 만들어주면 된다. 만약에, 동적 라우팅을 중첩으로 사용하고 싶다면 (파라미터 값이 여러 개인 경우) [...id].js처럼 이름 앞에 ...을 달아주면 된다.

 

동적 라우팅 페이지를 만들 때 주의할 점은 content/1이 아닌 그냥 content/로 접속할 경우 index.js가 없으면 404 오류가 뜰 수 있다는 점이다. 이런 오류를 방지하려면 [...id].js를 만들 때 [[...id]].js라고 대괄호를 한 번 더 감싸주면 된다. 대괄호를 한 번 더 감싸주는 것은 옵셔널하다는 의미를 가지기 때문에 id 파라미터가 있어도 되고 없어도 되고의 의미가 된다.

 

URL 파라미터를 불러올 때는 useRouter()

import { useRouter } from "next/router";

export default function Content() {
    const router = useRouter();
    const {id} = router.query; // 구조분해할당으로 query 객체의 id 값을 받아온다.

    return (
        <div>
            <h1>이 글의 게시글 번호는 {id}입니다.</h1>
        </div>
    )
}

라우터와 관련된 값 혹은 행위들을 할 때는 무조건 useRouter()를 import 해줘야 한다.

 

예를 들어, content/1 이라고 되어 있을 때, 1이라는 값을 가지고 오고 싶다면 useRouter()를 이용해서 router.query에 접근해야 한다. router.query는 객체 타입으로 되어 있으므로 router.query.id 혹은 구조분해할당을 이용해서 {id} = router.query로 id 파라미터를 값을 가져올 수 있다.

 

참고로, useRouter()를 이용하면 URL 파라미터 뿐만 아니라 쿼리 스트링 또한 router.query를 통해 불러올 수 있다는 점도 알아두자!

 

페이지 이동하는 3가지 방법 (Link, useRouter)

import Link from "next/link";
import { useRouter } from "next/router";

export default function Home() {
    const router = useRouter();
    const code = "ABC";
    const onClickEvent = () => {
        router.push(`/content/${code}`);
    }

    return (
        <div>
            // 첫 번째 방법
            <Link href={`/content/${code}`}>Content 페이지로 이동</Link>
            // 두 번째 방법
            <Link href={{
                pathname: "/content/[code]",
                query: {code: code}
            }}>Content 페이지로 이동</Link>
        </div>
        // 세 번째 방법
        <button onClick={onClickEvent}>Content 페이지로 이동</button>
    )
}

1) Link 이용하기

리액트에서도 Link를 이용해서 페이지 이동을 할 수 있었다. next.js에서도 Link로 이동이 가능한데, 대신 리액트에서는 to에 페이지 경로를 써줬다면 next.js에서는 href에 페이지 경로를 작성해줘야 한다. 

 

2) Link의 href 값으로 객체(pathname, query) 넣기

1의 방법처럼 href의 값으로 간단하게 페이지 경로를 넣어줘도 되지만, router 객체로도 넣어줄 수도 있다. pathname에는 페이지 경로를 넣어주고, query에는 pathname의 동적 파라미터로 전달할 값을 객체 타입으로 넣어주면 된다.

위 예시 코드에서는 pathname을 /content/[code]라고 해주었고, [code] 값으로는 query의 code 프로퍼티 값을 넣어주었다.

 

3) useRouter() 이용하기

페이지 이동을 함수로 만들어서 하고 싶을 경우, useRouter()를 이용하면 된다. useRouter()는 push나 replace 등 다양한 메서드들을 통해 라우팅을 지원한다. 우리가 구현하고 싶은 단순 페이지 이동은 push("경로")를 사용하면 된다. (Link처럼 경로가 아닌 router 객체를 넣어줘도 된다.)

 

참고로, useRouter()의 메서드에는 해당 경로로 이동하는 push 외에 앞으로 이동, 뒤로 이동, 새로고침 등 우리가 바닐라 자바스크립트에서 알고 있던 window.location에 해당하는 다양한 메서드들이 있다.

 

1. next.js의 라우팅은 pages 폴더 안에 있는 파일들의 경로이다.
2-1. 동적 라우팅을 할 때는 대괄호로 감싸준다. [id].js
2-2. 동적 라우팅이 중첩으로 여러 개일 경우 ...을 이름 앞에 붙여준다. [...id].js
2-3. 동적 라우팅을 옵셔널로 설정하고 싶을 경우 대괄호로 2번 감싸준다. [[...id]].js
3-1. 페이지 이동에는 Link 태그를 사용할 수도 있고, useReducer()를 사용할 수도 있다.
3-2. Link 태그 사용에는 href를 이용하며, 경로를 직접 넣어줄 수도 있고 router 객체를 넣어줄 수도 있다.
3-2. useReducer() 사용에는 router.push("경로")를 넣어준다.