React

[React] 상태관리 라이브러리 Recoil ♦︎

Yujzu 2023. 9. 18. 14:29

# React 상태관리 

[ 기본 도구 ]

1. useState : 컴포넌트의 로컬 상태를 관리, 단순한 상태 관리

2. useReducer : 상태와 관련된 로직을 함수로 정의하여 구조화 가능, 복잡한 상태 관리

3. useContext : 데이터를 전역적으로 공유할 수 있도록 기본 제공되는 Context API

 

[ 한계 ]

1. 성능 문제 : Context API 는 상태가 변경될 때마다 관련 컴포넌트가 모두 리렌더링된다.

2. 복잡한 상태 공유시 관리의 어려움

3. 비효율적인 상태 로직

 

# 상태 관리 라이브러리를 사용하는 이유

1. 효율적인 전역 상태 관리

- 라이브러리는 필요한 컴포넌트만 구독하도록 설계되어 성능을 최적화한다.

ex) Recoil의 Atom, Redux의 connect 등

 

2. 복잡한 상태와 비동기 작업 관리

- 라이브러리는 전역 상태를 논리적으로 구조화하고, 비동기 작업(API, 캐싱) 을 처리하는 도구를 제공한다.

ex) Recoil의 Selector, Redux의 middleware 등

 

# 대표적인 상태 관리 라이브러리

1. Redux

2. Recoil

3. mobX

4. Zustand

5. Jotai

6. immer

 

# Recoil

: Facebook에서 개발한 React 상태 관리 라이브러리

 

[ 특징 ]

1. 전역 상태와 컴포넌트 로컬 상태를 구분 없이 하나의 방식으로 관리한다.

- 상태를 컴포넌트 트리 전체에서 쉽게 공유하고 사용할 수 있다.

2. Selector을 통한 파생 상태(derived state) 관리

- 상태에서 파생된 값을 선언적으로 정의한다.

3. React의 Suspense와 자연스럽게 통합되어 비동기 데이터를 다루기 쉽게 만든다.

 

[ 설치 ]

$ npm install recoil

$ yarn add recoil

 

[ 구성 요소 ]

1.  Atom 

: 상태(state)의 최소 단위

- Recoil의 상태 저장소로, 기본 값을 가지고 있음

- 어떤 컴포넌트에서나 읽기와 쓰기가 가능한 전역 상태

- atom의 값을 읽는 컴포넌트들은 암묵적으로 atom을 구독한다.

   => atom에 변화(상태 변경)가 있으면 그 atom을 구독하는 컴포넌트들은 리렌더링된다.

import { atom } from 'recoil';

// 원본 상태 (atom)
const textState = atom({
  key: 'textState', // 고유한 ID (필수)
  default: '',      // 초기값
});

 

2. Selector

: 파생 상태(Derived State) 를 정의하는 데 사용된다.

- atom 의 값을 가공해서 새로운 값을 만들어주는 함수

- atom이나 다른 selector의 상태를 기반으로 계산된 값을 제공한다.

- 자체적으로 값을 저장하지는 않고, atom의 값이 변하면 자동으로 업데이트 된다.

- Selector은 상태가 변경될 때 필요에 따라 자동으로 재계산되며, 결과를 캐싱한다.

- useRecoilValue(selector)로 가공된 값을 가져올 수 있다 (변경 불가)

- 순수 함수 : 같은 인풋이 들어오면 같은 인풋을 리턴하고, side effect가 존재하지 않는 함수

 

 

# 파생 상태

: 기존 상태(state)에서 특정 로직을 적용해 계산된 값을 의미

- 원본 상태를 직접 저장하는 것이 아닌, 기존 상태를 기반으로 계산된 값을 사용하는 방식

 

[ 기본 구조 ]

const Selector = selector({
	key: '키값',
    	get: ({get}) => {
    	const 원본 = get(아톰)
        return 원본변형값
        }
    })

 

사용 예시)

import { selector } from 'recoil';
import { textState } from './atoms';

// 파생 상태 (selector)
const charCountState = selector({
  key: 'charCountState', // unique ID
  get: ({ get }) => {
    const text = get(textState); // Atom의 상태를 읽음
    return text.length;    // atom 데이터의 길이를 담아두는 selector
  },
});

 

- useRecoilValue() 를 사용해서 charCountState 값을 읽을 수 있다.

function CharacterCount() {
  const count = useRecoilValue(charCountState);

  return <>Character Count: {count}</>;
}

 

3. RecoilRoot

: Recoil 상태를 관리하기 위해 애플리케이션 루트에 추가해야 하는 컴포넌트

- 부모 트리에서 RecoilRoot 컴포넌트가 필요하다

import { RecoilRoot } from 'recoil';

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

 

4. useRecoilState

: Atom의 상태를 읽고 업데이트하는 데 사용하는 Hook

- 컴포넌트가 atom을 불러서 읽고 쓰고 사용한다.

import { useRecoilState } from 'recoil';
import { textState } from './atoms';

function TextInput() {
  const [text, setText] = useRecoilState(textState);

  const onChange = (e) => {
    setText(e.target.value);
  };

  return <input type="text" value={text} onChange={onChange} />;
}

 

[ 사용 방법 ]

1. <RecoilRoot>로 컴포넌트 최상단에 감싸주기 (atom이 머무를 곳)

2. atom 생성

3. useRecoilState로 atom 불러오기

- 아니면  useRecoilValue, useSetRecoilState로 분리해서 불러오기

예시)

const [cartItem, setCartItem] = useRecoilState(CartItemAtom)

// 분리해서 둘 중 하나만 가져오는 것도 가능
const cartItem = useRecoilValue() // value만 사용하는 경우
const setCartItem = useSetRecoilState() // set 함수만 사용하는 경우

// atom 초기값인 빈 배열에 아이템 추가
setCartItem((prev)=>[...prev,data])

 

4. atom 수정 or 사용하기

 

 


출처: Recoil 공식문서 https://recoiljs.org/ko/docs/introduction/getting-started

 

Recoil 시작하기 | Recoil

React 애플리케이션 생성하기

recoiljs.org