- Published on
Next.js를 사용하면서 겪었던 문제
- Authors
- Name
- Charles
1. 빌드시에 마주했던 경고문
이전에 md 파일을 생성해서 블로그 작업을 했을 때 보지 못했던 경고문이 현재 블로그 사이트로 마이그레이션 작업을 하면서 빌드시에 나타나는 경고문을 보고 현재 데이터를 불러와서 블로그 글을 생성하도록 로직이 구성되어있는데 그 부분이 문제인가? 라는 생각을 처음에는 했었다.
빌드시 경고문구
Entire page /posts/[slug] deopted into client-side rendering.
해당 문구를 검색해서 찾아본 결과 Next.js github issue에 해당 경고에 대한 내용이 있어서 참고를 해보았다.
[NEXT-1125] Misleading deopted-into-client-rendering warning on build
위의 내용은 해당 페이지에서는 useSearchParams를 사용하고 있지 않지만 똑같은 경고문이 출력된다는 것이었다.
전체 이슈 내용을 참고해보니 useSearchParams을 사용하는 컴포넌트를 dynamic import로 변경하고 { ssr: false } 옵션으로 해서 Suspence로 감싸주면 되는 것 같았다.
src/components/post/ListLayoutWithTags.tsx 'use client'; import PostList from '@/components/post/PostList'; import { SimplePost } from '@/types'; import { Suspense } from 'react'; import { Skeleton } from '@/components/ui/skeleton'; import dynamic from 'next/dynamic'; type ListLayoutProps = { posts: SimplePost[]; tags: Record<string, number>; start: number; end: number; total: number; }; const TagList = dynamic(() => import('@/components/post/TagList'), { ssr: false, }); const Pagination = dynamic(() => import('@/components/post/Pagination'), { ssr: false, }); export default function ListLayoutWithTags({ posts, tags, start, end, total, }: ListLayoutProps) { return ( <div className="flex flex-col"> <div className="flex justify-center"> <Suspense fallback={ <Skeleton className="h-[820px] min-w-[300px] max-w-[300px]" /> } > <TagList tags={tags} /> </Suspense> <PostList posts={posts} /> </div> <Suspense fallback={<Skeleton className="h-[80px] min-w-[744px] max-w-[744px]" />} > <Pagination hasNextPage={end < total} hasPrevPage={start > 0} total={total} /> </Suspense> </div> ); }
해당 컴포넌트에서 useSearchParams를 사용하고 있어서 해당 부분을 위와 같이 처리해 준 이후에는 해당 경고문이 사라졌다.
2. Minified React error #419
해당 에러는 개발환경에서는 발생하지 않았던 문제인데 배포를 하고나서 콘솔창을 확인했을 때 나타나는 에러였다.
The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.
서버 렌더링 중 오류로 인해 서버가 이 서스펜스 경계를 완료하지 못했습니다. 클라이언트 렌더링으로 전환했습니다.
React 문서에서 해당 에러에 대한 내용을 확인했는데 이걸보고 서스펜스 컴포넌트의 문제라는 것을 바로 알았어야 했는데 처음에는 엉뚱한 컴포넌트를 체크했었다.
파일을 확인 해보니 위에서 발생했던 원인과 비슷한 문제였는데
src/components/common/ScrollUp.tsx 'use client'; import { usePathname, useSearchParams } from 'next/navigation'; import { useEffect } from 'react'; export default function ScrollUp() { const pathname = usePathname(); const searchParams = useSearchParams(); useEffect(() => { window.scroll(0, 0); }, [pathname, searchParams]); return <></>; }
해당 컴포넌트에서도 useSearchParams를 사용하고 있었고
src/app/layout.tsx ... import ScrollUp from '@/components/common/ScrollUp'; ... export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="ko" suppressHydrationWarning> <meta name="theme-color" media="(prefers-color-scheme: light)" content="#fff" /> <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#000" /> <ManageScript /> <Suspense fallback={null}> <ScrollUp /> </Suspense> <body className={cn( 'min-h-screen w-full bg-light font-mont dark:bg-dark', fontSans.variable, )} > <Providers> {children} <Analytics /> </Providers> <SpeedInsights /> </body> </html> ); }
전체 레이아웃에서 해당 컴포넌트를 dynamic import하지 않아서 발생하는 문제였다.
그래서 해당 컴포넌트는 아래 Providers.tsx
컴포넌트로 옮겨서 수정 작업을 해주었다.
src/context/Providers.tsx 'use client'; import { SessionProvider } from 'next-auth/react'; import { ThemeProvider } from 'next-themes'; import dynamic from 'next/dynamic'; import { Suspense } from 'react'; const ScrollUp = dynamic(() => import('@/components/common/ScrollUp'), { ssr: false, }); export function Providers({ children }: { children: React.ReactNode }) { return ( <SessionProvider> <Suspense fallback={<></>}> <ScrollUp /> </Suspense> <ThemeProvider attribute="class" defaultTheme="system" enableSystem> {children} </ThemeProvider> </SessionProvider> ); }
해당 에러도 변경 작업 진행 후에 콘솔창에 에러가 해결되었다.
느낀점
여러 문제점을 겪으면서 Next.js가 많은 부분을 해주면서 내가 예상하지 못했던 문제들이 발생하고 해당 문제점을 파악하는데 상당한 시간을 쏟아야 한다는게 Next.js를 사용하면서 좋다고 생각이 되지는 않았다. 기능상에 문제가 있는 부분은 아니었지만 내 성격상 에러나 경고문구를 지나칠 수 없었기에... Next.js가 많은 장점을 가지고 있지만 개발 경험에서 단점도 존재한다는 것을 느끼는 계기가 되었다. 그래도 나와 비슷한 이슈를 겪은 사람들이 있고 충분히 찾아서 해결할 수 있었던 문제들이어서 다행이었다.