이전 글에서 Edge runtime으로 TTFB 문제를 해결했었는데, Express를 Next.js로 이미그레이션 후에는 Edge runtime을 사용할 수 없어서 다른 방법으로 문제를 해결했다.
일부 Node.js API를 지원하지 않기 때문에, 어떤 Node.js modules는 사용 못할 수도 있다.
ex) 파일 시스템을 읽거나 쓸 수 없다. 내 블로그 프로젝트에서는 sharp(이미지 리사이징 모듈), jsonwebtoken을 이용할 수 없었다.
MongoDB 스키마를 구현하면 에러가 발생한다. (https://mongoosejs.com/docs/nextjs.html)
다른 프로젝트에서는 TTFB 문제가 발생하지 않았는데 블로그에서만 TTFB 문제가 발생했다.
그래서 프로젝트들의 빌드 로그를 살펴봤는데, 블로그에서만 모든 라우트가 Dynamic으로 동작하고 있었다.
블로그
(모든 라우트가 Dynamic으로 동작하여 서버에서 렌더링된다)
다른 프로젝트
(Dynamic Route들만 Dynamic으로 동작하고, 나머지는 Static으로 동작한다)
Vercel + Node.js Runtime은 cold starts로 인해 함수를 처음 호출할 때 지연이 발생한다.
그래서 TTFB 문제가 발생했던 것이었다.
라우트의 동적, 정적 렌더링은 Next.js의 Full Route Cache 기능과 연관이 있다.
이 기능이 적힌 문서를 보고, 왜 모든 라우트가 Dynamic으로 동작하는지 일단 확인해보았다.
cookies
, headers
그리고 searchParams
를 사용했을 때dynamic = 'force-dynamic'
또는 revalidate = 0
라우트 segment 구성 옵션을 사용했을 때fetch
요청이 있을 때루트 Layout에서 전역으로 쿠키를 불러오고 저장할 수 있게 해주는 next-client-cookies
라이브러리를 사용하고 있었는데, Provider을 설정할 때, cookies
동적 함수를 사용되었던 것이다.
→ 루트 Layout에서 동적 함수를 사용하고 있어서, 모든 라우트가 동적으로 렌더링됐다.
export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="kr" suppressHydrationWarning={true}> <body> <script dangerouslySetInnerHTML={{ __html: setInitialThemeMode }} /> <Recoil> <ClientCookiesProvider value={cookies().getAll()}> <Provider> <TopNav /> <ReactQuery>{children}</ReactQuery> <ScrollToTop /> <Footer /> </Provider> </ClientCookiesProvider> </Recoil> </body> </html> ); }
export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="kr" suppressHydrationWarning={true}> <body> <script dangerouslySetInnerHTML={{ __html: setInitialThemeMode }} /> <Recoil> <ClientCookiesProvider value={cookies().getAll()}> <Provider> <TopNav /> <ReactQuery>{children}</ReactQuery> <ScrollToTop /> <Footer /> </Provider> </ClientCookiesProvider> </Recoil> </body> </html> ); }
"use client"; import { CookiesProvider } from "next-client-cookies"; export const ClientCookiesProvider: typeof CookiesProvider = (props) => ( <CookiesProvider {...props} /> );
"use client"; import { CookiesProvider } from "next-client-cookies"; export const ClientCookiesProvider: typeof CookiesProvider = (props) => ( <CookiesProvider {...props} /> );
Express에서 Next.js로 이미그레이션 후에 Next.js의 Route Handlers를 사용하고 있는데, Route Handlers에서는 브라우저에 쿠키를 직접 설정할 수 있으므로, 라이브러리를 제거하고 동적 함수를 제외했다.
로컬 환경에서는 애플리케이션의 TTFB(Time To First Byte)가 70~150ms정도 걸리는데, 배포 환경에서는 TTFB가 느리면 1500ms, 빠르면 400ms정도가
2024-03-12Next.js 14, Tailwindcss, Typescript 터치 이벤트는 일반적으로 터치 스크린을 가진 디바이스에서 이용가능하다. 하지만, 터치 스크린을 갖는 디바이스를 포함
2024-03-12Next.js 14는 다음과 같은 가장 중점으로 둔 릴리스이다. - Turbopack: App & Pages Router에서 5,000번의 테스트 통과 - 로컬 서버 시작이 53%
2024-03-12Next.js는 렌더링 작업과 데이터 요청을 캐싱하여 어플리케이션의 성능을 향상시키고 비용을 감소시킨다. 기본적으로 Next.js는 성능을 향상시키고 비용을 줄이기 위해 가능한 한
2024-03-12# Contact : jyw966@naver.com
Copyright © doromo. All Rights Reserved.