[PWA] (22) 중복예약 막기

Kimmy·2025년 5월 19일

PWA_PROJECT

목록 보기
34/47

🌽중복예약 막기

  • 예약할때 예약자 성명, 연락처 칸 -> 삭제

localStorage is not defined

Unhandled Runtime Error
Error: localStorage is not defined

  • Next.js(또는 React SSR 환경)에서 서버사이드 렌더링 시 localStorage를 사용할 수 없기 때문에 발생하는 오류라고 한다.

✔️ 원인
localStorage는 브라우저 환경에서만 존재함,
서버에서 렌더링할 때는 localStorage가 없는데, 직접 접근해서 에러 발생함!

✔️ 문제 코드 (SSR 환경에서 localStorage 직접 접근)

<ShopDetailNavigation
  shopId={params?.id}
  activeTab="designer"
  reviewCount={
    JSON.parse(localStorage.getItem("reviews") || "[]").filter(
      (review) =>
        review.shopId === Number(params?.id) &&
        review.status === "published"
    ).length
  }
/>

✔️ 수정 방법
1) localStorage 접근을 useEffect로 옮기고, 상태로 관리

const [reviewCount, setReviewCount] = useState(0);

useEffect(() => {
  if (typeof window !== "undefined") {
    const reviews = JSON.parse(localStorage.getItem("reviews") || "[]");
    const count = reviews.filter(
      (review) =>
        review.shopId === Number(params?.id) &&
        review.status === "published"
    ).length;
    setReviewCount(count);
  }
}, [params?.id]);

2) ShopDetailNavigation에 reviewCount 상태 전달

<ShopDetailNavigation
  shopId={params?.id}
  activeTab="designer"
  reviewCount={reviewCount}
/>

-> localStorage 접근 코드를 useEffect로 옮기고, reviewCount를 상태로 관리하여 ShopDetailNavigation에 전달하면
SSR 환경에서도 에러 없이 동작한다.

기존 코드 자체는 클라이언트용이지만,
Next.js의 특성상 SSR 구조에서는 처음에 서버에서도 실행될 수 있기 때문에
서버에는 없는 localStorage에 바로 접근하면 에러가 발생할 수 있다.
그래서 아래처럼 브라우저 환경에서만 localStorage를 사용하도록 조건을 넣는 것.

if (typeof window !== "undefined") {
  // localStorage 사용
}
  • 브라우저 환경: window 객체가 존재한다.
  • 서버(SSR) 환경: window 객체가 존재하지 않으므로 undefined.

🪟 window 객체

브라우저(클라이언트) 환경에서만 존재하는 전역 객체

브라우저에서 자바스크립트가 실행될 때,
웹페이지(탭) 하나당 하나의 window 객체가 자동으로 만들어진다.

이 객체는 브라우저의 창(window)을 대표하며,
localStorage, alert, document, location 등 브라우저에서 제공하는 여러 기능과 속성에 접근할 수 있게 해주는 역할을한다.

예시:

window.localStorage.getItem("key"); // localStorage 사용
window.alert("안녕하세요!");         // 알림창 띄우기
window.location.href                // 현재 페이지 주소

서버(SSR) 환경에는 window가 없고,
브라우저에서만 window가 있기 때문에
이 객체가 있으면 "지금 브라우저에서 실행 중"임을 알 수 있다.

예약 후 페이지 새로고침

window.location.reload(); 추가

예약완료 후 페이지가 새로고침되어 최신 예약 정보 반영하기.

    // 예약 완료 알림 표시
    alert(`예약이 완료되었습니다.
디자이너: ${designer.name}
시술: ${selectedServiceObj.name}
가격: ${selectedServiceObj.price.toLocaleString()}원
날짜: ${selectedDate}
시간: ${selectedTime}`);
    window.location.reload(); //추가
    onClose();
  };
profile
바리바리 개바리 🌼

0개의 댓글