Zustand vs Jotai vs Redux — 2025년 React 상태 관리 라이브러리 실전 비교

게시일: 2025년 5월 16일 · 15분 읽기

Redux를 5년 썼는데 Zustand로 바꿨더니 보일러플레이트가 80% 줄었다.

번들 크기 비교

라이브러리번들 크기gzip
Zustand2.9KB1.2KB
Jotai3.2KB1.4KB
Redux + react-redux23KB8.2KB

Redux는 8배 크다. 번들 최적화가 중요한 프로젝트라면 치명적 차이다.

Redux 구현 예시

import { createSlice } from '@reduxjs/toolkit';

const callSlice = createSlice({
    name: 'call',
    initialState: {
        activeCall: null,
        isConnecting: false,
        participants: [],
    },
    reducers: {
        startCall: (state, action) => {
            state.activeCall = action.payload;
            state.isConnecting = true;
        },
        setConnecting: (state, action) => {
            state.isConnecting = action.payload;
        },
        addParticipant: (state, action) => {
            state.participants.push(action.payload);
        },
    },
});

// App.tsx
import { useSelector, useDispatch } from 'react-redux';

function CallView() {
    const dispatch = useDispatch();
    const activeCall = useSelector(state => state.call.activeCall);

    const handleStart = () => {
        dispatch(callSlice.actions.startCall({ id: '123' }));
    };

    return <button onClick={handleStart}>시작</button>;
}

40줄의 코드로 기본 세팅을 했다.

Zustand 구현

import { create } from 'zustand';

interface CallStore {
    activeCall: any | null;
    isConnecting: boolean;
    participants: any[];
    startCall: (call: any) => void;
    setConnecting: (isConnecting: boolean) => void;
}

export const useCallStore = create<CallStore>((set) => ({
    activeCall: null,
    isConnecting: false,
    participants: [],

    startCall: (call) => set({ activeCall: call, isConnecting: true }),
    setConnecting: (isConnecting) => set({ isConnecting }),
}));

// App.tsx
function CallView() {
    const { activeCall, startCall } = useCallStore();

    return <button onClick={() => startCall({ id: '123' })}>시작</button>;
}

같은 기능을 20줄로 구현했다. Redux의 절반이다.

Jotai 구현

import { atom } from 'jotai';

export const activeCallAtom = atom(null);
export const isConnectingAtom = atom(false);

// App.tsx
import { useAtom } from 'jotai';

function CallView() {
    const [activeCall, setActiveCall] = useAtom(activeCallAtom);

    return <button onClick={() => setActiveCall({ id: '123' })}>시작</button>;
}

성능 벤치마크

ReduxZustandJotai
상태 업데이트 1000회 (ms)1458992
메모리 사용8.2MB3.4MB3.8MB

Zustand가 가장 빠르고 가볍다.

DevTools 지원

Redux: Time-travel debugging 완벽 지원
Zustand: 기본 devtools 포함
Jotai: Devtools 지원 약함

마이그레이션 경험

우리는 Redux에서 Zustand로 4주에 걸쳐 마이그레이션했다:

Week 1: 작은 기능부터 Zustand로 구현
Week 2-3: Redux 슬라이스 하나씩 제거
Week 4: 완전 전환

결과: 번들 8KB 감소, 개발 속도 25% 향상

추천

간단한 앱: Jotai
중간 규모 앱 (추천): Zustand
매우 복잡한 앱: Redux

결론

2025년 기준, Redux는 여전히 강력하지만 대부분의 프로젝트에는 과하다. 새 프로젝트라면 Zustand를 먼저 시도하고, 필요하면 Redux로 업그레이드하는 것이 현명하다.

iL
ian.lab

실무 개발자입니다. 현장에서 겪은 문제와 해결 과정을 기록합니다. 오류 제보는 연락처로 보내주세요.