About Next.js

Next.js란?

풀스택 웹 애플리케이션을 구축하기 위한 React 프레임워크.
기존에 React를 사용하던 것 처럼 사용자 인터페이스를 구축하고 Next.js를 이용해 추가 기능과 최적화가 가능
내부적으로 Next.js는 번들링(빌드), 컴파일 등과 같이 React에 필요한 도구를 추상화하고 자동으로 구성함. 따라서 구성에 시간을 낭비하지 않고 애플리케이션 구축에만 집중할 수 있다.
→ React보단 자유도가 떨어질 것이다. 대신 React에서 내가 추가적으로 해야하는 일을 대신 해줘서 할 일을 줄여준다!

주요 특징

  • Routing
    레이아웃, 중첩 라우팅, 로딩 상태, 오류 처리 등을 지원하는 서버 컴포넌트 위에 구축된 파일 시스템 기반 라우터
  • Rendering
    서버 컴포넌트와 클라이언트 컴포넌트를 사용한 CSR과 SSR. 게다가 정적 및 동적 렌더링을 서버에서 최적화함. Edge와 node.js 런타임에서 스트리밍함
  • Data Fetching
    서버 컴포넌트에서의 async/await를 이용한 단순화된 데이터 fetching, 요청 메모, 데이터 캐싱 그리고 재검증을 위한 확장된 fetch API 제공
  • Styling
    CSS 모듈, Tailwind, CSS-in-JS 등 선호하능 방식 사용 가능
  • Optimizations
    어플리케이션의 핵심 웹 바이탈과 사용자 경험을 개선하기 위한 이미지, 폰트, 그리고 스크립트 최적화.
  • TypeScript
    더 나은 타입 체크와 사용자 정의 플러그인, 타입 체커로 타입스크립트에 대한 지원 향상

App Router VS Pages Router

  • App Router
    서버 구성 요소 및 스트리밍같은 React의 최신 기능을 사용할 수 있는 최신 라우터
  • Pages Router
    서버에서 렌더링된 React 애플리케이션을 구축할 수 있게 해주고 이전 Next.js 애플리케이션에 대해 계속 지원되는 최초의 Next.js 라우터

Next.js의 작동방식

단계별로 애플리케이션 코드에 어떤 일이 발생할까?

  • 코드가 실행되는 환경: Development vs. Production
  • 코드가 실행될 때 : Build Time vs. Runtime
  • 렌더링이 발생하는 위치 : Client vs. Server

🔥 Next.js 컴파일러는 이렇게 동작해요
애플리케이션을 개발에서 프로덕션으로 이동하려면 컴파일, 번들화, 축소 및 코드 분할을 해야합니다. Next.js는 Rust로 작성된 컴파일러와 컴파일, 축소, 번들링 등에 사용할 수 있는 SWC가 있기 때문에 코드 변환과 기본 인프라의 대부분을 처리해 애플리케이션이 더 쉽게 프로덕션에 들어갈 수 있게합니다.

컴파일은 언제 동작합니까?

Next.js에서는 코드를 편집하는 개발 단계와 애플리케이션 프로덕션(제품화) 준비를 위한 빌드 단계 일부로 컴파일이 발생합니다.

Minifying(축소)는 왜 필요한가요?

개발자가 작성한 코드는 사람이 읽기 좋게 주석, 공백, 들여쓰기, 여러 줄 등 코드 실행에 불필요한 정보가 포함되어 있습니다.

축소는 코드의 기능을 변경하지 않고 불필요한 코드 서식과 주석을 제거해 성능을 향상하는 프로세스입니다.

번들링은 무엇인가요?

개발자는 더 큰 규모의 애플리케이션으로 구축하는데 사용할 수 있는 모듈, 컴포넌트, 기능들로 애플리케이션을 나눕니다. 번들링은 사용자가 웹 페이지를 방문할 때 요청하는 파일의 수를 줄이는 것을 목표로 종속성 웹을 해결하고 파일(및 모듈)을 브라우저에 최적화된 번들로 패키징하는 프로세스입니다.

코드 분할이란?

개발자는 일반적으로 애플리케이션을 다양한 URL에서 액세스할 수 있는 여러페이지로 나눕니다. 이런 각 페이지는 애플리케이션의 고유한 진입 점이 됩니다.

코드 분할은 애플리케이션의 번들을 각 진입점에 필요한 작은 덩어리들로 분할하는 프로세스인데, 목표는 해당 페이지를 실행하는 데 필요한 코드만 로드해 애플리케이션의 초기 로드 시간을 개선하는 것입니다.

Next.js에는 코드 분할 기능이 내장되어 있고, 디렉터리 내의 각 파일은 pages/ 빌드 단계에서 자동으로 자체 JS 번들로 코드 분할됩니다. (Page Router 설명인 것 같음)

추가적으로

  • 페이지 간 공유되는 모든 코드는 추가 탐색 시 동일한 코드 재다운로드를 방지하기 위해 다른 번들로 분할합니다.
  • 초기 페이지 로드 후 Next.js는 사용자가 탐색할 가능성이 있는 다른 페이지의 코드를 미리 로드할 수 있습니다. <Link>
  • 동적 가져오기는 처음에 로드되는 코드를 수동으로 분할하는 또 다른 방법입니다.

Build Time & Runtime

Build Time

프로덕션용 애플리케이션 코드를 준비하는 일련의 단계에 부여되는 이름

애플리케이션을 빌드하면 Next.js는 코드를 서버에 배포하고 사용자가 사용할 수 있도록 프로덕션에 최적화된 파일로 변환한다. 다음 내용이 포함된다.

  • 정적으로 생성된 페이지용 HTML 파일
  • 서버에서 페이지를 렌더링하기 위한 JavaScript 코드
  • 클라이언트에서 페이지를 인터랙티브하게 만들기 위한 JavaScript 코드

Runtime

애플리케이션이 구축되고 배포된 후 사용자의 요청에 대한 응답으로 애플리케이션이 실행되는 기간

클라이언트와 서버

클라이언트

애플리케이션 코드에 대한 요청을 서버에 보내는 사용자 장치의 브라우저를 나타냅니다. 서버로부터 받은 응답을 사용자가 상호 작용할 수 있는 인터페이스로 바꿉니다.

서버

애플리케이션 코드를 저장하고, 클라이언트로부터 요청을 받고, 일부 계산을 수정하고, 적절한 응답을 다시 보내는 데이터센터의 컴퓨터를 의미합니다.

렌더링이란?

React에서 작성한 코드를 UI의 HTML으로 변환하려면 피할 수 없는 작업단위. 서버나 클라이언트에서 발생할 수 있는데, 빌드 시 미리 발생하거나 런타임시 모든 요청에서 발생할 수 있습니다.

Next.js에선 SSR(Server-Side Rendering), SSG(Static Site Generation) 및 CSR(Client-Side Rendering)의 세 가지 유형의 렌더링 방법을 사용할 수 있습니다.

Pre-Rendering

서버 측 렌더링 및 정적 사이트 생성은 결과가 클라이언트에 전송되기 전에 외부 데이터를 가져오고 React 구성 요소를 HTML로 변환하기 때문에 사전 렌더링이라고도 합니다.

Client-Side Rendering vs. Pre-Rendering

CSR

표준 React 애플리케이션에서 브라우저는 UI를 구성하기 위한 JavaScript 지침과 함께 서버로부터 빈 HTML 셸을 받습니다. 초기 렌더링 작업이 사용자 장치에서 발생하므로 이를 클라이언트 측 렌더링이라 합니다.

Pre-Rendering

대조적으로 Next.js는 기본적으로 모든 페이지를 사전 렌더링합니다. 사전 렌더링은 HTML이 사용자 장치에서 JavaScript로 모든 작업을 수행하는 대신 서버에서 미리 생성된다는 것을 의미합니다. (JavaScript 작업이 완료되기 전에 미리 생성)

실제로, 완전히 클라이언트 측에서 렌더링된 앱의 경우 렌더링 작업이 완료되는 동안 사용자는 빈 화면을 보게 됩니다. 둘을 비교하면 아래와 같습니다.

Server-Side Rendering vs. Static Site Generation

SSR

SSR을 사용하면 각 요청에 대해 페이지의 HTML은 서버에 먼저 생성됩니다. 이후 페이지를 인터렉티브하게 만들기 위해 생성된 HTML, JSON 데이터 및 JavaScript가 클라이언트로 전송됩니다.

CSR에서 HTML은 빠른 non-interactive 페이지를 표시하는데 사용되는 반면, React는 JSON 데이터와 JavaScript를 이용해 구성요소를 인터렉티브하게 만듭니다. 이 과정을 우리는 Hydration이라 합니다.

Next.js에서 getServerSideProps를 사용해 서버 측 렌더링 페이지를 선택할 수 있습니다.

참고: React 18 및 Next 12 에는 React 서버 구성 요소 의 알파 버전이 도입되었습니다 . 서버 구성 요소는 서버에서 완전히 렌더링되며 렌더링하는 데 클라이언트 측 JavaScript가 필요하지 않습니다. 또한 서버 구성 요소를 사용하면 개발자는 일부 논리를 서버에 유지하고 해당 논리의 결과만 클라이언트에 보낼 수 있습니다. 이렇게 하면 클라이언트로 전송되는 번들 크기가 줄어들고 클라이언트 측 렌더링 성능이 향상됩니다.

SSG

정적 사이트 생성을 사용하면 HTML이 서버에서 생성되지만 서버 측 렌더링과 달리 런타임에는 서버가 없습니다. 대신 콘텐츠는 빌드 시 애플리케이션이 배포될 때 한 번 생성되고 HTML은 CDN에 저장되어 각 요청에 재사용됩니다.

Next.js에서 getStaticProps를 사용해 페이지를 정적으로 생성하도록 선택할 수 있습니다.

참고: 사이트를 구축한 후 Indremental Static Regeneration을 사용해 정적 페이지를 생성하거나 업데이트  할 수 있습니다. 이는 데이터가 변경된 경우 전체 사이트를 다시 구축할 필요가 없음을 의미합니다.

🔥 Next.js의 장점은 SSG, CSR, SSR 등 페이지 단위로 사용 사례에 가장 적합한 렌더링 방법을 선택할 수 있다는 것입니다.

네트워크란?

리소스를 공유할 수 있도록 연결된 컴퓨터(또는 서버)

Next.js 애플리케이션의 경우 애플리케이션 코드를 origin servers, CDN(Content Delivery Network) 및 Edge에 배포할 수 있습니다.

origin servers

애플리케이션 코드의 원본 버전을 저장하고 실행하는 기본 컴퓨터를 의미

CDN, Edge 서버와 구별하기 위해 원본이라는 용어를 사용합니다.

원본 서버는 요청을 받으면 응답을 보내기 전에 일부 계산을 수행합니다. 이 계산 작업의 결과는 CDN으로 이동할 수 있습니다.

CDN(콘텐츠 전달 네트워크)

HTML 및 이미지 파일과 같은 정적 콘텐츠를 전 세계 여러 위치에 저장하며 클라이언트와 원본 서버 사이에 배치됩니다. 새로운 요청이 들어오면 사용자와 가장 가까운 CDN 위치가 캐시된 결과로 응답할 수 있습니다.

이렇게 하면 각 요청마다 계산이 발생할 필요가 없기 때문에 origin에서의 로드가 줄어듭니다. 또한 지리적으로 더 가까운 위치에서 응답이 오기 때문에 속도가 더 빨라집니다.

Next.js에서는 사전 렌더링이 미리 수행될 수 있으므로 CDN은 작업의 정적 결과를 저장하는 데 매우 적합해 콘텐츠 전달을 더 빠르게 만듭니다.

The Edge

사용자에게 가장 가까운 네트워크의 주변(또는 Edge)에 대한 일반화된 개념입니다. CDN은 네트워크의 가장자리에 정적 콘텐츠를 저장하기 때문에 Edge의 일부로 간주될 수 있습니다.

Edge와 유사하게 CDN은 전 세계 여러 위치에 배포됩니다. 그러나 정적 콘텐츠를 저장하는 CDN과 달리 일부 Edge 서버는 작은 코드 조각을 실행할 수 있습니다.

이는 캐싱과 코드 실행이 모두 사용자에게 더 가까운 Edge에서 수행될 수 있음을 의미합니다.

일부 전통적으로 클라이언트 측이나 서버 측에서 수행되던 작업을 엣지(Edge)로 이동함으로써 응용 프로그램의 성능을 높일 수 있습니다. 이렇게 하면 클라이언트로 전송되는 코드 양이 감소하고, 사용자의 요청 일부가 원래 서버까지 이동하지 않아도 되므로 응답 지연이 줄어들어 성능이 향상됩니다.

Next.js에서 미들웨어를 사용해 Edge에서 코드를 실행할 수 있으며 React Server Components를 사용해 코드를 실행할 수 있습니다.

About Next.js