ssjeu_
[React] React 상태 관리 라이브러리 - Redux, React Query, SWR 본문
리액트 상태 관리 종류를 알아보기 앞서 리액트 프로젝트에서 일반적으로 사용하는 상태(state) 를 세 가지로 구분하면 다음과 같다.
- Local State: 리액트 컴포넌트 안에서만 사용되는 state
- Global State: Global Store에 정의되어 프로젝트 어디에서나 접근할 수 있는 state
- Server State: 서버로부터 받아오는 state
기존에는 리덕스와 같은 상태 관리 라이브러리에 Global State와 Server State를 전부 포함하는 방법으로 프로그래밍하였다.
최근 들어 data fetching 라이브러리를 사용함으로써 상태 관리 라이브러리에서 비동기 로직(Server State)을 제거하여 관심사가 분리되고 선언적으로 프로그래밍할 수 있게 되었다!
2020년부터 React Query 나 SWR 와 같은 data fetching 라이브러리들이 인기를 끌고 있는 추세이다.
Redux에서 Server State 처리
리덕스는 어떠한 액션(순수 객체)이 발생했을 때, 액션에 따라 데이터의 상태가 어떻게 변경되면 되는지를 리듀서(순수 함수)에 정의한다.
동기적인 로직(Global State)에서는 액션과 리듀서를 직관적으로 작성할 수 있지만, 비동기 로직(Server State)을 처리하기 위해선 어떻게 해야 할까? 바로 미들웨어를 사용해야한다. 리덕스 미들웨어는 발생한 액션을 가로채서 다른 로직을 실행할 수 있도록 한다. 비동기 로직을 처리하는 미들웨어는 redux-thunk와 redux-saga가 있다.
- redux-thunk : store에 던져진 액션을 가로채서 비동기 로직을 수행한 후 액션을 발생시킴
간단하게 리덕스에서 비동기 로직을 처리할 수 있게 되지만 동기 로직에서 순수 객체였던 액션의 형태가 변경되어 어딘지 찜찜한 코드가 되고, 개발자는 액션을 스토어에 던진 후 상태가 언제 반영되는지 정확한 시점을 모르게 된다
// (...더 찜찜하게 보이려고 async, await 은 사용하지 않았습니다 :3 ).
const getSomethingThunk = () => {
return dispatch => {
fetchSomething().then(res => {
dispatch({
type: "someAction",
payload: res.data,
});
});
};
};
store.dispatch(getSomethingThunk());
- redux-saga : 액션이 순수 객체의 모습을 되찾게 되지만 리덕스의 최대 단점인 장황한 코드가 더욱더 많아짐
function* getSomethingSaga() {
try {
const res = yield call(fetchSomething);
yield put({
type: "successAction",
payload: res.data,
});
} catch {
yield put({
type: "failAction",
payload: res.data,
});
}
}
function* someSaga() {
yield takeEvery("someAction", getSomethingSaga);
}
function* rootSaga() {
yield all[someSaga()];
}
store.dispatch({ type: "someAction" });
이외에도 리덕스에서 Server state를 관리한다고 생각했을 때 여러 가지 해결해야 할 사항이 있다.
ex) 유튜브를 구현한다고 생각
동영상 관련 데이터들은 리덕스 스토어에 저장되어 있다. 사용자 A가 동영상을 시청하는 동안 사용자 B가 동영상에 ‘좋아요’ 버튼을 클릭하면 좋아요 수를 최대한 실시간으로 반영하기 위해서는 주기적으로 서버 데이터를 폴링해서 리덕스 스토어의 데이터를 업데이트해 줘야 한다.
-> 즉 (어디에선가 다른 사람에 의해 변경된) 데이터가 반영될 수 있도록 적절한 타이밍에 개발자가 업데이트 필요
유튜브에는 사용자 프로필 이미지를 표시하는 여러 컴포넌트가 있다. 상단 nav에 로그인한 유저 정보, 댓글 창에 댓글을 단 유저, 동영상 올린 크레에이터 표시 등등.
-> 각 정보를 얻어오는 API가 동일하다고 가정한다면, 동일한 API 호출이 여러 번 일어나게 된다.
이뿐 아니라 리덕스에서 Global State와 Server State를 하나의 스토어에서 관리하게 되면서 스토어는 점점 비대해지고 관심사의 분리가 어렵게 된다.
SWR & React Query
그동안 당연하게 써왔던 리덕스에 생각보다 불편한 점이 많다. data fetching 라이브러리는 위에서 말한 리덕스의 단점들을 해결한다.
- 선언적으로 프로그래밍 가능 (장황하지 않은 코드)
- 동일한 API 요청이 여러 번 호출될 경우 한 번만 실행
- 데이터가 dirty 해진 경우 적절한 시점에 알아서 업데이트
- Global State와 Server State의 관심사를 분리
첫 번째 언급된 리덕스의 단점에 대해서 덧붙이자면, 리덕스에서 비동기 로직을 사용하기 위해서는 위에서 말씀드린 바와 같이 과정을 하나하나 기술해야 해서 장황한 코드가 필요했다. 반면 SWR이나 React Query을 사용할 경우에는 어떤 데이터를 언제 fetch 하면 되는지 목표만 기술하기 때문에 선언적으로 프로그래밍 할 수 있게 된다. 이렇게 되면 개발자가 코드를 읽을 때 글을 읽어내려가듯이 자연스럽게 흐름을 파악할 수 있다.
SWR, React Query는 사용해본 경험이 없어 상세한 사용 방법은 reference로 첨부한다.
'React ·JS' 카테고리의 다른 글
[React] React에서 이벤트 처리 (2) - 이벤트 위임 (0) | 2022.09.11 |
---|---|
[React] React에서 이벤트 처리 (1) - 버블링, 캡쳐링 (0) | 2022.09.11 |