해당 문서는 Next.js의 동작 원리를 심도있게 이해하고자 작성된 공식문서 번역 문서입니다. 원문의 의미를 최대한 반영하는 동시에 자연스럽게 이해할 수 있는 방향으로 번역하고자 노력하였습니다. 오역이 있을 수 있으니 확인 부탁드리며 피드백 주시면 반영하도록 하겠습니다.
원문주소:
https://nextjs.org/learn/foundations/how-nextjs-works
번들링은 무엇일까?
개발자들은 모듈, 컴포넌트, 함수의 작은 조각의 형태로 나누고 이 작은 조각들을 결합하여 좀 더 큰 조각들을 만드는 방식으로 어플리케이션을 만듭니다. 외부 서드파티 라이브러리와 내부 모듈을 내보내기(export), 가져오기(import)하는 것을 통해 복잡한 형태의 파일간 의존성이 만들어지게 됩니다.
번들링은 이러한 의존성 파일의 복잡한 형태를 해결하고 브라우저에 최적화된 형태로 의존성 파일들을 묶어(패키징)주는 과정입니다. 번들링의 목적은 사용자가 웹페이지에 방문했을 때 파일 요청의 수를 줄이는 것입니다.
코드 스플리팅이 무엇일까?
개발자들은 어플리케이션 제작시에 다른 URL을 통해 접근할 수 있는 여러 페이지로 나누는 방식으로 진행합니다. 각 페이지는 해당 어플리케이션으로 접근할 수 있는 고유한 진입점(entry ponit)이 되는 것입니다.
코드 스플리팅은 어플리케이션의 번들을 각 진입점에서 필요로 하는 만큼의 더 작은 단위의 덩어리로 쪼개는(스플릿팅) 과정입니다. 코드 스플릿팅의 목적은 해당 페이지에서 필요로하는 코드만 로드하는 것을 통해 어플리케이션의 초기 로드 시간을 향상(줄이는)하는 것입니다.
Next.js는 내장 코드 스플릿팅 기능을 제공합니다. pages/ 디렉토리에 있는 파일은 자동적으로 빌드단계에서 각 파일의 JavaScript 번들 모듈로 코드 스플릿팅이 됩니다.
더 알아보기
- 페이지간에 공유되는 코드는 또한 하나의 번들로 코드 스플릿팅이 되는데 이는 동일한 코드를 다시 다운로드하는 것을 방지하기 위한 것입니다.
- 처음 페이지가 로드 되고나면 Next.js는 사용자가 이동하고 싶어하는 다른 페이지들에 대한 코드를 사전 로딩할 수 있습니다.
- 다이나믹 임포트(동적 가져오기)는 초기에 로드 되는 코드를 직접 설정할 수 있는 코드 스플릿팅의 또 다른 방법입니다.
빌드타임과 런타임
빌드타임(빌드 단계)은 어플리케이션 코드를 프로덕션(상용 - 제품을 출시하는 단계) 상태로 만드는 일련의 과정을 말합니다.
어플리케이션을 빌드할 때, Next.js는 작성된 코드를 프로덕션에 최적화된 파일로 변환합니다. 프로덕션에 최적화된 파일이란 서버에 배포하는 것과 사용자에게 제공할 준비가 완료된 상태를 말합니다. 이러한 파일에는 다음이 포함됩니다.
런타임은(요청타임)은 어플리케이션이 빌드되고 배포 된 후에 사용자의 요청에 대한 응답의 과정에서 어플리케이션이 동작하는 일정 기간의 시간을 가리킵니다.
다음으로 클라이언트, 서버, 렌더링에 대한 용어들에 대해 살펴보겠습니다.
클라이언트와 서버
웹 어플리케이션 관점에서 보면, 클라이언트는 사용자의 디바이스(장치)에서 돌아가는 브라우저를 가리킵니다. 브라우저는 해당 어플리케이션 코드에 대한 요청을 서버에 전달합니다. 그리고 브라우저는 서버로부터 전달받은 응답을 사용자가 상호작용 할 수 있는 인터페이스로 변환합니다.
서버는 데이터 센터에 있는 컴퓨터를 말합니다. 서버는 어플리케이션 코드를 저장하고 클라이언트로부터 요청을 전달받고 연산 작업을 거쳐 적절한 응답은 다시 보내는 역할을 합니다.
렌더링이 무엇일까?
React로 작성된 코드를 UI의 형태로 보여주기 위해서는 필수적으로 HTML 코드로 변환해야 합니다. 이 과정을 렌더링이라 합니다.
렌더링은 서버 또는 클라이언트에서 진행될 수 있습니다. 빌드 타임에 사전 렌더링이 되거나 런타임에 요청이 있을 때마다 렌더링이 될 수 있습니다.
Next.js를 사용하면 3가지 종류의 렌더링을 사용할 수 있습니다. 서버 사이드 렌더링(Server-Side Rendering, SSR), 정적 사이트 생성(Static Site Generation, SSG), 클라이언트 사이드 렌더링(Client-Side Rendering, CSR)이 있습니다.
사전 렌더링
서버 사이드 렌더링과 정적 사이트 생성은 또한 사전 렌더링으로 분류됩니다. 왜냐하면 외부 데이터를 가져오는 과정과 React 컴포넌트를 HTML 요소로 변환하는 과정이 클라이언트로 결과(파일)가 전달되기 전에 진행되기 때문입니다.
클라이언트 사이트 렌더링 vs. 사전 렌더링
일반적으로 React 어플리케이션에서 브라우저는 서버로부터 비어있는 HTML 껍데기를 전달받습니다. 그 이후에 JavaScript를 통해 UI를 구성하게 됩니다. 이를 클라이언트 사이드 렌더링이라 부릅니다. 왜냐하면 초기 렌더링 과정이 사용자의 디바이스에서 일어나기 때문입니다.
참고: Next.js 어플리케이션은 React의 useEffect 훅을 사용하여 데이터 가져오기 또는 useSWR과 같은 데이터 페칭 훅을 활용하는 것을 통해 특정 컴포넌트에서 클라이언트 사이드 렌더링을 사용하도록 설정할 수 있습니다.
이와 달리, Next.js는 기본적으로 모든 페이지를 사전 렌더링 합니다. 사전 렌더링 한다는 것은 사용자의 디바이스에서 동작하는 JavaScript에 의해 렌더링이 되는 것이 아니라 서버에서 미리 HTML 파일이 생성된다는 것을 의미합니다.
이미 만들어진 HTML 파일을 볼 수 있는 사전 렌더링 된 어플리케이션과 달리, 클라이언트 사이드 렌더링 어플리케이션에서 렌더링 작업이 진행되는 동안 사용자는 빈 페이지를 보게됩니다.
두 가지 종류의 사전 렌더링에대해 살펴보겠습니다.
서버 사이드 렌더링
서버 사이드 렌더링을 사용하게 되면 해당 페이지의 HTML 파일은 매 요청 마다 서버에서 생성됩니다. 생성된 HTML, JSON 데이터와 해당 페이지에서 상호작용을 할 수 있도록 만들어주는 JavaScript 코드가 클라이언트로 전달됩니다.
클라이언트 단에서 HTML 파일은 상호작용이 불가능하지만 빠르게 화면을 보여주는데 사용이 됩니다. React가 JSON 데이터와 JavaScript 코드를 사용하여 컴포넌트를 상호작용 가능하도록 합니다.(예를들어 버튼에 이벤트 핸들러를 등록) 이러한 과정을 수화(hydration)라고 합니다.
Next.js에서 getServerSideProps를 사용해서 서버 사이드 렌더링 페이지를 선택할 수 있습니다.
참고: React 18과 Next 12 버전은 React 서버 컴포넌트 알파 버전을 소개합니다. 서버 컴포넌트는 온전하게 서버에서 렌더링이 되며 JavaScript를 활용한 클라이언트 사이드 렌더링을 필요로 하지 않습니다. 또한 서버 컴포넌트를 사용하면 특정 로직을 서버에서 보유하고 해당 로직의 결과만을 클라이언트로 전달하는 것이 가능합니다. 이는 클라이언트로 전달되어야 하는 번들 파일의 크기를 줄이고 클라이언트 사이드 렌더링 성능을 향상 시킵니다. 여기에서 React 서버 컴포넌트에 대해 자세히 학습하세요
정적 사이트 생성
정적 사이트 생성을 사용하면, HTML 파일은 서버에서 생성됩니다. 하지만 서버 사이드 렌더링과 달리 런타임에는 서버가 존재하지 않습니다. 대신에 컨텐츠가 빌드타임에 한 번 생성되고(어플리케이션이 배포 될 때) HTML 파일이 CDN에 저장이 되고 해당 페이지에 대한 매 요청 마다 해당 HTML 파일이 재사용 됩니다.
Next.js에서 getStaticProp를 사용해서 정적으로 생성될 페이지를 선택할 수 있습니다.
참고: 어플리케이션을 빌드한 후 정적 페이지를 생성하거나 변경하기 위해 증분 정적 생성(Incremental Static Regeneration)을 사용할 수 도 있습니다. 데이터가 변경 되었을 때 어플리케이션 전체를 빌드할 필요가 없다는 것을 의미합니다.
Next.js의 진가 페이지별로 가장 적절한 렌더링 방식을 선택할 수 있다는 것입니다. 정적 사이트 생성, 서버 사이드 렌더링, 클라이언트 사이드 렌더링 등을 말입니다. 어떤 렌더링 방식이 어떤 구체적인 사례에 적합한지 알기를 원한다면 데이터 페칭 문서를 확인하세요
다음 챕터에서 어플리케이션이 배포 된 후 코드가 저장되고 실행되는 장소에 대해서 알아보겠습니다.
네트워크는 무엇인가?
우리가 만든 어플리케이션 코드가 네트워크에 배포된 후에 어디에 저장이 되어 동작하는지 이해하는 것은 많은 도움이 됩니다. 네트워크는 리소스(resources)간 공유가 가능한 연결되어 있는 컴퓨터 또는 서버로 생각할 수 있습니다. Next.js로 만들어진 어플리케이션 코드는 오리진 서버(origin servers), 컨텐츠 전송 네트워크(CDNs, CDN 서버), 엣지 네트워크(the Edge, 엣지 서버)로 전달됩니다. 각각의 네트워크에 대해 살펴보겠습니다.
오리진 서버
앞에서 살펴본 것과 같이, 오리진 서버는 어플리케이션의 원본 코드를 저장하고 실행하는 메인 컴퓨터를 가리킵니다.
CDN 서버나 엣지 서버와 같은 어플리케이션 코드가 전달되는 다른 서버와 구분하기 위해 오리진(origin) 이라는 용어를 사용합니다.
오리진 서버가 요청을 받게되면, 응답을 보내기 전에 연산 작업을 거칩니다. 이 연산 작업의 결과는 CDN 서버로 전달됩니다.
컨텐츠 전송 네트워크(CDN 서버)
CDN 서버는 HTML 파일, 이미지 파일 등과 같은 정적 파일을 전 세계의 다양한 장소에 저장합니다. 그리고 CDN 서버는 클라이언트와 오리진 서버 사이에 위치합니다.
연산 작업이 매 요청 마다 진행될 필요가 없기 때문에 오리진 서버에 가해지는 부담을 줄어 듭니다. 또한 CDN 서버는 사용자가 좀 더 빠른 응답을 받을 수 있도록 하는데 CDN 서버가 해당 사용자와 지리적으로 사용자와 가까운 위치에서 응답을 보내기 때문입니다.
Next.js에서는 사전 렌더링은 미리 진행 되기 때문에 사전 렌더링 작업에 대한 정적 결과물을 저장하는 방식이므로 CDN 서버와 매우 궁합이 잘 맞습니다.
엣지 네트워크(엣지 서버)
엣지 네트워크는 사용자와 가장 가까운 네트워크의 주변부(또는 가장자리)를 가리키는 보편화된 개념입니다. CDN 서버는 엣지 네트워크의 일부로 여겨지는데 CDN 서버는 정적 파일을 네트워크의 주변부(가장자리)에 저장하기 때문입니다.
CDN과 비슷하게 엣지 서버는 전 세계의 다양한 지역으로 전달됩니다. 하지만 정적 파일을 저장하는CDN 서버와 달리 일부 엣지 서버는 코드 스니펫(작은 단위의 코드 조각)을 실행할 수 있습니다.
이는 사용자와 좀 더 가까운 엣지 서버에서 캐싱과 코드 실행을 가능하게 한다는 의미 입니다.
기존에 클라이언트나 서버에서 진행되었던 작업들을 엣지 서버에서 진행하게 되면서, 좀 더 성능이 향상된 어플리케이션을 제작할 수 있게 되었습니다. 클라이언트로 전달되는 코드의 양을 줄여주고 사용자의 요청의 일부가 오리진 서버 까지 전달될 필요가 없어짐으로 레이턴시(지연시간)가 줄어들기 때문입니다.
Next.js에서 미들웨어를 탑재한 엣지 서버에서 코드를 실행할 수 있습니다. 곧 React 서버 컴포넌트를 탑재할 예정입니다.
'FRONTEND' 카테고리의 다른 글
[NextJS] 공식문서 읽어보기 Learn - SEARCH ENGINE OPTIMIZATION - Crawling and Indexing (0) | 2023.05.26 |
---|---|
[NextJS] 공식문서 읽어보기 Learn - SEARCH ENGINE OPTIMIZATION - Introduction to SEO (0) | 2023.04.29 |
[NextJS] 공식문서 읽어보기 Learn - How Next.js Works - part.1 (0) | 2023.04.21 |
[NextJS] config 파일 및 폴더 (0) | 2023.04.10 |
[NextJS] Next.js 초기 세팅 테스트 (0) | 2023.04.03 |