최근 Recoil로 상태관리하고 있는 프로젝트 진행중에 새로고침시 Recoil 데이터/상태들이 💨증발💨해버리는 것을 발견했다.
그래서 필자는 이 문제를 어떻게 해결했는지에 대해 정리해보고자 한다.
필자는 민감한 정보를 recoil로 관리했기 때문에 localStorage와 sessionStorage를 사용하지 않으려 했다.
Web Storage의 이해
프론트엔드 개발을 하면서 상태관리는 항상 중요한 화두라고 할 수 있다.
일단 문제 해결을 하기 전에 다양한 스토리지 옵션에 대해서 이해해야된다고 생각한다.
localStorage
웹 브라우저에서 제공하는 데이터 저장소로, 브라우저를 종료하더라도 데이터가 유지된다.
(도메인별로 별도의 저장공간을 가지며, 최대 5MB까지 저장할 수 있음.)
// localStorage 사용 예시
localStorage.setItem('user', JSON.stringify({ name: 'John', age: 25 }));
const user = JSON.parse(localStorage.getItem('user'));
위 코드에서는 사용자 정보를 localStorage에 저장하고 불러오는 과정을 보여준다.
객체를 저장할 때는 반드시 JSON.stringify()를 사용해야 하며, 불러올 때는 JSON.parse()를 통해 다시 객체로 변환해야 한다!!!
sessionStorage
localStorage와 유사하지만, 브라우저 세션이 유지되는 동안만 데이터가 존재한다.
(탭을 닫거나 브라우저를 종료하면 데이터가 삭제됨 -> 새로고침을 하면 유지됨 O)
// sessionStorage 사용 예시
sessionStorage.setItem('tempData', 'This is temporary');
const tempData = sessionStorage.getItem('tempData');
Trouble Shooting : Recoil 새로고침 문제 해결하기
Recoil은 React를 위한 상태관리 라이브러리지만, 기본적으로 메모리에만 상태를 저장하기 때문에
페이지 새로고침 시 모든 상태가 초기화된다.
아래 코드 예시를 한 번 보자.
import { atom } from 'recoil';
export const userState = atom({
key: 'userState',
default: {
name: '',
isLoggedIn: false
}
});
이 코드는 기본적인 Recoil atom의 정의를 보여주는데, 새로고침 시 userState는 항상 기본값으로 초기화됩니다.
이럴 땐 당황하지 말고 recoil-persist를 사용해보자!
npm install recoil-persist
recoil-persist는 Recoil의 상태를 localStorage나 sessionStorage에 자동으로 동기화해주는 라이브러리이다.
하지만 필자가 위에서 설명했듯이 민감한 정보를 다루고 있지 않은가?
이 부분은 백엔드에서 처리해주는 것이 가장 보안적으로 좋지만 필자는 클라이언트 측에서 해결해보고 싶었다.
일단 예시코드로 살펴보자면
// 비민감 정보 - localStorage 사용 가능
export const uiPreferencesState = atom({
key: 'uiPreferences',
default: {
theme: 'light',
language: 'ko'
},
effects_UNSTABLE: [persistAtom]
});
비민감 정보는 localStorage를 사용함으로 일반 reocil atom 정의에 effects_UNSTABLE: [persistAtom]을 추가해주면 된다.
// 민감 정보 - 메모리에만 저장
import { atom } from 'recoil';
import { recoilPersist } from 'recoil-persist';
// sessionStorage 사용 설정
const { persistAtom } = recoilPersist({
key: 'user-session', // sessionStorage에 저장될 키 이름
storage: sessionStorage // 브라우저 세션 동안만 유지
});
// 사용자 인증 정보 상태
export const userCredentialsState = atom({
key: 'userCredentialsState',
default: {
token: '',
userId: '',
username: '',
isLoggedIn: false,
lastLogin: null
},
effects_UNSTABLE: [persistAtom]
});
하지만 민감한 정보 같은 경우엔? sessionStorage가 권장된다고 생각할 수 있다.
(storage:를 sessionStorage를 쓰겠다고 명시를 반드시 해주어야함!)
위의 localStorage와 같게 effects_UNSTABLE: [persistAtom]을 추가하지만, storage를 sessionStorage를 쓰는것이다.
이렇게 구현하게 된다면 recoil 상태는 sessionStorage에 저장되므로
- 같은 탭에서 새로고침해도 상태가 유지되고
- 브라우저 탭을 닫으면 상태가 삭제되며
- 다른 탭에서는 별도의 세션이 유지되어
안정적인 상태관리를 할 수 있게된다!
'React' 카테고리의 다른 글
[React] 이벤트 핸들링 개념정리 (1) | 2025.02.06 |
---|---|
[React] Props 개념 완벽 가이드 ✔︎ (0) | 2025.02.05 |
[React] 함수형 컴포넌트 vs 클래스형 컴포넌트 👊 (0) | 2025.02.03 |
[React] CSR, SSR의 개념과 차이점 완벽 이해하기 👍 (1) | 2025.01.31 |
[React] 컴포넌트 생명주기(Life Cycle) 완벽 이해하기! ♽ (0) | 2025.01.30 |