본문 바로가기
✨ Front-end/리액트(React)

[React] Redux 개념과 동작원리

by 환풍 2023. 9. 25.
728x90

Redux

Redux는 리액트 없이도 사용할 수 있는 상태관리(state management) JavaScript 라이브러리이다.
애플리케이션의 많은 부분에 필요한 "전역" 상태를 관리하는 데 도움이 된다.


왜 필요함?

상태관리가 왜필요할까? 하나의 컴포넌트가 사용하는 데이터 역할을 상태라고 본다.
state 는 자주 변하고 상황에 따라 최상위 루트까지 접근을 해야하는데, 
매번 props로 계속 내려주는 비효율적인 일을 생략하고, 최단거리로 사용할 수 있다.
그래서 예측이 가능하고, 예상대로 작동할 것이라는 확신을 갖도록 도와주기 때문이다.

react에서는 상태와 속성(props)을 이용한 컴포넌트 단위 개발 아키텍처를 배웠다면, Redux에서는 컴포넌트와 상태를 분리하는 패턴을 배운다.

Redux의 구조

Action ,Dispatch , Reducer , Store 이 네가지를 이용하여 상태관리 저장소를 만들고, 전달해주는 Redux의 중점인 키워드이다. Action → Dispatch → Store → View 순서로 데이터가 단방향으로 흐른다.(Flux)

Redux Hooks

Redux Hooks는 앞에 네가지 키워드와 컴포넌트를 연결시켜 redux의 state에 접근할 수 있도록 Hooks 메서드를 제공한다. 
그 중에서 크게 useSelector(), useDispatch() 이 두 가지의 메서드를 기억하면 된다.

사용방법

npm i redux : 일반설치

npm i redux react-redux : 리액트에서 사용시 설치

 

Action

어떤 동작을 할것인가, 객체형태로 정의를한다. 이때 type 을 필수로 사용한다.
어떤 동작을 하는지 명시해주는 역할을 하기 때문이며, 대문자와 Snake Case로 작성한다. 

여기에 필요에 따라 payload 를 작성해 구체적인 값을 전달한다.

{
   type: 'ADD_TODO',
   data: {
       id: 1,
       text: "Redux Help"
   }
}
액션 객체를 생성하는 함수를 만드는 경우가 더 많은데, 액션 생성자(Action Creater) 라 한다.

// payload가 필요 없는 경우
const increase () => {
  return {
     type: 'INCREASE',
  }
}

// payload가 필요한 경우
const addTodo (todo) => {
  return {
     type: 'SET_TODO',
     payload: todo
  }
}

Dispatch

Dispatch는 Reducer로 Action을 전달해주는 함수이다. Dispatch의 전달인자로 Action 객체가 전달된다.
Action 객체를 전달받은 Dispatch 함수는 Reducer를 호출한다.

1
2
3
4
5
6
7
// Action 객체를 직접 작성하는 경우
dispatch( { type: 'TODO' } );
dispatch( { type: 'SET_TODO', payload: 3 } );
 
// 액션 생성자(Action Creator)를 사용하는 경우
dispatch( increase() );
dispatch( addTodo(3) );
cs

Reducer

Reducer는 Dispatch에게서 전달받은 Action 객체의 type 값에 따라서 상태를 변경시키는 함수이다.
Reducer는 순수함수여야 한다.
외부 요인으로 인해 기대한 값이 아닌 엉뚱한 값으로 상태가 변경되는 일이 없어야하기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const count = 1
// Reducer를 생성할 때에는 초기 상태를 인자로 요구합니다.
const counterReducer = (state = count, action) {
 
  // Action 객체의 type 값에 따라 분기하는 switch 조건문입니다.
  switch (action.type)
 
    //action === 'INCREASE'일 경우
    case 'INCREASE':
return state + 1
    // action === 'DECREASE'일 경우
    case 'SET_TODO':
return state - 1
    // 해당 되는 경우가 없을 땐 기존 상태를 그대로 리턴
    default:
      return state;
// Reducer가 리턴하는 값이 새로운 상태가 된다.
 
// 만약 여러 개의 Reducer를 사용하는 경우, 
// Redux의 combineReducers 메서드를 사용해서 하나의 Reducer로 합쳐줄 수 있다.
  
import { combineReducers } from 'redux';
 
const rootReducer = combineReducers({
  counterReducer,
  anyReducer,
  ...
});
cs

 

Store

Store는 상태가 관리되는 단 하나의 저장소의 역할을 한다. (Redux 앱의 state가 저장되어 있는 공간) 아래 코드와 같이 createStore 메서드를 활용해 Reducer를 연결해서 Store를 생성할 수 있다.

1
2
3
4
5
6
7
8
9
import { createStore } from 'redux';
 
const store = createStore(rootReducer);
// Redux Hooks 메서드는 'redux'가 아니라 'react-redux'에서 불러온다.
import { useSelector } from 'react-redux'
const counter = useSelector(state => state.counterReducer)
console.log(counter) // 1
 
useDispatch()
cs


Action 객체를 Reducer로 전달해 주는 메서드이다.
위에서 Dispatch를 설명할 때 사용한 dispatch 함수도 useDispatch()를 사용한 것이다.

1
2
3
4
5
6
7
8
import { useDispatch } from 'react-redux'
 
const dispatch = useDispatch()
dispatch( increase() )
console.log(counter) // 2
 
dispatch( setNumber(5) )
console.log(counter) // 5
cs

 

3가지 원칙

Single source of truth


동일한 데이터는 항상 같은 곳에서 가지고 와야 한다는 의미로, Redux에는 데이터를 저장하는 Store라는 단 하나뿐인 공간이 있음과 연결이 되는 원칙이다.
State is read-only

상태는 읽기 전용이라는 뜻으로, React에서 상태갱신함수로만(set) 상태를 변경할 수 있었던 것처럼, Redux의 상태도 직접 변경할 수 없다. 즉,Action 객체가 있어야만 상태를 변경할 수 있음과 연결되는 원칙이다.
Changes are made with pure functions

변경은 순수함수로만 가능하다는 뜻으로, 상태가 엉뚱한 값으로 변경되는 일이 없도록 순수함수로 작성되어야하는 Reducer와 연결되는 원칙이다.

반응형

댓글