최근 카카오 테크 캠퍼스 과제 때문에
질문 2. 리액트 Context 나 Redux는 언제 사용하면 좋을까요? (로그인을 제외한 예시와 이유를 함께 적어주세요.)
에 대해서 답을 한적이 있었다.
이 때문에 이전 포스트 글인 https://velog.io/@k_gu_wae123/contextapi
컨텍스트 API에 대해서 글을 작성하였었다.
하지만 피드백을 통해서
Context API에 다시 고민하게 되는 계기를 얻게 되었다.
나는 처음에 Context API가 상태관리 도구 중에 하나로 오해했었다. 왜냐하면
React에서는 Context API를 사용하기 위해서는 Context의 Provider와 Consumer를 사용해야한다. 이때 Context에 저장된 데이터를 사용하기 위해서는 공통 부모 컴포넌트에 Context의 Provider를 사용하여 데이터를 제공해야 되고, 데이터를 사용하려는 컴포넌트는 Context 의 Consumer를 사용해서 실제 데이터를 사용하게 되기 때문이다.
그래서 전역적으로 어떻게 보면 상태를 이어주기때문에 관리하는 도구라고 생각을 하였다.
https://ko.react.dev/learn/passing-data-deeply-with-context
보통의 경우 부모 컴포넌트에서 자식 컴포넌트로 props를 통해 정보를 전달합니다. 그러나 중간에 많은 컴포넌트를 거쳐야 하거나, 애플리케이션의 많은 컴포넌트에서 동일한 정보가 필요한 경우에는 props를 전달하는 것이 번거롭고 불편할 수 있습니다. Context를 사용하면 명시적으로 props를 전달해주지 않아도 부모 컴포넌트가 트리에 있는 어떤 자식 컴포넌트에서나 (얼마나 깊게 있든지 간에) 정보를 사용할 수 있습니다.
공식문서에 대한 내용을 보면 상태관리라는 말이 따로 언급되어 있지 않고, 부모 컴포넌트가 트리에 있는 자식 컴포넌트에 정보를 사용할 수 있다
라고 되어있다.
https://docs.pmnd.rs/zustand/getting-started/introduction
작고 빠르며 확장 가능한 베어본 상태 관리 솔루션입니다. Zustand는 Hook기반의 편안한 API를 가지고 있습니다. 틀에 박힌 형식이나 고집이 없지만, 명시적이고 플럭스 같은 규칙이 충분합니다.
귀여워서 무시하지 마세요. 발톱이 있거든요! zombie child problem, React concurrency, context loss between mixed renderers. 과 같은 일반적인 함정을 처리하는 데 많은 시간을 들였습니다 . React 공간에서 이 모든 것을 제대로 처리하는 유일한 상태 관리자일 수 있습니다.
zustand의 공식문서에 대한 내용을 보면 유일한 상태관리자
라는 언급이 따로 있다.
앞서 공식문서에서 바라봤던 대로 공식 문서내에서 정의 차이가 확실히 나는것을 알 수 있다.
그러면 Context API와 상태관리 라이브러리들의 정확한 차이가 무엇일까?
위의 이미지 처럼 결국 Context API는 전역적으로 뿌려주는 것처럼 보이지만 어떻게 보면 통로라고 생각하는게 더 빠를 것 같다.
Context 는 실제로 아무것도 관리하지 않는다. 단순 값을 전달하는 파이프와 같다. 사용하는 주요 목적은 props-drilling 을 피하는 것이다.
props-passing 로직을 작성할 필요가 없기 때문에 코드가 단순해진다.
개념적으로는 종속성 주입의 한 형태이다. 자식 구성 요소에 특정한 상태값이 필요하다는 것은 알고 있지만 값 자체를 생성하거나 설정하려 하지 않는다. 대신 상위 요소가 런타임에 해당 값을 전달한다고 가정한다.
우선적으로 zustand는 구독의 형태로 상태관리를 한다.
Context가 상태관리가 아닌 이유는
이 3가지의 경우에 아무것도 해당하지 않는다.
사실 이건 정답이 없다. 이 고민을 카테캠 라이브 강의를 통해 여쭤보기도 했다. 그렇지만 그 분도 정답은 없다고 했었다.
생각해보니까 이 과정을 예전에 지인한테 물어본 적이 있었던 것 같다.
상태관리를 zustand 이걸로 전체로만 관리를 하는게 맞을까? 아니면 굳이 전역적으로 관리할 필요가 없는 상태관리는 useState를 통해서 일반 React Hook을 섞어서 관리하는게 맞을까?
사실 그때의 결론은 zustand만 써서 관리하는게 맞겠다라고 생각했다. 왜냐하면 전역적으로 관리하게 되면 나중에 유지 보수하기도 쉽고 한눈에 코드를 알아보기 쉽기 때문이다.
하지만 이번 계기를 통해 Context API + Zustand 두 개를 이용하여 상태관리를 써볼 계획이다.
강사님께 이런 답변을 들었었다.
사실 정답은 없지만 Zustand에서 전역적으로 관리를 하는것도 좋지만 정말 전역적으로 관리해야되는 정보들을 제외하고는 Context API를 통해서 특정 UI에게 맞는 상태를 이어주는 것이 개발할 때 방향성을 잡기도 좋다고 봐요.
이 이야기를 들어보니 확실히 납득이 되어버렸다. 물론 전역적으로 관리를 하게 되면 코드적으로는 유지보수하기 매우 편할 수도 있지만 과연 Render Tree를 그리게 되었을 때 코드 방향적으로 유기적일까? 라는 생각이 들었다.
물론 전역적으로 관리해야되는 상태들 예를 들자면 다크모드, 로그인같이 전역적으로 상태관리해야되는 것들은 무조건 상태관리 라이브러리를 쓰는 것이 좋다. 왜냐하면 Context API에서는 아직 해결하지 못한 리렌더링 이슈도 있고 퍼포먼스를 고려했을 때 상태관리 라이브러리들이 좋다. 그러나 어떻게 보면 큰 창고에서 상태를 뽑아 쓰기 때문에 내가 지정해줘야 되기 때문에 Store라는 큰 상태관리만 두고 봤을때 특정 상태관리가 어떤 UI에 이용되는지 모르는 경우가 있다.
그래서 context API를 사용함으로써 특정 UI에서만 상태관리를 이어주는 것이 개발 방향성이 효율적이지 않을까 라는 생각이 든다. 재렌더링 이슈야 useMemo나 useCallback으로 막아주면 되지않을까?