[TIL] Redux 라이브러리에 대한 이해

이진호·2023년 11월 2일
2

TIL

목록 보기
19/66
post-thumbnail

Redux란?

리액트에서는 부모로부터 받는 데이터를 props라고 한다. 특정 부모 컴포넌트에서 하단에 있는 자식 컴포넌트까지 데이터르 넘기기 위해서는 자식까지 이어지는 모든 컴포넌트들에게 해당 데이터를 props로 전달을 하여야 한다.
이것의 한계를 극복하기 위해서 나온 라이브러리로 전역에서 상태를 관리할 수 있도록 도와주는 라이브러리이다.
따라서 redux를 사용하면 다음과 같은 이점이 있다.

  • 전역 상태를 관리할 때 굉장히 효과적이다.
  • 상태 업데이트 관련 로직을 다른 파일로 분리시켜서 더 효율적으로 관리할 수 있다.
  • 컴포넌트끼리 똑같은 상태를 공유해야할 때에도 여러 컴포넌트를 거치지 않고 손쉽게 상태값을 전달하거나 업데이트할 수 있다.

주요 개념

리덕스에는 총 4가지의 주요 개념이 있다.

store

스토어는 전역 상태 값들을 보관하는 곳으로 리덕스의 상태값을 갖는 객체이다. 스토어에 리듀서와 미들웨어를 등록할 수 있으며 스토어에는 dispatch()메서드를 통해서 등록된 리듀서 내용에 따라 값이 변경된다.

reducer

리듀서는 액션이 발생했을 때 새로운 상태값을 만드는 함수로 리듀서의 구조는 다음과 같다.

	(state,action) => nextState

action

액션은 type 속성값을 가진 객체로 type 속성값 이외의 다른 어떠한 값이든 넣을 수 있다.
이때 type 속성값 이외의 넣는 값은 해당 기능을 수행하기 위해 필요한 데이터들을 넣을 수 있으며 주로 payload라는 객체를 통해서 값을 전달한다.

	const updateTodo = (id,content) => ({type: 'updateTodo', payload: {id,content});
    // updateTodo는 액션 객체를 만드는 생성자 함수라 해서 액션 생성자 함수라고 한다.
    // updateTodo가 반환하는 값이 type 속성이 포함된 액션 객체를 의미한다.

middleware

미들웨어는 리듀서가 액션을 처리하기 전에 실행되는 함수로 디버깅 목적으로 상태값 변경 시 로그를 출력하거나, 리듀서에서 발생한 예뢰를 서버로 전송하는 등의 목적으로 미들웨어를 활용할 수 있다.
스토어에 등록할 때 middleware를 바인딩 하는 방식으로 진행된다.

전체적인 흐름


[출처 : redux 공식 홈페이지]

Redux Toolkit (RTK)

redux에서 오피셜로 추천하는 패키지로 리덕스 앱을 만들기 위해 필요한 것들이 포함돼있다. store 셋업, 리듀서를 만들거나 불변하게 업데이트하는 로직 등 많은 경우에 좀 더 간단하게 사용이 가능하다.

리듀서 구성하기

기존 리듀서 구성 방식

참고로 무조건 아래처럼 구성을 해야하는 것은 아니다. 중요한 것은 dispatch 메서드에 액션 타입을 이용해서 이벤트를 발생시키는 것과 리듀서가 (state,action) => nextState의 형식으로 불변성을 유지한채로 구현돼야하는 점이다.

const ADD_TODO = 'ADD_TODO'; // 액션 타입 선언
export const addTodo = (todo) => ({type: ADD_TODO,payload: {todo}}); // 액션 생성자 함수

const reducer = (state,action) => {
	switch(action.type) {
    	case ADD_TODO : 
        	return {
            	...state,
                todo : state.todo.concat(action.payload.todo) // 순수함수성을 뛰어야 한다.
            };
        default : 
        	return state;
    }
}
export default reducer;

RTK 이용 리듀서 구성 방식

import {createSlice} from '@reduxjs/toolkit';

export const counterSlice = createSlice({
	name : 'counter',
    initialState: { value : 0},
    reducers: {
    	increment: state => {state.value += 1}, // createSlice 내부적으로 불변 처리를 해준다.
        decrement: state => {state.value -= 1},
        incrementByAmount : (state,action) => {
        	state.value += action.payload;
        }   
    }
});
export {increment,decrement,incrementByAmount} = counterSlice.actions;
export default counterSlice.reducer;

확실히 하나하나 해줄 필요가 없이 간단하게 필요한 내용들만 적을 수 있어서 좋았다.
이 외에도 createAction, createAyncThunk 등 다양한 메서드들이 존재한다

profile
dygmm4288

0개의 댓글