Redux 미들웨어 비동기 구현해보기 IT

redux 미들웨어에서 시간이 걸리는 요청이 발생하면 어떻게 동작할까?
: 요청  > 미들웨어 > 시간이 걸리는 동작(완료될 때 까지 블록) > 미들웨어 > 응답(완료까지 블록)


응답이 도착할 때 까지 블록되는 것은 원치 않으므로

백그라운드에서 비동기로 상태가 반경되는 것이 좋겠다. 무엇이 필요할까?
  • 비동기를 고려한 상태 설계 : 시간이 소요되므로 처리상태(요청, 성공, 실패)와 처리시간을 기록할 수 있어야 한다.
  • 백그라운드 프로세싱 및 체이닝 : 백그라운드_처리(시간이 걸리는 작업).then(다음 작업).then(다음 작업)
미들웨어는 동기처리를 유지하지만, 액션에 따라 비동기로 동작하게 하자.


이를 가능하게 하는 비동기 액션 생성자와

함수형태의 비동기 액션을 구동시키는 thunk 미들웨어 두가지를 구현해봤다.



1) 비동기 액션 생성자 : fetch_posts(reddit)

액션생성자를 함수(동기와 비동기 dispatch 처리가 혼합된 코드블록)로 정의한다.
(리듀서는 상태변경에 대한 것이지 동기/비동기 메커니즘에 대한 것은 아니므로 reducer에 담지 않는다.
(액션에 따라서 동기/비동기를 달리하므로 액션내에 비동기 코드블록을 담도록 한다.


동기액션은 dispatch을 호출해서 미들웨어까지 동기적으로 처리완료 되도록 하고

비동기액션은 Concurrent.future {레딧json요청}.then{파싱}.then{dispatch} 처럼

백그라운드 작업을 순차적으로 진행한 뒤 dispatch를 호출해서 

시간이 소요되는 작업 처리-상태변경-미들웨어 적용이 백그라운드에서 진행되도록 한다.
(백그라운드 프로세싱과 체이닝은 concurrent-edge gem의 future, 체이닝을 사용했다.


2) thunk 미들웨어

코드블록 형태의 lambda 액션과 
기본 hash 액션을 구동하는 미들웨어가 필요하다.

thunk란 미들웨어를 만들고 미들웨어 스택에 추가한다.
logger로 찍은 stdout은 다음과 같다.
며칠간 redux에서 주제가 되는 것들을 대략적으로 루비로 구현해 봤다.
(combine_reducer, subscribe, 미들웨어 스택, 미들웨어 작성, 비동기 액션생성자, thunk 까지 완료.
(그 밖의 상태간 트랜잭션이나, 보일러 플레이트 축소등은 흥미가 떨어져 여기서 멈췄다.


Redux 유익하고 재
미있었다. 

Redux 미들웨어 스택기능 구현해보기 IT

미들웨어란 핸들러스택을 의미한다.

처리결과를 다음 핸들러에 연쇄적으로 전달하는 방식으로

복잡한 처리를 단순화시킬 수 있다. (요청 > 핸들러1~n > 어플리케이션)


미들웨어 스택은 핸들러 파이프 개념을 갖는다. 루비로 구현하면 다음과 같은식이다.

Redux도 복잡한 처리를 위해서 디스패처를 연쇄시킬 필요성이 생길 수 있다.

Redux의 미들웨어 스택을 위와 같은 느낌으로 다음과 같이 구현할 수 있다.
간단한 샘플

실행결과. (로거 > 레코더 > 어플리케이션 순으로 진입해서 역순으로 연쇄적으로 처리된다.)
특별한건 없다. 


덧, Redux 홈의 몽키패칭 > 숨기기 > 제거 > 미들웨어 완성 부분은 읽어볼만하다. 

덧, 시나트라 + Rack의 핸들러 스택은 다음과 같은 모양이다. 그럴듯하다.


Redux 구현해보기 IT

Redux를 간단히 구현해보자.
  • 상태는 불변성을 갖는다.
  • 상태를 저장하는 저장소는 전역으로 1개
  • 상태의 부분부분을 가져오거나 변경할 수 있다.
  • 상태의 각 부분들은 각각 리듀서를 갖고 리듀서를 통해서만 변경된다.
  • 리듀서는 액션을 획득해서 동작한다.
  • 디스패치(액션)을 통해서 상태를 변경한다.
  • 액션은 type을 갖는다.
  • 리듀서는 액션의 type 정보를 통해서 취해야 할 동작이 무엇인지 판단할 수 있다.
  • 분할된 리듀서는 combine_reducers를 통해 하나의 루트 리듀서로 병합될 수 있다.
  • subscribe를 통해 디스패치 수행시 실행할 코드조각을 지정할 수 있다. 이를 리스너라고 하자
  • 리스너는 여러개가 될 수 있고 각 리스너에 명칭을 부여할 수 있다.
  • unsubscribe(리스너명)으로 디스패치에 수행될 리스너를 제거할 수 있다.
이러한 요건을 만족하는 Redux를 사용하는 어플리케이션은 아마도 아래와 같은 모양이 될테다.
root_reducer = Redux.combine_reducers( { state_key1: reducer1, state_key2: reducer2, ... }
redux = Redux.new(init_state, &root_reducer)
redux.subscribe("로거") { p redux.state }
redux.dispatch(action_creator(add_todo["redux 구현하기"])
redux.unsubscribe("로거")

Redux를 구현하면 아래와 같은 모양이 된다.
  • 미들웨어 스택(웜업 > 미들웨어 > 어플리케이션)을 만들 수 있게 한다거나..
  • 비동기를 위한 액션상태 추가나 그에 따른 코드는 구현치 않았다.
이를 기반으로 redux 홈에 있는 샘플(덧/뺄셈, todo)을 구현하면 아래와 같은 모양이 된다.
  • 리듀서나 액션쪽을 각각 분리해낼 수 있다. 개념검증 삼아 구현한 거라 1개 파일에 때려넣었다.


1 2 3 4 5 6 7 8 9 10 다음