Next.js 톺아보기

Next.js 톺아보기

생성일
2023년 07월 01일
태그
Next.js

Background

과거 학생 때 사이드 프로젝트를 진행하면서 주로 React 기반의 Single Page Application 서비스를 개발하였다. SPA는 최초에 필요한 정적 리소스를 전부 다운로드하고, 이후에는 변화하는 부분만을 파악하여 페이지를 갱신해준다. 이는 웹 서비스를 앱처럼 동작하게 만들어 유저에게 매끄러운 사용자 경험을 제공하여 많이 사용되었다.
 
하지만, 최근에는 조금 다르다. SPA의 최초에 필요한 모든 정적 리소스를 한 번에 다운로드하여 초기 렌더링 속도가 느리다는 단점과, 검색 엔진이 크롤링하는 시점에 JavaScript 파일들을 실행하지 않기 때문에 SEO에 취약하다는 큰 단점때문에 SPA를 지양하는 분위기이다.
 
학생 때는 React 기반의 프레임워크인 Next.js가 유행이더라 ~ 해서 생각 없이 라우팅 라이브러리처럼 사용을 했고, 심지어 기본적인 렌더링 방식이 SSG (Static Site Generation)방식인지도 모르고 사용했다.
회사에 들어와서는 본격적으로 Next.js를 활용하여 서비스를 개발했는데, 아직까지 자세한 동작방식에 대해서 지식이 부족하다는 생각이 들어 직접 빌드하고, 프로덕션을 시작해보면서 어떻게 동작하는지 살펴보려고 한다.

CSR은 무엇인가?

Next.js로 들어가기 전에, CSR (Client Side Rendering)이 무엇이고, 해당 렌더링 방식이 가지는 장, 단점을 알아보자.
Client Side Rendering은 웹 사이트의 JavaScript 리소스들이 서버가 아닌 브라우저 (클라이언트)에서 렌더링되는 방식이다.
자세한 작동방식은 다음과 같다.
notion image
  1. 브라우저가 서버에 요청을 한다.
  1. 서버에서는 브라우저 요청에 따른 응답으로 컨텐츠가 거의 비어있는 index.html 파일과 JavaScript 파일들을 브라우저에 전송한다.
  1. 브라우저는 전송받은 JavaScript 파일들을 다운로드 받는다.
  1. 브라우저는 다운로드 받은 JavaScript 파일들을 실행한다. 이 때 브라우저에서는 사용자에게 보통 로딩중임을 확인할 수 있는 로딩 컴포넌트를 제공한다.
  1. 페이지의 콘텐츠들이 보여지고 interactive 해진다.

CSR의 장점은?

사용자 경험이 매끄럽다.
→ 초기 속도는 느릴 수 있지만, 그 후에 페이지 reloading 없이 필요한 부분만 서버로부터 받아서 화면을 보여주기 때문에 속도는 Server Side Rendering에 비해 굉장히 빠르다. 웹 서비스에서도 앱을 사용하는 것과 같은 좋은 사용자 경험을 제공할 수 있다. 새로고침을 하지 않기 때문.

CSR의 단점은?

  1. 검색 엔진 최적화(SEO)에 취약하다.
→ 크롤링 시점에 JavaScript 파일이 비어있으므로 정보를 수집해가지 못한다.
  1. JS Bundle 사이즈가 커질수록 초기 렌더링 속도가 느려진다.
→ 필요한 JavaScript 리소스를 처음 렌더링 시 모두 다운로드 하기 때문에 초기 렌더링 속도가 느리다. 이는 Lazy Loading이나 Code Splitting으로 어느정도 보완이 가능하다.
 
이러한 Client Side Rendering의 단점들이 바로 Server Side Rendering이 가능한 프레임워크인 Next.js가 주목받게 된 계기이다.
그렇다면, 본격적으로 Next.js 내부 작동 방식을 뜯어보기 전에, Server Side Rendering은 어떻게 동작하길래 SPA의 단점을 보완할 수 있는 것일까?

SSR은 무엇인가?

브라우저(클라이언트)에서 렌더링되는 방식인 CSR과 다르게, SSR은 말 그대로 서버에서 렌더링을 진행하는 방식이다.
자세한 작동방식은 다음과 같다.
notion image
  1. 브라우저가 서버에 요청을 한다.
  1. CSR과 달리, 서버에서 JavaScript를 실행한 후, HTML 컨텐츠를 컴파일 및 준비한다.
  1. 컴파일된 HTML을 브라우저(클라이언트)에 전송한다.
  1. 브라우저(클라이언트)는 HTML을 다운로드 받아 사용자가 사이트를 볼 수 있게 한다.
  1. 그 후, 브라우저는 JavaScript를 다운로드 및 실행하여 페이지가 interactive 해지게 한다.

Next.js를 뜯어보자

이제는 직접 Next.js 프로젝트를 만들고, 이를 빌드하고, 시작할 때 어떠한 일들이 발생하는지 살펴보면서 내부 작동방식을 뜯어보려고 한다.
 
Vercel에서 제공하는 Next.js 템플릿을 설치해준다.
$ yarn create next-app .
 
생성된 Next.js 프로젝트를 빌드해보자.
$ yarn build
notion image
위의 사진과 같이 3가지 항목을 확인할 수 있다.
  • Route (pages)
  • Size - 클라이언트에서 특정 페이지에 방문할 때 필요한 asset들의 크기 (해당 페이지의 HTML, CSS, JavaScript, Image…)
  • First Load JS - 서버에서 특정 페이지를 렌더링할 때 필요한 asset들의 크기, First Load JS shared by all (서비스 전반에 사용되는 공통 코드, framework 코드 …)들의 크기
 
또한, 빌드를 하게 되면 다음과 같은 결과물들이 생성되고, /.next 디렉토리에 생성된다.
  • getStaticProps 를 사용하거나, 아무것도 사용하지 않아 Next.js에서 자체적으로 Automatic Static Optimization을 한 HTML 파일들
  • 전체적으로 사용되는, 혹은 특정 범위에 사용되는 CSS 파일들
  • Next.js 서버에서 컨텐츠를 pre-rendering 하기 위한 JavaScript 파일들
  • React를 통해 클라이언트에서 interact 하기 위한 JavaScript 파일들

Next.js 빌드 결과물 살펴보기

위의 설명과 같이 /.next 디렉토리에 다음과 같이 빌드 결과물들이 생성되었다. 하나씩 자세히 살펴보자
notion image
.next/static/chunks/pages
해당 페이지에 관련된 JavaScript 파일들이 들어간다. CNA 기본 템플릿을 실행해서, 네트워크 탭을 통해 확인할 수 있다.
  1. /
notion image
  1. /404
notion image
위의 두 페이지를 통해, _app.tsx JavaScript 파일은 모든 페이지에서 실행이 되는 것을 확인할 수 있다.
 
.next/static/media
next/image 로부터 static하게 import되는 이미지들이 해당 파일에 복사된다.
notion image
 
.next/static/css
서비스의 모든 페이지에 사용되는 CSS 파일들이 들어있다.
notion image
앞서 살펴본 .next/static 폴더에 있는 파일들은 빌드 타임에 이미지 최적화, code splitting 등 다양한 최적화 작업을 거친다.
 
.next/server
서버 사이드 로직의 파일들로 구성되어 있다. 따라서, 브라우저(클라이언트)로 전송되지 않는다. 서버 사이드 로직 파일들은, 페이지의 컨텐츠들을 pre-rendering할 때 사용된다.
notion image
아래 사진과 같이, .next/server 파일들은 네트워크 탭에서 찾아볼 수 없다.
notion image
 
.next/cache
해당 캐시를 활용하면 빌드 타임을 줄이고, 이미지 로딩 관련 성능 향상을 기대할 수 있다.
notion image
 
지금까지 CSR, SSR의 특징을 알아보고, 빌드했을 때 생성되는 리소스들에 대해서 알아보았다. 다음 아티클에서는 Next.js 프로덕션을 실행시켰을 때 사용되는 빌드 리소스들을 브라우저(클라이언트)에서 살펴보겠다.

References

댓글

guest