지난 강의 - 프로젝트 세팅에서 nextjs13의 최신 버전을 다운로드 받고 eslint와 prettier까지 설정했습니다. 이번 시간에는 app router를 사용해 route를 정의하는 방법을 알아보겠습니다.
Next.js 13에서 가장 눈에 띄는 개선점 중 하나는 바로 라우팅입니다.
개발자가 만드는 파일/폴더 구조를 이용해 routing을 만들 수 있는 file system 기반의 유연하고 강력한 라우팅, 지금 바로 알아보겠습니다.
여러분이 acme.com
라는 주소의 웹사이트를 개발하고 있고 acme.com/dashboard/settings 경로로 들어갔을때 보여야할 페이지를 만들어본다고 가정해보겠습니다.
acme.com/dashboard/settings
주소를 이루는 각 부분을 잘게 잘라서 next.js13의 app router에서 사용하는 용어로 변환해보려고 합니다. 이때 이 페이지는 app이라고 하는 디렉토리 하위에 생성되어야 하는데요,
이 app 디렉토리와 주소 경로의 각 부분을 next.js에서는 다음과 같이 정의합니다.
dashboard/settings
- url pathapp, dashboard, settings
- segment위 그림을 보면 app segment 하위의 경로들이 디렉토리로 생성되어 있음을 볼 수 있습니다. 이 때 root segment인 app은 url path에 포함되지 않으며 app router를 사용하려면 꼭 각 segment에 해당하는 디렉토리를 app
디렉토리 하위에 생성해야 합니다.
정리하면 구성하고자 하는 url path는 각 세그먼트로 나눌 수 있고 아래와 같이 디렉토리로 매핑하여 생각할 수 있는 것이지요.
app 세그먼트
는 - app 디렉토리
url path의 dashboard 세그먼트
는 - app 디렉토리
하위의 dashboard/ 디렉토리
url path의 settings 세그먼트
는 - app/dashboard 디렉토리
하위의 settings/ 디렉토리
next.js에서는 특정 이름을 가진 파일이 해당 디렉토리에서 특별한 역할을 수행합니다.
이 중 page.js
는 url path
로 사용자가 진입했을 때 해당 path에서 보여질 페이지를 담당합니다.
디렉토리를 생성함으로 세그먼트와 이 세그먼트들이 url path를 구성하지만,
acme.com/dashboard를 외부(페이지 방문자)에게 공개하기 위해서는 page.js를 해당 디렉토리에 생성합니다.
위 예제 그림에서 /dashboard url path를 통해 대쉬보드 페이지를 보여줄 수 있는 이유는 dashboard/ 디렉토리 하위에서 page.js를 생성했기 때문입니다.
page.js 외에도 각 세그먼트 디렉토리에서 특별한 역할을 수행하는 페이지들은 추후 더 자세하게 알아보겠습니다.
이때 특별한 파일
들은 .js 확장자 뿐만이 아닌 .jsx, .js, .tsx
로 사용이 가능합니다.
기본적인 페이지를 생성해보겠습니다.
/dashboard
url path로 접속하는 유저를 위해 /dashboard/page.tsx
를 생성합니다.
export default function page({children}: {children: React.ReactNode}) {
return (
<div>
<div>page</div>
<div>{children}</div>
</div>
)
}
next.js가 해당 페이지 컴포넌트를 잘 찾기 위해 컴포넌트를 정의하고 default export 해주어야 합니다. 이 때 children에는 어떤 내용이 들어갈지 알아보겠습니다.
아래 그림에서는 settings/ 디렉토리 하위에 여러 파일이 도식화되어있지만
현재까지 우리는 dashboard 하위에 page.tsx를 만들고 settings 세그먼트를 담당할 settings/
디렉토리까지 생성했으나 settings/
디렉토리에는 아무것도 없습니다.
앞서서 app이 root segment라고 했죠?
위 도식화에서 거대한 app이라는 tree는 blog 세그먼트로 시작되는 서브 트리
와 dashboard로 시작되는 서브 트리
로 이루어져 있습니다.
dashboard 서브트리에서 root segment는 dashboard 세그먼트 자기 자신이고 다른 서브트리에서 작성한 페이지들이 children에 들어가게 됩니다.
즉, 도식화에서 보면 settings가 children에 들어가게 되는 것이지요.
dashboard 내부에 적힌 error, layout, loading, not-found, template
은 잠시 잊어버리도록 하죠. 지금은 page.tsx
에 집중합시다.
page
.tsx의 default export 된 page
컴포넌트 props중 children에 서브 트리의 내용이 담깁니다. dashboard/settings
url path로 진입 시 해당 subtree에 있는 error, layout, loading, not-found, page, template
이 children에 속하게 됩니다.
http://localhost:3000/dashboard
로 접속했을때는 하위 세그먼트에 해당하는 url pathrk /dashboard
뒤에 붙지 않았기 떄문에 해당 children에 아무것도 없게 되겠죠?
간단하게 app directory 하위 dashboard의 page.tsx까지 생성해보았습니다.
파일의 생성 경로에 따라 자연스럽게 url path가 만들어집니다.
Next.js 13는 이렇게 생성된 파일 경로에 따른 직관적인 라우팅 시스템을 제공합니다. 이러한 Next.js 13의 url path 설정 모델은 파일 시스템 구조를 담습하고 있습니다.
이러한 접근법을 file-based routing
이라고 합니다.
file-based routing을 통해 개발자는 파일과 폴더들을 단순 배치하는 것만으로도 라우팅을 구성할 수 있게 됩니다.
동적 라우팅을 통해 어플리케이션에서 런타임에 생성되는 url path를 유저에게 제공할 수 있습니다. 데이터베이스에 생성되는 특정 파일에 대해 보여주는 페이지가 있다고 할 때 데이터가 삭제되면 페이지 또한 삭제되어야 합니다.
Next.js13의 동적 라우팅은 이러한 data-driven 어플리케이션을 만드는데 매우 유용하게 사용할 수 있는 기능입니다.
이 동적라우팅은 단순히 런타임에 생성되는 경로 뿐만 아니라 미리 빌드타임에 생성되는 경로들 또한 사용자에게 제공할 수 있습니다.
동적 라우팅을 생성하기 위해서는 세그먼트를 담당하는 디렉토리를 생성할때 디렉토리 이름을 대괄호[]
로 감싸야 합니다. 예시를 함께 보겠습니다.
app
디렉토리 하위에 blog
세그먼트가 있고 그 하위에 [slug]
라는 동적 세그먼트
를 만들어주었습니다.
앞서 라우트를 생성할때 해당 url path를 유저가 접근할 수 있게 page.tsx
를 dashboard 세그먼트 하위에 만들었었는데요, 동일하게 [slug]
세그먼트 하위에 page.js를 생성함으로 유저가 /blog/[slug]
url path로 접근할 수 있게 했습니다.
이때 slug는 동적인 세그먼트이므로 Example URL
에 나와있는 것 같이 다음의 url path 모두 유효한 세그먼트입니다.
/blog/a
/blog/b
/blog/c
앞서 작성했던 dashboard 세그먼트를 재활용하여 실습코드를 작성해보겠습니다.
dashboard 세그먼트 하위에 [slug]
세그먼트를 만들고 page.tsx를 작성합니다.
그리고 어떻게 동적 세그먼트에 접근할 수 있는지 확인해봅시다.
type PageParams = {
slug: string
}
export default function page({ params }: { params: PageParams }) {
console.log({ params })
return <div>{params.slug}</div>
}
위와 같이 page.tsx에서 params
props를 통해 해당 동적 세그먼트에 접근할 수 있습니다.
나중에 알아볼 또다른 layout.js 파일에서도 해당 props에 접근할 수 있답니다!
화면에 출력되는 layout 이나 template은 잠시 무시합시다. dashboard/1 url path로 접근했을때 코드에 작성한 것같이 params.slug가 화면에 표기됨을 확인했습니다.
한 url path가 여러개의 동적 세그먼트로 이뤄져있으면 각 세그먼트 값에 어떻게 접근할 수 있을까요?
다음과 같이 폴더 구조를 만들었습니다.
// app/dashboard/[slug]/[id]/page.tsx
export default function page({
params,
}: {
params: { slug: string; id: string }
}) {
console.log("params in [id]: ", params)
return <div>{params.id}</div>
}
params props
의 type을 동적 세그먼트의 이름으로 정의해주었습니다.
url path /dashboard/1
과 /dashboard/1/2
로 각각 접속했을때 서버 콘솔에 표기되는 props 형태를 살펴봅시다.
이 때 표기되는 화면은 다음과 같습니다.
url path /dashboard/1/2
로 접속.
어떤 일이 일어났는지 보면, [id]
동적 세그먼트를 담당하는 url path로 접근했을 때
부모 경로에 있는 page.tsx는 무시되고 [id] 세그먼트 디렉토리 내부에 있는 page.tsx만 표기됨을 확인할 수 있습니다.
이번 강의에서는 기본적인 라우팅, 페이지 생성과 동적 라우팅 동작 원리에 대해 알아보았습니다.
다음 강의에서는 라우팅 그룹과 페이지 네비게이션에 대해 알아보도록 하겠습니다. 감사합니다.