받아온 데이터 로컬 스토리지에 저장하기: Recoil을 이용하여

나는야 토마토·2022년 2월 28일
3

기능정리🧙

목록 보기
3/8
post-thumbnail
post-custom-banner

React와 Recoil을 이용하여 데이터를 로컬 스토리지에 저장해야하는 기능을 맡았다. 🤯🤯🤯 하지만! 하나씩 차근차근해보쟈!

우선 로컬스토리지에 대해서 알아보쟈!

로컬스토리지(local Storage)란?

로컬스토리지는 웹 스토리지 객체이다! 즉, 웹에서 데이터를 저장하는 공간(?)이라고 이해하면 더 쉽다. 웹 스토리지는 크게 로컬 스토리지와 세션 스토리지가 있다. 이 둘은 브라우저 내에 키-값쌍을 이용하여 저장할 수 있다.

쿠키와 다르다!🍪
쿠키는 만료 기한이 있는 키-값 저장소이다. 쿠키는 처음부터 서버와 클라이언트 간의 지속적인 데이터 교환을 위해 만들어졌기 때문에 서버로 계속 전송되어진다. 이러한 것이 문제가 된다! 왜...? 그 이유는 다음과 같다. 만약 4kb 용량 제한을 거의 다 채운 쿠키가 있다면, 요청을 할 때마다 기본 4kb의 데이터를 사용해야한다. 즉, 서버에 필요하지 않는 데이터가 4kb에 포함되어있을 수 있으므로 데이터가 낭비가 된다!!!

로컬스토리지와 세션스토리지는 서버로 자동 전송되어지지 않기 때문에 더 많은 자료를 보관할 수 있다!

localStorage vs sessionStorage

제공되는 프로퍼티와 메소드

  • setItem(key, value) : 키-값 쌍을 보관, 반드시 문자열
  • getItem(key) : 키에 해당하는 값
  • removeItem(key) : 키와 해당 값을 삭제
  • clear() : 모두 삭제
  • key(index) : 인덱스(index)에 해당하는 키
  • length : 저장된 항목의 개수

예제

// localStorage에 set
localStorage.setItem('test', 1);

// sessionStoage에서 get
sessionStorage.setItem('test');

// localStorage 모두 삭제
localStorage.clear();

Recoil

Recoil에서 간단히 설명하자면 Facebook이 만든 state 관리 라이브러리이다. React의 내부 상태만을 활용하며, 작은 Atom 단위로 관리가 되어진다. 그리고 Selector라는 순수함수를 이용한다. 상태가 변경이 되면 atom을 참조하는 컴포넌트만 리렌더링 되기 때문에 쉽게 구현될 수 있다는 장점을 가지고 있다! 또한 Recoil의 상태들은 상호의존성을 가질 수 있다. 데이터 흐름에 따라서 여러 상태들의 연관된 컴포넌트들을 유기적으로 관리할 수 있다!
더 자세한 사항은 공식문서를 이용해서 보면 된다

Local Storage Persistence (로컬 스토리지 지속성)

Atom Effect는 atom 상태를 브라우저 로컬 스토리지에 유지하기 위해 사용될 수 있다. localStorage는 동기식으로 데이터를 async/await 혹은 Promise없이 직접 받아올 수 있다
라는 말이 공식문서에 적혀있다!

공식 문서의 코드가 데이터 로컬 스토리지에 저장하는 방법을 알려주고 있다. 우리는 api를 통해 데이터를 불러오고, 그 데이터에서 사용자가 메모를 추가하면 데이터를 리스트에 넣거나, 수정, 삭제한다. 이 때 이렇게 변화되는 값을 로컬스토리지에 알맞게 넣어주면 된다.
사실 recoil의 업데이트하는 함수 setter함수와 아래의 코드를 이용하면 변화되는 값을 쉽게 넣어 줄 수있다.

/utilities/localStorage.js

export const localStorageEffect =
  (key) =>
  ({ setSelf, onSet }) => {
    const savedValue = localStorage.getItem(key);
    // console.log(savedValue);
    if (savedValue != null) {
      setSelf(JSON.parse(savedValue));
    }

    onSet((newValue) => {
      localStorage.setItem(key, JSON.stringify(newValue));
    });
  };

위 코드에 대해서 조금 더 설명하자면, 우선 작은 Atom 단위로 관리되어지는 recoil을 사용하기 위해서는 우리가 로컬스토리지에 넣어줄 userStoredList를 만들어주어야 한다.

import { atom } from "recoil";
import { localStorageEffect } from "../constants/localStorage";

export const userStoredList = atom({
  key: "userStoredList",
  default: [],
  effects: [localStorageEffect("user_list")],

이 때 atom()함수는 키와 값으로 이루어져 있으며, 저 default 배열에 우리가 넣어줄 값이 들어가게 된다. 이 때 effects는 react의 useEffect()와 유사하다. Atom Effects는 atom 상태를 브라우저 로컬 스토리지에서 유지하기 위해서 사용될 수 있다. localStorage 는 동기식이므로 데이터를 async/await 혹은 Promise 없이 직접 받아올 수 있다. 이 글은 공식문서를 통해 자세히 알 수 있다. effects에 사용하는 이유는 값이 변경됨에 따라 localstroage에 있는 값도 변화시켜야하기 때문이라고 추측할 수 있다!

이제 다시 /constants/localStorage.js로 돌아가서 자세히 설명하자면 다음과 같다.

const localStorageEffect = key => ({setSelf, onSet}) => {
  const savedValue = localStorage.getItem(key)
  // localstorage의 user_list에 해당되는 값 -> savedValue가 null	이라면 
  if (savedValue != null) {
    setSelf(JSON.parse(savedValue));
   }
    // setSelf() 함수 내에서는 Promise를 사용하거나 데이터를 비동기적으로 호출할 때 사용할 수 있다.

  // setting함수가 변화되었을 때 즉, component에서
  // setUserList(변화한 값);을 코드에 작성했을 때
  // localStorage.setItem(key, JSON.stringify(newValue)); 가 실행되어
  // localStorage에 키-값 형태로 들어가게 된다!
  onSet((newValue, _, isReset) => {
    // newValue 값의 길이가 0일 때
    // userlist에 대한 값을 삭제해주면 된다.
      const confirm = newValue.length === 0;
      confirm ? localStorage.removeItem(key) : localStorage.setItem(key, JSON.stringify(newValue));
  });
};

이제 router 설정이 /로 되어있는 Main.js에서 아래와 같이 코드를 작성하면 localStorage에 값이 있는 것을 확인할 수 있다!

import { useRecoilState } from "recoil";
import { userStoredList } from "../atoms";
import { useEffect } from "react";

const Main = () => {
  const [userList, setUserList] = useRecoilState(userStoredList);
  useEffect(() => {
    setUserList([
      {
        id: 100,
        name: "Keane Sykes",
        address: "Ap #765-5550 A, Av.",
        phone: "010-1152-3825",
        memo: "luctus, ipsum leo elementum sem, vitae aliquam eros turpis non",
      },
    ]);
  }, []);

  return <div>MainPage Hello World!</div>;
};

export default Main;

왜 삭제를 할 때 clear()가 아닌 localStorage.removeItem을 사용했는가?

localStorage.clear();를 사용하게 된다면 localStorage에 있는 내용이 모두 삭제가 되어진다. 하지만 좀 더 기능이 많아진다면 저 값만 삭제하고 싶을 수 있기에 좀 더 안전한 localStorage.removeItem(key)을 사용하였다.

profile
토마토마토
post-custom-banner

0개의 댓글