소셜 로그인
으로 구현한 로그인 로직에서 동일한 사용자로 로그인을 시도했음에도 로그인이 잘되는 경우와 에러가 발생하는 경우가 발생했다. 성공이면 성공, 에러면 에러가 나와야 하는데, 잘 되기도 하고 안되기도 하고 개발 입장에서는 원인을 파악하기 어려운 상황이었다. 다행히 그 원인을 리액트 공식문서 학습에서 엄격 모드
때문임을 알게 되었다.
동일한 사용자로 로그인을 시도하면 성공하는 경우도 있고 실패하는 경우도 발생
개발자 도구 네트워크를 확인하니 로그인 요청이 두 번 발생하고 있다.
엄격모드
는 컴포넌트의 부수효과를 두 번 호출한다.클립업
함수를 추가해서 두 번째 요청을 무시하도록 해야한다.const Callback = () => {
const searchParams = new URLSearchParams(window.location.search);
const code = searchParams.get(AUTHORIZATION_CODE);
const { data } = useAsync(() => postLogin(code));
const { handleLogin } = useAuthContext();
const navigate = useNavigate();
useEffect(() => {
if (data?.status === 'FORBIDDEN') {
const { nickname, profileUrl, oauthId } = data.data;
navigate(
`${REGISTER}?nickname=${nickname}&profileUrl=${profileUrl}&oauthId=${oauthId}`,
);
}
if (data?.status === 'OK') {
const { jwt } = data.data;
handleLogin(jwt);
navigate(HOME);
}
}, [data]);
return (
// 중략
const { data } = useAsync(() => postLogin(code))
이 원인으로 판단function useAsync<T>(
// 중략
const fetchData = async (): Promise<void> => {
dispatch({ type: 'LOADING' });
try {
const response: AxiosResponse<T> = await callback();
dispatch({ type: 'SUCCESS', data: response.data });
} catch (e) {
dispatch({ type: 'ERROR', error: e as AxiosError });
}
};
useEffect(() => {
if (skip) return;
fetchData();
}, deps);
// 중략
}
fetchData()
가 호출되지 않도록 클립업
함수를 추가한다. let ignore = false;
useEffect(() => {
if (skip) return;
if (!ignore) {
fetchData();
}
return () => {
ignore = true;
};
}, deps);
fetchData()
는 ignore
이 false 인 경우(첫 요청)에만 호출된다.엄격모드
로 useEffect가 재실행될 때는 ignore
이 true가 되어 두 번째 fetchData()
호출을 방지한다. 엄격모드
활성화 환경에서도 한 번의 요청만 처리되도록 수정하여 문제 해결계속해서 Effect의 좋은 점만을 생각하면서 사용을 해온 것 같다.
리액트 학습과 프로젝트 진행을 병행해 가면서 Effect 사용의 조심성이 계속 커지고 있다.
데이터 Fetch에서 특히 많이 사용하고 있는데, 이미 발생한 네트워크 요청은 실행 취소가 안되니, 클린업 함수에 대한 이해와 필요성을 많이 고민해 봐야겠다.