리액트와 상태 관리 라이브러리 (2)

리액트와 상태 관리 라이브러리 (2)

모던 리액트 Deep Dive: 리액트의 핵심 개념과 동작 원리부터 Next.js까지, 리액트의 모든 것 - 05장 리액트와 상태 관리 라이브러리 (2)

2. 리액트 훅으로 시작하는 상태 관리

useState와 Context를 동시에 사용해 보기

  • Context 생성: createContext 함수를 사용하여 컨텍스트를 생성한다. 이는 데이터를 전역으로 공유할 수 있는 컨테이너 역할을 한다.

  • Provider 제공: 생성한 컨텍스트를 Provider로 감싸 하위 컴포넌트에 전달한다. 이렇게 하면 모든 하위 컴포넌트에서 해당 컨텍스트에 접근할 수 있다.

  • useState로 상태 관리: 각 컴포넌트 내에서 useState를 사용하여 필요한 상태 값을 관리한다.

  • useContext로 컨텍스트 값 가져오기: 컨텍스트를 사용하는 컴포넌트에서 useContext 훅을 사용하여 컨텍스트 값을 가져온다.

import React, { useState, createContext, useContext } from 'react';

// 1. createContext 함수를 사용하여 컨텍스트를 생성합니다.
const MyContext = createContext();

// 2. Provider로 컨텍스트를 감싸 하위 컴포넌트에 전달합니다.
function App() {
  const [count, setCount] = useState(0);

  return (
    <MyContext.Provider value=8>
      <ChildComponent />
    </MyContext.Provider>
  );
}

// 3. useContext 훅을 사용하여 컨텍스트 값을 가져옵니다.
function ChildComponent() {
  const { count, setCount } = useContext(MyContext);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default App;

상태 관리 라이브러리 Recoil, Jotai, Zustand 살펴보기

  • RecoilJotaiContextProvider, 그리고 훅을 기반으로 가능한 작은 상태를 효율적으로 관리하는 데 초점을 맞추고 있다.

  • Zustand는 리덕스와 비슷하게 하나의 큰 스토어를 기반으로 상태를 관리하는 라이브러리다.

    • 하나의 큰 스토어는 Context가 아니라 스토어가 가지고 있는 클로저를 기반으로 생성되며, 이 스토어의 상태를 변경되면 이 상태를 구독하고 있는 컴포넌트에 전파애 리렌더링을 알리는 방식이다.

페이스북이 만든 상태 라이브러리 Recoil

Recoil은 리액트를 만든 페이스북에서 만든 리액트를 위한 상태 관리 라이브러리다.

RecoilRoot

Recoil을 사용하기 위해서는 RecoilRoot를 애플리케이션의 최상단에 선언해 둬야 한다.

  • RecoilRoot에서 Recoil에서 생성되는 상태값을 저장하기 위한 스토어를 생성하는 것을 확인할 수 있다.

RecoilRoot의 구조를 대략 다음과 같다.

  • Recoil의 상태값은 RecoilRoot로 생성된 Context의 스토어에 저장된다.
  • 스토어의 상태값에 접근할 수 있는 함수들이 있으며, 이 함수를 활용해 상태값을 접근하거나 상태값을 변경할 수 있다.
  • 값의 변경이 발생하면 이를 참조하고 있는 함수 컴포넌트에 모두 알린다.

atom

atom은 상태를 나타내는 Recoil의 최소 상태 단위다.

atomkey값을 필수로 가지며, 이 키는 다른 atom과 구별하는 식별자가 되는 필수 값이다.

  • 이 키는 애플리케이션 내부에서 유일한 값이어야 하기 때문에 atomselector를 만들 때 반드시 주의를 기울여야 한다.

defaultatom의 초깃값을 의미한다.

  • atom의 값을 컴포넌트에서 읽어오고 이 값의 변화에 따라 컴포넌트를 리렌더링하려면 다음 두 가지 훅을 사용하면 된다.

useRecoilValue

useRecoilValueatom의 값을 읽어오는 훅이다.

useRecoilState

useRecoilState는 좀 더 useState와 유사하게 값을 가져오고, 또 이 값을 변경할 수도 있는 훅이다.

현재 값을 가져오기 위해 이전에 작성한 훅인 useRecoilValue를 그대로 사용하고 있으며, 상태를 설정하는 훅으로 useSetRecoilState 훅을 사용하고 있다.

  • 이 훅은 내부에서 먼저 스토어를 가져온 다음에 setRecoilValue를 호출해 값을 업데이트하고 있다.

특징

  • 장점
    • 페이스북 팀에서 주도적으로 개발하고 있기 때문에 앞으로도 기대가 되는 라이브러리
    • selector를 필두로 다양한 비동기 작업을 지원하는 API를 제공하고 있기 때문에 비동기 작업을 수월하게 처리할 수 있다.
    • 리액트와 비슷하게 자체적인 개발도구를 지원한다.
  • 단점
    • 주 버전과 다르게 부 버전이 변경돼도 호환성이 깨지는 변경 사항이 발생할 수 있는 초기 버전으로 간주되어 라이브러리를 사용할 때에 추가적인 주의가 필요하다.

Recoil에서 영감을 받은, 그러나 조금 더 유연한 Jotai

JotaiRecoilatom 모델에 영감을 받아 만들어진 상태 관리 라이브러리다.

  • Jotil는 상향식(bottom-up) 접근법을 취하고 있다.
    • 작은 단위의 상태를 위로 전파할 수 있는 구조를 취하고 있음을 의미
  • Context의 문제점인 불필요한 리렌더링이 일어난다는 문제를 해결하고자 설계돼 있으며, 추가적으로 개발자들이 메모이제이션이나 최적화를 거치지 않아도 리렌더링이 발생되지 않도록 설계돼 있다.

atom

atom은 최소 단위의 상태를 의미한다.

  • atom 하나만으로도 상태를 만들 수도, 또 이에 파생된 상태를 만들 수도 있다.
const counterAtom = atom(0)

Jotaiatom을 생성할 때 별도의 key를 넘겨주지 않아도 된다.

  • atom 내부에는 key라는 변수가 존재하긴 하지만 외부에서 받는 값은 아니며 단순히 toString()을 위한용도로 한정돼 있다.

Jotai에서의 atom에 따라 상태를 저장하고 있지 않다.

useAtomValue

atom의 값이 어디서 변경되더라도 useAtomValue로 값을 사용하는 쪽에서는 언제든 최산 값의 atom을 사용해 렌더링할 수 있게 된다.

useAtom

useAtomuseState와 동일한 형태의 배열을 반환한다.

  1. atom의 현재 값을 나타내는 useAtomValue 훅의 결과를 반환한다.
  2. useSetAtom 훅을 반환하는데, 이 훅은 atom을 수정할 수 있는 기증을 제공한다.

특징

Recoilatom 개념을 도입하면서 API가 간결하다.

  • 객체의 참조를 통해 별도의 문자열 키가 없이 각 값들을 관리한다.
  • selector가 없이도 atom만으로 atom 값에서 또 다른 파생된 상태를 만들 수 있다.
  • 타입스크립트로 작성돼 있어 타입을 잘 지원한다.
  • 리액트 18의 변경된 API를 원할하게 지원한다.

작고 빠르며 확장에도 유연한 Zustand

Zustand는 리덕스에 영감을 받아 만들어졌다.

Zustand에서는 하나의 하나의 스토어를 중앙 집중형으로 활용해 이 스토어 내부에서 상태를 관리하고 있다.

import { create } from "zustand";

const useCounterStore = create((set) => ({
  count: 1,
  inc: () => set((state) => ({ count: state.count + 1 })),
  dec: () => set((state) => ({ count: state.count - 1 })),
}));

function Counter(){
  const { count, inc, dec } = useCounterStore()

  return (
   <div>
    <span>{count}</span>
    <button onClick={inc}>+</button>
    <button onClick={dec}>-</button>
   </div>
  )
}

특징

  • Zustand는 많은 코드를 작성하지 않아도 빠르게 스토어를 사용할 수 있다는 큰 장점이 있다.
  • 타입스크립트 기반으로 작성돼 있기 때문에 별도의 @types를 설치하거나 임의로 작성된 d.ts에 대한 우려 없이 타입스크립트를 자연스럽게 쓸 수 있다.
  • Zutand는 리덕스와 마찬가지로 미들웨어를 지원한다.

© 2021. All rights reserved.

Powered by Hydejack v9.1.6