React.js:

Recoil로 상태 관리하기

칠일오. 2023. 7. 14. 17:34

요번 사이드 프로젝트에서 상태 관리로 recoil을 사용하기로 해서 공부해 보았다!

공식 사이트에 들어가 보니 아주 친절하게 설명되어 있어서 추천한다.

 

우선 왜 Redux, Zustand와 같은 상태 관리 라이브러리를 사용해야 하는 걸까?

리액트는 컴포넌트 내부에서 변경 가능한 데이터. 즉, state를 가지는데 이를 다른 하위 컴포넌트로 전달하고 전달하고 하다 보면 나중에 변경이 필요할 때 전달 된 모든 state를 일일이 변경해주어야 하는 불상사가 생긴다. 때문에 전역에서 관리하여 보다 쉽게 변경할 수 있는 상태 관리 라이브러리가 등장하게 된 것이다.

 

그중 Recoil은 React에서 개발한 만큼 리액트와 유사한 문법 구조를 사용하기 때문에 크게 어렵지 않게 이용할 수 있다는 장점이 있다. 이게 무슨 말인지는 찬찬히 풀어보도록 하겠다. 그전에!!!! Recoil에는 2가지 개념을 알고 있어야 하는데 그게 무엇인지 본격적으로 알아보도록 하겠다.

 

우선 Recoil을 사용하기 위해 최상위 컴포넌트에 RecoilRoot 태그를 씌어주고 시작하겠다.

ReactDOM.createRoot(document.getElementById('root')!).render(
    <RecoilRoot>
      <React.StrictMode>
        <App />
      </React.StrictMode>
    </RecoilRoot>
)

 

Atoms

atoms는 상태의 최소 단위로, 업데이트와 구독이 가능하다. 즉, state처럼 atom이 업데이트되면 각각 구독된 컴포넌트에 렌더링이 일어난다. 참고로 recoil 폴더를 따로 만들어서 사용 용도에 맞는 이름의 파일을 생성하여 아래 코드를 작성하였다. 이렇게 하는 이유는 한 폴더에 모아서 관리하는 것이 유지보수 면에서 좋기 때문이다.

export const ItemAtom = atom({
	key: 'ItemAtom',
    default: []
})

atom 함수에는 기본적으로 key와 default를 작성한다.

  • key는 전역적으로 유일한 값으로 작성해야 한다. 전역에 있는 상태를 가져와서 사용하는 것이기 때문에 같은 이름일 경우 혼선이 생기기 때문에 반드시 유일해야 한다.
  • default의 경우 데이터 타입에 따라 결정이 된다. 나의 경우 배열 타입이기 때문에 위 코드처럼 작성하였다.
const [item, setItem] = useRecoilState(ItemAtom);

이제 작성한 atom을 사용할 컴포넌트에서 위 코드처럼 작성해서 사용하면 된다. 딱 보면 느껴지겠지만 useState와 굉장히 유사한 형태이다. 이 때문에 이 글 상단에서 "리액트와 유사한 문법 구조를 사용하기 때문에 크게 어렵지 않게 이용할 수 있다"라고 한 것이다.

useState와 다른 점이라면 단지 useState가 아닌 useRecoilState를 사용한다는 점과 괄호 안에 다른 파일에 작성한 ItemAtom을 import로 가져와서 연결시켜 준다는 점뿐이다. 이것만 보더라도 참 쉽다!라는 생각이 드는 라이브러리다.

 

특히 개발을 하다보면 item만 사용할 때도, setItem만 사용할 때도 있는데, Recoil은 이를 분리해서 사용할 수 있게도 해준다.

const item = useRecoilValue();
const setItem = useSetRecoilState();
👀 잠깐!
• useRecoilState() : 첫 요소가 상태의 값이며, 두 번째 요소가 호출되었을 때 주어진 값을 업데이트하는 setter 함수를 리턴한다. useState와 비슷하지만, 상태가 컴포넌트 간에 공유될 수 있다는 차이가 있다.
• useRecoilValue() : 주어진 Recoil 상태의 값을 리턴한다. 
• useSetRecoilState() : 쓰기 가능한 Recoil 상태의 값을 업데이트하기 위한 setter 함수를 리턴한다.

여기까지만 알아봐도 Recoil 최고다...라는 생각이 들었다.

 

 

Selector

atoms나 다른 selectors를 입력으로 받아들이는 순수 함수(pure function)다. 상위의 atoms 또는 selectors가 업데이트되면 하위의 selector 함수도 다시 실행된다. 컴포넌트들은 selectors를 atoms처럼 구독할 수 있으며 selectors가 변경되면 컴포넌트들도 다시 렌더링 된다.

주로 atom을 기반으로 파생된 데이터를 계산하는 데 사용된다. 아래 selector 함수를 보자.

const Selector = selector({
	key: 'AllItemSelector',
    get: ({get}) => {
    	const AllItem = get(ItemAtom);
        return AllItem
    }
})

selector의 경우 key와 get 매소드를 작성하며, get 프로퍼티에는 함수를 작성한다. 작성한 atom을 연결하여 원하는 데이터 형태로 반환하면 된다.

 

정말 간단한 기초 개념에 대해서 알아보았는데 추가적으로 새로운 정보가 생기면 돌아오겠다...!

 


📜 출처