본문 바로가기

프론트엔드/React

[ React ] [Chapter 16] 리액트의 리덕스 란

728x90

리덕스 란

 

리덕스는 상태 관리 라이브러리 이다.

 

1.리덕스를 사용 하면 애플리케이션의 전체 상태를 관리할 수 있다.(리덕스 같은 라이브러리를 사용하지 않아도 리액트 만으로도 물론 가능하다.)

 

2. 컴포넌트 코드로부터 상태 관리 코드를 분리할 수 있다. 아무래도 컴포넌트에서 상당히 많은 코드를 작성하게 되는데 그러다 보면 컴포넌트 쪽 코드가 많아져서 가독성이 떨어지는 경우가 있다. 그래서 상태 관리 코드를 분리해주면 컴포넌트 쪽 코드가 좀 더 가벼워 집니다.

 

3.미들웨어를 활용한 다양한 기능 추가가 가능하다. 데이터를 처리하는 중간과정에서 어떤 로직을 넣어서 필요한 기능을 추가할 수 있다.

 

4.서버사이드(SSR) 렌더링 시 데이터 전달이 간편하다.

 

5.리액트 context api 보다 효율적인 렌더링이 가능하다.

 

리덕스 규칙

 

1.하나의 애플리케이션 안에는 하나의 스토어가 있다.

하나의 애플리케이션에선 단 한개의 스토어를 만들어서 사용해야 한다. 여러개의 스토어를 사용하는것은 가능은 하나, 권장하지는 않는다. 하지만 특정 업데이트가 너무 빈번하게 일어나거나, 애플리케이션의 특정 부분을 완전히 분리시키게 될 때 여러개의 스토어를 만들 수도 있지만 그렇게 하면 개발 도구를 활용을 하지 못하게 된다.

 

2.상태는 읽기 전용

리액트에서 state를 업데이트해야할 때 setState를 사용하고, 배열을 업데이트 해야 할 때는 배열 자체에 push 하지 않고 concat 함수나 새로운 배열을 만들어 비구조 할당으로 등등 이렇게 업데이트를 하는데

리덕스도 마찬가지이다. 기존의 상태는 건들이지 않고 새로운 상태를 생성하여 업데이트 해주는 방식으로 해주면 나중에 개발자 도구를 통해서 뒤로 돌릴 수도 있고 다시 앞으로 돌릴 수도 있다.

리덕스에서 불변성을 유지 해야 하는 이유는 내부적으로 데이터가 변경 되는 것을 감지 하기 위하여 shallow equality 검사하기 때문이다. 이를 통하여 객체의 변화를 감지 할 때 객체의 깊숙한 안쪽까지 비교를 하는 것이 아니라 겉핥기 식으로 비교를 하여 좋은 성능을 유지하는 것이다.

 

3.변화를 일으키는 함수, 리듀서는 순수한 함수여야 한다.

순수한 함수 라는 개념이 익숙하지 않지만 3가지만 기억 하면 된다

3-1. 리듀서 함수는 이전 상태와 액션 객체를 파라미터로 받는다.

3-2. 이전의 상태는 절대로 건들이지 않고 변화를 일으킨 새로운 상태 객체를 만들어서 반환합니다.

3-3. 똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과값을 반환 해야 한다.

이 3가지 사항만 주의 하면 된다.

 

리덕스 구조

 

 

리덕스에는 4가지의 기본 요소가 있다 액션, 미들웨어, 리듀서, 스토어가 있다.

그리고 프론트엔드 애플리케이션을 만들 때 이러한 리덕스의 요소들과 뷰를 연결해서 사용한다.

 

처리 플로우

 

먼저 뷰 쪽에서 상태값을 변경하고 싶을 때 액션을 발생 시키고, 그 액션을 미들웨어가 처리를 하고,(미들웨어에 원하는대로 여러가지 기능을 넣을 수도 있다 안넣었으면 따로 처리하는것은 없다) 처리를 하면 리듀서에서 액션에 의해 상태값이 어떻게 변경되는지 처리하는 로직을 담고 그로직에 의해 처리를 한다. 리듀서에서 처리를 하면 새로운 상태값이 되고 그 새로운 상태값을 스토어가 저장을 하고 뷰에게 알려준다.

 

리덕스 요소 중 액션

액션은 type 속성값을 갖고 있는 객체이다.

하나의 객체로 표현이 되는데 액션 객체는 다음과 같은 형식으로 이뤄져 있다.

{ type : 'itjava' ...부가적데이터 }
store.dispatch({ type : 'itjava/add', title : '음음' })
store.dispatch({ type : 'itjava/re', id : 11 })

액션 코드로 살펴보면 위 코드에는 2가지 액션이 있는데 여기서 dispatch는 액션이 발생했다는 것을 리덕스에게 알려주는 함수이다.

 

액션을 구분하기 위해서 type 속성값을 사용합니다 즉 액션을 구분하기 위함이기 때문에 type 속성값은 유니크 해야합니다.

 

function addItJava({ title }) {
	return { type : 'itjava/add', title };
}
store.dispatch(addItJava({ title : '음음' }))

이 코드는 첨에 보여준 코드랑 다른데 다른 점이 함수를 이용한것입니다. 이렇게 직접 객체를 설정 하는 것이 아니라

함수를 이용해 해당 객체 생성을 유니크하게 관리를 해줘야 합니다. 꼭 이렇게 해야 한다는건 아니지만 개발 생산성과 관리의 유용성 등 을 생각하면 직접 객체 설정 보다는 함수로 관리 하는 편이 좋습니다

 

export const ADD = 'itjava/add';

exprot function addItJava({ title }) {
	return { type : ADD, title };
}

그리고 위 코드 처럼 액션 type을 따로 상수로 빼서 관리 하는게 좋습니다 왜냐하면 나중에 리듀서에서도 사용할 것이기 때문입니다.

 

리덕스 요소 중 미들웨어

미들웨어를 사용하면 액션이 디스패치 된 다음 리듀서에서 해당 액션을 받아와서 업데이트 하기 전에 추가적인 작업을 할 수 있다.

 

보통 리덕스에서 미들웨어를 사용하는 주된 사용 용도는 비동기 작업을 처리할 때 많이들 사용 한다.

예를 들어 리액트 앱에서는 우리가 만약 백엔드 API를 연동해야 된다면 리덕스 미들웨어를 사용하여 처리하곤 합니다.

 

미들웨어는 누구든지 그냥 만들어 사용이 가능 하나, 일반적으로는 리덕스 미들웨어 라이브러리를 설치 하여 사용 한다.

비동기 작업에 관련된 라이브러리는 redux-thunk , redux-saga , redux-observable , redux-promise-middleware 등이 있다.

const itjava = store => next => action => next(action);

하나의 미들웨어는 위 코드 처럼 함수이다.

 

그리고 화살표 함수가 여러번 사용이 되는데 저렇게 여러번 사용이 되서 복잡해 보일 수 있는데 그리 복잡하지 않다.

 

하나씩 살펴보겠다.

어떠한 함수가 있었는데(store) 그 함수를 실행을 하면 그 뒤에 있는 next => action => next(action); 함수가 반환이 되는 거고 또 실행을 하면 최종적으로 이 함수가action => next(action); 나와서 action 실행하면 next() 함수를 호출을 한다.

 

즉 이 함수를 function 키워드를 사용 하여 작성한다면 다음과 같을것이다

function itjava(store) {
  return function (next) {
    return function (action) {
      // 하고 싶은 작업...
    };
  };
};

 

리덕스 요소 중 리듀서

리듀서는 액션이 발생했을 때 새로운 상태값을 만드는 함수이며, 변화를 일으키는 함수이다.

 

현재의 상태와, 전달받은 액션을 참고하여 새로운 상태를 만들어서 반환한다.

 

역시나 리듀서에서도 상태값을 불변 객체로 관리 해야 한다.

 

function reducer(state, action) {
	// 상태 업데이트 로직
}

 

리덕스 요소 중 스코어

 

리덕스에서는 한 애플리케이션 당 하나의 스토어를 만들게 됩니다. 스토어 안에는 현재의 앱 상태와 리듀서가 들어가 있고, 추가적으로 몇가지 내장 함수들이 들어가 있다

createStore(리덕스함수, ...미들웨어 함수)

스코어로 디스패치 함수를 불러와 액션을 일으킵니다. 또 한 subscribe 함수로 액션 처리가 끝난다는 걸 알수도 있습니다.

   관련 글

 

저의 글을 읽어 주셔서 감사합니다. 오늘도 즐거운 하루 보내세요.

저의 글이 조금이나마 도움이 되셨다면 로그인이 필요 없는 공감♥ 한번 꾸욱 눌러주세요 하하~

728x90