본문 바로가기
Ect./Library

클라이언트 데이터 상태 관리를 위한 Recoil

by 쿠리의일상 2023. 7. 22.
Recoil 은 React 상태 관리 라이브러리

리액트에서 상태를 관리하기 위해 일반적으로 상태를 컴포넌트 내부에서 관리하거나 Redux 같은 라이브러리를 사용해준다. 다만 리덕스는 보일러플레이트 코드가 많고 컴포넌트와 액션 사이의 연결을 설정하는 작업이 번거로워 이러한 불편함을 해결해주기 위해 리코일을 사용하는 추세라고 한다.

리코일은 상태값을 저장하고 업데이트하는데 사용되는 Atom 과 이를 기반으로 다른 값을 계산하는데 사용하는 Selector로 구성된다.

 

Recoil의 특징

  1. 중앙 집중화된 상태 관리
    1. 상태가 어디에서 변경되었는지 추적하고 컴포넌트간 일관성 있는 데이터 흐름을 유지 가능
  2. 비동기 상태 관리
    1. useRecoilCallback 훅으로 비동기적인 상태 업데이트가 가능하다
  3. 상태 업데이트 최적화
    1. 해당 상태를 사용하는 컴포넌트만 리렌더링 되도록 최적화처리
  4. ts 지원
  5. 개발자 경험 개선

 

Recoil 설치

npm install recoil

 

설정하기

RecoilRoot 로 루트 컴포넌트를 감싸서 사용한다.

몽고DB에 비유하자면 DB를 나눠줄 때 RecoilRoot로 나눠주는 것과 유사하다고 생각된다.

import {RecoilRoot} from 'recoil';

function Main() {
  return (
    <RecoilRoot>
      <App />
    </RecoilRoot>
  );
}

즉 여러개의 RecoilRoot가 존재할 수 있다는 의미이며 컴포넌트에서 recoil과 연동할 때 해당 컴포넌트와 가장 가까이 있는 RecoilRoot가 사용된다.

 

리코일 사용하기

Atom
상태 정의 방법으로 하나의 값이며 컴포넌트에서 읽고 쓸 수 있다.

상태를 정의할 때는 key와 default 값을 설정해준다.

import { atom } from 'recoil';
 
export const counterState = atom({
  key: 'counterState',
  default: 0,
});

 

useRecoilState
파라미터에 atom으로 지정해준 변수명을 넣어서 상태를 읽고 쓸 수 있다.
useState 와 유사하게 배열을 리턴해준다.
import { useRecoilState } from 'recoil';
import { counterState } from './atoms';
 
function Counter() {
  const [count, setCount] = useRecoilState(counterState);
 
  const increment = () => {
    setCount(count + 1);
  };
 
  const decrement = () => {
    setCount(count - 1);
  };
 
  return (
    <div>
      <p>{count}</p>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
}
  • useRecoilValue : 반환해주는 배열 값 중 읽을 수 있는 value 만 리턴
  • useSetRecoilState : setter 함수만 리턴

 

selector
전역 상태에서 파생된 데이터로 다른 atom에 의존하는 동적인 데이터를 만들 수 있게 해준다.

즉, 기본적이고 최소한의 상태는 atom에 저장하고

명시한 함수를 통해 상태값을 변경해주는건 selector에서 실행한다.

상태의 특정 부분만 선택하거나 상태를 사용하여 연산한 값을 조회할 때 다른 데이터에 의존하는 동적 데이터를 구축할 수 있게 해준다.

const filteredList = selector({
 key: 'filteredList',
 get: ({get}) => {
   const filter = get(filterState);
   const default = get(DefaultState);
   
   return default.filter(el => el.type === filter);
 }
});
  • 읽기 전용 selector
    • 위의 예시처럼 get 속성을 사용하여 내부 atom에 접근하여 특정 작업을 수행한다.
  • 양방향 selector
    • get 뿐만 아니라 set 속성도 있으므로 set을 사용하여 내부 atom의 값을 직접 변경해줄 수 있다.

 

 

Recoil에서 Selector 는 순수 함수로써 Promise를 반환 후 비동기 데이터를 불러오게 해준다.

사실 리코일로 서버/클라이언트 데이터를 모두 다룰 순 있지만 데이터의 fetch에 있어선 리액트 쿼리가 더 잘 처리할 수 있고, 서버 데이터와 클라이언트 데이터를 구분하는 것이 유지보수에도 좋기 때문에 비동기 데이터 처리는 리액트 쿼리로 구현해준다.

 

전에 개인 프로젝트에 리코일을 사용했을 땐 단순히 서버딴에서 정보만 불러오는데에 그쳤기 때문에 selector를 굳이 사용해주진 않았었다. 이번에 맡게될 프로젝트에는 리코일이 채택되었으므로 selector를 사용하려고 한다.

다음에는 리액트 쿼리에 대해 정리해볼 예정이다. 아직 안 써본거라 개념부터 정리하고..