Ducks Pattern에 대해서 알아보자!
1. Duck file
액션 타입(Actions), 액션 생성 함수(Action Creators), 리듀서(Reducer), 그리고 Side Effects까지 모아놓은 파일을 의미한다.
Duck file들로 리덕스에 필요한 요소들을 관리하는 것을 덕스(Ducks) 패턴이라고 한다.
Actions : action의 type을 나타내는 이름
Reducer : 각각의 Action을 처리하는 역할을 하는 함수
Action Creators : Action 객체를 생성하는 함수
Side effects : Reducer가 아닌 외부와 연관된 동작들을 의미
2. Pattern
소프트 웨어를 설계하는 정형화된 방법을 말한다.
3. Ducks Pattern
액션 타입, 액션 생성 함수, 리듀서를 하나의 모듈처럼 한 파일 안에 작성하고 관리하는 패턴을 말한다.
4. Ducks 파일의 규칙
(1) 리듀서 함수를 default export 해야 한다.
(2) 액션 생성 함수를 export 해야 한다.
(3) 접두사를 붙인 형태로 액션 타입을 정의해야 한다.
(4) 모듈 또는 애플리케이션 이름, 리듀서 이름, ACTION_TYPE을 슬래시로 구분해서 순서대로 써야 한다.
// Actions (Action Types)
const SET_COUNT = 'my-app/counter/SET_COUNT';
const INCREASE = 'my-app/counter/INCREASE';
const DECREASE = 'my-app/counter/DECREASE';
액션 타입은 영어 대문자만을 사용하여 SNAKE_CASE 형태로 이름 짓고,
외부에서 액션 타입을 필요로 할 경우에는 export할 수 있다.
Duck file 예시
// 액션 타입
const SET_COUNT = 'my-app/counter/SET_COUNT';
const INCREASE = 'my-app/counter/INCREASE';
const DECREASES = 'my-app/counter/DECREASE';
// 덕스 패턴에서는 액션 타입을 정의할 때, 다른 모듈과 이름이 중복되지 않도록 접두사를 붙인다.
// 리듀서
export default function reducer(state = 0, action ={}) {
switch (action.type) {
case SET_COUNT:
return action.count;
case INCREASE:
return state + 1;
case DECREASE:
return state - 1;
}
}
// 액션 생성 함수
export function setCount(count) {
return { type: SET_COUNT, count: count };
}
// export const setCount = count => ({ type: SET_COUNT, count });
export function increase() {
return { type: INCREASE };
}
// export const increase = () => ({ type: INCREASE });
export function decrease() {
return { type: DECREASE };
}
// export const decrease = () => ({ type: DECREASE });
// 필요한 경우 Side Effects 작성
export function getCount() {
return dispatch => get('/count').then(count => dispatch(setCount(count)));
}
5. Todo 프로젝트에 Ducks pattern 적용하기
*참고 (아래 게시글에서 이어지는 코드입니다.)
https://dev-ini.tistory.com/286
[Redux] Redux로 프로젝트 시작하는 법 (간단한 Todo 프로젝트 만들어보기)
Redux랑 React 연동해서 간단한 프로젝트를 만들어볼 것이다. * 필자는 Vite를 사용하여 React 개발 환경을 설정하였다. (참고 ) https://dev-ini.tistory.com/58)* Toolkit은 사용하지 않은 버전이다. 추후 학
dev-ini.tistory.com
(1) redux폴더 안에 ducks 폴더를 만들고, 그 안에 todoDuck.js 파일을 만든다.
(2) todoDuck.js 파일에 아래와 같이 작성한다.
// Actions (Action Types)
// 기존에 작성했던 actions.js 파일에 있는 action type들을 ducks 패턴의 규칙에 따라 변경해서 작성함
const ACTION_TYPE_ADD_TODO = "my-app/todo/ADD_TODO"; // "app이름/reducer이름/대문자로 쓴 action type"
const ACTION_TYPE_REMOVE_TODO = "my-app/todo/REMOVE_TODO";
const ACTION_TYPE_REMOVE_ALL = "my-app/todo/REMOVE_ALL";
// Reducer
const initialState = [];
export default function reducer(state = initialState, action) {
switch (action.type) {
case ACTION_TYPE_ADD_TODO:
return state.concat(action.text);
case ACTION_TYPE_REMOVE_TODO:
return state.slice(0, -1);
case ACTION_TYPE_REMOVE_ALL:
return [];
default:
return state;
}
}
// Action Creators
// 기존에 작성했던 actions.js 파일에 있는 action creator들을 ducks 패턴의 규칙에 따라 변경해서 작성함
export function addTodoActionCreator(text) {
return {
type: ACTION_TYPE_ADD_TODO,
text: text
}
}
export function removeTodoActionCreator() {
return {
type: ACTION_TYPE_REMOVE_TODO,
}
}
export function removeAllActionCreator() {
return {
type: ACTION_TYPE_REMOVE_ALL,
}
}
(3) src > redux > reducers > index.js 코드를 아래와 같이 ducks 폴더에서 reducer를 가져오도록 수정한다.
index.js
import { combineReducers } from "redux";
// import todoReducer from "./todoReducers";
import todoReducer from "../ducks/todoDock"; // 이렇게 가져옴
const rootReducer = combineReducers({
todo: todoReducer,
});
export default rootReducer;
(4) src > redux > containers > TodoAppContainers.js 코드 또한 아래와 같이 ducks 폴더에서 Action Creator를 가져오도록 수정한다.
import { connect } from "react-redux";
// import { addTodoActionCreator, removeAllActionCreator, removeTodoActionCreator } from "../actions";
import { addTodoActionCreator, removeAllActionCreator, removeTodoActionCreator } from "../ducks/todoDock";
import TodoApp from "../../components/TodoApp";
function mapStateToProps(state) {
return {
todoItems: [...state.todo, ...(state.fetchTodos?.data || [])], // ✅ `fetchTodos`가 없으면 빈 배열 사용
};
}
function mapDispatchToProps(dispatch) {
return {
addTodo: (text) => {
dispatch(addTodoActionCreator(text));
},
removeTodo: () => {
dispatch(removeTodoActionCreator());
},
removeAll: () => {
dispatch(removeAllActionCreator());
},
};
}
export default connect(mapStateToProps, mapDispatchToProps)(TodoApp);
이렇게 하면 ducks pattern 적용이 완료된다!
'Libraries > Redux' 카테고리의 다른 글
[Redux] Async Logic, Middleware (0) | 2025.02.06 |
---|---|
[Redux] redux-actions (1) | 2025.02.03 |
[Redux] Redux로 프로젝트 시작하는 법 (간단한 Todo 프로젝트 만들어보기) (1) | 2025.01.30 |
[Redux] Redux와 React를 연동하기 (1) | 2025.01.18 |
[Redux] Reducer (0) | 2025.01.12 |