너와 나의 프로그래밍
Development Etc. - Recoil 본문
Intro🙂
React의 많은 상태 관리 라이브러리들 중에 대표적인 라이브러리는 아마 Redux가 아닐까 싶다. Redux를 대표적으로 많이 사용하는 만큼 장점도 있지만 단점도 분명 존재한다.
처음 Redux가 나왔을 때는 Prop driling이 해결되는구나! 누가 만들었는지 이제 유지보수도 편하겠네! 라고 무작정 좋아했지만 그 만큼 복잡하고 Flux 패턴의 대한 정확한 이해와 사용하는데 따른 코드의 양도 방대해지고 Action과 Reduce, Store의 관리도 복잡해지기 시작했다.
그런데 최근 Recoil이라는 상태 관리 라이브러리라는 것이 나왔고 관심있게 보다가 사용을 해보니 Redux 보다 코드의 양이 적고 유지관리도 굉장히 쉬워서 러닝커브도 높지 않다고 생각이 들었다.
Recoil?🤔
Recoil 공식 홈페이지에서는 Recoil을 **“React를 위한 상태 관리 라이브러리다.”**라고 정의하고 있다. 딱 봐도 Facebook에서 만든거 같아서 조금 찾아보니 역시나 2021년에 Facebook에서 만든게 보였고 React.js를 만든곳에서 만든 상태 관리 라이브러리라고 소개를 하니 뭔가 더욱 신뢰가 갔다.
npm install recoil
or
yarn add recoil
Recoil을 사용하기 위해선 먼저 npm이나 yarn 명령어로 Recoil을 설치해 준다.
그리고 Redux와 마찬가지로 App.js에서 Main이 되는 Component를 <RecoilRoot></RecoilRoot>로 감싸준다.
import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
} from 'recoil';
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}
Recoil을 설치했고 App.js(jsx, jsx)에 RecoilRoot로 Main Component를 감싸줬다면 이제 Recoil을 사용하기 위한 준비는 끝났다.😊
Recoil의 기본 개념✏️
Atom
Recoil에서 가장 중요한 3가지 중 Atom은 Redux의 store와 같은 개념으로 생각하면 된다. 정확하게는 store라고 보긴 힘들겠지만 Redux의 store로 이해하면 간단하지 않을까 싶다.
// atom.js(ts)
import { atom } from 'recoil'
const textState = atom({
key: 'textState', // unique ID (with respect to other atoms/selectors)
default: '', // default value (aka initial value)
});
Atom을 사용할 때는 recoil의 atom을 import 시켜주고 매서드 객체 안에 key와 default 값을 설정해주면 된다. 이때 key의 값은 절대 중복되면 안된다.
// CharacterCounter.js(jsx/tsx)
import { useRecoilState } from 'recoil';
import { textState } from "./atom";
function CharacterCounter() {
return (
<div>
<TextInput />
<CharacterCount />
</div>
);
}
function TextInput() {
const [text, setText] = useRecoilState(textState);
const onChange = (event) => {
setText(event.target.value);
};
return (
<div>
<input type="text" value={text} onChange={onChange} />
<br />
Echo: {text}
</div>
);
}
atom으로 설정된 값은 useRecoilState로 읽기/쓰기가 가능하다. 마치 useState와 사용법이 유사한데, text는 state, setText는 setState처럼 사용이 가능하다. useRecoilState도 마찬가지로 사용하면 된다.
경우에 따라 atom를 활용하는 몇가지 다른 메서드가 있다.
- useRecoilValue : atom을 읽기만 할 때
- useSetRecoilState : atom을 쓰려고만 할 때
- useResetRecoilState : atom을 초깃값으로 초기화할 때
- useRecoilCallback : 컴포넌트가 등록되지 않고 atom을 값을 읽어야 할 때.
필요에 따라 지원되는 메소드가 있어 편리하다.
참고로 해당 atom을 구독하는 컴포넌트가 있다면 atom에 변화가 있을 때 해당 atom을 구독하는 컴포넌트들이 재 랜더링이 되는 경우가 있어 굉장히 주의깊게 사용해야 될 것 같다.
Selector
Selector는 Recoil에서 함수나 파생된 상태를 나타낸다. 그리고 주어진 종속성 값 집합에 대해 항상 동일한 값을 반환하는 “순수함수”다. 실제로 get을 통해 number 값을 return해주면 set에서도 return값이 number여야 한다.
말이 좀 어렵지만 코드를 보면서 이해를 하면 빠르게 이해할 수 있다.
// CharacterCounter.js(jsx/tsx)
import { useRecoilState } from 'recoil';
import { charCountState } from "../recoil/Counter/selector";
function CharacterCounter() {
return (
<div>
<TextInput />
<CharacterCount />
</div>
);
}
function TextInput() {
const [text, setText] = useRecoilState(textState);
const onChange = (event) => {
setText(event.target.value);
};
return (
<div>
<input type="text" value={text} onChange={onChange} />
<br />
Echo: {text}
</div>
);
}
import { selector } from "recoil";
import { textState } from "./atom";
export const charCountState = selector({
key: "charCountState",
get: ({ get }) => {
const text = get(textState);
return text;
},
set: ({ set }, newValue) => {
set(textState, newValue);
},
});
생성된 atom을 get을 통해 전달해줄 수도 있고 set을 통해서 새로운 인자를 통해 전달받아 값을 atom의 값을 변경할 수 있다.
여기서 한가지 의문이 들었던 것은 atom의 useRecoilState 메서드도 atom의 값을 변경할 수 있는데 왜 Selector를 사용할까? 라는 생각이 들었다.🙄
다른점이라고 보긴 힘들지만 selector의 set을 사용하게 되면 다른 atom의 값도 함께 변경할 수 있기 때문에 useRecoilState로 하나의 atom을 변경할 때가 아닌 다른 atom도 같이 변경하고 싶을 때 사용하면 좋을 것 같다.
마무리👍
Recoil의 대한 기본 개념은 크게 2가지라고 볼 수 있지만 그 안에서 활용할 수 있는 다양한 방법들을 Recoil 메서드를 통해 지원하고 있다. 실제 레퍼런스 API 문서를 확인해 보면 정말 다양한 메서드들이 있는 것을 볼 수 있다.
조금 더 나아가면 atomFamily나 selctorFamily 같은 파라미터를 활용한 상태 관리도 할 수 있다.
아직 Redux를 사용하고 있는 회사들의 프로젝트가 많은데 요즘 채용공고를 보면 간간히 Recoil로 상태관리를 하는 회사들도 많이 봤다.
아무래도 러닝커브가 낮은 점과 Redux보다 코드 양이 적고 간결하게 사용할 수 있다는 점이 굉장히 매력적인 것 같다.
굳이 Redux를 고집하는 것이 아니라면 Recoil도 사용해 보는 것을 추천한다.
참고 : https://recoiljs.org/ko/docs/introduction/getting-started
'Etc. > Development Etc.' 카테고리의 다른 글
Development Etc. - React-Quill(Quill) for Typescript + Next.js (0) | 2023.06.14 |
---|---|
Development Etc. - MSW(Mock Service Worker) (0) | 2023.01.15 |
Development Etc. - GraphQL (0) | 2022.08.30 |
Development Etc. - Android/iOS Kakao PostCode Progressive (0) | 2022.05.09 |
Development Etc. - AWS Amplify '[ERROR]: !!! Build failed, !!! Non-Zero Exit Code detected' for Next.js or React.js (0) | 2021.10.28 |