[라이브러리] 상태 관리 라이브러리

김하은·2024년 5월 24일
3

라이브러리

목록 보기
3/3

프론트엔드에서 상태 관리란?

상태(State)란?

State: A Component's Memory

사용자가 어플리케이션의 인풋창에 무언가를 입력하면 입력 필드가 업데이트 되고, 캐러셀에서 다음을 클릭하면 이미지가 변경되며, '구매'를 클릭하면 제품이 장바구니에 담겨야 합니다. 이처럼 컴포넌트는 사용자와 어플리케이션 간의 상호작용의 결과에 따라 화면을 변경해야 합니다. 따라서 컴포넌트는 현재 입력값, 현재 이미지, 장바구니 항목 같은 것들을 '기억'해야하는데 React에서는 이런 종류의 컴포넌트별 메모리를 state, 즉 상태라고 합니다.
리액트 공식 문서_State

상태 관리(State Management)란?

FE에서의 상태관리란 데이터를 설계된 UI, UX에 맞게 설계하고 구현하는 일입니다. 또한 네트워크를 통해 서버로 전달되는 클라이언트의 요청에 따라 변화하는 상태를 관리하는 일입니다.
블로그_[FE] 프론트엔드에서의 상태관리란 무엇인가? (1) 등장배경과 정의

상태 관리가 필요한 이유

  1. 상태(데이터)가 바뀌었을 때 페이지 전체가 아닌 해당 부분만 렌더링 시킬 수 있다.
  2. 의도하지 않은 UI/UX를 보여주지 않을 수 있다.
  3. 네트워크 통신 횟수를 획기적으로 줄일 수 있다.
    유튜브_[10분 테코톡] 패트릭의 상태관리

상태 관리를 하는 다양한 방법들

React 내장 상태 관리 도구

React 내장 상태 관리 도구 에는 useState, useReducer, Context가 있는데, useState와 Context의 특징과 한계점에 대해 알아보았다.

useState

useState는 가장 기본적인 상태 관리 훅으로 간단한 상태 변화를 다룰 때 사용됩니다. 컴포넌트 내부에서 사용자의 상호작용이나 데이터 변화에 따른 상태의 업데이트가 필요할 때 useState를 통해 이를 간편하게 처리할 수 있습니다.

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>현재 카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>증가</button>
      <button onClick={() => setCount(count - 1)}>감소</button>
    </div>
  );
}

리액트 상태 관리: useState, useContext, useReducer 활용하기

장점

  • DOM에 접근 없이도 데이터가 변경되면 값을 변경할 수 있음
  • DOM 중심의 상태관리 로직에서 데이터 중심의 상태관리 로직으로 변화함
    - 어디서 상태가 변경되었는지 추적에 유리함
    유튜브_[10분 테코톡] 온스타의 상태관리

한계점

  • state는 오직 자식 컴포넌트에게만 전달되기 때문에, 상태를 사용하는 컴포넌트 간 거리가 멀 경우 Props Drilling 현상이 발생할 수 있다.
    • 어디서 상태가 변경되었는지 추적이 어려워짐
    • 불필요한 렌더링이 발생할 수 있음
    • 이외에도 유지보수의 어려움, 컴포넌트 재사용성 저하, 리팩토링의 어려움 등의 문제가 있음

      리액트 공식 문서_Prop drilling

Context

컨텍스트를 활용하면, 부모 컴포넌트가 props를 통해 상태를 전달하지 않아도, 자식 컴포넌트의 깊이와 상관없이 특정 정보를 '전달'할 수 있다. 따라서 Props Drilling 문제를 해결하고, 전역 상태를 관리하는 데 유용하다.
Passing Data Deeply with Context


리액트 공식 문서_Using context in distant children

사실 Context는 상태 관리 도구는 아니며 그저 전역적으로 state를 공유하는 기능만 수행한다. 상태 관리는 사실상 useState, useReducer가 해준다.
[React] 상태 관리 라이브러리의 이해 - Redux 동작 원리

장점

  • Props Drilling 문제를 해결해 전역 상태 관리에 유용함
  • 추가적인 라이브러리 없이 리액트 자체에서 제공되는 기능임
    • 비교적 간편하게 사용할 수 있음
    • 라이브러리 다운로드로 인한 앱 용량 증가를 막을 수 있음

한계점

  • 불필요한 렌더링이 많음
    • context의 상태값이 달라지면 구독하고 있는 하위 컴포넌트가 모두 다시 렌더링 됨
    • 많은 하위 컴포넌트를 가지고 있거나, 렌더링 비용이 높은 컴포넌트들에게 문제가 될 수 있음
  • 복잡한 상태 로직이나 미들웨어를 필요로 하는 경우에는 한계가 있음

총평

  • 단순히 Props Drilling 해결이 목적이고 렌더링 최적화가 필요없는 경우에 적합함
  • 상태(state) 변경이 거의 일어나지 않으면서 전역 상태로 관리해야 하는 locale이나 theme정보 등을 관리할 때 적합함
  • 간단한 상태 관리가 필요한 소규모 프로젝트의 경우 적합함

전역 상태 관리 라이브러리

전역 상태 관리 라이브러리는 애플리케이션의 여러 상태를 효율적으로 관리하기 위한 도구이다. 애플리케이션의 상태를 전역적으로 관리할 수있는 것이 가장 큰 장점이며 라이브러리 마다 세부적인 특징은 다르다. 전역 상태 관리 라이브러리에는 Redux, MobX, Recoil, Zustand, Jotai, Valtio 등이 있다.

유튜브_프론트엔드 상태관리 실전 편 with React Query & Zustand

🧐전역 상태 관리 라이브러리가 해결하고자 하는 문제

  1. 저장된 상태를 컴포넌트 트리 어디에서든지 읽어 올 수 있는 기능 제공
  2. 저장된 상태를 수정하는 기능 제공
  3. 렌더링을 최적화하는 메커니즘 제공
  4. 메모리 사용을 최적화하는 메커니즘 제공
    Medium_[번역] 리액트 상태 관리의 새로운 흐름

Redux

A JS library for predictable and maintainable global state management
Redux 공식 문서

Redux는 리액트 애플리케이션에서 가장 널리 사용되는 상태 관리 라이브러리 중 하나다. Flux 아키텍쳐와 reducer의 개념을 합쳐서 만든 전역 상태 관리 라이브러리이다. 공식 문서에서는 애플리케이션의 복잡성을 낮춰서 작성한 코드가 어떤 결과를 가져올지 예측 가능하게 만들어주는 도구라고 소개하고 있다.
유튜브_Redux - 1. 수업소개


대표적인 특징은 다음과 같다.

  • 중앙 집중식 상태 관리: 애플리케이션의 모든 상태를 하나의 스토어에서 관리하여 일관성과 예측 가능성을 높인다.
  • 불변성: 상태는 불변 객체로 관리되며, 상태 변경은 순수 함수인 리듀서를 통해 이루어진다.
  • 액션과 디스패치: 상태 변경은 액션 객체를 디스패치하여 이루어지며, 액션은 상태 변경의 의도를 명확히 나타낸다.
  • 미들웨어: Redux Thunk나 Redux Saga와 같은 미들웨어를 사용하여 비동기 로직이나 부수 효과를 관리할 수 있다.
  • 디버깅 도구: Redux DevTools와 같은 강력한 디버깅 도구를 제공하여 상태 변화와 액션을 추적하고 디버깅을 용이하게 한다.
  • 렌더링 최적화: connect 함수와 useSelector 훅을 사용하여 필요한 상태가 변경될 때만 컴포넌트를 다시 렌더링하도록 최적화할 수 있어서, 불필요한 업데이트를 방지하여 성능을 향상시킨다.


직접 설치해본 결과 Redux 5.0.1 버전의 용량은 약 289.8 kB 였는데 실제로 애플리케이션에서 사용하는 경우, 필요한 미들웨어와 DevTools 등을 포함하면 이보다 약간 더 커질 수 있을 것 같다.

장점

  • 크고 복잡한 앱에서 확장성이 높음
  • 액션에 따른 모든 변경을 추적 가능
  • "특정 상태 조각이 언제 변경되었으며 데이터는 어디에서 왔는지" 동작을 예측 가능
  • Redux DevTools로 디버깅과 상태 변화의 추적을 용이하게 할 수 있음
  • 풍부한 Redux 관련 오픈소스 생태계
    velog_리덕스를 써야 할 때 & 리덕스의 장단점 (feat. 공식문서)

단점

  • 사용법이 상대적으로 복잡하며, 보일러플레이트 코드가 많음
  • Redux 자체뿐만 아니라 미들웨어, 바인딩 라이브러리 등 학습해야할 것이 많음

총평

Redux 공식 문서에 따르면 다음과 같은 경우에 사용하길 권장한다.

  • 앱의 여러 위치에서 필요한 상태의 양이 많을 때
  • 앱 상태가 자주 업데이트되는 경우
  • 상태를 업데이트 하는 로직이 복잡한 경우
  • 중간 또는 큰 규모의 코드베이스를 가지고 많은 사람들이 작업할 때
  • 시간이 지남에 따라 상태가 어떻게 업데이트되는지 확인해야 할 때
    Redux 공식 문서

Recoil

Redux와 같은 기존의 전역 상태 관리 도구는 리액트 라이브러리가 아니어서 리액트 내부 스케줄러에 접근할 수 없다는 단점이 있었다. 이런 단점은 리액트에 동시성 모드(Concurrent mode)와 같은 새로운 기능이 도입되었을 때 이 기능들이 최적으로 작동하지 못하는 문제를 야기했다. Recoil은 이런 문제를 해결하기 위해 만들어 졌고, 2020년 페이스북 팀의 한 엔지니어가 실험 단계로 컨퍼런스에서 공개하면서 세상에 알려지게 되었다.

간단히 말해, Recoil은 기존 상태 관리 도구들이 가지고 있던 한계를 극복하고, 리액트 애플리케이션의 성능과 개발 효율성을 높이기 위한 목적으로 개발되었다. 즉, 리액트의 최신 기능들, 특히 동시성 모드와 같은 고급 기능을 지원하기 위해 만들어진 상태 관리 라이브러리이다.


Atomos — A New Recoil Visualization Tool Powered by React Flow

리코일의 주요 특징은 다음과 같다.

  • 리액트 문법 친화적이다. 리액트의 상태처럼 간단한 get/set 인터페이스로 사용할 수 있는 보일러 플레이트가 없는 API를 제공한다.
  • 비동기 처리를 추가적인 라이브러리 없이(e.g. redux-thunk, redux-saga) 리코일 안에서 가능하다.
  • 내부적으로 캐싱을 지원한다. 동일한 atom 값에 대한 내부적으로 메모이제이션된 값을 반환하여 속도가 빠르다.

직접 설치해본 결과 Recoil7.7 버전의 용량은 약 2.2 MB였다.

장점

  • 낮은 러닝 커브와 적은 코드량
  • 간편한 비동기 처리
  • 랜더링 최적화

한계점

  • 안정성
    • 레포지토리가 facebook/Recoil이 아닌 facebookexperimental/Recoil임
  • 관련 오픈소스 생태계가 redux에 비해서 부족함
  • 아톰이 여러 군데에서 사용되면 사이드 이펙트가 발생할 수 있음
    • 전역 상태를 아톰으로 관리하고 어느 컴포넌트에서도 바로 아톰을 구독해서 업데이트를 받을 수 있기 때문
  • 아톰과 셀렉터가 많아지면 의존성이 여러 방향으로 엮이면서 점점 어떤 의존이 이루어지는지 파악하기 어려워짐
    • 컴포넌트를 컨테이너/프레젠테이션 방식으로 나누어 상태를 관리하는 부분/보여주기만 별도로 가져가는 방법을 이용하면 이런 이슈를 컨트롤할 수 있음

유튜브_[10분 테코톡] 패트릭의 상태관리
리액트 상태 관리 라이브러리, 어떤 것을 써야 할까?

zustand

주스탠드(zustand)는 독일어로 ‘상태’라는 뜻을 가졌고, 조타이(Jotai)를 만든 카토 다이시가 주스탠드도 만들어 관리하고 있다. 데이터를 중앙 집중형 스토어에 저장하고 Action을 통해 데이터를 조작하는 패턴인 Flux 패턴을 따르는데, 이런 점은 Redux와 비슷한다. 주스탠드는 특정 라이브러리에 종속되어 만들어진 도구는 아니므로 바닐라 자바스크립트에서도 사용이 가능하다.

zustand의 주요 특징은 다음과 같다.

  • 주스탠드는 발행/구독 모델(pub/sub)을 기반으로 이루어져 있다.
    • 스토어의 상태 변경이 일어날 때 실행할 리스너 함수를 모아 두었다가(sub), 상태가 변경되었을 때 등록된 리스너에게 상태가 변경되었다고 알려준다(pub).
  • 스토어를 생성하는 함수 호출 시 클로저를 사용한다.
    • 이로 인한 특징으로 상태를 변경, 조회, 구독하는 인터페이스를 통해서만 상태를 다루고, 실제 상태는 생명 주기에 따라 처음부터 끝까지 의도하지 않는 변경에 대해 막을 수 있다는 점이 있다.
  • 상태를 위에서 내리는 방식은 top-down 방식으로 상태를 관리한다.
    • 전체적인 오버뷰에서 디테일 세부사항으로 스토어 모델링을 하는 것이 좋다.
    • 예를 들어, 블로그를 위한 스토어를 만든다고 하면 블로그 > 포스트 > 작가, 제목, 내용 이런 식으로 말이다.

리액트 상태 관리 라이브러리, 어떤 것을 써야 할까?

직접 설치해본 결과 zustand4.5.2 버전의 용량은 326.9kB 였다.

장점

  • 낮은 러닝 커브와 적은 코드량
  • 랜더링 최적화
  • Redux DevTools로 디버깅과 상태 변화의 추적을 용이하게 할 수 있음
  • 아톰을 바꿔주는 로직을 컴포넌트나 커스텀 훅이 아닌 스토어에서 바로 할 수 있음
  • 다양한 미들웨어 지원
  • 일시적 업데이트(Transient Update)를 이용해서 상태가 자주 바뀌더라도 매번 업데이트가 일어나지 않고 리렌더링을 제어할 수 있음

단점

  • 성능이 중요한 앱에서 탑다운 방식은 적합하지 않음
  • 비교적 생긴지 얼마 되지 않은 도구이기 때문에, IDE 등에서 쓸 수 있는 익스텐션, 플러그인, 스니펫 등이 많이 없음

Jotai

조타이(Jotai)는 아토믹 접근(Atomic Approach)을 가지고 만든 리액트 상태 관리 도구다. 이런 점은 Recoil과 비슷하다. 조타이의 가장 기본적인 단위는 아톰(Atom)이다. 원시 타입과 객체 타입을 담을 수 있고, 다른 아톰에서 값을 가져와서 만드는 것도 가능하다.

상태를 밑에서 부터 조립해서 위로 올리는 방식인 bottion-up 방식을 사용한다. 처음에 아톰을 정의하고, 그것을 차곡차곡 큰 조각의 상태들로 만들어 나간다. 이러한 바텀업 방식은 성능이 중요한 앱에서 많이 사용된다.

리액트 상태 관리 라이브러리, 어떤 것을 써야 할까?


직접 설치해본 결과 Jotai2.8.1 버전의 용량은 528.4kB 였다.

장점

  • 낮은 러닝 커브
  • 리렌더링을 줄여주는 selectAtom이나 splitAtom과 같은 유틸에 대한 지원이 많음
  • 바텀업 방식은 성능이 중요한 앱에서 많이 사용됨

단점

  • 아직 다른 경쟁 도구들에 비해 사용자 수가 많지 않고, 레퍼런스가 부족함

표로 비교해 보기

7 Best React State Management Libraries for Any Project Size

[번역] 리액트 상태 관리의 새로운 흐름

서버 상태 관리 라이브러리

클라이언트 애플리케이션에서 서버에서 가져온 테이터를 효율적으로 관리하고 동기화하는 데 중점을 둔다. TanStack Query(구 React Query), Apollo Client, SWR 등이 있다.


결론

다른 사람들은 어떤 라이브러리를 사용할까?


현업에서 Redux가 4년 정도 자리를 잡고 있었고, 기존에 있는 것들을 함부로 바꾸기는 어렵기 때문에 현재도 압도적인 1위를 차지하고 있는 것으로 보인다. 하지만 러닝 커브가 높고 많은 세팅을 필요로하기 때문에 신사업이나 새로 하는 프로젝트에서는 많이 쓰고 있지 않다고 한다.
유튜브_프론트엔드 개발자가 React 상태관리 선택이 중요한 이유ㅣ유니콘 기업 현직자

우리 프로젝트에는 어떤 방법을 써야할까?

  1. 지금 내가 해결하려는 문제를 구체적으로 먼저 정의 (무엇을 해결하려고 하는가?)
  2. 이 문제를 해결하기 위해 더 잘 해결할 수 있는 도구가 있는지 생각하기

참고 자료

profile
아이디어와 구현을 좋아합니다!

0개의 댓글