[Tech] React 상태 관리 (Redux, React Query, SWR)

Intro


리액트에서의 State는 다음과 같이 구분될 수 있음.

  • Local state
  • Global state
  • Server state

이러한 상태들을 관리하기 위한 라이브러리들이 존재함.

  • 1 Redux
  • 2 Fetch library (SWR, react-query, ...)

무슨 이유로 다음의 라이브러리들이 구분되어 존재하는지 정리함.

1 REDUX


Redux는 Context API 가 지금의 형태로 사용방식이 개선되기도 전에, 그리고 useReducer 라는 Hook 이 존재하기도 전 부터 만들어진 라이브러리임.

사실 Context API 가 개선되기 전에는 프로젝트에서 글로벌 상태관리를 하는게 굉장히 까다로움. 기존에는 주로 리덕스와 같은 상태 관리 라이브러리에 Global State와 Server State를 전부 포함하는 방법으로 프로그래밍을 했음.

npmtrends 를 통해, 현재 리액트를 사용하는 프로젝트 중 45%가 리덕스를 사용하고 있다는 것을 알 수 있음.

리덕스에서 동기적인 로직(Global State)에서는 액션과 리듀서를 직관적으로 작성할 수 있지만, 비동기 로직(Server State)을 처리하기 위해선 미들웨어를 사용해야 함. 리덕스 미들웨어는 발생한 액션을 가로채서 다른 로직을 실행할 수 있도록 하며, 비동기 로직을 처리하는 미들웨어는 redux-thunk와 redux-saga가 있음.

// react-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" });

근데 이렇게하면 리덕스에서 Global State와 Server State를 하나의 스토어에서 관리하게 되면서 스토어는 점점 비대해지고 관심사의 분리가 어렵게 됨.

2 Fetch library


SWR, react-query 와 같은 data fetching 라이브러리를 사용함으로써 상태 관리 라이브러리에서 비동기 로직을 제거하여 관심사(Global state, Server state)가 분리되고 선언적으로 프로그래밍할 수 있게 되었음.

// SWR

import useSWR from "swr";

function Profile() {
  const { data, error } = useSWR("/api/user", fetcher, options);

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;
  return <div>hello {data.name}!</div>;
}

Server state 를 변경하여, Global state를 업데이트 해야하는 경우, Server state를 refetch하지 않고 mutate 함수에 키뿐 아니라 데이터를 같이 파라미터로 전달하면 refetch 없이 업데이트

const Profile = () => {
  const { mutate } = useSWRConfig();
  const [profile, setProfile] = useState({ name: "jojiiiiyoung" });

  const handleEditProfile = () => {
    await updateProfile(profile);
    // mutate 함수에 data 인자를 전달하면 refetch 없이 즉시 변경
    mutate(`/user/${userId}`, profile, false);
  };
};

이렇게 data fetching 라이브러리는 다음과 같은 리덕스의 단점들을 해결가능.

  • 선언적으로 프로그래밍 할 수 있음(장황하지 않은 코드)
  • 동일한 API 요청이 여러 번 호출될 경우 한 번만 실행
  • 데이터가 dirty 해진 경우 적절한 시점에 알아서 업데이트
  • Global State와 Server State의 관심사를 분리

1년 동안 받은 깃헙 스타 개수를 기반으로 인기 지수를 측정하는 risingstars를 확인하면 React Query가 9위, SWR이 14위인 것을 보아 현재도 두 라이브러리의 인기는 여전히 순항 중인 것을 확인할 수 있음.

Reference


좋은 웹페이지 즐겨찾기