Next.js 라우팅

dante Yoon·2021년 9월 19일
3

NextJS

목록 보기
1/8
post-thumbnail

회사에서 진행하는 프로젝트에서 next.js를 본격적으로 사용하는 부분이 생김으로 인해 더 이상 next.js를 무시할 수 없게 되었습니다.

리엑트는 페이스북에서 UI라이브러리라고 소개하고 있지만, 단순 라이브러리라고 하기에는 리엑트를 사용하기 위한 러닝커브가 꽤 가파르고 리엑트에서만 쓰이는 문법또한 존재하므로 라이브러리가 아닌 프레임워크라고 저는 생각합니다.

리엑트에 express, webpack과 같은 번들러를 사용해서 충분히 서버사이드 렌더링을 구현할 수 있기에 프레임워크를 위한 프레임워크를 학습하는데 많은 시간을 투자하지 않았습니다.

리엑트 관련 프로젝트를 진행하면서 SSR이 거의 옵션이 아닌 기본 스펙이 되어버리는 케이스가 많고, 리엑트 서버사이드 렌더링 => nextjs라는 글들도 많이 보여 nextjs의 학습은 결국 리엑트를 사용하는 프론트엔드 개발자라면 한번은 거쳐야 할 단계라는 생각이 들었습니다.

nextJS는 프론트엔드 프레임워크를 넘어, 자체적으로 api또한 제공할 수 있는 vercel에서 만든 풀스택 프레임워크입니다.

vercel또한 자체 cms 배포 기능등 웹 생태계에 유용한 기능을 많이 제공하고 있음으로 이 회사의 기술을 배우는 것은 장기적으로 이득이 될 것이라고 생각합니다.

Next.js 라우팅

리엑트는 자체 라우팅을 제공하지 않음으로 (그래도 여전히 리엑트는 프레임워크라고 생각합니다.)
react-router-dom, react-router와 같은 라이브러리를 이용해 클라이언트 사이드 라우팅을 구현합니다.

넥스트는 자체적으로 라우팅 기능을 제공합니다.

페이지 라우팅

pages 폴더는 프로젝트 루트 혹은 src 폴더 아래에 위치할 수 있습니다. pages폴더 안에 있는 파일명이 바로 해당 페이지의 주소가 됩니다.

/notes 주소에서는 pages/notes/index.jsx 파일에서 렌더링하는 페이지가 보이게 됩니다.

다이나믹 라우팅

/notes/와 같이 /로 끝나는 주소가 아닌 params가 붙은 주소가 있습니다.
바로 /notes/1/2 와 같은 경우입니다.

앞선 예제 사진의 디렉토리 처럼
[id].jsx 로 동적 주소를 받을 수 있습니다.

이러한 id는 다음과 같이 next/link에서 제공하는 useRouter를 이용해 추출할 수 있습니다.

// [id].jsx
import React from "react";
import { useRouter } from "next/router";

const NoteId = () => {
  const router = useRouter();
  console.log({ query: router.query, router: router })
  return (
    <div>Note</div>
  )
}

http://localhost:3000/notes/1?can=123 를 요청했을 때,
router 객체를 콘솔에 찍어보면 다음과 같습니다.

asPath: "/notes/1?can=123"
back: ƒ ()
basePath: ""
beforePopState: ƒ ()
components: {/notes/[id]: {}, /_app: {}}
defaultLocale: undefined
domainLocales: undefined
events: {on: ƒ, off: ƒ, emit: ƒ}
isFallback: false
isLocaleDomain: false
isPreview: false
isReady: true
locale: undefined
locales: undefined
pathname: "/notes/[id]"
prefetch: ƒ ()
push: ƒ ()
query: {can: "123", id: "1"}
reload: ƒ ()
replace: ƒ ()
route: "/notes/[id]"
[[Prototype]]: Object
[[Prototype]]: Object

catch all routes

위와 같이 [id].jsx 파일을 만듬으로 인해 /notes/1 과 같은 주소에 대한 페이지를 받아볼 수 있었지만, /notes/1/2와 같이 param이 하나 더 추가 된다면, 해당 페이지는 404에러를 보여줍니다.

몇개의 params가 주소 뒤에 붙을지 모르기 때문에, 모든 params에 대한 페이지 접속을 허가하기 위해서는 catch all routes 기능을 사용할 수 있습니다.

다음의 폴더 구조를 보면 params 가 spread operator를 통해 나타나 있습니다.

[[...params]].jsx 파일은 다음과 같이 되어있습니다.

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

const Notes = () => {
  const router = useRouter();
  const { params } = router.query;
  console.log({ params })
  return (
    <div>Note</div>
  )
}

export default Notes;

params는 배열 형식으로 router.query를 통해 뽑아볼 수 있으며, 이름은 params가 아닌 어떤 형태로도 괜찮습니다.

// http://localhost:3000/notes/1/1?can=123 접속 시
params: (2) ["1", "1"]

다시 폴더구조를 살펴보면 [...params]가 또다른 배열인 []로 감싸져 있습니다.
pages/notes 경로 아래에 , index.jsx 파일 또한 필요 없습니다. notes 경로 아래에서 일어나는 모든 페이지는 [[...params]].jsx 파일만 수정하면 됩니다.
index.js를 만들면 오류가 생기므로, catch all routes를 사용할 때는 index.js를 사용하지 않도록 조심합시다.

페이지 네비게이션

넥스트는 next/link 에서 제공하는 Link 컴포넌트를 이용해 클라이언트 사이드에서의 페이지 네비게이션을 이용할 수 있습니다. 앱 밖에 있는 외부 링크는 기본 html의 a 태그를 사용해야 합니다.

사용법은 간단합니다 react-router의 Link 태그와 비슷합니다.

import React from "react";
import Link from "next/link";

const Page = () => {
  return (
    <div>
      <h1>
        IndexPage
      </h1>
      <Link href="notes" ><a>Note</a></Link>
    </div>
  )
}

export default Page;

이때 Link 태그 내부를 a태그로 감싸주는 것은 공식 다큐먼트의 권장사항입니다. lint를 사용할 경우 해당 href를 생략했기 때문에 오류를 발생시킴으로, 이 부분에 대한 린트 사용을 해제해야 합니다.

만약 params가 포함된 다른 주소로 이동하기 위해서는 다음과 같이 href와 as 속성을 같이 사용합니다.


const Notes = () => {
  const router = useRouter();
  const { params } = router.query;
  console.log({ params })
  return (
    <div>
      <h1> Note</h1>
      <Link href="/notes/[id]" as={`/notes/1`}>note 1</Link>
    </div>
  )
}

export default Notes;

pragramatic navigation

Link 태그를 제외하고 useRouter()의 리턴 객체를 가지고 프로그래밍을 통해 페이지 네비게이션을 할 수 있습니다. 이 방법은 router.push를 이용하는 것인데 Link 컴포넌트와 마찬가지로 클라이언트 사이드 렌더링 환경에서만 작동합니다.

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

const Notes = () => {
  const router = useRouter();
  const { params } = router.query;
  console.log({ params })
  return (
    <div>
      <h1> Note</h1>
      <Link href="/notes/[id]" as={`/notes/1`}>note 1</Link>
      <button onClick={() => router.push("/notes/[id]", "/notes/2")}>note 2</button>
    </div>
  )
}

export default Notes;

Link 컴포넌트의 as, href 처럼, 첫 인자는 href, 두번째 인자로는 실 경로를 입력합니다.

오늘은 넥스트의 라우팅에 대해 알아보았습니다.
새로운 기술을 배우는 것은 항상 즐겁지만은 않습니다. 하지만 익숙해지면 모든 환경에서 유용하게 사용할 수 있습니다.
항상 배운 것을 복습하시고 실제로 사용해보시길 바랍니다.

profile
성장을 향한 작은 몸부림의 흔적들

0개의 댓글