Recoil 사용기 - 1 (Basic)

soonrok·2022년 12월 13일
0

Recoil

목록 보기
1/2
post-thumbnail

프로젝트를 진행하면서 상태 관리는 불가피한 영역이다. 사실 이 부분을 위해서 기존에는 Zustand를 사용했었는데, 최근 취업을 위해 많의 회사들의 공고를 보니 사용 기술로 Recoil을 선택하고 있었다.
학기가 끝난 지금 시간이 조금 붕 뜨는 감이 있어 이번 기회에 Recoil을 공부하고 공식문서에 제시된 간단한 프로젝트를 직접 만들어 볼 생각이다. 또한 간단한 프로젝트를 진행하면서 생기는 의문점에 대해 공식문서에 기재된 API를 직접 살펴보며 깊게 이해하는 시간도 가져보자.

Recoil이란??

Recoil은 React의 전역 상태 관리를 위한 라이브러리로 atomsselectors라는 두 가지 주요 개념을 가지고 있다.

  • Atoms : 저장하고 싶은 상태의 단위
  • Selectors : Atoms을 이용해 파생된(계산된) 데이터의 단위

예를 들어 검색창을 만들었을 때, 사용자가 검색한 단어인 word와 단어의 길이인 lengWord는 다음과 같이 대조될 수 있다.

  • word : 사용자가 생성한 데이터(source of truth)로 Atoms의 단위
  • lengWord : word라는 Atoms으로부터 계산될 수 있는 Selector의 단위

atoms는 여러 컴포넌트에서 공유되는 상태로 한 컴포넌트에서 변화를 일으키면 해당 atoms를 사용하고 있는 다른 컴포넌트에서도 값의 변화가 일어난다.
또한 selectors는 atoms의 값에 의해 변화되기 때문에 의존하고 있는 atoms의 값에 변화가 일어날때마다 갱신된다.

Recoil의 사용

프로젝트 생성

Recoil을 사용할 프로젝트를 먼저 생성해보자.

// 프로젝트 디렉토리를 생성할 위치로 이동 후
npx create-react-app 프로젝트-디렉토리-이름

나는 프로젝트 디렉토리명으로 recoil-study을 사용했다.
이후, 기본적으로 생성되어 있는 파일들과 코드들을 정리하고 다음과 같이 남겨준다.
index.js파일도 다음과 같은 코드만 남겨둔다.

// index.js

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

Recoil 설치 및 루트설정

Recoil을 사용하기 위해서는 패키지 매니저를 통해 설치해야 한다.

// npm을 사용하는 경우
npm install recoil

// yarn을 사용하는 경우
yarn add recoil

나는 npm을 사용하기 때문에 npm을 통해 설치했다.

Recoil을 사용하는 컴포넌트는 그 부모 컴포넌트 어딘가에 RecoilRoot가 필요한데 전역으로 사용하기 위해서는 가장 최상단에 있는 <App />가 적절할 것으로 보인다.
이제 Recoil을 사용할 준비가 끝났다!

Atoms와 Selectors의 생성

atoms과 selectors의 사용법은 다음과 같다. 먼저 src 디렉토리 아래 store 라는 상태를 관리하는 디렉토리를 하나 만들고 그 아래 textStore.js라는 파일을 만든다.

  • Atoms
    어떠한 상태값을 하나 만들기 위해서는 상태의 단위를 의미하는 atom를 이용해 만들 수 있다.
// textStore.js

import { atom } from 'recoil';

const textState = atom({
  key: 'textState',
  default: '',
});

export { textState }

atom을 사용할때 인자로 넘겨주는 option 객체는 기본적으로 keydefault값을 포함해야 한다. key는 해당 atom을 식별하는 유일한 값이며, default는 해당 상태가 가질 초깃값을 의미한다.
마지막으로 다른 곳에서 textState를 사용할 수 있도록 export해야 한다.

  • Selectors
    상태를 가지고 있는 atom 으로부터 파생된(계산된) 값을 가지는 Selectors는 selector를 이용해 만들 수 있다. 위의 textState의 길이 값을 가지는 selector를 만들어보자.
// textStore.js

import { atom, selector } from 'recoil';

... 이전 코드 생략
const charCountState = selector({
  key: 'charCountState',
  get: ({ get }) => {
    const text = get(textState);
    return text.length;
  },
});

export { textState, charCountState };

selector를 사용할때 인자로 넘겨주는 option 객체는 atom 과 마찬가지로 key라는 해당 selector를 식별하는 유일한 값을 가지고 추가적으로 get이라는 프로퍼티를 가진다. get프로퍼티가 가지는 함수는 selector가 반환할 값을 계산하는 함수로 첫 번째 인자로 다른 atom이나 selector의 값을 참조할 수 있는 함수를 받는다.(보통 get이라는 이름을 쓴다.) 위 코드에서 charCountState라는 selector는 textState라는 atom값에 의존하고 있기 때문에, textState의 상태 값이 변할때마다 charCountState는 갱신된다.

그럼 여기까지 작성된 textStore.js의 상태를 확인하고 다음에는 사용해보자!

App.js에서 Recoil 사용하기

그럼 이제 실제 컴포넌트인 App.js에서 Recoil을 사용해보자. 컴포넌트에서 전역 상태로 관리되고 있는 atom을 사용하기 위해서는 useRecoilState 라는 훅을 사용하는데 해당 훅은 React에서 제공하는 useState 와 사용법이 비슷하다.

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

물론 recoil에서 useRecoilState를 가져오고, 우리가 만든 textStore에서 textState를 가져와야 사용할 수 있다.
또한 우리가 만든 selector를 가져오는 과정도 비슷하다. 하지만 우리가 만든 selector는 getter의 역할만 하기 때문에 atom을 읽거나 쓰는 useRecoilState 훅이 아니라 읽기만 하는 useRecoilValue 훅을 사용해서 읽으면 된다.

const count = useRecoilValue(charCountState);

이제 간단하게 input요소를 만들고 그 아래 텍스트의 길이를 출력하는 코드를 작성해보자.

// App.js

import { useRecoilState, useRecoilValue } from "recoil";
import { textState, charCountState } from "./store/textStore";

function App() {
  const [text, setText] = useRecoilState(textState);
  const count = useRecoilValue(charCountState);
  return (
    <div>
      <input type="text" value={text} onChange={(e) => setText(e.target.value)} />
      <p>글자수: {count}</p>
    </div>
  );
}

export default App;

결과

보이는 것과 같이 text가 변할때마다 textState라는 atom의 상태가 변하고, 해당 atom에 의존하고 있는 charCountState가 갱신되어 글자수가 변하는 것을 볼 수 있다.

profile
I Will be Relaxed Person

0개의 댓글