[React] Props drilling & GlobalState

0 0 0

Props drilling

Prop Drilling은 props를 하위 컴포넌트로 전달하기만 하는 중간 컴포넌트들을 거쳐, 컴포넌트 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정입니다.

예를 들어 마이페이지에서 프로필로 데이터를 전달하려면 마이페이지 -> 내정보 -> 프로필 이렇게 props를 계속 전달해야 합니다. 세 단계 정도는 괜찮아 보이지만, 10단계, 15단계로 깊어지면 props가 어디서 왔는지 찾기 어려워집니다. 그래서 전역 상태 관리(Global State)가 필요합니다.



GlobalState

하나의 state가 여러 페이지에서 필요할 때, 매번 props로 전달하기 번거롭기 때문에 여러 컴포넌트에서 함께 쓰는 Global State가 필요합니다.

Redux

  • 장점
    • 데이터가 단방향으로 흘러서 버그를 예측하기 쉽습니다.
    • 어떤 액션이 실행되고 데이터가 어떻게 흐르는지 알 수 있어 디버깅이 쉽습니다.
    • 상태 변경 기록이 남아 이전 상태로 되돌릴 수 있습니다.
    • 데이터를 한곳에서 관리합니다.
  • 단점
    • 초기 설정과 코드 작성이 복잡합니다.
    • 작은 기능도 여러 파일을 만들어야 해서 코드량이 늘어납니다.
    • 상태 기록 기능을 쓰려면 불변성을 지켜야 해서 매번 새 state 객체를 만들어야 합니다.

Mobx

  • 장점
    • Redux보다 코드가 간결하고 쉽게 사용할 수 있습니다.
    • 불변성을 신경 쓰지 않아도 됩니다.
    • store의 구성과 역할을 파악하기 쉬워 가독성이 좋습니다.
    • 다른 라이브러리가 덜 필요합니다.
  • 단점
    • 참고 자료가 적습니다. (특히 MobX v6)
    • Redux DevTools 같은 다양한 도구가 부족합니다.
    • 버전별 차이가 큽니다.

SWR

  • 서버 데이터를 앱 데이터처럼 사용
  • 데이터 갱신을 위한 re-fetching을 간단히 구현할 수 있습니다.
  • 가져온 데이터를 캐시해 앱 전역에서 공유하므로 불필요한 요청을 줄일 수 있습니다.

React-query

캐싱 정책이 내장된 REST API용 라이브러리

  • 캐싱
  • 데이터를 변경하면 관련 조회를 자동으로 다시 실행합니다. (예: 게시글을 작성하면 목록 조회 API를 자동으로 다시 호출)
  • 데이터가 오래됐다고 판단되면 다시 조회합니다. (invalidateQueries)
  • 같은 데이터를 여러 번 요청하면 한 번만 요청합니다. (옵션으로 중복 호출 허용 시간 조절 가능)
  • 무한 스크롤 (Infinite Queries)
  • 비동기 과정을 선언적으로 관리할 수 있습니다.
  • React Hook과 사용 방식이 비슷합니다.

Recoil

  • 장점
    • 캐싱
    • 비동기 처리를 깔끔하게 할 수 있습니다.
    • 단순합니다.
    • React와 개발 방향성이 같습니다.
    • 선언적 프로그래밍
  • 단점
    • 안정성에 대한 우려
    • 실험적인 API들
    • devtools의 부재
    • 관련 오픈소스 생태계가 Redux보다 부족함


주로 서버 데이터를 저장하는 도구는 React-query , Apollo-Client
주로 클라이언트 상태를 저장하는 도구는 Recoil
둘 다 다루는 도구는 Redux
당시 많이 쓰이던 조합은 Redux Toolkit, React Query + Recoil, Apollo Client + Recoil

Recoil 사용법

초기 설정

//_app.tsx 파일 
import { RecoilRoot } from 'recoil';

function App() {
  return (
    <RecoilRoot>
	    ...
      	<Component />
     	...
    </RecoilRoot>
  );
}
// src/component/commons/stores
const textState = atom({
  key: 'textState', // state의 이름
  default: '', //초기값
});

컴포넌트는 필요한 atom을 참조하고, 그 atom이 바뀌면 atom을 참조하는 모든 컴포넌트가 다시 렌더링됩니다.

import { useRecoilState } from "recoil";
import { textState } from "../../src/components/commons/stores";

function TextInput() {
  const [text, setText] = useRecoilState(textState);

  const onChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={onChange} />
      <br />
      Echo: {text}
    </div>
  );
}

Recoil은 useRecoilState로 사용합니다.

축약 작성법

const [text] = useRecoilState(textState);
데이터만만 사용할 경우에는 뒤에 set은 안해도 상관없음

const [, setText] = useRecoilState(textState);
set만 사용할 경우에는 앞에 콤마만 붙이고 사용해도 상관 없음

Recoil VS Code 확장 프로그램

위 확장 프로그램을 설치하면 Recoil 코드를 더 편하게 작성할 수 있습니다.

댓글 0