신입개발일기 / Loading page & Provider

단단·2025년 7월 28일
  1. 과제 라우터에서 ...withErrorAndSuspenseBoundary 사용하지 않기.

router.tsx

const withErrorAndSuspenseBoundary = (element: React.ReactNode) => ({
    element: (
        <ErrorBoundary fallback={<ErrorArea />}>
            <Suspense fallback={<LoadingArea />}>{element}</Suspense>
        </ErrorBoundary>
    ),
});
  1. 과제 프로바이더 구조 이해하기

💡 React Provider 제대로 이해하기: 내 프로젝트에선 이렇게 동작!

✅ Provider란?

React에서 Provider공통으로 사용되는 데이터를 전역 상태처럼 관리하고, 필요한 컴포넌트에 쉽게 공급하는 역할을 한다.

쉽게 말하면, React에서의 물류센터 같은 존재입니다. 어떤 데이터든 이 센터에 넣어두면, 아래에 있는 어떤 컴포넌트든 필요할 때 가져다 쓸 수 있다.


🔄 왜 Provider가 필요할까? (feat. 택배 기사)

여러 컴포넌트가 같은 데이터를 필요로 하는 상황을 상상해볼게요. 예를 들어, 사용자 정보가 있다면 이건 헤더, 사이드바, 댓글, 대시보드에서도 필요하겠지?

❌ Provider 없이: Prop Drilling

<App user={user}>
  <Header user={user}>
    <Nav user={user}>
      <Profile user={user} />
    </Nav>
  </Header>
</App>

이렇게 props를 계속 넘겨야 해요. 이것을 Prop Drilling이라고 부릅니다. 택배 기사가 1층에서 출발해 꼭대기까지 계단으로 올라가서 직접 배달하는 상황이라고 보면 돼요.

✅ Provider 사용

<UserContext.Provider value={user}>
  <App />
</UserContext.Provider>

이제 Header, Nav, Profile 어디서든 useContext(UserContext)만 쓰면 데이터를 바로 쓸 수 있어요. 마치 1층에 물류센터를 두고 필요한 사람이 와서 직접 가져가는 구조죠.


🗂 프로젝트 구조 속 Provider 예시

src/
└── pages/
    └── inquiries/
        └── pages/
            └── indexes/
                └── pages/
                    └── MessagePage/
                        ├── MessagePage.tsx
                        └── components/
                            ├── MessageAllGetProvider/
                            │   └── MessageAllGetProvider.tsx
                            ├── MessageLocalValueProvider/
                            │   └── MessageLocalValueProvider.tsx

🧩 실제 연결 구조

1️⃣ MessagePage.tsx

const MessagePage = () => {
  return (
    <MessageAllGetProvider>
      <MessageLocalValueProvider>
        <MessageLayout
          MessageTable={<MessageTableBox />}
          MessageDatePicker={<MessageDatePicker />}
          // ...
        />
      </MessageLocalValueProvider>
    </MessageAllGetProvider>
  );
};
  • MessageAllGetProvider: 서버에서 데이터 조회
  • MessageLocalValueProvider: 로컬 상태 관리 (ex. 날짜 선택)

2️⃣ MessageAllGetProvider.tsx

const MessageAllGetProvider = ({ children }) => {
  const { company, site } = useCompanySelectProvider();
  const [pagination, setPagination] = useState({ page: 1, size: 20, total: 0 });
  const [dateRange, setDateRange] = useState();
  const [selectedSite, setSelectedSite] = useState(company.siteUrls[0]);

  const { isFetching, data } = useInquiryAllGetQuery({
    path: { companyId: company?.uuid },
    query: { pagination, siteUrl: selectedSite, dateRange },
    body: {},
  });

  const changePagination = (newPage) => setPagination(newPage);
  const changeSite = (site) => setSelectedSite(site);

  return (
    <MessageAllGetContext.Provider
      value={{
        changePagination,
        pagination,
        selectedSite,
        changeSite,
        dateRange,
        setDateRange,
        inquiries: data?.inquiries || [],
      }}
    >
      {children}
      {isFetching && <LoadingOverlay />}
    </MessageAllGetContext.Provider>
  );
};

3️⃣ 하위 컴포넌트에서 사용하는 방법

const MessageTableBox = () => {
  const { inquiries, changePagination } = useMessageAllGetProvider();

  return (
    <Table>
      {inquiries.map((inquiry) => (
        <Row key={inquiry.id}>{inquiry.title}</Row>
      ))}
    </Table>
  );
};

4️⃣ CustomApiSettingUpdateProvider 예시

const CustomApiSettingUpdateContext = createContext({
  uuid: '',
  setUuid: () => {},
  name: '',
  status: '',
  media: '',
  apiMedias: [],
  handleNameInputChange: () => {},
  handleStatusItemClick: () => {},
  handleMediaItemClick: () => {},
  handleSubmitButtonClick: () => {},
  handleCancelButtonClick: () => {},
});

이걸 사용하는 컴포넌트는 다음과 같아요:

const {
  name,
  handleNameInputChange,
  handleSubmitButtonClick
} = useCustomApiSettingUpdateProvider();

return (
  <>
    <Input value={name} onChange={handleNameInputChange} />
    <Button onClick={handleSubmitButtonClick}>등록</Button>
  </>
);

🧠 요약: Provider 패턴의 핵심 정리

구분역할
createContext()데이터를 전역처럼 사용할 수 있게 ‘컨텍스트’를 만듦
Context.Provider데이터를 하위 컴포넌트에 전달하는 ‘공급자 역할’
useContext()하위 컴포넌트에서 Context에 접근하는 훅
Provider 컴포넌트실제로 값을 정의하고 상태를 관리하는 컴포넌트
장점Prop drilling 방지, 유지보수 쉬움, 관심사 분리, 재사용성 ↑

💬 마무리

Provider는 React에서 공통 데이터나 상태를 효율적으로 관리할 수 있게 도와주는 핵심 개념이다.
특히 복잡한 페이지일수록, 여러 상태와 데이터를 여러 컴포넌트에 전달할 일이 많을수록 Provider 패턴은 필수라고 할 수 있다.

이 구조를 이해하고 나면, 협업이나 유지보수에서도 훨씬 수월해질 거다.
복잡한 상태 로직, 중첩된 데이터 전달로 고생하고 있다면, 꼭 Provider 패턴을 적극적으로 활용해보자! 💪

profile
단단한 개발자

0개의 댓글