Front-End/Next

Next.js 프레임워크

Voyage_dev 2024. 8. 2. 23:29
✔️ Next.js 프레임워크가 무엇이고 동작 원리 및 페이지 역할에 대해 살펴보자

 

Next.js란?

https://nextjs.org/

  • Vercel에서 만든 풀 스택 웹 어플리케이션 구축 프레임워크
  • 페이스북 팀에서 만든 react-page라는 리액트 기반 서버 사이드 렌더링 프로젝트 → 여기서 영감을 받음
  • 라이브러리가 아니다

서버 사이드 렌더링의 원리(스텝)

https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming

  • 해당 페이지에서 필요한 모든 데이터가 서버로 fetch된다 (A)
  • 서버는 이 HTML을 렌더링을 한다 (B)
  • B에서 만든 HTML과 CSS, JavaSCript가 클라이언트로 보내지게 된다 (C)
  • 인터랙션이 없는 UI가 HTML과 CSS에 의해서 보여지게 된다
  • 마지막으로, React는 Hydration이라는 과정을 통해서 인터랙션을 브라우저 화면에서 적용을 시켜준다

이 방법은 굉장이 연속적이고 블록킹이 많이 존재한다. 모든 데이터가 패치가 되었을 때 서버가 하나의 페이지 즉 하나의 HTML을 하나씩 렌더링을 할 수 있다는 것을 의미한다. 클라이언트 차원에서도 하나의 페이지에 모든 컴포넌트가 다운로드 된 이후에 UI를 한 번에 하나씩 Hydration을 할 수가 있다. 하지만 이 방법은 성능적으로 굉장히 좋지가 않다. 페이지 한 번에 하나씩밖에 할 수가 없고 렌더링을 하는데 오래 걸리면 기다리는 시간도 굉장히 길다.

 

Next.js는 이러한 로딩 시 발생하는 퍼포먼스 이슈를 해결하기 위해서 스트리밍을 사용했다.

https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming

  • 보이는 것처럼 HTML을 쪼개서 청크로 만들고 연속적으로 서버에서 클라이언트로 하나씩 보내는 방법을 선택했다

https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming

  • 그렇기 때문에 모든 데이터를 기다리지 않고 화면이 조금씩 조금씩 보이기 때문에 사용자는 화면의 부분적인 정보를 더 빠르게 볼 수가 있다.

컴포넌트를 쪼갤 때 예를 들어, 상품 정보와 같이 우선순위가 높은 컴포넌트 그리고 레이아웃과 같이 데이터에 의존하지 않는 컴포넌트들을 먼저 전송을 할 수가 있게 되었다. 그러면 리액트는 그 컴포넌트들을 먼저 Hydration을 할 수가 있다. 그 다음에 리뷰라든지 연관 상품 같은 우선순위가 좀 낮은 컴포넌트들을 처리를 할 수가 있게 된다. 이렇게 로딩 UI와 스트리밍을 통해서 리액트는 페이지를 렌더링하는 성능을 굉장히 혁신적으로 끌어 올렸다.

 

Next.js 시작하기

npx create-next-app@latest
  • TypeScript : Y
  • ESLint : Y
  • Tailwind CSS (옵션)
  • /src directory : N
  • App Router : N (다음에 다룰 예정)
  • import alias : N
npm run dev

 

_app.tsx

  • 어플리케이션 전체 페이지의 시작점, 루트 컴포넌트
  • 이 루트 컴포넌트에서 하위에 이 컴포넌트들이 하나씩 하나씩 다 꼬리를 자식 노드 형태로 퍼져 나가는 구조이다
  • 에러 바운더리를 설정을 해서 전역에서 발생하는 에러를 처리하게 된다. _app..tsx에서 감싸주게 되면 모든 프로젝트의 컴포넌트에 영향을 다 미치기 때문에 에러 바운더리를 설정할 수 있다
  • 전역 CSS를 여기서 설정해 줄 수가 있다. 모든 컴포넌트에 적용되는 스타일을 적용하고 싶을 때 반영해 줄 수 있다
  • 모든 페이지에 사용되는 데이터를 제공하는 데도 설정해 줄 수 있다.

즉, 뭔가 전역에서 작업을 해야 되는 일이 있을 때 _app..tsx 파일을 가장 먼저 찾으면 원하는 설정을 할 수 있다.

 

_document.tsx

  • _app..tsx가 전체를 초기화를 한다면 _document.tsx는 어플리케이션의 HTML을 초기화하는 역할을 하고 있다
  • CSS-in-JS의 스타일을 서버에서 모아서 HTML로 제공하는 역할도 하고 있다

_app.tsx vs _document.tsx 차이점

  • <html>이나 <body>에 DOM 속성을 추가하고 싶다면 _document.tsx 사용
  • _app..tsx는 클라이언트 또는 서버에서 실행이 될 수 있지만, _document.tsx는 무조건 서버에서 실행
    • 따라서, 여기에는 이벤트 핸들러를 추가하는 것은 불가능하다
    • 이벤트 추가는 클라이언트의 hydrate에서 이루어지기 때문이다
  • next/document의 <Head />는 _document.tsx에서만 사용할 수 있다. 또 다른 <head />는 next/head에서 제공하는데 이 <head />는 페이지에서 사용할 수 있다
    • next/document <Head /> 에서는 <title /> 속성을 사용할 수 없다. next/head <head />에서는 title 등 SEO에 필요한 정보를 사용할 수 있다
  • getServerSideProps, getStaticProps등을 여기에서는 사용할 수 없다

에러페이지

에러 발생 시 처리하는 페이지를 커스텀하게 만들어 줄 수 있다

 

pages/_error.tsx

import { NextPageContext } from 'next';

function Error({ statusCode = 500 }) {
	return <p>{statusCode}에러가 발생</p>
}

Error.getInitialProps = ({res, err}: NextPageContext) => {
	const statusCode = res ? res.statusCode : err ? err.statusCode : ''
	
	return { statusCode }
}

export default Error
  • pages/404.tsx : 404 클라이언트 에러 발생시 나타나는 페이지
  • pages/500.tsx : 500 서버 에러 발생시 나타나는 페이지

다음에는 Next.js 프레임워크에서 라우트 구조를 어떻게 가져가고 사버 라우팅과 클라이언트 라우팅의 차이 그리고 API랑 데이터 패칭 관련된 내용을 정리해 보자