[Redux] 추가 정리

김지민·2023년 5월 1일
0

Redux

목록 보기
2/2

1. Redux를 사용한 이유

로그인 정보를 관리하고자 했을 때, 로그인 정보를 관리하기 위한 state를 구성하고
이를 컴포넌트들이 공유하면서 사용하려면, 컴포넌트간의 state 전파 및 변경 관리가 복잡해 집니다.

때문에, 컴포넌트 외부에서 전역적으로 상태관리를 하면서 로그인 정보와 같은 전역 상태를 redux store에 저장하고, 컴포넌트에서 이를 사용하며, 상태 전파 및 변경 관리를 보다 쉽게 할 수 있습니다.

react의 특성상 컴포넌트 간의 상태 전파시 props drilling 문제로 쓸데없는 리렌더링 문제도 야기 될 수 있습니다. 상태를 전역적으로 관리하면서 성능도 개선하기 위해서 redux를 사용했습니다.

2. Redux 구성 원리

1) action

상태를 변경하기 위한 객체, 상태 변경의 과정을 담고 있습니다.

2) dispatch

상태 변경을 위한 action을 reducer에 전달하는 것을 dispatch라고 합니다.

3) Reducer

상태 변화를 일으키기 위한 함수를 reducer라고 합니다. reducer는 현재 상태와 처리한 액션을 파라미터로 받아서 새로운 상태를 반환합니다.

한마디로 store에 저장되어 있는 객체를 변환 시키는 것을 목적으로 action이라는 상태 변화를 위한 함수를 정의하고 이를 dispatch를 통해서 reducer에서 action이 실행되게 하는 것이다.

3. 오픈소스 들여보기

dispatch가 실행되면 모든 reducer를 돌면서 state와 action를 실행시킵니다.
reducer를 실행시켜 final과 previous 두 개의 객체를 만들어서 두개의 객체를 비교해 줍니다.
그 다음에 변경 여부는 값이 아닌 reference 비교로 결정됩니다.

참조 비교와 변수와 상수 값의 비교

참조 비교를 하는 이유는?
불변성을 유지하면서 상태를 업데이트하기 위해
객체나 배열의 값을 비교한다면, 객체나 배열 내부의 값이 변경됐는지 알아내기 위해 반드시 모든 값을 비교해야 합니다. 이 경우 비교하는 데 시간이 많이 걸리고, 객체나 배열의 크기가 크면 성능에 문제가 생깁니다.

불변성 유지
객체나 배열 드의 값이 생성된 후에는 그 값을 변경할 수 없는 것
값을 수정할 때는 원본 데이터를 변경하지 않고 새로운 객체를 생성

그래서 우리는 Immer과 같은 라이브러리를 사용한다!

다시 정리하자면

-> 오픈 소스를 보면, combinationreducers에서 reducer가 이전 객체와 이후 객체를 참조 비교하는 것을 발견할 수 있다!
-> 그래서 우리는 reducer에서 immer 함수를 써서 새로운 객체를 반환한다.
-> 새로운 객체를 복사하는 비용이 들어감에도 불구하고 참조 비교를 왜 하는가?
-> 리렌더링 과정에서는 비교가 필수적이고, 실행될 때마다 비교를 해야한다. 그런데 이때 값 비교가 이루어지면, 시간이 많이 걸리고 객체나 배열의 크기가 크면 성능의 문제가 생긴다.
-> 때문에 우리는 불변성을 지키며 개발을 해야한다!

그냥 개발하는 것보다 이유를 알고 개발하면 복잡한 구동원리의 디테일한 부분까지 놓치지 않고 코드를 작성할 수 있을 수 있다는 것을 깨달았다.

3. 다른 상태관리 라이브러리

1) redux
대규모 프로젝트에서 유용하게 쓰일 수 있기 때문에
-> redux devetool를 보면서 시간 여행이 가능
상태 변화의 순서을 앞뒤로 이동하면서 확인

불변성 유지, 예측 가능한 상태 관리 제공

2) 모벡스
관찰 가능한 상태를 선언적으로 정의하고, 상태가 업데이트 될 때, 자동으로 뷰를 업데이트

반면, redux는 액션과 리듀서를 통해 상태를 업데이트하고, 이를 구독하는 컴포넌트에서 업데이트를 수동적으로 처리

-> redux가 더 귀찮을 수 있지만, 이러한 수동 처리가 예측가능하게 해주기 때문에 복잡성이 증가할 수록 중요한 요소가 될 수 있다.

3) recoil
react hook을 사용해서 간편
상태의 의존성을 자동으로 추적하기 때문에 상태의 업데이트 관리합니다.

업데이트의 자율성을 없애는 것이 개발의 편리하게 만들 수 있습니다.

4. redux - saga를 사용한 이유

미들웨어
미들웨어는 액션과 리듀서 사이에서 동작하는 함수, 액션과 리듀서 사이에서 미들웨어를 거치면, 액션이 디스패치 되어서 리듀서에 도달하기 전에 미들웨어에서 추가적인 작업(라우팅)을 할 수 있다.

한번에 dispatch를 여러번 해주게 한다.

1) thunk

  • 단순한 비동기 작업 처리가 적합, api 호출, promise 처리, 타이머 등 간단한 비동기 작업을 처리할 때 용이하다.

로그인
-> request(서버), success, failure

로그아웃
-> request(서버) , success, failure

thunk saga는 비동기 작업을 위해서 사용되는 미들웨어입니다. 데이터를 받아와서 상태를 업데이트 해야한다.

오래 걸릴 때, 다른 작업을 진행하게 한다.

2) saga

  • 여러 사이드 effect, delay, takelatest, throttle(디도스 공격 방어)
  • 비동기 작업의 순서 보장이 용이함, redux saga는 제너레이터 함수를 이용해 작성하기 때문에, 비동기 작업의 순서를 보장할 수 있다.

5. async await 하면 되지 않나..? 왜 굳이 비동기 처리를 해주어야 하나?

그 전에 동기 비동기 복습!

// 비동기(aysnchronous) 실행 방식 
// 실행순서와는 별개로 독립적인 자기의 시간표에 따라서 동작한다.

console.log(1);
console.log(2);
setTimeout(function(){console.log(3)}, 5000);
console.log(4);

//1
//2
//4
//3

우리는 통신을 할 때, 주로 비동기 처리를 해준다. 왜냐하면 통신할 때는 항상 어떻게 진행될지 예측가능하기 어렵기 때문이다.

통신하는 동안 다른 작업을 진행할 수 있다 -> 비동기적으로 작업을 처리했기 때문이다.

그러면 redux saga 비동기 처리를 해보자!
간단한 액션예제

  • 요청 액션
  • 비동기 요청 액션
  • 비동기 요청 성공 액션
  • 비동기 요청 실패 액션

액션 함수를 요청하면 비동기 호출을 요청하고(request) 이에 따른 비동기 성공 (success), 실패(failure)가 나오게 된다.


functio* postUpsertSaga(info) {
  yield call(sagaApi, PostUpserAction.upsertPost, BlogApi.usertPost, info.payload)
   
  	function * succuess(success) {
      const {postNo, categoryNo} = yield success.data;
      yield put(PostsAction.getPosts(categoryNo));
      yield goPostDetailPage(categoryNo, postNo); // 게시글 자세히 보기
    },
     
      function* failure(error) {
        const {message} = yield error;
        yield alert(message !== undefined ? message : '게시글 편집 실패.');
      });
}

exoprt default function* root() {
  yield all([
    takeLastest(PostUpsertAction.POST_UPSERT.INDEX, postUpsertSaga) // asyncall
  ]);
}

call을 사용해서 saga를 묶어서 호출한다.

  • upsertPost를 호출해 게시글 upsert 작업을 시작한다.
  • 게시글 upsert작업이 성공한다.
  • api 결과값에 있는 게시글 번호와 카테고리 번호로 게시글 자세히 보기
  • 실패 할 경우 편집 실패 메시지. 발생

async/await 문법을 통해 서버에 요청을 날리는게 가장 간편한 방법처럼 보이지만,
많이 쓸수록 컴포넌트에 비즈니스 로직이 직접 의존하는 경우가 많아지고, 얽히고 섥혀서 ui를 수정하기 위해 비즈니스 로직을 건드려야 하거나 그 반대의 경우도 생길 수 있다.

profile
💡Habit is a second nature. [Git] https://github.com/Kimjimin97

0개의 댓글