TaskMaster - 작업 관리 프로젝트를 진행하던 중 localStorage 동기화 관련해서 문제를 겪게 되었다😱
yarn add recoil
RecoilRoot로 감싸야 한다. RecoilRoot가 Recoil 상태 관리의 context를 제공하기 때문이다.const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<RecoilRoot>
<App />
</RecoilRoot>
</React.StrictMode>
);
const initialTasks = JSON.parse(localStorage.getItem('tasks')) || [];
initialTasks에 초기값을 정의한다. localStorage에 저장된 tasks 항목을 가져온 다음 JSON 문자열 형태로 저장하는데 이때 localStorage에 tasks 항곰이 없거나 'null'일 경우를 대비해서 빈 배열 [ ]을 기본값으로 사용하도록 한다. 결과적으로 initialTasks는 localStorage에 저장된 작업 목록을 담고 있거나, 저장된 항목이 없는 경우 빈 배열을 담게 된다.
import { atom } from 'recoil';
export const tasksState = atom({
key: 'tasksState',
default: initialTasks,
});
key는 tasksState는 atom의 고유한 식별자이다. Recoil 상태는 이 key를 통해 구분되고 이 key는 유일해야한다. 그리고 앞전에 정의해둔 initialTasks를 기본값으로 설정한다. 이 atom은 App에서 전역 상태로 사용된다. tasksState를 사용하면 Recoil의 상태 hook(useRecoilState, useRecoilValue, useSetRecoilState)을 통해 상태를 읽고 업데이트할 수 있다.
const [tasks, setTasks] = useRecoilState(tasksState);
const updateLocalStorage = (updateTasks) => {
localStorage.setItem('tasks', JSON.stringify(updateTasks))
}
const handleAdd = (task) => {
const updatedTasks = [...tasks, task];
setTasks(updatedTasks);
updateLocalStorage(updatedTasks)
}
const handleUpdate = (updated) => {
const updatedTasks = tasks.map((t) => (t.id === updated.id ? updated : t));
setTasks(updatedTasks);
updateLocalStorage(updatedTasks)
};
const handleDelete = (deleted) => {
const updatedTasks = tasks.filter((t) => t.id !== deleted);
setTasks(updatedTasks);
updateLocalStorage(updatedTasks);
};
const handleEdit = (edited) => {
if (edited) {
const updatedTasks = tasks.map((t) => t.id === edited.id ? edited : t);
setTasks(updatedTasks);
updateLocalStorage(updatedTasks);
}
}
useEffect(() => {
updateLocalStorage(tasks)
}, [tasks]);
Recoil을 도입하여 React 애플리케이션에서 localStorage와의 독립성 문제를 효과적으로 해결했다. 이전에는 체크박스를 클릭하여 작업 상태를 변경하거나 다른 작업을 수행할 때마다 UI가 즉시 업데이트되지 않고, 사용자가 직접 페이지를 새로고침해야만 localStorage의 데이터가 반영되는 문제가 있었다.
Recoil을 통해 관리되는 상태인 tasksState atom을 활용하여, 작업의 상태 변경이 발생할 때마다 Recoil 상태가 업데이트되고 변경 사항이 자동으로 UI에 반영되도록 하였다. 예를 들어, 체크박스를 클릭하여 작업의 상태를 변경하면 tasksState가 업데이트되어 UI가 실시간으로 변경된다. 이 과정에서 Recoil은 React 컴포넌트들 사이에서 상태를 관리하고, 변경 사항이 있을 때마다 해당 상태를 자동으로 동기화시킨다.
이렇게 함으로써 사용자의 작업 데이터는 항상 최신 상태로 유지되고, 페이지를 새로고침하지 않아도 일관된 데이터를 사용자에게 제공할 수 있다. 이러한 접근 방식은 사용자 경험을 크게 향상시키며, 데이터의 정확성과 일관성을 유지하는 데 중요한 역할을 한다.
이렇게 구현하니, 작업의 상태 변경이나 다른 작업 수행 시 UI와 localStorage 간의 동기화 문제를 해결할 수 있었고, 사용자는 항상 실시간으로 업데이트된 데이터를 확인할 수 있게 되었다.
이번 프로젝트를 하면서 그동안 알고 있기만 했던 recoil 라이브러리를 처음 사용해봤는데 생각보다 사용법도 매우 간단했다. 사용방법이 직관적이고 쉽게 사용할 수 있었는데 특히, 어플리케이션의 전역 상태를 관리하는데 복잡한 설정이나 코드가 거의 없어서 빠르게 적용할 수 있었다. Recoil의 상태 관리 방식을 통해 localStorage에 저장된 데이터를 손쉽게 불러오고, 상태 변경 시마다 자동으로 localStorage에 업데이트할 수 있었는데 덕분에 데이터를 새로고침을 해도 유지할 수 있었고 코드도 간결해서 매우 만족스러웠다. 이런 recoil의 특성으로 상태 관리와 데이터 저장소 동기화를 효율적으로 처리할 수 있었고, 개발 경험도 향상되었다고 생각한다. 앞으로도 recoil을 적극적으로 활용해볼 계획이다.