프로젝트에 리덕스를 붙이려면 복잡한 과정을 거쳐야 하고 실제로 next에서도 리덕스를 붙일 때 많이 복잡하다.
이것을 간편하게 해주는 라이브러리가 있는데 next redux wrapper이다. (여기서 확인하자. 최신버전으로 올라와서 next 9버전에서도 사용할 수 있다.)
일반 리덕스와는 동작이 다른데 진행중인 프로젝트 안에서(prepare-front-store폴더구조) store폴더로 들어가서 configureStore.js파일 생성한다. next redux wrapper도 버전이 올라가면서 예전과는 사용방법이 달라졌기 때문에 버전을 항상 조심하자.
// configureStore.js
const configureStore = () => {
};
const wrapper = createWrapper(configureStore);
export default wrapper;
명령어를 치게되면 createWrapper를 가져올 수 있다.
// 6버전으로 해서 진행
npm i next-redux-wrapper@6
그리고 debug는 true로 하는 코드를 작성한다.
// configureStore.js
import { createWrapper } from "next-redux-wrapper";
const configureStore = () => {};
const wrapper = createWrapper(configureStore, {
debug: process.env.NODE_ENV === "development",
});
export default wrapper;
그리고 _app.js(기존에 pages폴더에 작성한 파일)파일에 아래와 같이 맨마지막을 wrapper로 아래와 같이 감싸준다.
// _app.js
import React from "react";
import PropTypes from "prop-types";
import Head from "next/head";
import "antd/dist/antd.css";
// 추가
import wrapper from "../store/configureStore";
const NodeBird = ({ Component }) => {
return (
<>
<Head>
<meta charSet="utf-8" />
<title>NodeBird</title>
</Head>
<Component />;
</>
);
};
NodeBird.propTypes = {
Component: PropTypes.elementType.isRequired,
};
// 추가
export default wrapper.withRedux(NodeBird);
리덕스도 설치해주자.
npm i redux
그리고 최신버전 next redux-wrapper에서는 Provider로 감싸주면 문제가 되기 때문에 감싸주지 말자.(중복이 발생)
// _app.js
// Don't do that
const NodeBird = ({ Component }) => {
return (
<Provider>
<Head>
<meta charSet="utf-8" />
<title>NodeBird</title>
</Head>
<Component />;
</Provider>
);
};
// <></> void state YES!
const NodeBird = ({ Component }) => {
return (
<>
<Head>
<meta charSet="utf-8" />
<title>NodeBird</title>
</Head>
<Component />;
</>
);
};
configureStore.js를 설정해주자. redux나 mobx나 또는 context API로 둘이 대체가 되는게 아닌가?
// configureStore.js
import { createWrapper } from "next-redux-wrapper";
import { createStore } from 'redux';
const configureStore = () => {
const store = createStore(reducer);
return store;
};
const wrapper = createWrapper(configureStore, {
debug: process.env.NODE_ENV === "development",
});
export default wrapper;
아래와 같이 components들이 분리되어 있고 데이터들이 흩어져 있는데 이러한 데이터들을 흩어지지 않게 하기위해서는 부모 컴포넌트를 두어서 부모컴포넌트에서 데이터를 받아서 자식 컴포넌트로 각각 보내줘야 한다.
매번 수동적으로 부모 컴포넌트를 만들어서 부모컴포넌트에서 데이터를 받아서 자식 컴포넌트로 보내주는 이러한 과정들은 매우 귀찮다.
이러한 것들을 중앙에서 하나로 관리를 해서 컴포넌트한테 뿌려주는 중앙 데이터 저장소 역할을 하는 것이 redux이다.
react에서 context API로 중앙 저장소 역할을 한다. 데이터들을 중앙저장소에서 하나로 다 모아두고 컴포넌트가 필요로 할 때 데이터를 전체를 다 가져다 쓰거나 부분적으로 쓰거나 할 수 있게 해준다.
중앙 데이터 저장소는 하나 정도는 두는게 좋다.
(react의 contextAPI, redux, mobx, graphQL(Apollo) => 중앙데이터 저장소 역할)
4가지 선택지 중에서 규모가 어느정도 되는 서비스이면 중앙저장소 하나를 선택하는 것이 효율적이다.
데이터 관리가 용이한데 만약 컴포넌트 별로 데이터를 따로 들고 있으면 그 데이터를 다른 컴포넌트에 전달하는 것도
귀찮고 서로 컴포넌트간에 데이터가 불일치해서 다른 화면을 렌더링 할 수도 있다. 즉 데이터는 중앙에서 한번에 관리하는 것이 좋다. (가장 많이 선택하는 것이 redux, 초보를 탈출해서 생산성을 위해 mobx 쓰는것도 좋다.)
(그리고 사용자가 만들고자 하는 앱이 별로 크지 않으면 가볍게 contextAPI를 쓰면 된다.)
차이점은 redux는 원리가 매우 간단하기 때문에 에러가 날 일이 없다.(아예 안난다는 것이 아니고 에러가 나더라도 해결이 용이하다는 뜻) 에러가 나면 다 추적이 잘되고 앱이 엄청 안정적이게 된다. 단점은 코드량이 많아진다.
결론 redux는 더 많은 코드를 쓰는 대신에 앱은 안정적이게 된다.
mobx는 코드량은 많이 줄여지는데 실수를 하는 경우에 tracking(추적)하기가 어려워진다. 어느정도 trade-off가 있다.
하나를 얻으면 하나를 잃는...
초보일때는 redux 초보를 벗어나면 mobx를 쓰기는 한데 내 실력이 늘었다고 해서 무조건 mobx로 가는 것이 아니라,
개발자 성향, 팀 성향에 따라서 달라지므로 잘 선택해야한다.
만약 라이브러리를 쓰기 싫다 그러면 context API를 쓰면 되는데
contextAPI VS redux mobx(라이브러리)의 가장 큰 차이점은 비동기를 지원하기 싶냐 어렵냐이다.
보통 중앙 저장소가 있으면 그 중앙저장소는 서버에서 데이터를 많이 받는다. 서버에서 데이터를 받아오는 것은 비동기인데 데이터를 받아온다는 것은 데이터를 보내달라! 하면 100%받아오는 것이 아니라, 가끔식 서버가 고장났을 수도 있고 네트워크 에러가 생겼을 수도 있고 그러한 경우가 있다.
즉 데이터가 안 올수도 있다. 항상 실패에 대비해야 된다는 점, 즉 비동기를 다룰때는 실패에 대비해야 된다는 점이 중요하다.
비동기는 3단계로 나눠지는데 1. 데이터 보내달라 - 2.성공해서 받았다 - 3.혹시나 실패해서 실패에 대비한거
이러한 비동기 3단계를 contextAPI에서 구현할려면 사용자가 직접 다 구현을 해줘야 한다.
단점은 useEffect에 많이 요청을 보낸다.
아래와 같은 코드가 컴포넌트에 많이 들어간다.
컴포넌트는 화면그리는 거에 집중하는 것이 가장 좋은데 데이터까지 다루는 것은 컴포넌트의 역할은 아니라고 생각하자. 여러 컴포넌트에서 아래와 같이 데이터를 가져오는 코드가 있으면 의도치 않은 코드 중복이 발생하게 된다.
데이터 요청은 별도의 모듈이나 라이브러리가 해야하기 때문에 컴포넌트에서는 데이터 요청을 하지말자.
// UserProfile.js에 있는 코드
useEffect(() => {
axios.get('/data')
.then(() => {
setState(data)
})
.catch(() => {
setError(error);
})
})
// LoginForm.js에 있는 중복된 코드
useEffect(() => {
axios.get('/data')
.then(() => {
setState(data)
})
.catch(() => {
setError(error);
})
})
redux나 mobx한테 위와 같은 동작을 즉 비동기 동작을 맡길 수 있다. context API를 쓰면 직접 구현을 해줘야 한다.
그냥 처음부터 redux나 mobx를 쓰자. 화면을 데이터를 가져오는 부분이랑 분리시키는게 가장 큰 장점이다.
redux는 reducer들을 여러개로 쪼갤 수 있기 때문에 중앙저장소가 너무 커지는 것도 어느정도 쪼갤 수 있는 시스템을 갖춰놨다고 볼 수 있다.
<출처 조현영: [리뉴얼] React로 NodeBird SNS 만들기>
[리뉴얼] React로 NodeBird SNS 만들기 - 인프런 | 강의
리액트 & 넥스트 & 리덕스 & 리덕스사가 & 익스프레스 스택으로 트위터와 유사한 SNS 서비스를 만들어봅니다. 끝으로 검색엔진 최적화 후 AWS에 배포합니다., 새로 만나는 제로초의 리액트 노드버
www.inflearn.com
'React > NodeBird(ZeroCho)' 카테고리의 다른 글
정규표현식 맛보기 (0) | 2021.10.28 |
---|---|
리덕스의 원리와 불변성 (0) | 2021.10.26 |
회원가입 페이지 만들기(커스텀 훅) (0) | 2021.09.17 |
프로필 페이지 만들기 (0) | 2021.09.17 |
noreferrer&noopener (0) | 2021.09.17 |