Next.js 블로그 리펙터
June 10, 2023
React를 배우면서 배웠던 스택으로 CRUD가 작동하는 블로그를 만들었다. 하지만 CSR로 작동하는 블로그의 특징때문에 Reactjs는 사실 좋은 솔루션이 되지는 못했다. 정적인 페이지가 주를 이루는 블로그는 SSR이나 SSG로, 서버에서 렌더링이 이루어져야 더 알맞을 것이다.
React.js 앱으로써의 블로그
이전 블로그는 배웠던 스택들을 구현하는 데 의미를 둔 블로그다. 이 때문에 불필요하게 앱 자체가 동적으로 제작되었다. CSR로 블로그의 글이 렌더링 되어 유저에게 보여지려면 html 파싱과 js 로드를 기다려야 했으며 js로드 이후, 파이어베이스에 있는 데이터를 가지고 와야 하므로 간단한 블로그 앱이더라도 로딩 화면을 피할 수 없었다. 특히 파이어베이스는 최초 데이터 요청에서 상당한 시간이 걸리므로 앱이 굉장히 무겁게 느껴지는 문제가 있었다.
Static Site Generation (SSG)
어차피 정적인 콘텐츠를 담고 있는 블로그라면 빌드 시점에 모든 데이터들을 미리 파싱하여 클라이언트의 서버 페이지 요청이 발생했을 때 html 파일만 전달해 준다면 JS로드, data feching시간을 아낄 수 있으므로 TTFB가 극적으로 개선될 수 있다. (홈 페이지 새로고침 시 LCP: 614.8ms-> 106.7ms)
프로젝트 구성
app ┣ adminedit ┃ ┣ post ┃ ┃ ┣ [id] ┃ ┃ ┃ ┗ page.tsx ┃ ┃ ┗ page.tsx ┃ ┣ project ┃ ┃ ┣ [id] ┃ ┃ ┃ ┗ page.tsx ┃ ┃ ┗ page.tsx ┃ ┗ page.tsx ┣ posts ┃ ┣ [id] ┃ ┃ ┗ page.tsx ┃ ┗ page.tsx ┣ projects ┃ ┣ [id] ┃ ┃ ┗ page.tsx ┃ ┗ page.tsx ┣ favicon.ico ┣ globals.css ┣ layout.tsx ┣ page.tsx ┣ paper.tsx ┗ providers.tsx service ┣ fireabse.ts ┣ functions.ts ┣ posts.ts ┗ projects.ts
이번 프로젝트는 app router를 사용했다. app router는 page router의 페이지 단위 렌더링과 달리 컴포넌트 단위로 CSR,SRR등 렌더링 방식을 정할 수 있다. app router에 대한 자세한 설명은 블로그 글을 참고. 블로그 앱은 간단한 구조를 가진다. 리펙터 전과 달리 게시물 작성, 수정, 삭제 기능은 아직 구현되지 않았다. 회원 가입, 댓글 등록, 게시물 관리 등의 기능은 추후에 업데이트 예정이다.
Build
Route (app) Size First Load JS ┌ ○ / 464 B 88.2 kB ├ ○ /adminedit 138 B 77.5 kB ├ ○ /adminedit/post 1.51 kB 135 kB ├ λ /adminedit/post/[id] 1.51 kB 135 kB ├ ○ /adminedit/project 1.81 kB 140 kB ├ λ /adminedit/project/[id] 1.81 kB 140 kB ├ ○ /favicon.ico 0 B 0 B ├ ○ /posts 2.74 kB 85.8 kB ├ ● /posts/[id] 714 B 347 kB ├ ├ /posts/execution-context ├ ├ /posts/object ├ ├ /posts/afterdomain-network ├ └ [+14 more paths] ├ ○ /projects 463 B 88.2 kB └ ● /projects/[id] 502 B 347 kB ├ /projects/backtest-web-ui ├ /projects/used-car ├ /projects/nextjsblogrefactor └ [+3 more paths] + First Load JS shared by all 77.3 kB ├ chunks/2443530c-5d6554c027dffe62.js 50.5 kB ├ chunks/488-e2f64e02fe50c321.js 24.9 kB ├ chunks/main-app-e765d59e6d8648d6.js 218 B └ chunks/webpack-358ff51c8dfcedfd.js 1.73 kB Route (pages) Size First Load JS ─ ○ /404 183 B 74.1 kB + First Load JS shared by all 73.9 kB ├ chunks/framework-43665103d101a22d.js 45.1 kB ├ chunks/main-595a6c8a5a786d64.js 26.9 kB ├ chunks/pages/_app-b34b2dcd2ffe424c.js 198 B └ chunks/webpack-358ff51c8dfcedfd.js 1.73 kB λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps) ○ (Static) automatically rendered as static HTML (uses no initial props) ● (SSG) automatically generated as static HTML + JSON (uses getStaticProps)
dynamic routes를 이용해서 블로그 글이 SSG로 빌드 시점에 생성된다. 나머지는 Static페이지로 CSR로 렌더링 되는 페이지는 없다.(client component는 존재함)