Redux
+TypeScript
์ ๋ํ ํฌ์คํธ์ ๋๋ค.
ํ๋ก์ ํธ์ ์ ์ฒด์ ์ธ ๋ฐ์ดํฐ(์ํ)๋ฅผ ๋ณด๋ค ์ฝ๊ณ ํ๋ฆ์ ๋ง๊ฒ ๊ด๋ฆฌํ๊ธฐ ์ํด์ ์ฌ์ฉํฉ๋๋ค.
React.js
๋ฅผ ๊ธฐ์ค์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์งํํ๋ค๋ณด๋ฉด ์ปดํฌ๋ํธ๋ง๋ค ๊ฐ๊ฐ์ state
๋ฅผ ์ด์ฉํด์ ๊ด๋ฆฌํ๊ธฐ ๋ณด๋ค๋ ํ๋์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๋ฉด ํธํ๊ฒ ๋ค๋ ์๊ฐ์ด ํ๋ก์ ํธ๊ฐ ์ปค์ง์๋ก ๋ค๊ฒ ๋ฉ๋๋ค.
๋ฌผ๋ก Redux
๋ฅผ ์ฌ์ฉํ์ง ์๊ณ React.js
๋ง์ผ๋ก๋ ๊ฐ๋ฅํฉ๋๋ค. ์ต์์ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ์ ์ํ๊ณ props
๋ฅผ ์ด์ฉํด์ ํ์ ์ปดํฌ๋ํธ๋ก ๊ณ์ ์ ๋ฌํ๋ฉด ๋ฉ๋๋ค. ์ง์ ๊ฒฝํํด๋ณด์๋ฉด ์๊ฒ ๋๊ฒ ์ง๋ง ๊ฐ๋
์ฑ์ด ๋งค์ฐ ์์ข์์ง๊ณ ํ๋์ ์์ ์ ์ํ ๋ณ๊ฒฝํด์ผํ ์ฝ๋๊ฐ ์ ๋ง ๋ง์์ง๋๋ค.
์ด๋ฐ ๋ถํธํจ์ ํด๊ฒฐํ๊ธฐ ์ํด์ ๋๋ถ๋ถ Redux
๋ฅผ ์ฌ์ฉํฉ๋๋ค. Redux
๋ ํ๋์ ์ํ๋ฅผ ๊ฐ๋ ํฐ ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๊ณ ์ฝ๋๊ฐ ๊ผฌ์ด์ง ์๊ธฐ ์ํด์ Flux
ํจํด์ ์ด์ฉํด์ผ๋ง ๊ทธ ๊ฐ์ฒด๋ก ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
์ค๊ฐ ์ ๋ฆฌ๋ฅผ ํ์๋ฉด Redux
๋ ํ๋์ ํฐ ์ํ๋ฅผ ๊ฐ๋ ๊ฐ์ฒด์ธ store
๋ฅผ ๊ฐ๊ณ ๊ทธ store
๋ฅผ ๊ฐ ์ปดํฌ๋ํธ์์ ๊ฐ์ ธ์์ ์ฌ์ฉํ๋ฏ๋ก props
๋ฅผ ์ด์ฉํด์ ๋ฐ์ดํฐ๋ฅผ ๋ด๋ ค์ฃผ๋ ๊ณผ์ ์ด ํ์์๊ฒ ๋ฉ๋๋ค. ๋ํ React.js
์์๋ ๊ฐ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ๋ store
๋ฅผ ์ธ์งํ๊ณ ๊ตฌ๋
ํจ์ผ๋ก์จ store
๊ฐ ๋ณ๊ฒฝ๋จ์ ์ํด์ ํด๋น ์ปดํฌ๋ํธ๋ ๋ฆฌ๋๋๋ง์ ํ๊ฒ ๋ฉ๋๋ค. ๋ํ ๋ฐ์ดํฐ์ ํ๋ฆ์ ํ์
ํ๊ธฐ ์ํด์ Flux
ํจํด์ ์ด์ฉํด์ผ๋ง store
๋ฅผ ๋ณ๊ฒฝํ ์ ์์ผ๋ ๋ฐ์ดํฐ์ ์ ๋ขฐ์ฑ๋ ๋์์ง๋๋ค.
store
: ์ ์ฒด์ ์ธ ๋ฐ์ดํฐ(์ํ)๋ฅผ ๊ด๋ฆฌํ๋ ํ๋์ ํฐ ๊ฐ์ฒดaction
: ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ํ type
๊ณผ ์ํ๋ฅผ ์์ ํ๊ธฐ ์ํ payload
๋ฅผ ๊ฐ๋ ๊ฐ์ฒดdispatch
: ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ํด action
๋ฅผ ์ธ์๋ก ๋ฐ๋ ํจ์reducer
: ์ํ์ ๋ํ ์ ์์ ์ํ์ ๋ณ๊ฒฝ์ ๋ํ ์ ์๋ฅผ ๊ฐ๋ ํจ์๋ฐ์ดํฐ๊ฐ ํ ๋ฐฉํฅ์ผ๋ก๋ง ํ๋ฅด๊ฒ ๋ณด์ฅ๋ ์ ์๋๋ก ํด์ฃผ๋ ์ํคํ
์ฒ์
๋๋ค.
action
์ dispatch
ํด์ reducer
๋ก ๋ณด๋ธ ํ ์ ์๋ ์ฒ๋ฆฌ๋ฅผ ์๋ฃํ๊ณ ์๋ก์ด state
, store
๋ฅผ ๋ง๋ญ๋๋ค.
Redux
๋ง์ ์ฌ์ฉํ ์์์ ๋๋ค.
// legacy_createStore๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ Redux์์ ์ด์ ๋ redux-toolkit์ ์ฌ์ฉํ๋ผ๊ณ ๊ถ์ฅํ๊ธฐ ๋๋ฌธ
import {
legacy_createStore as createStore,
combineReducers,
applyMiddleware,
} from "redux";
// type ( as const๋ฅผ ์ด์ฉํด์ ๋ถ๋ณ์์ ์ ์ )
const ADD_USER = "ADD_USER" as const;
const ADD_POST = "ADD_POST" as const;
// action ( ์ก์
์ ์์ฑํ๋ ํจ์... ์ง์ ์ ์ผ๋ก ์ก์
์ ์ ๋ฌํด๋ ๋์ง๋ง ์ก์
์ด ๋ง์์ง๋ฉด ํท๊ฐ๋ ค์ ์ก์
ํฌ๋ฆฌ์์ดํฐ๋ฅผ ์ ์ํจ )
const addUser = () => ({ type: ADD_USER });
const addPost = (payload: number) => ({ type: ADD_POST, payload });
// ์ก์
์ ํ์
( reducer์์ ์ฌ์ฉ )
type UserAction = ReturnType<typeof addUser>;
type PostAction = ReturnType<typeof addPost>;
// reducer
// ์ ์ ๋ฆฌ๋์ ์ ์
const userInitialState = {
users: 333,
};
type UserStateType = typeof userInitialState;
const userReducer = (
state: UserStateType = userInitialState,
action: UserAction
): UserStateType => {
switch (action.type) {
case ADD_USER:
return {
...state,
users: state.users + 1,
};
default:
return state;
}
};
// ๊ฒ์๊ธ ๋ฆฌ๋์ ์ ์
const PostInitialState = {
posts: 5555,
};
type PostStateType = typeof PostInitialState;
const postReducer = (
state: PostStateType = PostInitialState,
action: PostAction
): PostStateType => {
switch (action.type) {
case ADD_POST:
return {
...state,
posts: state.posts + action.payload,
};
default:
return state;
}
};
// ๋ฆฌ๋์ ํฉ์นจ
const rootReducer = combineReducers({
user: userReducer,
post: postReducer,
});
// middleware ( ์ง์ ๋ง๋ ๊ฐ๋จํ ๋ฏธ๋ค์จ์ด... action์ด reducer๋ก ์ ๋ฌ๋๊ธฐ ์ ์ ์คํ )
const logger = (store: any) => (next: any) => (action: any) => {
// ์ํ๋ ์์
( action์ด reducer๋ก ์ ๋ฌ๋๊ธฐ ์ )
console.log("middleware >> ", action);
// next()๋ฅผ ์ด์ฉํด์ action์ด reducer๋ก ์ ๋ฌ๋จ
return next(action);
};
// store ์์ฑ ( getState, subscribe, getState ๋ฑ์ด ๋ค์ด์์ )
const store = createStore(rootReducer, applyMiddleware(logger));
console.log(store.getState());
store.dispatch(addUser());
store.dispatch(addPost(1111));
console.log(store.getState());
/**
* { user: { users: 333 }, post: { posts: 5555 } }
* middleware >> { type: 'ADD_USER' }
* middleware >> { type: 'ADD_POST', payload: 1111 }
* { user: { users: 334 }, post: { posts: 6666 } }
*/