반응형
😃 Redux
특징
- 단방향 패턴
- UI -> Action -> Reducer -> Store -> UI변경
역할
- Store: 상태 저장
- Action: 무슨일이 발생했는지
- Reducer: Action보고 상태 변경
단점
전통적인 Redux
counter +1를 하나 만들기 위해
- ActionType선언
- Action Creator 생성
- Reducer작성
- store구성 (const store = createStore(countReducer))
- dispatch(increment()) 를 컴퍼넌트에서 선언
- 불변성 유지를 위한 작업이 번거러움
😏Redux Toolkit
Redux의 불편한점 개선을 한 버전
특징
- ActionType 선언, Action Creator 생성 불필요
- 보일러 플레이트 해결
- 하나의 동작을 위해 여러코드를 변경해야한다는 점
장점
- 별도의 ActionType , ActionCreator 생성 불필요
- 내부적으로 불변성유지를 해줌
const counterSlice = createSlice({
name: "counter",
initialState: {
value: 0
},
reducers: {
increment(state) {
state.value++
},
decrement(state) {
state.value--
}
}
})
/*
Redux 방식
return {
...state,
user: {
...state.user,
profile: {
...state.user.profile,
address: {
...state.user.profile.address,
city: "Seoul"
}
}
}
}
*/
/* Redux Kit 방식 */
state.user.profile.address.city = "Seoul"
단점
- 과도한 오버엔지니어링
- 단순 모달 띄우는 경우 많은 코드 작성
const modalSlice = createSlice({ name: "modal", initialState: { open: false }, reducers: { openModal(state) { state.open = true }, closeModal(state) { state.open = false } } })dispatch(openModal())const open = useSelector( state => state.modal.open )
😫React Tool Kit으로 Login 만들기
항목 역할
| createSlice | state/reducer/action 생성 |
| configureStore | store 생성 |
| useAppSelector | 타입이 적용된 state 조회 |
| useAppDispatch | 타입이 적용된 dispatch |
| PayloadAction<T> | action payload 타입 지정 |
| createAsyncThunk | 비동기 로직/API 처리 |
| RootState | 전체 state 타입 |
| Provider | React에 Redux 연결 |
Login Store 만들기
import { createSlice, type PayloadAction } from "@reduxjs/toolkit";
interface LoginState {
isLogin: boolean;
email: string | null;
}
const initialState: LoginState = {
isLogin: false,
email: null,
};
const loginSlice = createSlice({
name: "login",
initialState,
reducers: {
login: (state, action: PayloadAction<string>) => {
state.isLogin = true;
state.email = action.payload;
},
},
});
// 컴포넌트에서 dispatch할 때 필요
export const { login } = loginSlice.actions;
// configureStore에 등록할 때 필요
export default loginSlice.reducer;
Login을 Store에 구성하기
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";
import loginReducer from "../features/login/loginSlice";
export const store = configureStore({
reducer: {
counter: counterReducer,
login: loginReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Provider로 Store제공하도록 설정
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import "./index.css";
import App from "./App.tsx";
import { store } from "./app/store.ts";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
);
컴퍼넌트에 적용하기
import { useState, type SubmitEvent } from "react";
import "./App.css";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux";
import { login } from "./features/login/loginSlice";
import type { RootState } from "./app/store";
function App() {
const [id, setId] = useState("");
const dispatch = useDispatch();
const loginState = useSelector((state: RootState) => state.login);
const handleSubmit = (e: SubmitEvent<HTMLFormElement>) => {
e.preventDefault();
dispatch(login(id));
};
return (
<>
<form onSubmit={handleSubmit}>
<label htmlFor="id">ID</label>
<input
id="id"
name="id"
type="text"
placeholder="아이디를 입력하세요"
value={id}
onChange={(e) => setId(e.target.value)}
/>
<button type="submit">로그인</button>
</form>
<p>{loginState.email}</p>
</>
);
}
export default App;
위와같이 redux toolkit으로 할려면
createSlice생성 및 PayloadAction선언 → store.ts에 등록 → 컴퍼넌트에서 상태갱신은 useDispatch, 상태조회는 useSelectors으로 확인 한다. 하나의 기능을 위해서 여러가지의 과정을 거쳐야 하는 단점이 존재한다
🦞 Zustand
Zustand는 JavaScript/TypeScript 애플리케이션에서 사용할 수 있는 가볍고 단순한 상태 관리 라이브러리
특징
- Redux와 다르게 Action → dispatch → reducer구조가 아닌 Store → State + Action
- dispatch필요 없음
역할
- Store: State+Action을 동시에 관리(Redux처럼 Action을 따로 관리하지 않음)
Zustand으로 Login 만들기
코드 용어/역할/사용 예
| create | Store 생성 | create<LoginStore>(...) |
| set | State 변경 | set({ isLogin: true }) |
| get | 현재 State 조회 | get().isLogin |
| state | 현재 Store의 상태 | (state) => state.id |
| Store Hook | Store 접근 + 구독 | useLoginStore(...) |
| Selector | 필요한 값을 선택 | (state) => state.isLogin |
LoginStore만들기
import { create } from "zustand";
interface LoginState {
isLogin: boolean;
email?: string;
login: (email: string) => void;
}
export const useLogin = create<LoginState>((set) => ({
isLogin: false,
email: undefined,
login: (email) => {
set({
isLogin: true,
email,
});
},
}));
컴퍼넌트에서 사용하기
import { useState, type SubmitEvent } from "react";
import "./App.css";
import { useLogin } from "./features/login/loginStore";
function App() {
const [id, setId] = useState("");
const login = useLogin((state) => state.login);
const email = useLogin((state) => state.email);
const handleSubmit = (e: SubmitEvent<HTMLFormElement>) => {
e.preventDefault();
login(id);
};
return (
<>
<form onSubmit={handleSubmit}>
<label htmlFor="id">ID</label>
<input
id="id"
name="id"
type="text"
placeholder="아이디를 입력하세요"
value={id}
onChange={(e) => setId(e.target.value)}
/>
<button type="submit">로그인</button>
</form>
<p>{email}</p>
</>
);
}
export default App;
위 처럼 Redux Tool kit 보다 코드양이 간소화 되었다.
코드양으로봐서는 장점이 확실히 있다.
개인적으로는 Store에 State/Actions을 관리하는것이 혼란을 주지 않을까 싶긴하다
반응형
'React' 카테고리의 다른 글
| 😀 React Custom Hook (0) | 2026.06.02 |
|---|---|
| ⚽️Zustand (0) | 2025.12.01 |
| 🍏 React Hook (0) | 2025.10.24 |
댓글