트러블슈팅 1

대분류
트러블슈팅
개별 기능 구현 내용
기록일자
2024/04/08 12:37
소분류
테스트 코드
일정 분류
3주차
작성자
여태원

1. 발생한 이슈

프로젝트 중간 시점즈음에 빌드에러를 해결하려다 보니까 시간이 오래걸리고 잡기 힘들어지는 문제(빌드에러난 상태에서 추가적으로 코딩하다보니 계속 문제가 꼬인거같음)

2. 문제 탐색

: 소거법으로 폴더,파일,코드를 하나하나 비활성화 시켜가면서 문제 원인 탐색
- 위 방법을 바탕으로 오류가 나는 페이지 코드들을 분석 후 왜 오류가 나는지 원인 분석
소거법으로 폴더, 파일, 코드들을 하나하나 비활성화 시키면서 문제 원인 분석
문제 원인을 가지고 구글링한 정보를 바탕으로 리팩토링

3. 문제 원인 및 해결 방안

1. window 나 localstorage 와 같은 클라이언트 사이드 전용 객체에 서버 사이드 렌더링이나 빌드 타임에 접근하려고 할 때 발생합니다. Next.js는 빌드 타임에 모든 페이지를 사전에 렌더링(SSR) 하기 때문에, 이 시점에서 클라이언트 사이드 전용 객체를 참조하면 오류가 발생합니다.
기존 문제 코드 : 기존의 sessionStorage 또는 localStorage는 클라이언트에서 사용되는 window 전역 객체인데, SSR을 할 때 window를 인식하지 못해서 생기는 문제
/* src > store > useRoleStore */ export const useUserRoleStore = create<UserRoleState>((set) => ({ isTeacher: sessionStorage.getItem('isTeacher') === 'true' , setIsTeacher: (value: boolean) => { set({ isTeacher: value }); sessionStorage.setItem('isTeacher', value.toString()); } } }));
TypeScript
복사
해결방안 : useEffect를 사용하여 렌더링 후 실행되도록 하거나, type window !== undefined 인 경우를 체크해주면된다
/* src > store > useRoleStore */ export const useUserRoleStore = create<UserRoleState>((set) => ({ isTeacher: typeof window !== 'undefined' ? sessionStorage.getItem('isTeacher') === 'true' : null, setIsTeacher: (value: boolean) => { set({ isTeacher: value }); // null 값이 아닐 때만 sessionStorage에 저장하도록 변경 if (typeof window !== 'undefined' && value !== null) { sessionStorage.setItem('isTeacher', value.toString()); } } }));
TypeScript
복사
/* src > app > (clrm) > payment > page.tsx */ useEffect(() => { if (typeof window !== 'undefined') { const reservationId = window.localStorage.getItem('reservationId'); setReserveId(reservationId); } }, []);
TypeScript
복사
2.
useSearchParams을 사용할 경우 해당 페이지가 클라이언트 사이드 렌더링이되어 빌드시점에 html이 비어있을 수 있기 때문에 오류가 발생합니다.
해결방안 : 특정 구역의 컴포넌트 렌더링을 지연시킬 수 있는 기능을 가진 Suspense훅을 사용하여 데이터가 준비될 때까지 대기시키면 된다.
import type { Metadata } from 'next'; import { Inter } from 'next/font/google'; // import './globals.css'; import Header from '@/components/common/bars/Header'; import SideBar from '@/components/common/bars/SideBar'; import { ReactNode, Suspense } from 'react'; const inter = Inter({ subsets: ['latin'] }); export const metadata: Metadata = { title: '클룸', description: 'Generated by create next app' }; interface ClrmRootLayoutProps { children: ReactNode; } export default function ClrmRootLayout({ children }: ClrmRootLayoutProps) { return ( <div> <SideBar> <Header /> <Suspense>{children}</Suspense> </SideBar> </div> ); }
JavaScript
복사
공식문서 참고