Redux 2편: redux 그래서 어떻게 쓰는건데요

이은지·2022년 2월 20일
1

월요일 말도 안돼


그래서 redux 왜 쓰는진 알았는데 어떻게 쓰냐구요? 알려드릴게요

얘네들을 이해하면 됩니다.

  • 액션 객체
  • 액션 생성 함수
  • 리듀서 함수

하나하나 알아봅시다.

💚 대략적인 큰그림부터 그려보자

redux store에서 모든 state와 state의 변경을 관리한다고 했었지 않습니깡.
좀 더 정확히 이야기하면 이렇습니다.

리듀서 함수: state 변경할 수 있는 권한을 가지고 있는 유일한 함수.
컴포넌트들: "리듀서님 state 좀 이렇게 이렇게 변경해주세요!" 하고 요청.

근데 리듀서 함수는 엄격한 친구라 아무렇게나 요청하면 요청을 받아주지 않는다.
액션 객체라는 형식을 지켜서 요청해야 받아줌

💚 redux store 구성요소

보통 이렇게 구성이 되어 있다.

하나하나 살펴보자. 카운터 예제가 가장 간단하므로 카운터 예제로 살펴보쟈.
(참고로 이렇게 리듀서와 액션 관련 코드들을 하나의 파일에 작성하는 방식을 Ducks 패턴이라고 부른다.)

// 액션 타입
const INCREASE_NUMBER = "counter/INCREASE_NUMBER";
const DECREASE_NUMBER = "counter/DECREASE_NUMBER";

// 액션 생성 함수
export const increase = () => {
	return {
    	type: INCREASE_NUMBER;
    }
}; 

export const decrease = () => {
	return {
    	type: DECREASE_NUMBER;
    }
};

// 리듀서 함수
export default function counter(state={number:0}, action){
	switch(action.type) {
    	case INCREASE_NUMBER:
        	return {
            	...state,
                number: number+1
            };
        case DECREASE_NUMBER:
        	return {
            	...state,
                number: number-1
            };
        default:
        	return state;
    }
}

액션 객체

위에서 언급한 것처럼, 일종의 요청서 혹은 주문서라고 생각하면 된다.
컴포넌트가 액션 객체라는 요청서에 "state를 이렇게 변경해줘~"라는 요청을 적어서 리듀서 함수에게 전송하는 거다.
이 요청서에 적어 보내야 리듀서가 그 요청을 들어준다.

액션 객체는 보통 이렇게 생겼다.
{type: 액션 타입명, payload: 같이 보내고싶은 데이터}
여기서 type은 필수고, 데이터는 옵션이다. (데이터 이름이 꼭 payload일 필요는 없다. 여러 개를 보낼 수도 있다.)

예를 들어,
{type: "increase_number", amount: 2} // amount만큼 카운터를 증가시켜주세요!
이렇게 생긴 액션을 전달하면 리듀서 함수에서는 컴포넌트가 보낸 amount라는 데이터값을 참조해서 카운터를 2만큼 증가시킬 수 있다.

리듀서 함수

state를 관리하고 변경하는 총 책임자.
컴포넌트들의 요청에 따라 state를 업데이트하고, 업데이트된 state를 리턴한다.

리듀서에는 액션별로 state를 업데이트하는 방법이 정의되어 있다.
위에 코드를 보면 switch문을 사용해 각 액션별로 state를 업데이트 하는 코드가 적혀있는 것을 볼 수 있다.
Ex INCREASE_NUMBER 라는 액션이 발생하면 number 라는 state를 1 증가시킨다.(state 변경)

모든 state 업데이트가 이 리듀서 함수에 정의되어 있는 방법대로 이루어진다.
redux store 내의 state를 업데이트 하려면 꼭 리듀서 함수를 거쳐야 함.

액션 생성 함수

말그대로 파라미터를 받아서 액션 객체를 리턴해주는 함수다.
컴포넌트에서 좀 더 깔끔하게 액션을 발생시키기 위해 사용한다. (참고로 액션을 발생시킨다는 걸 "dispatch한다"고 한다.)
따라서 리듀서함수와 같은 파일에 export const로 정의하고, 컴포넌트에서 import 해서 쓴다.

컴포넌트: 액션 수행에 필요한 데이터를 액션생성함수의 파라미터로 넘겨준다.
액션생성함수: {type: 액션명, payload: 컴포넌트가 넘겨준 데이터} 이렇게 생긴 액션객체를 리턴.
다시 컴포넌트: 액션생성함수가 리턴해준 액션객체로 액션을 dispatch
리듀서 함수 : 컴포넌트가 발생시킨 액션에 따라 state를 변경

꼭 액션함수를 써서 액션을 dispatch할 필요는 없다.
그냥 컴포넌트 내에서 이렇게 할 수도 있다.
dispatch({type: "increase_number", payload: 2})

근데 일단 보기에 좀 난잡하고, 매번 type 어쩌구 타이핑 하는 게 번거롭다.
무엇보다 비동기 작업이 필요할 때 그 작업을 액션생성함수 내에서 처리하는 경우가 많아서, 그냥 나는 이렇게 통일해서 쓴다.

다음 글에서는 redux 내에서 비동기 작업을 처리하는 방법에 대해 알아보겠다.

0개의 댓글