2021/05/17 - redux-thunk 내용추가
Next Redux Wrapper
일반적으로 React에 Redux를 붙일 때에는 하나의 Redux store만 존재하기 때문에 어렵지 않다.하지만 Next.js에서 Redux를 사용하게 되면 여러 개의 Redux store가 생성된다.
그 이유는 Next.js에서는 User가 Request를 보낼때마다 Redux store를 새로 생성하기 때문이다. 그리고 Next.js에서 제공하는 getInitialProps와 getServerSideProps에서도 Redux store에 접근이 가능
하도록 해야되기 때문에 NextJS에서 Redux를 붙일때 꽤나 복잡하다. 하지만 이를 간편하게 해주는 라이브러리가 있는데 바로 Next Redux Wrapper
이다.
next redux wrapper 설치
/store/configureStore.js
1 | import { createWrapper } from 'next-redux-wrapper'; |
_app.js
1 | ... |
Next에서는 버전 6 이후부터는 일반적으로 Redux를 사용했을때 Provider로 감싸주는 부분이 생략되었다.
(별도로 Provider로 감싸주지 않아도 알아서 처리해준다)
이제 각 각의 컴포넌트에서 만들어준 store 객체를 이용해서 action을 dispatch해주게 되면 store에 있는 상태값이 바뀌게 된다.
1 | store.dispatch({ |
HYDRATE
만들어 준 reducer에서 action.type으로 사용할 HYDRATE를 next-redux-wrapper
로부터 import해준다.
HYDRATE의 등장은 SSR을 위한 것으로, getInitialProps와 getServerSideProps에서도 Redux store에 접근이 가능하도록 하기 위한 처리이다.
1 | import { HYDRATE } from 'next-redux-wrapper'; |
분리된 reducer는 아래와 같이 combineReducers를 사용해서 합쳐준다.(기존의 방식과 다른 부분은 SSR을 위해 HYDRATE 상태를 포함하는 reducer가 포함시키는 부분이다
)
1 | import { HYDRATE } from 'next-redux-wrapper'; |
styled-components와 SSR
SSR에서 styled-components를 적용하기 위해서는 별도의 설정이 필요하다.
SSR일때는 Front 서버에서 HTML을 데이터와 합쳐서 화면에 그려주게 된다.
styled-component는 SSR에 대한 별도의 설정이 없다면, styled-components가 적용이 안된 상태로 화면에 렌더링되는 것이다.
상태 데이터 속성 이름과 시퀄라이즈
DB쪽에서는 시퀄라이즈를 통해 특정 정보가 또 다른 정보과 관계가 있다면, 해당 데이터들을 함쳐서 첫 문자를 대문자로 바꿔준다.
따라서 상태값 속성 중에 상태 자체로써만 사용되는 데이터 속성의 경우에는 전부 소문자 표기로 속성이름을 넣어주고, 다른 정보와 관련이 있는 속성의 경우에는 첫 문자를 대문자로 해서 넣어주도록 한다.
front/reducers/post.js
User, Images, Comment는 복수의 정보들을 합쳐서 주기 때문에 아래와 같이 첫 문자를 대문자 표기로 하였다. (프론트 개발시에는 서버쪽에서 어떻게 데이터를 보낼 것인지에 대해 서버 개발자에게 사전에 협의하는 것이 중요하다)
1 | const initialState = { |
redux-thunk
redux의 기능을 향상시켜주는 middleware인 redux-thunk는 redux가 비동기 액션을 dispatch할 수 있도록 도와준다.
하나의 비동기 액션에서 dispatch를 여러번 할 수 있다.
(비동기 액션에 여러 개의 동기 액션 처리 가능)
공식 사이트 : https://github.com/reduxjs/redux-thunk
middleware는 3단 고차함수의 형태를 가진다.
본래 동기 액션의 경우에는 객체형태이지만, 비동기 액션의 경우에는 함수이기 때문에 지연함수로써 나중에 실행하도록 처리한다.
1 | // 동기 액션 처리하기 이전에 각 action의 속성을 logging해주는 middleware |
로그인, 로그아웃 처리의 경우, 서버로 한 번 들렸다가 처리되기 때문에 단순 요청 액션 객체가 있는 것이 아닌, 각 각의 처리에 대해서 Request, Success, Failure에 해당하는 action이 분리해서 존재한다.
로그인의 경우 redux-thunk 사용 예시
thunk는 아래와 같이 dispatch를 여러번 처리할 수 있다.
1 | export const loginAction = (data) => { |
제너레이터 함수의 이해
redux-saga에서는 제너레이터 함수를 사용하기 때문에 우선적으로 제너레이터 함수에 대해 이해가 필요하다.
1 | const gen = function* () {}; |
제너레이터의 yield가 있는 부분은 함수의 중단점이다.
자바스크립트 함수의 특징은 몸체 부분이 전부 실행되지만, 제너레이터 함수의 경우에는 yield 지점에서 멈추고, yield 와 함께 숫자나 문자를 넣어주면 value로 반환이 된다.
함수 실행 도중에 중간에 멈추게 하기 위한 목적에서 제너레이터 함수가 사용되기도 하며, 제너레이터 함수는 테스트 시에 매우 유용
하다.
1 | // 절대 멈추지 않는 함수 |
위와같은 특성을 이용해서 이벤트 리스너와 같은 처리를 할 수 있다.
redux-saga
실습 Repository :https://github.com/LeeHyungi0622/react-nextjs-twitter
처리에 대한 delay를 함으로써 비동기 처리와 같은 효과를 줄 수 있다.
더블 클릭에 대한 요청에 대해서 take latest처리(thunk에서는 클릭한 요청이 모두 요청된다)
스크롤 이벤트 리스너에 비동기 요청을 처리하는 경우, DDos 공격과 같이 무한으로 연속된 형태로 서버에 요청을 보낼 수 있다.
이러한 문제를 redux-saga에서는 throttle과 debounce를 적용해서 1초에 3번이상 액션이 발생하면 차단하는 것과 같은 조건처리 기능을 추가할 수 있다.throttle은 스크롤링 이벤트 구현시에 많이 사용
되고,debounce의 경우에는 검색창에 검색어를 입력할때 매번 결과창이 업데이트되면 정신없을때, 입력한 검색어가 완성이 되었을때 결과창이 없데이트 될 수 있도록 처리
할때 사용한다.redux-sage 설치
1
2
3$ npm i redux-saga
# Next.js에서 redux-saga를 적용하기 위해
$ npm i next-redux-saga
thunk와는 다르게 sagaMiddleware에는 추가적인 기능이 있다.
configureStore.js
1 | import createSagaMiddleware from 'redux-saga'; |
_app.js
1 | import withReduxSaga from 'next-redux-saga'; |
/front/sagas/index.js
saga에는 다양한 effects (all, fork, call, put)가 존재한다.
(1) all : 배열 내에 작성해 준 제너레이터 함수들을 일괄 실행시켜준다.
(2) fork : 제너레이터 함수를 실행시켜주는 역할로 비동기 함수를 실행해준다. (response와 상관없이 요청을 보내고 바로 다음 요청을 실행한다)
(3) call : fork와 같이 제너레이터 함수를 실행하는 역할을 하지만 fork와는 다르다.
call은 동기 함수 실행을 담당한다.(response를 기다렸다가 다음을 실행)
(4) take : 첫번째 인수의 액션이 실행되면, 두번째 인수로 넣어준 제너레이터 함수가 실행된다.
take의 단점은 일회성이다. 따라서 제너레이터 함수 내에서 while(true){ }로 감싸주거나, takeEvery를 사용
한다.takeLatest를 사용
해서 실수로 두 번 연달아서 클릭 이벤트가 발생했을때 마지막 이벤트만 실행될 수 있도록 처리해준다.
(응답을 하나 취소하는 것이지 서버로의 요청은 취소가 되지 않는다
)
1 | function* watchLogIn() { |
throttle을 이용해서는 1회 요청의 제한시간을 지정해줄 수 있다.
1 | function* watchAddPost() { |
(4) put : dispatch 객체와 같은 기능
root saga를 만들어서 내부에 비동기 처리들을 일괄 작성해둔다.
thunk에서는 비동기 액션 creator를 직접 실행하지만, saga에서는 비동기 액션 creator가 event listener와 같은 느낌을 준다.
redux-saga 예시코드
1 | import { all, fork, call, put, take } from 'redux-saga/effects'; |
redux-saga를 쪼개서 reducer와 연결하기
위와같이 일괄적으로 index.js에 redux-saga에 대한 코드를 작성하게 되면, 코드가 길어지게 된다.
reducer를 합칠때와 같이 combineReducer와 같은 것을 사용해서 합칠 필요가 없다.
실습 Repository :https://github.com/LeeHyungi0622/react-nextjs-twitter
sagas/ 폴더 이하의 파일에는 비동기 처리에 대한 코드를 작성해주고, reducer에서는 비동기 처리에 대한 각 각의 action.type에 대한 조건 처리를 추가해주면 된다.
redux-saga 관련 코드가 실행되는 흐름에 대해서 노트 필기를 해보았다. 복습할때 참고하도록 하자.