이 글은 useSyncExternalStore
를 이미 알고 있다는 가정 하에 작성되었습니다.
처음 들어보셨다면 공식문서를 읽고 오시는 것을 추천합니다.
1. useGlobalState
를 만들었다.
공식문서에서는 useSyncExternalStore
를 이렇게 정의한다.
useSyncExternalStore is a React Hook that lets you subscribe to an external store.
useSyncExternalStore 는 외부 store를 구독할 수 있는 React 훅입니다.
옵저버 패턴을 이용하는 이 훅을 이용해 외부 store에 데이터를 저장하고, 리액트 컴포넌트가 store를 구독하게하여
store가 바뀔 때 마다 컴포넌트를 리렌더링하는 기능을 만들 수 있다.
따라서 전역상태관리를 할 수 있다고 생각했고, 실제로 많은 사람들이 그렇게 사용하는 걸 봤다.
그래서 나도 팀원들이 익숙한 useState
, recoil
과 사용법이 유사한 전역상태관리 훅 useGlobalState
를 만들었다.
사용 흐름은 다음과 같다.
- Component에서
GlobalState
를 이용해useGlobalState
를 호출한다. useGlobalState
은 내부적으로GlobalState
에게 자신을 호출한 Component의 re-render 함수를 넘겨준다.- Component 는
useGlobalState
에게 받은setState
를 호출하여GlobalState
를 변경한다. GlobalState
는 state를 변경하며 동시에 내부적으로emitChange
를 호출하여 자신을 구독중인 Component들을 re-render한다.
밑에서 직접 테스트 해볼 수 있습니다.
사용흐름을 코드에 주석으로 달아놓았습니다😎
2. 라이브러리 배포
간단한 전역상태관리 훅이지만 npm에 배포해보았다.
typescript를 지원하고, react18 버전에서만 사용할 수 있다.
yarn add @yogjin/react-global-state-hook
3. 학습계기
동글 프로젝트(글을 관리하고 블로그에 포스팅할 수 있는 서비스)를 진행하면서 전역상태가 필요한 부분이 있었다.
동글은 오른쪽 사이드바 부분에서 글의 정보를 확인하고 블로그에 발행할 수 있다.
그런데 휴지통에 있는 글은 블로그에 발행하는 버튼이 없어야하고, 글의 정보만 확인할 수 있어야했다.
이를 구현하기 위해 글 컴포넌트에서 현재 보고있는 글의 성격에 따라 isDeleted
상태를 set하고 사이드바에서는 isDeleted 상태를 이용해 조건부 렌더링을 해야했다.
기존 useState를 이용하면 props drilling 문제가 있었다.
사이드바는 글 컴포넌트에 종속적이지 않았기 때문에, 글과 사이드바의 공통 최상위 컴포넌트에서 현재 보고있는 글의 정보(activeWritingInfo
)를 넘겨줘야했기 때문이다.
대신 react-router-dom에서 제공하는 useOutletContext 를 활용해서 Outlet
에 간단하게 activeWritingInfo
context를 넘겨주어서 해결했었다.
Outlet
을 감싸는 context API를 따로 만들 필요가 없었고 간편해서 꽤 만족스러웠다.
위 코드에서 아쉬운 점은 딱 2가지 정도였다.
- state의 setter를 그대로 넘겨주고 있음 -> reducer를 이용해 개선가능
- 처음 저 코드를 본다면 익숙하지 않음 (실제로 리뷰가 달렸었다)
위 경우에는 제공하는 훅을 이용했기 때문에 깔끔했지만,
전역 상태를 만들 때 Context API를 이용하면 상태가 많아질 수록 감싸줘야하는 Context Provider가 많아진다는 게 살짝 아쉬웠다.
(감싸고 있는 내부 컴포넌트들에서만 context를 이용한다는 걸 선언적으로 알 수 있어서 좋은 점은 나도 강력히 동의한다)
또한 recoil를 이용해도 됐지만, 단순한 전역상태를 관리하기 위해 큰 라이브러리를 설치한다는 점이 약간 불편했다.
주저리주저리 말이 많았지만, 한 마디로
"Context API와 reducer를 이용한 상태관리 대신 새로운 시도를 해보고 싶었다" 로 정리가능하다😁
4. 마치며
공식문서에도 나와있듯이 React 상태관리는 기존 usestate
나 useReducer
를 이용하는걸 권장한다.
즉 useSyncExternalStore
는 리액트의 전역상태관리를 위해 사용하라고 나온 훅은 아니다.
하지만 훅 특성상 충분히 전역상태관리로도 이용할 수 있다고 생각한다.
상태관리를 지원하는 다른 라이브러리들도 useSyncExternalStore
를 이용하고 있기도 하다.
직접 간단한 전역상태 라이브러리를 구현하면서 배운 점은 다음과 같다.
- 리액트의
useState
타입선언 tanstack-query
의 동작방식- 옵저버 패턴
'우아한테크코스 5기 프론트엔드' 카테고리의 다른 글
[프로젝트 동글] 근거있는 Typescript 컨벤션 (0) | 2023.08.28 |
---|---|
jest + react-testing-library 테스트 코드 작성 및 github actions로 자동화 하기 (0) | 2023.08.27 |
[우아한테크코스 프로젝트 기록] 3차 데모데이 ~ 론칭 페스티벌 (5) | 2023.08.22 |
[우아한테크코스 프로젝트 기록] 2차 데모데이 ~ 3차 데모데이 (1) | 2023.08.05 |
[우아한테크코스 프로젝트 기록] 1차 데모데이 ~ 2차 데모데이 (2) | 2023.07.23 |