본문 바로가기
프론트엔드

[react] recoil(state management)은 리액트 19부터 사용이 불가능하다.

by ISA(류) 2025. 3. 17.

예전에 기획해둔 작은 규모의 프로젝트를 미루다가 최근에 개발을 진행하면서 경험한점 + 프론트엔드 상태관리에 대한 짧막한 정리(이전에 정리한거보다 좀더 실사례를 들어서 구체적으로)으로 해볼까한다.

 

사실 내 성격상 이런 사소한 것들을 글로 쓰는게 의미 있냐?는 의문이 들긴하지만  잘 활성화된 개발 블로그들의 경우 보통 이런 내용들이 많은 유입을 끌어들이는 걸로 보이니 조금은 벤치마킹하는 것도 나쁘지 않을거같다.

 

React 19가 오면서 cra(create-react-app)부트스트랩이 지원종료 한건 소식을 들어서 알고 있었다. 사실 그전부터 별로 좋아하지도 않았던 (특유의 블랙박스, 무거움)부트스트랩이고 개인적으로 보일러플레이트를 만들어서 사용했는데

최근(?)에 접했던 번들러인 vite에 대한 경험이 나름 좋았던지라 기존 보일러 플레이트가 아닌 vite를 통해서 프로젝트를 부트스트랩하기로 결정했고. 그렇게 진행하다보니 자연스럽게 리액트 19로 프로젝트를 만들었다.

그러면서 개인적으로 가벼우면서 그 특유의 atom구조가 맘에 들어서 recoil를 상태관리로 선택했다.

 

평범하게 store를 만들고 React App과 연결 할 provider 그리고 그 state를 이리저리 처리할 hooks를 짠 후 컴포넌트에 연결해보니 오류가 발생했다.

Uncaught TypeError: Cannot destructure property 'ReactCurrentDispatcher' of 'import_react.default.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' as it is undefined.
    at currentRendererSupportsUseSyncExternalStore (index.js:505:5)
    at useRecoilValueLoadable (index.js:5353:26)
    at useRecoilValue (index.js:5372:20)
    at useRecoilState (index.js:5420:11)
    at useDaoxin (useDaoxin.tsx:10:25)
    at DaoXinGraph (index.tsx:22:19)
    at react-stack-bottom-frame (react-dom-client.development.js:22428:20)
    at renderWithHooks (react-dom-client.development.js:5757:22)
    at updateFunctionComponent (react-dom-client.development.js:8018:19)
    at beginWork (react-dom-client.development.js:9683:18)

에러 내용은 대충 아래와 비슷한 내용이였는데. 대충 리액트에서 recoil에서 쓰는 함수를 더 이상 지원하지 않는다는 에러였다.

 

개발을 진행하면서 형상관리가 중요한 이유인데. 사실 그전까지 멀쩡히 동작하던 프로그램이 recoil hook을 호출하자 말자 에러가 발생했고 + error log에 대놓고 뭐가 문제인지 써있으니 recoil 자체가 문제라는 사실은 바로 알 수 있었다.

먼저 해결방법으로 내가 모르는 좋은 방법이 있나 싶어서 gpt에게 에러로그를 긁어서 물어봤다.

 

도와줘요 gpt에몽.

물론 문제 해결에 도움은 되지 않았지만 해당 에러가 대충 어떤 상황에서 발생한다는 것과 그것을 확인하고 해결하는 방법을 친절히 알려주는 chatgpt가 너무 고마웠다.(free라서 free한가봐) 덕분에 소거법에 쓸 리소스를 절약했으니 좋았으!

 

혹시나 싶어서 버전은 확인해본결과 사실.. 방금 설치한거 답게 둘다 동일하게 react19를 의존하고 있더라.

이럴때는 어쩔 수 없이 갓 구글신님에게 문제를 물어보는 수 밖에..

위와 같이 보통 구글에 gpt에게 했던것 처럼 error로그나 또는 예상가는 키워드를 검색하면 스택오버플로우나 ㅎㅎ github 이슈에 해당 문제에 대한 issue가 나온다. 그럼 그를 통해서 문제를 파악하고 제시된 해결책이나 또는 자신에게 맞는 해결책을 도출해서 적용해보면 문제가 해결되는데. 아주 극소수의 경우에그렇지 않다면 issue를 만들고 오픈소스 컨트리뷰터가 되는 것이다. 나도 해보고 싶다.

 

이 문제의 경우 이미 issue가 기존에 등록 되어 있었다.

https://github.com/facebookexperimental/Recoil/issues/2318

 

React 19 support · Issue #2318 · facebookexperimental/Recoil

It appears recoil does not work with the react 19 RC that came out today. I'm guessing this will not be resolved, since Meta has abandoned this project, but I'd love to be wrong! TypeError: react__...

github.com

별다른 내용은 없다. 페이스북이 페이스북했다는 가벼운 결론.. 18까지는 잘써먹었으나 보내줘야한다는 슬픈 사실을 알려줄뿐

내가 recoil 프로젝트의 메인테이너가 되어서 개발을 진행 할만큼의 의리는 없는거 같으니 재빠르게 묻어주고 다른 상태관리 도구를 선택해야할 시간이 왔다.

 

크게 어려울건 없었다. 이미 대체제로 유망한 것은 많았으니 단지 취향에 좀 더 맞아서 recoil를 선택했을뿐...

심플하게 리덕스툴킷과 zustand, jotai중에서 각 장단점을 비교해보고 jotai로 결정했다.

 

큰 이유는 없고 리덕스툴킷은 무거워서, zustand는 리덕스향이 나는 구조, jotai가 atom이라는 recoil이 맘에 들었던 구조를 따르고 있어서다. 사실 뭐 소규모 개인 프로젝트에 무슨 큰 이유가 필요하겠는가..?

 

마이그레이션 순서는 간단했다.

  1. recoil를 삭제한다.
  2. jotai를 설치한다.
  3. store의 provider를 바꿔준다.
  4. state의 create function을 바꿔준다.
  5. hook의 use state function을 바꿔준다.

작디 작은 store

프로젝트에서 package.json 제외하고 store와 hooks에 있는 파일만 수정하면 되는 심플한 일. 사실 정상적으로 기본적인 설계만해도 큰 공수가 드는 작업은 아니다.

 

jotai는 개인적으로 selector가 없는게 아쉽더라.

 

결론을 내리자면 recoil은 2년전부터 유지보수가 중단되어서 react19 기점으로 지원 중단된 'ReactCurrentDispatcher' 라는 것을 의존하므로 업데이트 전까지 recoil을 사용이 불가능하다. 그리고 그럴 가망은 거의 없다.

recoil 같은 방식이 좋았던 사람이라면 jotai를 사용하자 쉽고 간편하다.

 

이제 상태관리에 대한 간단한 정리를 진행해보자. 이전에 내가 상태관리를 어케 정의내렸던가 자세히 기억은 안나지만(그냥 확인해보면 되는거아닌가?) ui 상태와 그외 상태쯤으로 정의 내렸던거 같다. 사실 뭐 크게 달라진건 없지만 프론트엔드가 기본적으로 uiux를 다루고 + 여러 도구나 여러 환경적인 요인이 생긴 현재에선 조금만 더 디테일하게 정의하는게 나을거같다.

 

1. props는 쓰라고 있는 기능이다. 불필요하게 컨텍스트나 global state를 사용하지말자. 애초에 컴포넌트 뎁스가 너무 깊다는건 dom의 깊이가 깊은 것과 같이 최적화 해야 할 잘못된 설계다.

2. 고정 된 데이터는 아니지만 자주 변하지 않으며 재사용성이 높으면 store를 쓰자.(특정 목록, 인증정보 등)

3. 고정 된 데이터도 아니고 자주 변하진 않지만 유니크한 경우 그냥 쿼리 류로 벡엔드에서 바로 기존 모놀리스식처럼 연결하자.(게시글,댓글등)

 

 

반응형