Next.js는 리액트 기반의 서버사이드 렌더링 프레임워크이다.
React는 클라이언트 사이드에서만 작동한다는 특징이 있는데, 이로 인해 SEO 효과가 저조했으며 초기 렌더링시 성능 부담이 크다는 문제점이 존재했다. 이러한 문제점을 해결하기 위해 Next.js가 도입되기 시작했다.
app router
가 도입되면서 page router
와 app router
두 가지 방식으로 나뉘게 되었다.
app/
디렉토리로 라우팅을 처리하는 방식pages/
디렉토리로 라우팅을 처리하는 방식두 라우팅 방식의 차이점은 서버 컴포넌트를 사용하는지에 대한 유무이다.
*서버 컴포넌트 : 넥스트 서버에서 리액트를 미리 렌더링해서 프론트 또는 브라우저 또는 클라이언트로 데이터를 보내줄 때 완성된 HTML을 미리 보내주는 것
프론트 입장에서 HTML 로딩 시간 감소, HTML과 JS 용량 감소 등의 이점이 생겼다.
그러나, 서버 컴포넌트는 유저의 브라우저에서 진행하던 일을 넥스트 서버에서 다 진행하기 때문에 서버의 부담이 증가한다.
이 문제를 원활하게 해결하고자 서버에서 캐시를 적극적으로 활용했다.
npx create-next-app 프로젝트명
*리액트 프로젝트 생성 명령어와 매우 유사하다 (npx create-react-app
)
app router
는 app 디렉토리 내에 root layout을 필수로 포함해야 한다.
Root Layout
은 모든 페이지에 공통적으로 적용되는 레이아웃으로, 필수 레이아웃이다. Root Layout에는 html 태그와 body 태그가 포함되어야 한다.
만일, 라우터별로 레이아웃을 따로 만들고 싶다면 해당 디렉토리 내에
layout.tsx
파일을 별도로 생성하면 된다.
*RootLayout > HomeLayout > HomePage
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Dynamic Routes
는 동적 데이터(변수)로 라우터를 설정할 때 사용한다. 디렉토리명을 대괄호[]
로 묶어서 생성하면 해당 경로는 동적 데이터를 사용할 수 있다.
예를 들어, https://velog.io/@kim_unknown_
과 같이 경로에 유저의 id가 들어가야 한다면, [userId]
와 같이 디렉토리를 생성한다.
Route Groups
는 라우터에 영향을 주지 않으면서 라우터를 그룹화할 때 사용한다. 디렉토리명을 소괄호()
로 묶어서 생성하면 내부에 있는 디렉토리들을 그룹화할 수 있다.
예를 들어, 아래와 같이 특정 서비스의 로그인 전 단계와 로그인 후 단계의 경로를 구분하여 그룹화할 경우, (beforeLogin) 과 (afterLogin)은 경로가 되지 않는다. 단순 묶음 폴더의 역할을 하는 것 뿐이다.
따라서 실제 브라우저 주소창에는 /login
, /join
, /logout
, /leave
로 경로가 보이게 된다.
app
/* 로그인 전 라우터 */
⌞(beforeLogin)
⌞login
⌞join
/* 로그인 후 라우터 */
⌞(afterLogin)
⌞logout
⌞leave
Layout
: 페이지를 넘나들 때 새로 마운트(리렌더링)가 되지 않는다.Template
: 페이지를 넘나들 때마다 새로 마운트(리렌더링)가 된다.때문에 마운트 필요에 따라 적절하게 레이아웃과 템플릿을 구분하여 사용해야 한다. 레이아웃과 템플릿은 공존하면 안된다.
Next에서는 <a>
태그 대신 <Link>
컴포넌트를 사용한다.
<a>
태그를 사용하여 경로 이동 시, 화면이 깜빡거리며 페이지가 새로고침 되기 때문에 좀 더 부드러운 경로 이동을 위해 <Link>
컴포넌트를 사용한다.
import Link from "next/link";
<Link href="/home">홈</Link>
Next에서는 <img>
태그 대신 <Image>
컴포넌트를 사용한다.
<Image>
컴포넌트를 사용하게 되면 넥스트에서 이미지를 최적화해준다.
Image 컴포넌트에서 제공하는 기능은 다음과 같다.
import Image from "next/image";
import logo from '../public/logo.png';
<Image src={logo} alt="logo" />
redirect
함수는 다른 URL로 리다이렉트 시킬 때 사용한다.
import { redirect } from 'next/navigation';
export default function Default() {
redirect('/home');
}
Parallel Route
는 여러 개의 페이지를 동시에 보여줄 때 사용한다. (ex. 뒤에 페이지가 남아있으면서 그 위로 모달을 띄울 때)
Parallel Route를 적용할 때는 디렉토리명 앞에 골뱅이(@)
를 명시한다. (ex.@modal
)
다만, 같은 계층에 위치한 페이지끼리 병렬적으로 렌더링할 수 있기 때문에 다른 계층 구조의 페이지는 병렬적으로 렌더링할 수 없다.
서버 컴포넌트를 클라이언트 컴포넌트로 전환하기 위해서는 파일 최상단에 "use client"
를 명시한다.
서버 컴포넌트는 클라이언트 컴포넌트를 임포트하는 것이 가능하지만, 클라이언트 컴포넌트는 서버 컴포넌트를 임포트는 것이 불가능하다.
클라이언트 컴포넌트가 서버 컴포넌트를 임포트하면 클라이언트 컴포넌트로 바뀌어버린다.
- 서버 -> 클라이언트 (O)
- 클라이언트 -> 서버 (X)
default.tsx
는 Parallel Route의 기본값이다.
export default function Default(){
return null;
}
Intercepting Routes
는 서로 다른 라우트에서 한 화면을 같이 뜰 수 있게 해준다. Intercepting Routes를 적용할 때는 디렉토리명 앞에 (상대경로..)
를 명시한다.
(.)
을 사용하여 동일 레벨 세그먼트 매칭(..)
을 사용하여 1단계 윗 레벨 세그먼트 매칭(..)(..)
을 사용하여 2단계 윗 레벨 세그먼트 매칭(...)
을 사용하여 app 디렉토리의 루트에 위치한 세그먼트 매칭ex. (.)myPage (인터셉트 라우트) / myPage (일반 라우트)
*Interception Routes는 클라이언트 단을 통해서 진입할 때 적용되며, 브라우저로 주소창을 입력하여 직접 진입하거나 새로고침을 할 경우에는 일반 라우트로 넘어간다.
따라서, 가로채기가 발생하는 상황과 발생하지 않는 상황에 따라 두 디렉토리가 모두 필요하다
Private Folder
는 폴더 정리용으로 사용되며, 라우터에 영향을 주지 않는다. Private Folder를 적용할 때는 디렉토리명 앞에 언더바(_)
를 명시한다.
라우터에 영향을 안주는 폴더 3가지
- (그룹 폴더)
- @페러렐 라우트
- _프라이빗 폴더
감사합니다
잘 봤습니다 😁😆