팀프로젝트

트러블 슈팅: 페이지 새로고침/이동 시 데이터 유지하기🌟

choijming21 2024. 11. 26. 17:52

1.  문제 발생❓

유저가 입력을 진행하던 중 실수로 새로고침을 하거나 뒤로가기를 했을 때 모든 입력 데이터가 초기화되어 supabase에 데이터 값이 null값으로 들어가는 문제가 발생했습니다.

 

< 초기 설정 코드 > 

const OneTimeContent = () => {
 const [formData, setFormData] = useState<EggPopFormWithImageFile>({
   main_category_id: 0,
   sub_category_id: 0,
   user_id: userId,
   egg_pop_name: "",
   // ... 기타 초기값
 });
}

 

 

 

 

 

 

2.  원인 추론 🔎

React의 state는 페이지 새로고침 시 모든 상태가 초기화 됨

 

 

 

 

 

 

3.  해결 과정 📋

웹 스토리지(Web Storage)의 특징과 사용 사례 검토

  1. sessionStorage 검토
    • 세션 기반의 임시 저장소로, 탭/창이 닫힐 때 데이터가 자동으로 삭제됨
    • 동일 출처의 다른 탭과 데이터가 공유되지 않아 독립적인 상태 관리 가능
    • 새로고침 시에도 데이터가 유지되어 일시적인 폼 데이터나 설정값 저장에 유용
    • 단점: 탭 종료 시 모든 데이터가 손실되어 지속성이 필요한 데이터 저장에는 부적합
  2. localStorage 검토
    • 브라우저에 영구적으로 데이터를 저장할 수 있는 저장소
    • 브라우저를 종료하고 재시작해도 데이터가 유지됨
    • 동일 출처의 모든 탭/창에서 데이터가 공유되어 전역 상태 관리에 용이
    • 구현이 간단하고 직관적인 API 제공 (setItem, getItem)
    • JSON.stringify()와 JSON.parse()를 활용해 객체도 저장 가능

 

최종 선택: localStorage

  • 간단한 구현 방식으로 빠른 개발 가능
  • 브라우저를 종료하고 재시작해도 데이터가 유지 가능

 

localStorage 적용

1) localStorage를 활용한 데이터 임시 저장 로직 구현

// 초기값 설정 시 localStorage 데이터를 먼저 확인
const getInitialData = () => {
  try {
    const savedData = localStorage.getItem(ONETIME_CLUB_CREATE);
    if (savedData && userId) {
      const data = JSON.parse(savedData);
      return {
        formData: { ...data.formData, user_id: userId },
        selectedGender: data.selectedGender,
        selectedAge: data.selectedAge
      };
    }
  } catch (error) {
    console.error("초기 데이터 로드 실패:", error);
  }
  return {
    formData: {
      // 기본값 반환
    }
  };
};

 

 

2) 단계별 데이터 저장 구현

const throttledHandleNext = useThrottle(() => {
  // 현재 단계 데이터 localStorage에 저장
  localStorage.setItem(
    ONETIME_CLUB_CREATE,
    JSON.stringify({
      formData,
      selectedGender,
      selectedAge
    })
  );

  // 다음 단계로 이동 
  if (step === 6) {
    throttledHandleSubmit();
  } else {
    setStep((prev) => (prev + 1) as 1 | 2 | 3 | 4 | 5 | 6);
  }
}, 300);

 

 

3) 컴포넌트 마운트 시 데이터 복원

useEffect(() => {
  try {
    const savedData = localStorage.getItem(ONETIME_CLUB_CREATE);
    if (savedData) {
      const data = JSON.parse(savedData);
      setFormData(data.formData);
      setSelectedGender(data.selectedGender);
      setSelectedAge(data.selectedAge);
    }
  } catch (error) {
    console.error("로컬스토리지에서 가져오기 실패:", error);
  }
}, []);

 

 

4) 모임 생성 완료 시 임시 데이터 삭제

const handleSubmit = async () => {
  try {
    // 데이터 저장 로직...
    
    // 성공 시 임시 저장 데이터 삭제
    localStorage.removeItem(ONETIME_CLUB_CREATE);
    
    router.replace(`/club/one-time-club-sub/${data.egg_pop_id}`);
  } catch (error) {
    console.error("제출 중 오류 발생:", error);
  }
};

 

 

 

 

 

4.  결과 ❤‍🔥

 

  • 단계별 데이터 안전성 확보
    • 각 단계 완료 시점에 데이터 자동 저장
    • 중간 단계에서의 데이터 손실 방지
  • 사용자 경험 개선
    • 실수로 인한 데이터 손실 방지
    • 이전 작성 내용 복원으로 재입력 불편 해소