[React.js] Recoil 잘 써보기

2021. 8. 5. 20:33PROJECT/SIDE PROJECT

사이드 프로젝트를 진행하면서 React 상태관리 라이브러리로 Recoil을 사용했다.

간단명료한 concept와 React 함수형 컴포넌트에 친화적인 부가 기능이 (useState와 동작/사용법이 흡사한 형태의 hook이 제공됨)이 특장점이다.

 

Redux & Redux-saga 조합과 다르게 Recoil은 초기 진입장벽이 거의 없었다. (Redux & Redux-saga ... 아직도 이해 못해서 백로그에 천년만년 묵히고 있는 중 ㅎㅎㅎㅎㅎ)

제공되는 object도 atom, selector 두 가지 뿐이고 값을 읽거나 쓰는 것도 useRecoilState hook을 통해 React state와 동일한 모양새로 구현할 수 있다. React "전용" 상태관리 라이브러리면 말 다했다 ㅎㅎ

 

그런데 Recoil을 쓸 수록 고민되었던 부분이 atom과 selector 간의 구독관계....

 

진짜 잘 쓰면 React Component 내에서 API 호출과 데이터 핸들링 하는 로직을 다 제거할 수 있을 것 같은데, 

손 가는 대로 쓱쓱 개발하면 또 금세 atom과 selector의 관계가 모호해져버리는.... 실제로 selector로 atom을, atom을 selector를 대체하여 사용해도 기능상으로는 문제가 없었다. 다만 소스가 누더기일 뿐 ㅎㅎ

 

다행히 다른 쪽 세팅 때문에 내가 하던 쪽에 여유가 생겨서 리팩토링을 시작했다.

 

초기상태

- atom과 selector의 경계가 무너짐
예) employeeId 만 atom으로 사용하다가 employee 상세정보를 참조해야할 일이 생겨서
     해당 atom을 employee object로 바꿔버림. atom은 최소한의 핵심 정보를 담아야 한다는 원칙이 무너짐.
- atom과 selector 간의 구독 관계가 모호함

  구독에 대한 처리를 component 내의 useEffect에 걸어두는 코드들이 생기면서 atom과 selector간의 구독관계를 한 눈에 파악할 수 없게 되어버림

- backend 호출부의 산재 

  useEffect에 걸어 backend 호출을 처리하니  useEffect deps의 변화에 의한 재호출 + 해당 컴포넌트 prop 변화로 인한 재렌더 & 재호출이 함께 일어나 최초 진입 시 backend 호출이 2-3회 발생함

 recoil 구독 관계를 활용하여 backend 호출 처리를 깔끔하게 할 수 있는데 전혀 활용을 하지 못했음

 

개선목표

- atom과 selector를 명확히 구분하자

- selecor의 구독 기능을 십분 활용하여 backend 호출 처리를 우아하게(?) 해보자

 

개선일지

0. atom과 selector를 효율적으로 관리할 수 있는 폴더 구조는 뭘까 고민하기
1. 우리 프로젝트의 atom과 selector가 뭔지 정리해보기

2. api를 쪼개거나 합쳐야할 부분 있는지 고민하고 backend 개발자님께 요청드리기 

3. atom - selector - api 연결하기 

4. 생성한 atom과 selector로 컴포넌트 지역 state 및 useEffect 대체하기 --> 깔끔해지는 코드를 보면서 희열을 느꼈다 ㅋㅋㅋㅋ

  component 단의 side effect 처리 코드가 모두 사라지니 뼈대가 더 잘 보이는 느낌!
  대신 recoilState의 import 가 늘어다나 보니 오히려 import 라인은 늘어나서 지저분했음... <-- 개선 방법이 있을거같은데?!

 

 

느낀점

.리팩토링 시간을 가질 수 있다는게 얼마나 행복한지..! 소스를 정리하고 최적화할 수 있어 즐거웠다

.recoil을 상용 product 전체에 적용하기에는 이른 것 같다 (개발도구부족, 계속해서 사라지고 개선되는 기능들.. 하지만 매력적이다!)

.모든 시나리오에서 atom과 selector의 역할이 정확히 정해지는 것은 아니다

 

 

우여곡절

+) recoil chrome extension을 쓰려고 하니 recoil 0.2.0버전 이상에서 특정 함수명이 변경되는 바람에 
extension이 정상동작 하지 않았다. issue 등록은 되어있고, 한 줄 수정인데도 두달 넘게 머지가 되지 않고 있는듯.... 
마냥 기다릴 수 없어서 아래 포스트를 참고하여 patch-package 를 해봤다 :) 
https://medium.com/naver-place-dev/patch-package%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-npm-%ED%8C%A8%ED%82%A4%EC%A7%80-%ED%8C%A8%EC%B9%98-patch-%EC%82%AC%EB%A1%80-feat-react-native-ee1fc399b7c2

 

+) async selector의 refresh를 강제할 필요할 때 어떻게 구현해야하나 막막했는데, 아래와 같이 공식 가이드가 있었다. 

요약하자면 1. seq 성격을 가지는 dummy atom을 만들고 구독하게하라 2. selector대신 atom을 사용하라 .....

둘 다 나도 생각했던 내용이라 약간 실망했다... 더 멋지고 신박한 수가 있을 줄 ㅠㅠ 

ㅠㅠ refreshSelector 같은 훅 만들어주세요 facebook님 ㅠㅠ 

https://recoiljs.org/docs/guides/asynchronous-data-queries/#query-refresh

 

Asynchronous Data Queries | Recoil

Recoil provides a way to map state and derived state to React components via a data-flow graph. What's really powerful is that the functions in the graph can also be asynchronous. This makes it easy to use asynchronous functions in synchronous React compon

recoiljs.org

 

 

 

 

 

 

 

 

 

 

 

'PROJECT > SIDE PROJECT' 카테고리의 다른 글

Node.js 기본 서버 구축  (0) 2021.12.26
[React] Excel 다운로드 & 업로드  (0) 2021.06.20