요즘 채용 공고를 찾아보면 어렵지 않게 Next.js에 대한 내용을 찾아볼 수 있습니다.
그래서 나름대로 궁금했던 Next.js에 대한 내용들에 대해 정리해보았습니다.
Web2.0 시대로 넘어가며 자바스크립트를 사용한 동적 웹 페이지를 구현할 수 있게 되었고, Ajax의 등장으로 화면의 일부만 동적으로 변경할 수 있게 되면서 CSR 기반 SPA의 발전으로 이어졌습니다.
최근에는 CSR의 초기 로딩 및 SEO의 문제가 대두되며 다시 SSR 기반으로 기술의 트렌드가 이동 중입니다.
SSR를 지원하는 여러가지 프레임워크가 존재하지만 기존 리액트 기반의 문법을 그대로 사용하며 개발이 쉽고 방대한 커뮤니티의 도움을 받을 수 있기에 개발자의 열렬한 지지를 받는것이 아닐까 싶습니다.
클라이언트에서 모든 정적 리소스를 최초 한번 다운로드하고 자바스크립트 코드를 통해 동적으로 브라우저에 렌더링하는 방식으로 클라이언트 측에서 렌더링을 처리하기 때문에 네이티브 앱에 가깝게 구현 가능합니다.
리액트의 보일러플레이트 코드를 보면 HTML 파일에는 root div 요소 하나만 존재합니다.
이에 따라서 실제 페이지의 의미 있는 요소는 스크립트가 모두 실행된 이후에만 볼 수 있는데, 웹 크롤러는 HTML만을 읽기 때문에 SEO에 영향을 끼칩니다.
CSR로 구현한 어플리케이션은 자연스레 SPA 형태를 띕니다.
서버에서 HTML과 번들링 된 스크립트를 클라이언트에 넘겨주는 렌더링 방식입니다.
동적 데이터로 페이지를 구성하면서도 좋은 SEO를 유지할 수 있습니다.
정적 사이트 생성
완전히 정적인 HTML 웹 사이트를 생성하는 방법으로 어플리케이션 빌드 시점에 모든 웹 페이지를 정적 HTML 파일로 변환하고 클라이언트의 요청에 따라 이미 완성된 정적 HTML 파일을 반환해주는 방식입니다.
💡 내용이 거의 변하지 않는 랜딩 페이지와 같은 경우에 적합한 방식이다.
점진적 정적 재생성
SSG와 동일하게 빌드 시점에 페이지를 생성하고 설정시간 마다 새로 페이지를 생성하는 방식입니다.
💡 마치 SSR과 SSG의 장점을 결합한 하이브리드 방식이라 할 수 있다.
npx create-next-app@latest
CNA(create next app)를 통해 app을 생성하게 되면 다음과 같은 메시지가 표시됩니다.
What is your project named? my-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias (@/*)? No / Yes
What import alias would you like configured? @/*
여기서 Tailwind CSS를 사용할지와 App Router를 사용할지 물어보는데, 아래에서 Next.js가 왜 Tailwind CSS를 권장하는지와 App Router가 뭔지에 대해 알아보도록 합시다.
create next app으로 넥스트 개발환경을 세팅할 때 테일윈드를 사용할 것이냐고 물어보는데, Next.js의 공식 문서를 살펴봐도 Tailwind CSS를 사용하기를 적극적으로 권하는 것 같았습니다. 왜 Next.js는 Tailwind CSS를 권장하는 걸까요?
보편적으로 리액트로 어플리케이션을 구현할 때 CSS-in-JS 라이브러리를 주로 사용합니다. 기존의 셀렉터 기반 CSS는 다음과 같은 문제를 가지고 있습니다.
위 문제들을 해결하기 위해 CSS-in-JS 개념이 제시되었고 여러 라이브러리(Styled Components, Emotion)가 등장하게 되었습니다.
대부분의 CSS-in-JS 라이브러리는 런타임에 스타일시트 JS 번들을 포함시켜 문서의 head 태그에 style 태그를 추가하거나 CSSStyleSheet API로 직접 CSSOM에 적용시키는 방식을 사용합니다.
그렇기 때문에 JS 번들의 용량이 증가하여 페이지 렌더링 시간이 길어지는 성능상 단점이 존재하지만 개발의 효율 측면에서 생산성 향상의 이점이 크기 때문에 리액트와 함께 유행되고 지금까지 널리 사용되어 왔습니다.
하지만 CSS-in-JS는 SSR에서 hydrate 이전에 HTML 요소에 스타일이 적용되지 않은 상태의 날 것의 문서가 보여지는 문제가 존재합니다.
💡 hydrate
SSR에서 등장하는 개념으로 번역하면 “수분을 공급하다” 정도가 될 것 같다.
위에서 이야기 했듯이 SSR, 즉 서버 사이드 렌더링은 서버에서 완성된 HTML 파일과 번들링 된 자바스크립트를 클라이언트로 전송한다. 클라이언트 측 자바스크립트가 실행되기 전까지는 동적인 상호작용을 할 수 없는데, 자바스크립트가 실행되어 DOM에 동적인 스크립트를 불어넣으며 보충한다는 점에서 Hydration라고 표현한다.
Next.js는 React v16부터 제공하는 hydrate 기능을 사용해 Hydartion을 제공한다.
그렇기 때문에, 초기 HTML에 포함되는 요소에 대한 스타일은 Critical CSS 기법을 적용해 날 것의 문서가 보여지지 않도록 하는 처리가 필요합니다. 하지만 이 경우 너무나도 복잡한 작업이 동반되어야 할 것 같습니다. Critical CSS를 분리해 문서에 포함시키고..
CSS-in-JS의 장점인 동적 변수를 사용할 수 없고, keyframes와 같은 애니메이션을 사용함에 있어서 제약이 있음에도 불구하고 SSR 환경에서 불안한 CSS-in-JS 방식을 제외하고 남는 스타일 적용 방식들 중에 Tailwind CSS가 가장 나은 솔루션이기 때문에 권장하고 있는 것 같다.
Next.js는 별도의 세팅 없이 pages 폴더를 활용해 라우팅을 사용할 수 있게 하여 효율적인 개발이 가능했습니다. 현재는 공식적으로 Next.js v13에서 소개한 앱 라우터를 사용하도록 권장하고 있습니다.
공식문서에서는 앱 라우터를 다음과 같이 설명하고 있습니다.
공유 레이아웃, 중첩 라우팅, 로딩 상태, 오류 처리 등을 지원하는 React Server Components를 기반으로 구축된 새로운 라우터
기존 pages 라우터는 파일별로 라우팅이 되는 방식에서 앱 라우터는 디렉토리 기준으로 라우팅이 되는 차이가 있고 예약된 파일 이름으로 특수 파일을 생성해 개발할 수 있다는 차이가 존재합니다.
https://velog.io/@huurray/React-Hydration-에-대하여
https://velog.io/@shinhw371/CSS-why-Nextjs-recommand-Tailwind
https://www.youdad.kr/frontend-rendering-ssg-isg-ssr-csr/
https://medium.com/@zero86/next-js-next-js-개념-정리-4374f81f118b