혼자 적어보는 노트

데브코스 최종 프로젝트 - 14일차 / Recoil 연결 및 자동 로그인 본문

프로젝트

데브코스 최종 프로젝트 - 14일차 / Recoil 연결 및 자동 로그인

jinist 2022. 8. 6. 06:24

 

 

14일차 - Recoil 연결 및 자동 로그인 구현

 

 

전체적인 UI가 나오고 로그인/회원가입을 담당하는 팀원이 API를 연결해주셔서

이제 그 내용들을 토대로 Recoil을 세팅하기로 했다.

 

사실 나는 Redux에 조금 더 익숙한 상태이긴 했고

빠른 프로젝트의 완성을 위해 익숙한 Redux로 갈 지, Recoil로갈 지 팀원들끼리 고민을 했었었다.

 

프로젝트에 Recoil을 사용하게된 이유?

1. 팀원들이 전역상태 라이브러리의 경험이 없는 상태기때문에 (Redux보다) 낮은 러닝커브의 라이브러리 필요

2. 전역상태로는 로그인정도만 구현할 예정이라 복잡하지 않은 라이브러리 필요

3. 사실 Context API로도 간단하게 구현할 수 있는 부분이겠지만 Recoil을 사용해봄으로써 Redux와 Context와 비교 경험

 

나도 Recoil은 처음이라 공식문서 튜토리얼, 사용 사례들을 보면서 적용하려 했는데

atom으로 적용하는건 정말 간단했지만 next와 결합해서 storage를 불러오는데에서 삽질이 있었다..

 

React Hydration Error,,

Recoil의 state작성 부분에서 Side Effects로 Localstarage를 연결시키려다가 생긴 에러,,

공식문서

 

SSR에서 window객체를 사용할 수 없다는 사실은 일부 알고있긴 했지만

난사실 아래처럼 window만 체크해주면 해결되는줄 알았다.

typeof window !== 'undefined'

공식문서의 해결 방법으로는 useEffect안에서 사용하는 방법들이 제시되었는데

Recoil환경 세팅을 하는데 useEffect라고,,?

 

테스트겸 여러 삽질을 하다가 그냥 atom으로 선언해둔 user state를 핸들링할 핸들러를

hook으로 구현하고 그 안에서 storage를 처리하기로 했다.

 

import { useRecoilState, useResetRecoilState } from 'recoil';
import { userState } from '~/recoil';
import { UserApi } from '~/service';
import WebStorage from '~/service/core/WebStorage';
import { LoginValues } from '~/types';

export const useUser = () => {
  const [currentUser, setCurrentUser] = useRecoilState(userState);
  const resetUser = useResetRecoilState(userState);
  const isLoggedIn = currentUser.accessToken !== null;

  const login = async (data: LoginValues) => {
    const response = await UserApi.login(data);
    setCurrentUser(response);
    WebStorage.setToken(response.accessToken);
  };

  const updateUser = async (token: string) => {
    const response = await UserApi.getUser();
    setCurrentUser({
      accessToken: token,
      user: { id: response.id, nickname: response.nickname, profileImage: response.profileImage }
    });
  };

  const logout = async () => {
    WebStorage.removeToken();
    resetUser();
  };

  return {
    currentUser,
    isLoggedIn,
    login,
    logout,
    updateUser
  };
};

 

 

로그인 유지

로그인 시 state에 token과 함께 유저 정보를 담지만 새로고침을 할 경우

state가 초기화가 되어 로그인이 풀리는 현상이 발생했다.

 

이전에 만든 Layout컴포넌트 내부에서 현재 유저의 토큰과 Storage의 토큰을 비교하여

값이 다르다면 다시 user정보를 update하도록 처리해주었다.

const Layout = ({ children, footer, full }: LayoutProps) => {
  const { currentUser, updateUser } = useUser();

  useEffect(() => {
    const token = WebStorage.getToken();
    if (token && currentUser.accessToken !== token) {
      updateUser(token);
    }
  });
  
  
  // ..생략
 
 }

 

 

Comments