React 내에서 useState Hook만을 사용하여 State 관리 시, 발생할 수 있는 문제점은 아래와 같다.
- 만일 State를 function으로 관리한다면, Router에 등록한 모든 컴포넌트에서 Interface를 생성하고 Props를 받아야한다.
- 여러 State를 관리하게 될수록 더욱 더 많은 type을 지정해주어야 한다.
- state 수정이 필요할 때마다 최종적으로 state를 사용할 컴포넌트가 아닌 상위의 다른 컴포넌트들을 거쳐 컴포넌트 마다 props로 State를 전달해야 한다.
강의에서 작성한 예제에 따라, App.tsx에서 만든 const [isDark, setIsDark]
를 Routes 폴더의 Chart.tsx에서 사용한다고 해보자. 그렇다면 App.tsx에서 다루는 state와 function은 아래와 같이 Router, Coins, Coin 컴포넌트들을 거쳐 최종적으로 목표 지점 컴포넌트에 도달한다.
App (isDark, modifierFn)
-> Router -> Coins (modifier)
-> Router -> Coin -> Chart (isDark)
이전에 프로젝트에서는 Login State를 Global State로 사용하기 위해, isLoggedIn State를 Router와 NavBar에 전달해서 사용했던 적이 있다. 이 프로젝트 같은 경우엔 규모가 작았기 때문에 다소 복잡했었더라도 State Management를 따로 사용하지 않아도 괜찮았지만, 로그인 상태에 따른 서비스 변화가 있을 경우 부모 컴포넌트에서 자식 컴포넌트로 연쇄 Props 전달, Interface 설정으로 상당한 불편을 겪을 수 있을 것이다.
이 문제를 해결하기 위해, 이번 파트에선 Recoil을 사용한다. Recoil의 핵심개념은 Atom이다. 어떤 컴포넌트에도 종속되지 않는 Atom 안에 Value를 만들어두고, 꼭 필요한 Component에서 해당 Atom에 접근해 Value를 사용하는 방식이다.
그럼 이제 작업중인 React App이 존재하는 디렉토리에서npm install recoil
혹은 npm i recoil
로 Recoil을 설치하자. 그 다음으로 진행하는 순서는 아래와 같다.
- atoms.ts 파일을 만들어 atom을 import하고, 원하는 Theme atom을 만든다.
- index.tsx에서 {RecoilRoot}를 import하고, App Component를 감싸준다.
- App.tsx에서 state 대신 atom을 사용한다.
아래는 코드 중 일부를 발췌한 것으로, 디테일은 ... 표시로 생략했다.
//atoms.ts
import { atom } from "recoil";
export const isDarkAtom = atom({
key:"isDark",
default: false,
});
//index.tsx
import { QueryClient, QueryClientProvider } from "react-query";
import ReactDOM from "react-dom/client";
import App from "./App";
import { RecoilRoot } from "recoil";
...
root.render(
<>
<RecoilRoot>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</RecoilRoot>
</>
);
//App.tsx
...
import { useRecoilValue } from "recoil";
import { isDarkAtom } from "./atoms";
...
function App() {
const isDark = useRecoilValue(isDarkAtom)
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router />
<ReactQueryDevtools />
</ThemeProvider>
</>
);
}
export default App;
이렇게 App component를 감싼 Recoil을 통해 Atom을 Components와 연결하며 한번에 State를 관리할 수 있게 되었다.