JotaiJotai

상태
React를 위한 기본적이고 유연한 상태 관리

Comparison

Jotai는 React에서 불필요한 리렌더링 문제를 해결하기 위해 탄생했습니다.
불필요한 리렌더링은 렌더링 과정에서 동일한 UI 결과를 생성할 때 발생하며, 사용자는 아무런 차이를 느끼지 못합니다.

이 문제를 React 컨텍스트(useContext + useState)로 해결하려면 많은 컨텍스트가 필요하고 몇 가지 문제에 직면하게 됩니다.

  • Provider 지옥: 루트 컴포넌트에 많은 컨텍스트 프로바이더가 존재할 가능성이 높습니다. 이는 기술적으로 문제가 없고, 때로는 서로 다른 하위 트리에 컨텍스트를 제공하기 위해 바람직할 수도 있습니다.
  • 동적 추가/삭제: 런타임에 새로운 컨텍스트를 추가하는 것은 깔끔하지 않습니다. 새로운 프로바이더를 추가해야 하고, 그 자식 컴포넌트들이 다시 마운트되기 때문입니다.

전통적으로 이 문제를 해결하기 위한 상향식 접근법은 선택자 함수를 사용하는 것입니다.
use-context-selector 라이브러리가 그 예시입니다.
이 접근법의 문제점은 선택자 함수가 리렌더링을 방지하기 위해 참조적으로 동일한 값을 반환해야 하며, 이는 종종 메모이제이션 기법을 필요로 한다는 것입니다.

Jotai는 Recoil에서 영감을 받아 아톰 모델을 기반으로 하향식 접근법을 채택했습니다.
아톰을 조합하여 상태를 구축하고, 아톰 의존성을 기반으로 렌더링을 최적화할 수 있습니다.
이를 통해 메모이제이션의 필요성을 피할 수 있습니다.

Jotai는 두 가지 원칙을 가지고 있습니다.

  • 기본적: 기본 API는 useState처럼 단순합니다.
  • 유연함: 아톰은 다른 아톰을 파생시킬 수 있고 그래프를 형성할 수 있습니다. 또한 임의의 아톰에 의해 업데이트될 수도 있습니다. 이를 통해 복잡한 상태 모델을 추상화할 수 있습니다.

Jotai는 React의 useContext와 어떻게 다른가요?

Jotai의 핵심 API는 매우 간결하며, 이를 기반으로 유틸리티를 쉽게 구축할 수 있습니다.

비유

Jotai를 useContext의 대체재로 생각할 수 있습니다. 다만 Jotai는 단순성과 최소한의 API를 지향하며, useContextuseState보다 훨씬 더 많은 기능을 제공합니다.

사용 방식 차이

이전에 자식 컴포넌트에 데이터를 공유하던 방식과 Jotai를 사용하는 방식을 비교해 보겠습니다. 이번에는 앱 내에서 여러 Context를 사용하는 실제 예제를 살펴보겠습니다.

// 1. useState를 사용한 로컬 상태
const Component = () => {
const [state, setState] = useState(0)
}
// 2. 로컬 상태를 끌어올려 Context로 공유
const StateContext = createContext()
const Parent = ({ children }) => {
return (
<StateContext.Provider value={useState(0)}>
{children}
</StateContext.Provider>
)
}
const Component = () => {
const [state, setState] = useContext(StateContext)
}
// 3. 여러 상태와 Context 사용
const State1Context = createContext()
const State2Context = createContext()
const Parent = ({ children }) => (
<State1Context.Provider value={useState(0)}>
<State2Context.Provider value={useState(0)}>
{children}
</State2Context.Provider>
</State1Context.Provider>
)
const Component1 = () => {
const [state, setState] = useContext(State1Context)
}
const Component2 = () => {
const [state, setState] = useContext(State2Context)
}

이제 Jotai가 어떻게 이를 단순화하는지 살펴보겠습니다. 여러 Context 대신 아톰(atom)을 사용할 수 있습니다.

import { Provider, atom, useAtom } from 'jotai'
const atom1 = atom(0)
const atom2 = atom(0)
// 선택 사항: useContext처럼 Provider를 사용할 수 있지만,
// ...하나만 필요하다면 생략할 수 있습니다.
// ...이 경우 Jotai는 기본 Provider를 사용합니다 (Provider-less 모드).
const Parent = ({ children }) => {
return <Provider>{children}</Provider>
}
const Component1 = () => {
const [state, setState] = useAtom(atom1)
}
const Component2 = () => {
const [state, setState] = useAtom(atom2)
}

How is Jotai different from Zustand?

이름

Jotai는 일본어로 "상태"를 의미합니다. Zustand는 독일어로 "상태"를 의미합니다.

Analogy_69GKHc3MZfQQuNz7k87naX

Jotai는 Recoil과 비슷합니다. Zustand는 Redux와 비슷합니다.

상태가 위치하는 곳

상태를 관리하기 위해 두 라이브러리 모두 모듈 수준이나 컨텍스트 수준에 존재할 수 있는 스토어를 제공합니다. Jotai는 컨텍스트를 우선으로, 모듈을 그 다음으로 설계되었습니다. Zustand는 모듈을 우선으로, 컨텍스트를 그 다음으로 설계되었습니다.

상태 구조화 방법

Jotai의 상태는 아톰(atom)으로 구성됩니다. 즉, 하향식(bottom-up) 접근 방식을 사용합니다. Zustand의 상태는 하나의 객체로 이루어져 있습니다. 즉, 상향식(top-down) 접근 방식을 사용합니다.

기술적 차이

가장 큰 차이점은 상태 모델입니다. Zustand는 단일 스토어를 사용하지만(여러 개의 독립적인 스토어를 만들 수도 있음), Jotai는 기본 아톰으로 구성되고 이를 함께 합성할 수 있습니다. 이 점에서 프로그래밍 사고 모델의 차이라고 볼 수 있습니다.

어떤 것을 사용해야 할까

  • 새로운 것을 배우고 싶다면, 둘 중 아무거나 선택해도 괜찮습니다.
  • Zustand를 좋아한다면, Jotai도 마음에 들 것입니다.
  • React Context 대안이 필요하다면, Jotai는 충분한 기능을 제공합니다.
  • React 외부에서 아톰을 읽고 쓰고 싶다면, Jotai는 store API를 제공합니다.
  • 새로운 라이브러리를 만들고 싶다면, Jotai가 좋은 기본 요소를 제공할 수 있습니다.
  • 그 외에는 두 라이브러리가 일반적인 목표와 기본 기술 면에서 매우 유사하니, 둘 다 사용해 보고 피드백을 공유해 주세요.

Jotai와 Recoil의 차이점은 무엇인가요?

(주의: 작성자는 Recoil에 대해 잘 알지 못하므로, 이 내용은 편향적이거나 부정확할 수 있습니다.)

개발자

  • Jotai는 Poimandres(이전 react-spring) 조직의 몇몇 개발자들이 협력하여 개발했습니다.
  • Recoil은 Facebook 팀에서 개발했습니다.

기본 개념

  • Jotai는 학습이 쉬운 기본 API에 초점을 맞추고 있으며, 특정 방식을 강요하지 않습니다. (Zustand와 동일한 철학)
  • Recoil은 올인원 방식으로 다양한 캐시 전략을 제공합니다.

Technical difference_FoyfUcEWAmJvZjYEtcBxhy

  • Jotai는 아톰 객체의 참조 동일성에 의존합니다.
  • Recoil은 아톰 문자열 키에 의존합니다.