Web-Frontend/React.js

[React.js] Redux

서노리 2023. 7. 20. 02:00
반응형

Redux

redux란 자바스크립트의 상태 관리 라이브러리로 클라이언트쪽의 데이터를 중앙 관리하기 위해 사용한다. 상태 관리 라이브러리 중 가장 npm trend가 높고 원리가 간단하다. 하지만 코드량이 상당히 많아질 수 있고, 서버쪽의 데이터를 관리하기 위해서는 react query를 사용하거나 redux-saga 등 비동기처리 미들웨어가 필수적이라는 단점이 있다.

 

Redux의 기본 개념 : 세 가지 원칙

1. Single source of truth

  • 동일한 데이터는 항상 같은 곳에서 가지고 온다.
  • 즉, 스토어라는 하나뿐인 데이터 공간이 있다는 의미이다.

2. State is read-only

  • 리액트에서는 setState 메소드를 활용해야만 상태 변경이 가능하다.
  • 리덕스에서도 액션이라는 객체를 통해서만 상태를 변경할 수 있다.

3. Changes are made with pure functions

  • 변경은 순수함수로만 가능하다.
  • 리듀서와 연관되는 개념이다.
  • Store(스토어) – Action(액션) – Reducer(리듀서)

 

Store

  • 스토어는 상태가 관리되는 오직 하나의 공간이다.
  • 스토어는 현재 애플리케이션의 상태와 리듀서, 몇 가지 내장 함수를 지닌다.
  • 스토어는 상태 값을 수시로 확인해 뷰에게 변경된 사항을 알려주게 된다.

Action

  • 액션은 상태 값에 어떠한 변화가 필요할 때 참조하는 객체이다.
  • 액션 객체는 type 필드를 반드시 가져야한다.
  • 액션 생성함수 : 액션을 만들어주는 함수로 매번 직접 액션 객체를 생성하지 않기 위해 사용한다.
// 액션 생성 함수

const addTodo = text => {
  return {
    type: 'todos/todoAdded',
    payload: text
  }
}

 

Reducer

  • 리듀서는 상태 값에 변화를 일으키는 함수이다.
  • 액션을 리듀서에 전달하여 스토어의 상태를 업데이트하게 된다.
  • 즉, 현재 상태 값과 액션 객체의 타입을 참고하여 새로운 상태를 반환한다.
  • 액션을 리듀서에 전달하기 위해서는 dispatch 메소드를 사용한다.

Dispatch

  • 디스패치는 스토어의 내장 함수 중 하나로 액션을 발생시키는 역할을 한다.
  • 디스패치 함수가 호출되면 스토어는 리듀서 함수를 실행시켜서 새로운 상태를 만든다.
store.dispatch({ type: 'increment' })

 

Provider

  • react-redux에 내장된 컴포넌트
  • Provider 컴포넌트로 하위 컴포넌트들을 감싸줌으로써 하위 컴포넌트들이 redux의 store에 접근할 수 있게 해준다.
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

redux 사용하기

0. redux, redux-devtools 설치하기

npm i redux react-redux
npm i --save-dev redux-devtools-extension

 

 

1. Store 만들기

// rootReducer 를 가진 Store 생성

import { createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer from '../reducers/index';

const store = createStore(rootReducer, composeWithDevTools());

 

2. reducer 만들기

import { combineReducers } from 'redux';
import account from './account';
import todos from './todos';

const rootReducer = combineReducers({
  account,
  todos
});

export default rootReducer;

위는 combineReducers 함수로 여러 개의 reducer 모듈들을 하나의 모듈로 합쳐, rootReducer라는 이름으로 export시키는 방법이다.

 

밑은 account 모듈의 코드이다.

//액션 타입 정의
//DUCKS 패턴 사용시에는 리듀서 이름을 액션에 삽입

const LOGIN = 'account/LOGIN';
const LOGOUT = 'account/LOGOUT';

//액션 생성 함수
export const login = userAccount => ({type:LOGIN, userAccount});
export const logout = userAccount => ({type:LOGOUT, userAccount)};

//초기 상태, 객체가 아니어도 된다.
const initialState = {
	userName : '',
    loggedIn : false
}

//리듀서
export default function account(state = initialState, action){
	switch(action.type){
    	case LOGIN:
        	return {...state, LoggedIn : true}
        case LOGOUT:
        	return {...state, LoggedIn : false}
            
        default:
        	return state; //반드시 default는 state return
    }
}

이렇게 액션과 액션 생성함수, 리듀서 함수를 기능별로 한 파일에 몰아 넣는 방식을 Ducks 패턴이라고하며 가장 트렌디한 패턴이라고 한다. 또 다른 방식으로는 액션과 리듀서를 서로 다른 파일에 정의하는 패턴이 있다.

 

3. 컴포넌트에서 사용하기

정석적인 리덕스 사용 방법은 컴포넌트를 Presentational 컴포넌트와 Container 컴포넌트로 나누고, 모든 액션과 상태를 Container 컴포넌트에서 불러온 후, Presentational 컴포넌트에 props로 넘겨주는 패턴이다.

const Login({ userName, loggedIn, login, logout }){
	...
}
const loginContainer = () => {
	const { userName, loggedIn } = useSelector(state => ({ //반드시 객체를 반환할 필요는 없다
    	userName : state.account.userName,
        loggedIn : state.account.loggedIn
    }));
    
    //store의 dispatch를 사용하게 하는 Hook이다.
    const dispatch = useDispatch();
    
    const onLogin = () => dispatch(login()); //앞서 리듀서 파일에서 작성했던 액션 함수이다
    const onLogout = () => dispatch(logout());
   
   return (
   	<Login
            login={onLogin}
            logout={onLogout}
            userName={userName}
            loggedIn={loggedIn}/>
   );
}

 

※ useSelector  사용 시 주의할 점

위 코드에서 처럼 useSelector 사용 시 객체로 가져올 수 있다. 하지만 객체로 가져올 시, 하나의 상태값이 변경되면 다른 상태값들도 리렌더링이 이루어진다. 따라서 다음과 같이 분할하여 가져오는 방법도 있다.

const userName = useSelector(state => state.account.userName);
const loggedIn = useSelector(state => state.account.loggedIn);

참고

 

Redux(리덕스)란? (상태 관리 라이브러리) - 하나몬

Redux(리덕스)란? 무엇인지 부터 간단한 실습까지 (상태 관리 라이브러리 리덕스 알아보기) ⚡️ Redux(리덕스)란? Redux(리덕스)란 JavaScript(자바스트립트) 상태관리 라이브러리이다. Redux(리덕스)의

hanamon.kr

 

 

[React] Redux 이해하기

Redux는 Context API를 기반으로 만들어진 상태 관리 라이브러리로 reducer와 action이라는 개념 또한 존재해 상당히 유사하다. 프로젝트의 규모에 따라 Context API만으로도 충분하다. Context API와의 차이점

muhly.tistory.com

 

반응형