서론
회원가입 시 약관 동의, 사용자 유저 정보 등에 관한 state 값을 관리해야 하는 상황이 있다.
[ 관리해야 할 상태 값들 ]
- 약관 동의
- 전체 동의 여부
- 이용 약관 동의 여부
- 개인정보 수집 및 이용 동의 여부
- 마케팅 수신 정보 동의 여부
- 사용자 유저 정보
- 휴대폰 본인인증 여부
- 사용자 정보 값
- 사용자 이름 값
- 사용자 생년 값
- 사용자 생월 값
- 사용자 생일 값
- 사용자 휴대폰 번호 값
- 사용자 아이디 값
- 사용자 닉네임 값
- 사용자 비밀번호 값
- 사용자 비밀번호 확인 값
- 사용자 사업자 여부 값
- 사용자 휴대폰 번호(거래용) 값
- 사용자 전화번호 값
- 사용자 이메일 값
- 사용자 도·시 값
- 사용자 시·군·구 값
- 사용자 상세주소 값
- 사용자 회사명 값
- 사용자 직급/직책 값
- 사용자 주요 사업 분야 값
- 사용자 정보 값 유효 여부
- 사용자 이름 값 유효 여부
- 사용자 생년 값 유효 여부
- 사용자 생월 값 유효 여부
- 사용자 생일 값 유효 여부
- 사용자 휴대폰 번호 값 유효 여부
- 사용자 아이디 값 유효 여부
- 사용자 닉네임 값 유효 여부
- 사용자 비밀번호 값 유효 여부
- 사용자 비밀번호 확인 값 유효 여부
- 사용자 사업자 여부 값 유효 여부
- 사용자 휴대폰 번호(거래용) 값 유효 여부
- 사용자 전화번호 값 유효 여부
- 사용자 이메일 값 유효 여부
- 사용자 도·시 값 유효 여부
- 사용자 시·군·구 값 유효 여부
- 사용자 상세주소 값 유효 여부
- 사용자 회사명 값 유효 여부
- 사용자 직급/직책 값 유효 여부
- 사용자 주요 사업 분야 값 유효 여부
현재 구현하고 있는 서비스의 회원 정보가 다른 서비스에 비해 많은 점도 있지만,
회원가입 로직을 구현하기 위해 최소한 필요한 정보들만 사용한다고 해도 관리해야 할 상태 값들이 5~6개가 넘어갈 것이다.
(여기에 실시간으로 '올바른 비밀번호가 아닙니다. 대소영문자, 숫자, 특수기호를 조합하여 12자 이상 작성해주세요' 와 같은 에러 메세지 상태값도 관리하게 된다면 더 많아질 것이다...)
한 컴포넌트에서 이런 로직을 처리하려면 코드 줄 수가 길어질 뿐만 아니라, 재사용성도 매우 떨어지게 된다.
게다가 현재 모바일 / PC 각각 다른 컴포넌트를 출력해야 하기 때문에, 현재 상황에서 컴포넌트 분리는 필수적이라고 할 수 있다.
이럴 때 이 모든 state 값을 props 로 보내게 된다면... 상상만 해도 코드 가독성이 떨어질 것 같지 않은가?
이런 많은 props를 어떻게 관리하면 좋을까, 고민을 하던 도중, 나의 상황에서 Context와 Recoil 상태 관리 도구를 살펴보기로 했다.
(후보에 Redux가 없는 이유는, 코드를 최소한으로 짜더라도 보일러 플레이트가 많기 때문에 Redux를 걷어내고 Recoil로 마이그레이션하는 경우가 많다. 따라서 Redux 대신 Recoil만 후보에 넣었다.)
Context
Context 공식 사이트
https://ko.reactjs.org/docs/context.html
언제 Context를 써야 할까?
공식 문서에서는 아래와 같은 상황에서 Context를 쓰는 것이 적합하다고 명시하고 있다.
" context는 React 컴포넌트 트리 안에서 전역적(global)이라고 볼 수 있는 데이터를 공유할 수 있도록 고안된 방법입니다.
그러한 데이터로는 현재 로그인한 유저, 테마, 선호하는 언어 등이 있습니다. "
나의 경우에는 특정 트리에서 전역적으로 상태를 관리할 필요가 있기 때문에 사용할 이유는 충분하다.
Context 단점
하지만 이러한 Context에는 단점이 존재한다. 공식 문서에서는 아래와 같은 Context의 단점을 조심하라고 명시하고 있다.
" context를 사용하면 컴포넌트를 재사용하기가 어려워지므로 꼭 필요할 때만 쓰세요.
여러 레벨에 걸쳐 props 넘기는 걸 대체하는 데에 context보다 컴포넌트 합성이 더 간단한 해결책일 수도 있습니다.
하지만 이러한 역전이 항상 옳은 것은 아닙니다. 복잡한 로직을 상위로 옮기면 이 상위 컴포넌트들은 더 난해해지기 마련이고 하위 컴포넌트들은 필요 이상으로 유연해져야 합니다. "
또 다른 단점들도 있다.
- 컴포넌트의 상태는 공통된 상위요소까지 끌어올려야만 공유될 수 있으며, 이 과정에서 거대한 트리가 다시 렌더링되는 효과를 야기하기도 한다.
= Context 로 관리하는 state값이 변경될 때마다 Context의 모든 자식 요소들은 재렌더링이 된다. (모든 자식 요소가 재덴더링이 되는 것을 원치 않는다면 memoization 필수) - Context는 단일 값만 저장할 수 있으며, 자체 소비자(consumer)를 가지는 여러 값들의 집합을 담을 수는 없다.
- 이 두 가지 특성이 트리의 최상단(state가 존재하는 곳)부터 트리의 말단(state가 사용되는 곳)까지의 코드 분할을 어렵게 한다.
Context 를 사용했을 때 내가 원하는 기능을 동작하게 할 순 있지만... 단점이 너무 찝찝하지 않은가?
더 좋은 상태 관리 도구가 있다면 Context 대신 사용할 수 있을 거라고 생각했다.
이제 Recoil 을 살펴보자.
Recoil
Recoil 공식 사이트
https://recoiljs.org/ko/docs/introduction/getting-started
언제 Recoil을 써야 할까?
Context 와 같이 전역 상태 관리를 하기 위해 사용할 수 있다.
Context와의 차이점
Context와 Recoil이 어떤 점이 다른지 공식 문서에서 다음과 같이 설명하고 있다.
- 공유상태(shared state)도 React의 내부상태(local state)처럼 간단한 get/set 인터페이스로 사용할 수 있도록 boilerplate-free API를 제공한다. (필요한 경우 reducers 등으로 캡슐화할 수도 있다.)
- 우리는 동시성 모드(Concurrent Mode)를 비롯한 다른 새로운 React의 기능들과의 호환 가능성도 갖는다.
- 상태 정의는 점진적이고(incremental) 분산되어 있기 때문에, 코드 분할이 가능하다.
- 상태를 사용하는 컴포넌트를 수정하지 않고도 상태를 파생된 데이터로 대체할 수 있다.
- 파생된 데이터를 사용하는 컴포넌트를 수정하지 않고도 파생된 데이터는 동기식과 비동기식 간에 이동할 수 있다.
- 우리는 탐색을 일급 개념으로 취급할 수 있고 심지어 링크에서 상태 전환을 인코딩할 수도 있다.
- 전체 애플리케이션 상태를 하위 호환되는 방식으로 유지하기가 쉬우므로, 유지된 상태는 애플리케이션 변경에도 살아남을 수 있다.
Recoil은 Context의 단점을 보완해주는 기능들을 갖고 있는 것을 볼 수 있다.
Recoil 단점
- 개발자 도구가 완벽하지 않다. 디버깅 및 스냅샷 테스트를 하는데 있어 신뢰성이 부족하다.
- 모든 API들이 높은 신뢰성을 보장하지 않는다. useGetRecoilValue, useRecoilRefresher 등은 공식문서도 UNSTABLE로 분류.
위와 같은 단점이 생길 수 있다.
아직 해결되지 않은 이슈들은 아래에서 확인할 수 있다.
Recoil github issue
https://github.com/facebookexperimental/Recoil/issues
Context vs Recoil 결과는?
위의 모든 상황을 고려했을 때, Recoil을 사용하기로 결정하였다.
Context 의 단점을 보완해주는 장점과, 아직 신뢰도가 떨어진다는 단점을 비교했을 때 충분히 단점을 이길 수 있다는 생각이 들었고, Recoil은 아직 개발 단계이지만 그만큼 많은 개발자들이 관심을 갖고 개발을 진행하고 있기 때문에 미래를 위해 충분히 투자할 가치가 있다고 생각한다.
결론
Recoil 승!
'React' 카테고리의 다른 글
[ React ] 정적 파일을 public 폴더에 관리하기 vs src 폴더에 관리하기 (0) | 2023.03.27 |
---|---|
[ React + TypeScript + Vite ] public 경로 단순하게 설정하는 방법 (0) | 2023.03.27 |
[React Vite] CRA에서 Vite로 마이그레이션(migration) 하기 (0) | 2023.01.31 |
[React Vite] React Vite TypeScript 환경에서 SPA 프로젝트 세팅하기 (0) | 2023.01.27 |
[React] 렌더링 최적화 (1) | 2023.01.26 |
Comment