5. 개발 - 상태 관리 리팩토링 - useReducer

2022. 7. 18. 22:51·프로젝트 회고/이미지편집기 개발

1) 기존 상태 관리 - useState

기존에는 노드들(텍스트, 이미지)의 상태를 useState를 활용해서 상태 관리했다.

const [nodes, setNodes] = useState([])

이미지 편집기에서 특정 노드의 속성을 변경하는 경우가 많은데, 이런 경우에 특정 노드를 id를 통해서 찾고 걔의 속성을 변경하는 식의 코드가 들어가야 한다. immer을 사용해서 객체, 배열의 상태 변경을 쉽게 해도 중복되는 코드의 양이 너무 많았다.

setNodes(state, draft => {
	const target = draft.find(node => node.id === targetId)
    target[property] = newProperty
})

이런 코드들이 많은 곳에 중복으로 들어갔다.

2) 변경 상태 관리 - useReducer

그래서 useReducer를 활용해서 상태관리 부분을 reducer.js로 따로 빼놓고 dispatch 해서 사용하는 식으로 변경했다.

export function arrayOfObjectReducer(state, action) {
    let newState = state.slice()
    let target = null
    let targetIdx
    let maxId
    if(action.id) {
        target = newState.find(each => each.id === action.id)
    }
    
    // console.log(action)
    switch (action.type) {
        case 'CHANGE__ITEM':
            targetIdx = newState.findIndex(each => each.id===action.id)
            newState[targetIdx] = {...newState[targetIdx], ...action.changes}
            break
        case 'ADD__ITEM':
            maxId = -1
            newState.forEach(item => {
                if (item.id > maxId) maxId=item.id
            })
            newState = [...newState, {...action.item, id: state.length > 0 ? maxId+1 : 1}]
            break
        case 'DELETE__ITEM':
            newState = newState.filter((each) => each.id !== action.id)
            break
        case 'COPY__ITEM': 
            const copiedItem = {...newState.find(each => each.id === action.id)}
            copiedItem.x += 20 
            copiedItem.y += 20
            maxId = -1
            newState.forEach(item => {
                if (item.id > maxId) maxId=item.id
            })
            copiedItem.id = state.length > 0 ? maxId+1 : 1
            newState = [...newState, copiedItem]
            break
        case 'SET':
            newState = action.newState
            break
        case 'MOVE__FRONT':
            newState = [...newState.filter(each => each.id !== action.id), target]
            break
        case 'MOVE__REAR':
            newState = [target, ...newState.filter(each => each.id !== action.id)]
            break
        case 'MOVE__FORWARD':
            // 인덱스 한칸 뒤로 +1
            targetIdx = newState.findIndex(each => each.id === action.id)
            // 이미 맨뒤에있으면 안함
            if(targetIdx === newState.length-1) break
            // 서로 바꾸기
            change(newState, targetIdx, targetIdx+1) 
            break
        case 'MOVE__BACKWARD':
            // 인덱스 한칸 앞으로 -1
            targetIdx = newState.findIndex(each => each.id === action.id)
            if(targetIdx === 0) break
            change(newState, targetIdx, targetIdx-1)
            break
        default:
            break
    }
    return newState
}

요런 식으로 특정 노드의 상태 변경, 삭제, 추가, Z-index 변경 등을 따로 reducer.js에 담은 다음에 dispatch해서 사용하도록 했다. 

이렇게 했더니 중복되는 부분이 사라지고 상태 변경에 문제가 생겼을 때 상태관리 부분만 체크하면 되서 훨씬 디버깅하기에도 편해졌다. (기존에는 해당 로직이 있는 함수부분과 상태 2부분을 확인해야 했다.)

결론

useReducer는 사실 useState(state => reducer(state)) 와 같다.

객체의 속성을 변경하거나 객체들로 이뤄진 배열의 경우에는 useState로만 상태 관리하기에는 중복, 디버깅하기 어려운 문제가 발생한다.

이런 경우에는 useReducer를 활용해서 효과적으로 상태 관리를 할 수 있다.

저작자표시

'프로젝트 회고 > 이미지편집기 개발' 카테고리의 다른 글

7. 정리 - 끝  (0) 2022.07.20
6. 개발 - 뒤로가기(작업 취소), 앞으로 가기(복구) Z-index 조정 기능  (0) 2022.07.20
4. 개발 - 편집기 주 화면 구현, 배경, 노드(이미지, 텍스트) 추가, 편집 기능  (0) 2022.06.30
3. 개발 - 기본 구조  (0) 2022.06.19
2. 액션 정의하기, 앱 구조와 화면 레이아웃 잡기  (0) 2022.06.15
'프로젝트 회고/이미지편집기 개발' 카테고리의 다른 글
  • 7. 정리 - 끝
  • 6. 개발 - 뒤로가기(작업 취소), 앞으로 가기(복구) Z-index 조정 기능
  • 4. 개발 - 편집기 주 화면 구현, 배경, 노드(이미지, 텍스트) 추가, 편집 기능
  • 3. 개발 - 기본 구조
정현우12
정현우12
  • 정현우12
    정현우의 개발 블로그
    정현우12
  • 전체
    오늘
    어제
    • 분류 전체보기 (79)
      • 프론트엔드 (56)
        • JavaScript, TypeScript (12)
        • 스타일링 (1)
        • React (13)
        • Next.js (4)
        • 개발 환경 (9)
        • 테스트 (3)
        • 성능 최적화 (11)
        • 함수형 프로그래밍 (2)
        • 구조 (1)
      • 프로젝트 회고 (23)
        • 이미지편집기 개발 (7)
        • 엑셀 다운로드, 업로드 공통 모듈 개발 (4)
        • 사용자 매뉴얼 사이트 개발 (3)
        • 통계자동화 솔루션 개발 (1)
        • 엑셀 편집기 개발 (5)
        • API 플랫폼 (1)
        • 콜센터 솔루션 OB 캠페인 (1)
        • AI 스튜디오 (1)
      • 백엔드 (0)
  • 블로그 메뉴

    • 홈
    • 포트폴리오
    • 태그
  • 인기 글

  • 태그

    frontend
    라이브러리 선정
    React-boilerplate
    JavaScript
    이미지 편집기
    Github Actions
    사용자 매뉴얼 사이트
    엑셀 에디터
    로딩 성능 최적화
    TypeScript
    렌더링 성능 최적화
    회고
    Next.js
    엑셀
    useReducer
    커스텀 훅
    웹 성능 최적화
    React
    memoization
    webpack
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
정현우12
5. 개발 - 상태 관리 리팩토링 - useReducer
상단으로

티스토리툴바