# TIL-20210930

# Today

  • medium Article

# Contents

최근 프로젝트에서 Recoil을 통해 상태관리를 하려고 시도 했으나, 현재 정식 배포판이 있지 않고 facebook개발팀 위주로 사용한다는 소식을 접하게 되어 프로젝트에서 다시 걷어내는 일이 있었다.

그래서, 이번엔 Redux에서 Recoil로 상태관리 library를 전환하는 글을 보고 간단하게 정리 해보려고 한다.

출처 : Why I've Moved from Redux to Recoil for State Management (opens new window)

다음 이미지는 필자가 생각하는 Redux에서 Recoil로 라이브러리를 변경하게 된 큰 이유이다.

이미지

# Intro

개발한 어플리케이션의 상태를 관리하는 일은 꽤 큰 작업이다. React는 최근까지만 해도 자체적인 상태관리 도구를 사용하지 않았지만, 최근에 Context API를 통해 자체적인 상태관리가 가능게 되었다.

Context API는 많은 제약이 있고 한번에 한가지 상태만 가질 수 있다. 만약에 여러가지 상태를 관리하고 싶다면 Context Provider를 여러개 설정하여 상태를 관리해야 한다. 이렇게 구성하게 되면 Components간의 State drilling이 발생하게 된다. 점점 상태는 Component와 관계가 흐려지고 코드도 복잡해진다. 그렇다보니 Context API를 이용하는 것도 만만한 일이 아니다.

상태 관리를 하기 위해 Redux와 같이 약간의 제약이 있지만 third-party 상태관리 라이브러리를 사용해볼 수 있다. Redux는 사용하기 위한 사전 작업(boilerplate)을 구성하는 것이 복잡하다. React에서 Redux를 사용하기 위한 연동 과정이 꼭 필요하다. 많은 상태를 관리하기 위해서는 여러가지 코드를 수정하고 추가할 필요가 있어 점점 관리하기 어려워 질 수 있다.

Recoil은 이러한 문제를 많이 해소할 수 있다. 먼저 Recoil은 설정하기 매우 쉽다. 상태를 atom으로 구성하여 어떤 Component에서도 쉽게 상태를 사용할 수 있게 된다.

# What is Recoil?

Recoil은 React를 위한 상태관리 library이다.

  • 설정이 쉽다.
  • React적으로 생각할 수 있다. (useState의 hook과 유사하다.)
  • hooks을 이용해 쉽게 읽고 쓸수 있다.
  • 순수함수를 이용해 비동기처리를 할 수 있다.

# Atom

상태를 저장하는 단위. javascript의 모든 타입을 상태로 가질 수 있다. object, number, array, etc..

  • atom은 keydefault 값을 통해 생성할 수 있다.
import { atom } from "recoil";

const usersState = atom({
  key: "usersState",
  default: [],
});
  • 필요한 컴포넌트 어디에서든 atom으로 만든 상태를 가져와 사용할 수 있다.
import { useRecoilValue } from "recoil";

function UsersList() {
  const users = useRecoilValue(usersState);

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}
  • 상태를 어디에서든 업데이트도 할 수 있다. 이때는 useRecoilValue 대신 useRecoilState를 사용해야 한다.
import { useState } from "react";
import { useRecoilState } from "recoil";

function CreateUser() {
  const [, setUsers] = useRecoilState(usersState);
  const [name, setName] = useState("");

  function handleSubmit() {
    e.preventDefault();
    setUsers((users) => [
      // 여기 뭔가 code가 이상해서 setUser제거 했습니다.
      ...users,
      {
        id: generateNewId(),
        name,
      },
    ]);
  }
  function genertateNewId() {
    // return ...
  }
}

# Recoil Root

Recoil상태를 이용하기 위해서는 상위 Component에서 RecoilRoot를 반드시 감싸줘야 합니다.

import { RecoilRoot } from "recoil";

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

# Conclusion

내가 Recoil로 변경한 이유는 쉽게 사용할 수 있기 때문이다. 어려운 boilerplate를 생성할 필요도 없고, hooks을 이용한 쉬운 상태관리가 가능하기 때문이다. 이러한 이유로 충분히 변경할 가치가 있는 일이라고 생각한다.

Recoil에 대해 더 자세히 알어보려면 공식 문서를 참고하세요~ Recoil 공식문서 (opens new window)

# 결론

필자는 Redux의 flux방식을 맘에들어하지 않았다. Action을 통해 상태를 변경하고 상태의 비동기 처리 또한 쉽게 하기 어려운 점을 Redux의 단점이라고 생각했다. 실제로 간단한 예제코드를 살펴보면 사용 방식은 매우 간단하다.

React의 Hooks을 사용한 State관리와 똑같지만 atom이라는 전역 상태를 나누어 저장하고 component가 직접 필요할 때문 불러서 사용할수 있게 한다.

내가 의문이들었던 부분은 결국 여러개의 component가 state를 공유하는 상황이 오면 state의 현재 상태가 흐려지게 되서 현재 어떤 상태인지 알기 어려워진다는 점이다. 이 부분은 좋게 생각하면 한가지 상태가 여러 component에 공유해야 하는 상황일 때는 좋으 방식으로 작용하지만, 매번 초기 분기에 따라서 여러가지 상태가 존재할 수 있는 상태가 있다면 Component를 여러번 거치면서 예상치 못한 상태를 component로 전달 할 수도 있을거라고 생각했다.