해당 글은 Next 13 이전 버전을 기준으로 작성하였습니다.
Next.js는 파일 시스템 기반의 라우터를 사용합니다.
- 폴더(Folders)는 라우트를 정의하는데 사용됩니다.
- 파일(Files)은 라우트 세그먼트에 대해 표시될 UI를 생성하는데 사용됩니다.
Next.js 프로젝트는 기본적으로 pages/
디렉토리를 가지고 있습니다. 이 디렉토리 안의 모든 파일은 곧 페이지와 라우팅 규칙을 뜻합니다. 따라서 페이지 라는 것은 pages/
디렉토리 안의 .js
, .jsx
, .ts
, .tsx
에서 export한 리액트 컴포넌트라고 알 수 있습니다.
Next.js는 파일과 폴더명으로 라우터가 분리가되고 인식을 하기때문에 다음과 같은 규칙들이 준수되어야 합니다.
pages 라우팅 규칙
특별한 파일
_app: .js .jsx .tsx 커스텀 앱
_document: .js .jsx .tsx 커스텀 문서
_error: .js .jsx .tsx 커스텀 오류 페이지
404: .js .jsx .tsx 404 오류 페이지
500: .js .jsx .tsx 500 오류 페이지
라우트 규칙
폴더 규칙
index: .js .jsx .tsx 홈페이지
folder/index: .js .jsx .tsx 중첩된 페이지
파일 규칙
index: .js .jsx .tsx 홈페이지
file: .js .jsx .tsx 중첩된 페이지
동적 라우트
폴더 규칙
[folder]/index: .js .jsx .tsx 동적 라우트 세그먼트
[...folder]/index: .js .jsx .tsx 모든 세그먼트 포착
[[...folder]]/index: .js .jsx .tsx 선택적 모든 세그먼트 포착
파일 규칙
[file]: .js .jsx .tsx 동적 라우트 세그먼트
[...file]: .js .jsx .tsx 모든 세그먼트 포착
[[...file]]: .js .jsx .tsx 선택적 모든 세그먼트 포착
pages/
내의 각 폴더는 라우트 세그먼트를 나타냅니다. 각 라우트 세그먼트는 URL 경로의 해당 세그먼트에 매핑됩니다.
예시 폴더구조는 다음과 같습니다.
접근하는 방법은 각각 다음 주소로 접근합니다.
/ // root 경로
/main // mainPage
/post // postPage
/post/[postid] // postDetailPage
루트를 제외한 나머지 같은 경우 폴더 이름이 세그먼트가 된 것을 확인 할 수 있습니다.
export type PostDetailPropsType = {
postId: string
}
export async function getServerSideProps({params}: { params: PostDetailPropsType }) {
const {postId} = params;
return {
props: {
postId
}
}
}
const PostDetailPage = (props: PostDetailPropsType) => (
<>This is PostPage :( {props.postId}</>
);
export default PostDetailPage;
페이지와 달리 컴포넌트는 파람으로 가져올 수 없습니다. 그 이유는 페이지 밖에서 getServerSideProps 혹은 getStaticProps를 사용할 수 없기 때문입니다. 그러면 무조건 props로 넘겨주는 방법밖에 없을까요? 정답은 useRouter 훅을 사용하면 됩니다.
import { useRouter } from "next/router";
const PostTitle = () => {
const { query } = useRouter()
return <header>{query.postId} 게시물에 관한 정보입니다.</header>
};
export default PostTitle;
useRouter는 동적 매개변수 이외에도 param값 들도 받아올 수 있습니다.
다음 주소로 url을 입력을 합니다. http://localhost:3000/post/32?name=brian22&age=22
그러면 다음과 같은 결과를 위에 query를 출력함으로서 받아올 수 있습니다.
{
age : "\"20\"",
name : "\"brian\"",
postId : "32"
}
리액트 웹 애플리케이션을 서버에서 렌더링을 하려고 만든 프레임 워크가 아닙니다. 다양한 기능을 비롯하여 성능을 최적화할 수 있느 많은 방법을 제공합니다. 그 중 하나가 바로 클라이언트에서 내비게이션을 처리하게하는 것입니다.
기존 html
의 <a>
태그를 이용하여 페이지를 연결할 수도 있지만 <Link>
컴포넌트를 통해 서로 다른 라우트 간의 이동을 최적화 할 수 있습니다.
Next.js는 현재 화면에 표시되는 모든 Link에 대해 연결된 부분 또는 페이지를 미리 불러올 수 있습니다. 만약 미리 불러오는 기능을 끄고싶다면 Link 컴포넌트에 preload={false} 속성을 주면 됩니다.
const Layout = () => (
<header>
<nav style={{display: 'flex', gap: '5px'}}>
<Link href={'/main'}>Main</Link>
<Link href={'/post'}>Post</Link>
<Link href={'/post/13'}>Post</Link>
<Link href={'/post/[postId]'} as={'/post/13'}>Post</Link>
<Link href={{pathname: '/post/[postId]', query: {postId: 13}}}>Post</Link>
</nav>
</header>
)
코드 아래 3개의 포스트 상세페이지로 가는 <Link>
는 사용법은 다르지만 모두 한 경로를 나타내고 있습니다. 이처럼 복잡한 URL을 사용한다면 href에 속성에 객체를 전달할 수도 있습니다.
useRouter 훅에서 제공하는 push()
메소드도 사용할 수 있습니다.
const navigate = useRouter();
const onClick = async () => {
await navigate.push('/post/32')
}
...
const Layout = () => (
<header>
<nav style={{display: 'flex', gap: '5px'}}>
<Link href={'/main'}>Main</Link>
<Link href={'/post'}>Post</Link>
<button onClick={onClick}>PostDetail</button>
</nav>
</header>
)
서버 컴포넌트 는 서버/클라이언트를 모두 불러 사용할 수 있지만, 클라이언트 컴포넌트는 클라이언트 컴포넌트만 가져다 사용할 수 있습니다.
서버 컴포넌트에서 클라이언트 컴포넌트로 전달되는 props는 직렬화 가능해야 합니다. 함수, 날짜 같은 것들은 전달할 수 없습니다.