본문 바로가기

프로젝트/나무(나누고 나눔받는 무한 지식 품앗이)

[React & Recoil] a태그로 인한 새로 고침 + 새로 고침 시 리코일 전역 데이터 날라가는 현상

반응형

마이페이지에 탭 메뉴로 로그인한 유저가 보낸 요청 리스트와 작성한 글 리스트를 보내는 기능이 있다. 로그인한 유저의 데이터는 리코일을 통해 관리하고 있었다. 

문제가 있었다. 원하는 대로 데이터가 뿌려지지 않았다. 아래부터 위로 거슬러 올라가며 다양한 가설들을 제기해보고 테스트해보기를 반복했다. 어제 밤부터 오늘 오후 3시 반까지 지속되었던 인고의 시간들을 기록해보고자 한다.

문제 1. 전역에서 관리되는 로그인 유저의 정보가 느리게 가져와진다. 즉, 컴포넌트가 렌더링 되고 전역 데이터가 가져와지기 전까지 delay가 있다. 

그러면 탭 메뉴를 감싸고 있는 부모 컴포넌트에서 전역 데이터를 가져와 탭 메뉴에 props로 보내주면 괜찮아질까?

=> NO. 똑같은 에러만 보인다.

 

문제 2. 에잇..그러면 하는 수 없이 자식 컴포넌트에서 전역 데이터를 가져온 후 리액트 쿼리를 통해 요청 리스트를 가져와야겠네. 그런데 react-query 문이 리코일 데이터를 가져오기까지의 delay를 기다려주지 않고 바로 실행되어, 결과적으로는 undefined인 데이터를 가지고 요청을 보내려고 하니 undefined 오류가 뜨네? 

react-query 문이 리코일 전역 데이터를 가져오기 전까지 기다려줄 수는 없을까? 

=> NO. recoil에서 selector를 사용했다면 useRecoilValueLoadable 이라는 것을 사용해볼 수 있지만, atom은 그런게 없다.

 

문제 3. 오잉? 그런데 왜 마이페이지만 들어가면 새로 고침이 되지? React는 SPA라 라우팅이 되어도 새로 고침 현상이 일어날 일이 없는데? 새로 고침이 되면서 전역 데이터가 세팅되는 모든 과정이 반복된다. 그래서 더 느려지는 것 같다!

원인은 라우팅 쪽 코드에 있었다. 내가 header 컴포넌트의 위치를 router 바깥으로 해두어서 팀원 분이 header 컴포넌트 내에 컴포넌트 이동에 useNavigate를 사용하지 못하고 a 태그로 작업하실 수 밖에 없는 상황이였다. 

같은 Routes 내부 즉 같은 레벨? 에 있지 않으면 useNavigate 또는 Link 를 통해 페이지를 이동할 수 없다고 한다. 그래서 a 태그를 통해 header 내부 페이지 이동 이벤트를 구현하셨던 것이였다. 

  return (
    <QueryClientProvider client={queryClient}>
      <AppContainer>
        <GlobalStyle />
           <Header />
           <Router>
             <MainContainer>
               <SideBar />
               <Routes>
                 <Route path="/*" element={<MainHome />} />
                 <Route
                   path="/mypage"
                   element={isLogin ? <MyPage /> : <LoginPage />}
                  />
               </Routes>
            </MainContainer>
           </Router>
      </AppContainer>
    </QueryClientProvider>
  );

a 태그는 페이지의 이동 개념이기 때문에 새로 고침이 일어나는 꼴이 된다. 따라서 전역 데이터를 불러오는 것부터 시작해서 모든 과정을 다시 시작한다.

https://okky.kr/questions/1287475

 

OKKY - html에서 a태그로 이동시 새로고침을 해야하는 이유?

html에서 페이지들을 만들어서 각 페이지간 이동을 하게 했는데이동까지는 문제가 없으나 해당 html에 들어가면 1. css가 적용이 안된다던지2. 배열을 이용해 만든 함수가 리셋이 안되어서 화면에

okky.kr

바로 코드를 바꿔주었다. header 컴포넌트 내부의 a태그도 전부 지우고 useNavigate를 사용하여 페이지를 이동할 수 있도록 하였다.

<QueryClientProvider client={queryClient}>
      <AppContainer>
        <GlobalStyle />
        <Router>
          <Header />
          <MainContainer>
            <SideBar />
            <Routes>
              <Route path="/*" element={<MainHome />} />
              <Route
                path="/mypage"
                element={isLogin ? <MyPage /> : <LoginPage />}
              />
            </Routes>
          </MainContainer>
        </Router>
      </AppContainer>
    </QueryClientProvider>

=> 마이페이지 이동 시, 새로 고침되던 이슈 해결!

=> 그런데 아직도 문제가 있다.. 마이페이지에서 새로 고침하면 유저 요청 리스트 데이터가 또 안뜬다.

 

문제 4. 그래, 이제 마이페이지로 이동할 때마다 새로 고침되던 현상은 해결됐다. 메인페이지에서 마이페이지로 이동하였을 때 유저가 보낸 요청 리스트도 잘 뜬다. 문제는 마이페이지에서 새로 고침하면 아까와 같은 에러를 다시 만난다. 즉, 새로 고침하면 전역 데이터가 저장되는 모든 과정이 반복된다. 새로 고침을 해도 전역 데이터가 저장되는 모든 과정이 반복되지 않게 하는 방법은 없을까?

이럴 때는 recoil-persist를 사용하면 된다.

recoil을 사용하다가 전역 상태가 새로고침 후 초기화되는 현상이 발생한다고 한다. recoil-persist를 사용하면 새로 고침을 해도 recoil state가 날아가지고 않고 sessionStorage 또는 localStorage에 보관된다. 아무런 설정도 해주지 않으면 key는 "recoil-persist", 저장소는 localStorage가 된다. sessionStorage에 저장하려면 추가적인 설정이 필요한 것 같다.

import { atom } from 'recoil';
import { recoilPersist } from 'recoil-persist';

const { persistAtom } = recoilPersist();

export const userData = atom({
  key: 'userData',
  default: {},
  effects_UNSTABLE: [persistAtom]
});

=> 모든 이슈 해결 완료! 이제 아무리 새로 고침해도 로그인 유저의 데이터가 잘 보인다! 

 

 

1. 항상 오버 커뮤니케이션 하도록 노력하자. 특히 내가 짠 코드가 아닌 부분을 건드리게 될 때 문제가 생기면 혼자 파악하려고 하지말고 그 코드를 짠 팀원에게 꼭! 물어보며 같이 문제 상황을 파악해라.
2. 리액트 쿼리는 왠만하면 쓰는게 좋다. 안쓰더라도 로딩 로직은 꼭 넣어라. 로딩 인디케이터는 필수다.
3. 기본 틀을 짤 때 내가 맡은 기능만 생각해서 짜지 말고, 다른 팀원들이 맡은 기능도 고려하자. 돌을 잘 닦아놔야 이후에 문제가 잘 생기지 않는다.
반응형