웹 개발 다음 Step, Next.js!

aydennote·2024년 9월 4일
1

Next.js

목록 보기
2/2
post-thumbnail

Page router 장점

1. 간편하고 직관적인 페이지 라우팅

1. 정적 경로

  • / , /search

2. 동적 경로

  • [id].tsx : 하나의 URL 파라미터를 받아 사용
  • [...id].tsx : Catch All Segment로 모든 URL 파라미터를 받아 사용
  • [[...id]].tsx : Optional Catch All Segment로 모든 URL 파라미터와 인덱스 경로까지 대응 가능.

2. 다양한 방식의 사전 렌더링

Next.JS는 React의 단점인 느린 FCP(First contentful paint) 보완해주는 렌더링 방식을 제공한다.

1. 서버사이드 렌더링 (SSR)

  • 요청이 들어올 때마다 사전 렌더링을 진행
  1. 유저 ➡ 서버 : 접속 요청
  2. 서버 : JS 실행(렌더링), 서버에 데이터 요청 및 수신.
  3. 서버 ➡ 유저 : 렌더링 된 HTML 전송
  4. 유저 : HTML 파일 화면에 렌더링

2. 정적 사이트 생성 (SSG)

  • 빌드 타임에 미리 페이지를 사전 렌더링
  • SSR 방식에서 JS 실행 단계에서 서버에 데이터 요청 및 수신 받는데 오래 걸리는 경우, 사용자가 화면을 렌더링하는 데 시간이 오래 걸리는 문제를 보완.

3. 증분 정적 재생성 (ISR)

  • SSG 페이지를 일정 시간마다 재생성
  • 일반적인 SSG 방식의 경우, 이미 만들어진 페이지는 다시 만들지 않기 때문에 최신 데이터 반영이 여렵다는 단점이 있는데 이를 보완.

  • on-demand 방식의 경우, Next.js 서버에 Revalidate 요청을 보내 유저의 특정 행동 이후에 페이지 재생성이 가능하다.

Page router 단점

1. 복잡하고 비효율적인 페이지별 레이아웃 설정

const Page = () => {
	return (
      ...
    )
}

export default Page

Page.getLayout = (page:ReactNode) => {
  return <MainLayout>{page}</MainLayout>;
}

페이지별로 서로다른 레이아웃을 적용하고 싶다면 각 페이지별로 레이아웃 코드를 작성하고 App 컴포넌트에 props로 레이아웃을 적용시키는 코드를 작성해야 된다.

2. 데이터 패칭이 페이지 컴포넌트에 집중

getServerSideProps, getStaticProps 함수를 페이지 컴포넌트에 작성하여 백엔드 서버로부터 데이터를 불러와 페이지 컴포넌트에게 Props로 데이터를 전달해줘야 한다.

3. 불필요한 컴포넌트들도 JS Bundle에 포함

전체 렌더링 과정에서 JS는 총 두 번 실행된다.
첫 번째는 서버에서 JS 코드들을 HTML로 렌더링 할 때 실행되고 두 번째는 하이드레이션을 진행 할 때 실행된다.

하이드레이션은 페이지에 아직 JS 코드들이 없어 JS 코드를 입히는 과정이다.
즉, 상호작용에 필요한 코드들만 JS Bundle 작업이 이루어지고 해당 코드가 입혀지면 되는 것이다. 나머지 UI에 필요한 코드들은 이미 1번 서버에서 HTML로 렌더링 할 때 이용이되었으니 말이다.

그런데, 실제로는 JS Bundle시 UI에 사용된 코드들을 포함한 컴포넌트들이 Bundle된다.

이렇게되면 JS Bundle 용량이 불필요하게 커지게 된다. 용량이 커지면서 당연하게 하이드레이션 과정의 소요시간이 길어지게 되고 TTI에 이르기까지 오래걸리는 것이다.


App router 장점

1. 간단한 레이아웃 설정

/search 경로로 시작하는 모든 페이지의 레이아웃이 적용되기 때문에 /search/setting 경로 또한 layout이 적용된다.

/search/setting 경로에 layout을 생성하게 되면 layout이 중첩되어 적용이 된다.

페이지 경로와 상관 없이 공통적으로 Layout을 적용하고 싶다면, 위 사진처럼 폴더명을 소괄호로 묶어 라우트 그룹 설정하여 공통적인 Layout 적용이 가능하다.

2. 서버 컴포넌트

React v18 이상에서 사용 가능한 서버에서만 작동되는 컴포넌트이다.
서버 컴포넌트가 필요한 이유는 기존 Page router 단점 중에 불필요한 컴포넌트까지 JS Bundle 되는 문제를 해결하기 위해 등장했다.

클라언트 컴포넌트와 서버 컴포넌트로 분리하여 1번 과정에서는 전체 컴포넌트가 실행이 되고, 2번 과정에서는 하이드레이션을 위해 브라우저에서 클라이언트 컴포넌트만 실행된다.

Bundle 용량이 줄어든다는 장점 때문에 페이지 대부분을 서버 컴포넌트로 구성하는 것이 권장되고 클라이언트 컴포넌트는 꼭 필요한 경우에만 사용하는 것이 좋다.

컴포넌트 구성 기준은 상호작용이 필요한 컴포넌트들은 클라이언트 컴포넌트로 만들고 나머지 컴포넌트들을 전부 서버 컴포넌트로 구성하면 된다.

서버 컴포넌트 주의사항

  1. 서버 컴포넌트에는 브라우저에서 실행될 코드가 포함되면 안 된다.
    예를들어,React hook이나 브라우저에서 실행되는 기능을 담고 있는 라이브러리 등이 있다.

  2. 클라이언트 컴포넌트는 클라이언트에서만 실행되지 않는다.
    이름이 클라이언트 컴포넌트이기 때문에 클라이언트에서만 실행되는 것으로 착각할 수 있는데 위에도 작성되어 있듯이 클라이언트 컴포넌트는 사전 렌더링을 위해 서버에서 1번 실행되고 하이드레이션을 위해 브라우저에서 1번 실행된다.

  3. 클라이언트 컴포넌트에서 서버 컴포넌트를 import 할 수 있다.
    원래 서버 컴포넌트는 JS Bundle에서 제외되기 때문에 브라우저에서 실행되지 않는다.
    하지만, Next.JS는 수월한 개발환경을 위해 클라이언트 컴포넌트에서 서버 컴포넌트를 import 하면 서버 컴포넌트를 클라이언트 컴포넌트로 자동으로 변환시켜준다.

어쩔 수 없이 클라이언트 컴포넌트에서 서버 컴포넌트를 import 해야할 상황이라면 import 문을 사용하기 보다 위 사진처럼 props로 children을 받아 구현하는 것이 좋다.
이렇게 구현하면 서버 컴포넌트의 결과물만 클라이언트 컴포넌트에 children이라는 props 로 전달되기 때문에 직접 실행시키지 않아 서버 컴포넌트가 클라이언트 컴포넌트로 자동 변환되지 않는다.

  1. 서버 컴포넌트에서 클라이언트 컴포넌트에게 직렬화 되지 않는 Props는 전달 불가하다.
    예를 들어, 함수, 클래스 인스턴스, 혹은 다른 복잡한 객체들은 일반적으로 JSON 형태로 직렬화하는 것이 불가능한데 이러한 데이터들은 전달이 불가능하다.

App router 단점

1. 비교적 복잡한 페이지 라우팅

1. 정적 경로

  • /page.tsx , /search/page.tsx

2. 동적 경로

  • [id]/page.tsx : 하나의 URL 파라미터를 받아 사용
  • [...id]/page.tsx : Catch All Segment로 모든 URL 파라미터를 받아 사용
  • [[...id]]/page.tsx : Optional Catch All Segment로 모든 URL 파라미터와 인덱스 경로까지 대응 가능.
profile
기록하는 개발자 Ayden 입니다.

0개의 댓글