기록

[React] Context를 사용한 전역 상태관리

avocado8 2024. 12. 26. 17:09

 

올해도 창작물 연말정산 백업 페이지를 만들던 중... 저번과는 다르게 파이어베이스를 활용한 인증과 데이터베이스를 사용하고 있었는데, 만들다 보니 매 컴포넌트마다 사용자 정보를 useEffect로 새로 불러오고 있다는 것을 깨달았다. 이거... 너무 비효율적이자나 <! 그래서 오랜만에(ㅎ) context를 다시 공부하게 됏다...

 

여태껏 쓰고 있던 방식

컴포넌트마다 useEffect를 사용해, 렌더링될 때 유저 정보를 가져오도록 했었다.

 

근데 컴포넌트가 많아지다 보니 일일이 복붙하다가... 그럴필요잇나? 싶어져서

로그인 사용자 인증 정보는 어차피 로그인한 이상 어디서든 쓰니까, 이렇게 하면 매번 같은 코드를 갖다붙여야 하니 귀찮기도 하고 유지보수도 어렵다. context로 빼서 상태관리를 해주자.

 

context란?

공식문서를 보는 것이 편하다 :> ...

https://ko.react.dev/learn/passing-data-deeply-with-context

 

Context를 사용해 데이터를 깊게 전달하기 – React

The library for web and native user interfaces

ko.react.dev

 

아무튼 그래서 context를 어떻게 쓰냐? 공식문서에 따르면 이렇다.

  1. Context를 생성하세요. (제목 레벨을 위한 것이므로 LevelContext라고 이름 지어봅시다.)
  2. 데이터가 필요한 컴포넌트에서 context를 사용하세요. (Heading에서는 LevelContext를 사용합니다.)
  3. 데이터를 지정하는 컴포넌트에서 context를 제공하세요. (Section에서는 LevelContext를 제공합니다.)

그러니까 props는 부모에서 자식으로 전달하는데, 자식 컴포넌트의 깊이가 깊어지거나, 중복 사용되는 경우가 많거나 하면 관리가 굉장히 귀찮아진다. 그럴 때 쓰는 것이 context다. 공식문서의 문장을 빌리자면 context는 " 데이터를 사용할 트리의 내부 컴포넌트에 props를 전달하는 대신 “순간이동”시킬 방법" 이라고 한다.

 

시키는 대로 해보자.

1. context 만들기

우선 src/context/ 디렉토리를 만들고, AuthContext.tsx 파일을 만들어준 뒤 createContext로 context를 만들어주자.

나는 user과 uid(사실 user 객체 안에 uid가 있다. 근데 귀찮아서... 이것까지 따로 뺐다)를 사용할 것이므로, 타입은 아래처럼 지정해주고 기본 상태는 null로 해주었다.

 

그다음에는 context 사용하기인데, context를 사용하려면 useContext 훅을 사용한다.

근데... 제공을 해줘야 쓰지 (ㅎ)

그니까 제공하는 부분부터 만들어야겠다.

 

2. Provider 설정하기

context를 사용하려면 리액트노드를 context provider로 감싸주어야 한다.

AuthContext.Provider 요소로 감싸주면 되는데, 이것도 함수로 빼자.

AuthProvider 함수 내에서, 원래 하려고 했던 동작인 useEffect의 코드를 작성해주고 (onAuthStateChanged는 파이어베이스에서 인증정보를 가져오는 함수이다.),

리턴할 때 children을 AuthContext.Provider로 감싸준다. value는 설정할 context이다.

그리고!! main.tsx에서 전체 App도 AuthContext로 감싸줘야 한다. 그래야 하위 컴포넌트들이 context에 접근할 수 있다.

 

3. context 사용하기 ( 커스텀 훅 만들기 )

context를 사용할 때는 useContext 훅을 사용한다.

근데 그것도 여러번 쓰면 귀찮으니까 커스텀 훅으로 만들어 보다 편하게 사용해주자. :3 

 

이제됏다

이제 노가다 뛰던 컴포넌트 코드로 돌아가서 리팩토링해주자.

 

원래 매번 setState로 user, uid를 선언해주고, useEffect로 정보를 불러왔는데 이제 

const {user, uid} = useAuth();

한 줄로 끝난다 !

위 컴포넌트에선 user은 필요없어서 안 갖고왔다.

 

아무튼 편해졌다.

context를 잘 활용하도록 하자 .⛄