앞선 프로젝트 회고에서 useState를 useReducer로 최적화하는 방법에 대하여 살펴보았습니다.
"회사 프로젝트 후기 - (5) useReducer로 상태관리 최적화"
앞선 글에서 언급된 방법은 몇 가지 문제점을 가지고 있습니다. 첫째로, 리듀서 함수와 액션 생성자 함수를 개별적으로 관리해야 합니다. 이는 코드를 여러 곳에 분산시켜 유지보수를 어렵게 만들 수 있습니다. 둘째로, 액션 함수를 사용할 때 리듀서 함수를 통해 가져와야 하는 불편함이 있습니다. 이는 코드의 가독성을 저하시킬 수 있습니다.
따라서, 오늘은 OcrReducer.js 파일에서 createSlice를 활용하여 최적화를 진행해보고, OcrMain.js 파일에서는 useDispatch와 useSelector를 사용하여 상태를 업데이트하고 가져오는 로직을 작성하는 방법을 살펴보려고 합니다.
이러한 최적화를 통해 코드의 가독성과 유지보수성을 향상시킬 수 있습니다. createSlice를 사용하면 리듀서 함수와 액션 생성자 함수를 한 곳에서 관리할 수 있습니다. 이를 통해 코드의 구조를 단순화하고 중복을 줄일 수 있습니다. 또한, useDispatch를 사용하여 액션을 간편하게 디스패치하고, useSelector를 사용하여 필요한 상태를 쉽게 가져올 수 있습니다. 이는 코드의 가독성을 높이고 개발자의 생산성을 향상시킵니다.
1. createSlice 적용하기
createSlice도 createReducer, createAction 과 마찬가지로 Redux toolkit을 통해서 사용할 수 있습니다. createSlice의 이점은 객체의 불변성을 고려하지 않고 상태를 관리할 수 있다는 점입니다.
아래의 코드에서는 초기 상태를 먼저 선언합니다. 그리고 createSlice 함수를 사용하여 ocrSlice라는 슬라이스(slice)를 생성합니다. 슬라이스 내부의 속성에는 name, reducers가 있는데 reducer s객체에는 액션과 관련된 리듀서 함수들을 정의합니다.
각 리듀서 함수는 현재 상태(state)와 액션(action)을 매개변수로 받습니다. 함수 내부에서는 액션의 페이로드를 사용하여 상태를 업데이트합니다. 예를 들어, setGroupList 리듀서 함수는 groupList 액션의 페이로드를 사용하여 state.group.groupList 값을 업데이트합니다.
export const initialState = {
group: {
groupList: [], groupCode: ""
},
file: {
fileList: [], fileInfo: []
},
page: {
pageInfo: { CONTEXT: '' },
pageCode: "",
pageIndex: 0
},
docCode: "",
amendTimeList: []
};
const ocrSlice = createSlice({
name: 'ocr',
initialState,
reducers: {
setGroupList(state, action) {
state.group.groupList = action.payload;
},
setGroupCode(state, action) {
state.group.groupCode = action.payload;
},
setFileList(state, action) {
state.file.fileList = action.payload;
},
setFileInfo(state, action) {
state.file.fileInfo = action.payload;
},
setPageInfo(state, action) {
state.page.pageInfo = action.payload;
},
setPageCode(state, action) {
state.page.pageCode = action.payload;
},
setPageIndex(state, action) {
state.page.pageIndex = action.payload;
},
setDocCode(state, action) {
state.docCode = action.payload;
},
setAmendTimeList(state, action) {
state.amendTimeList = action.payload;
},
},
});
export const {
setGroupList,
setGroupCode,
setFileList,
setFileInfo,
setPageInfo,
setPageCode,
setPageIndex,
setDocCode,
setAmendTimeList,
} = ocrSlice.actions;
export default ocrSlice.reducer;
2. useDispatch 적용하기
const dispatch = useDispatch()는 Redux의 useDispatch 훅을 사용하여 디스패치 함수를 가져오는 코드입니다. Redux는 액션을 디스패치하여 상태를 업데이트하는 데 사용되는 상태 관리 라이브러리입니다. 디스패치 함수는 액션을 생성하고 Redux 스토어에 전달하는 역할을 합니다.
useDispatch 훅은 함수 컴포넌트 내에서 디스패치 함수를 사용할 수 있게 해줍니다. useDispatch를 호출하여 디스패치 함수를 가져온 후, 해당 함수를 사용하여 액션을 디스패치할 수 있습니다.
예를 들어, dispatch(setGroupList(['group1', 'group2']))와 같이 액션 크리에이터 함수인 setGroupList를 호출하여 액션을 디스패치할 수 있습니다. 이를 통해 Redux 스토어의 상태를 업데이트하고, 이에 따라 UI가 변경될 수 있습니다.
즉, const dispatch = useDispatch()를 사용하여 dispatch 변수에 디스패치 함수를 할당하고, 나중에 해당 함수를 호출하여 액션을 디스패치할 수 있습니다.
OcrMain.js
import React from 'react';
import { useDispatch } from 'react-redux';
import {
initialState,
setGroupList,
setGroupCode,
setFileList,
setFileInfo,
setPageInfo,
setPageCode,
setPageIndex,
setDocCode,
setAmendTimeList
} from './OcrReducer';
export default function OcrMain() {
const state = initialState;
const { groupList, groupCode } = state.group;
const { fileList, fileInfo } = state.file;
const { pageInfo, pageCode, pageIndex } = state.page;
const { docCode, amendTimeList } = state;
const dispatch = useDispatch();
.
.
.
if (res?.rs_value ?? false) {
const payload = [...res.rs_value];
dispatch(setGroupList(payload));
}
}
추가
useSelector를 통해서 전역으로 관리되는 state를 가져오는 것이 위 방법의 일반적인 용법입니다. 그러나 위 코드의 베이스가 되는 Ocr 보정 페이지에서 관리되는 상태는 전역 관리가 필요없기에 useSelector를 사용하지 않았습니다.
이상 '회사 프로젝트 후기 - (6) createSlice, useDispatch로 상태관리 한번 더 최적화' 였습니다.
글 읽어 주셔서 감사합니다.
"도움이 되셨다면 공감과 댓글로 지지해주세요!!"