ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React Strict Mode에서 API 사용
    Front-end/React 2023. 1. 17. 22:50
    728x90

    yotrakbutda - White cloud on black background

    React 18 부터 Stric Mode development 환경에서는 컴포넌트가 두번 렌더링됩니다. 정확히 말하면 mount → unmount → remount의 lifecycle로 이루어집니다.

    공식 문서: https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state

     

    Strict Mode – React

    A JavaScript library for building user interfaces

    reactjs.org

    모든 컴포넌트들에 대해서 unmount한 후 remount 되는 상황을 검사하기 위함입니다. 그래서 useEffect로 lifecycle 로직을 아래와 같이 구현한다면, mount 로직 unmount 로직 mount 로직이 수행됩니다.

    useEffect(() => {
    	// mount 로직
        return () => {
        	// unmount 로직
        }
    }, []);

    이때 mount 로직 부분에 외부 API 콜이 있을 때, 중복해서 불리면 안되는 경우 오류가 발생합니다. 회사에서 겪은 문제로 aws cognito에서 /oauth2/token을 다음과 같이 사용합니다.

    useEffect(() => {
    	// mount 로직
        const fetch = async () => {
        	await axios.post(`${COGNITO_DOMAIN}/oauth2/token`, ...);
        }
        fetch().catch();
        return () => {
        	// unmount 로직
        }
    }, []);

    테스트를 해보면 "invalid_grant" 오류 발생합니다.

    unmount -> remount 시에 오류 발생
    unmount 후 remount시에 invalid_grant

    aws cognito /oauth2/token 엔드포인트 문서에 정리되어있는 invalid_grant 내용을 보면 다음과 같습니다.

    새로 고침 토큰이 취소되었습니다.
    권한 부여 코드를 이미 사용했거나 해당 코드가 존재하지 않습니다.

     

    같은 authorization_code를 사용하여 두 번의 api 콜을 하였기 때문이라고 생각합니다. “권한 부여 코드를 이미 사용했거나…” 이 구절에 대한 해석인데, 정확한 해석인지 한 번더 고민해봐야겠습니다.

    해결 방법 1: Strict Mode 안 쓰기

    별로 좋지 않습니다. Strict Mode는 컴포넌트의 생명주기 검사를 해주기 때문에 안정적인 개발에 매우 유용합니다.

    해결 방법 2: 요청 취소

    axios “취소 토큰”을 사용하여 요청 취소를 할 수 있습니다. 컴포넌트가 unmount될 때 처음 요청을 cleanup 부분에서 취소하는 것입니다. 취소 토큰에 대한 내용은 공식 가이드로 쉽게 이해할 수 있었습니다. 이 때 주의할 점이 하나의 취소 토큰을 모두 요청의 cancelToken으로 지정하면 처음 요청과 remount시 요청이 모두 취소됩니다. 따라서 useEffect 내부에서 취소 토큰을 선언하여 요청마다 다른 취소 토큰을 사용하도록 해주어야 합니다.

    useEffect(() => {
    	const source = axios.CancelToken.source();
    	// mount 로직
        const fetch = async () => {
        	await axios.post(`${COGNITO_DOMAIN}/oauth2/token`, {
            	cancelToken: source.token
            });
        }
        fetch().catch((thrown) => {
        	if (axios.isCancel(thrown) {
            	// 의도된 cancel error
            } else {
            	// 의도하지 않은 error
            }
        });
        return () => {
        	// unmount 로직
            source.cancel();
        }
    }, []);

     

    취소된 요청은 cancel error를 throw합니다. 따라서 try catch와 axios의 isCancel을 사용하여 해당 부분의 cancel error를 처리해줍니다.

     

    취소가 정상적으로 동작하면 사진과 같이 Network에서 canceled를 확인할 수 있습니다.

    canceled된 요청

    fetch를 사용하는 경우, AbortController를 사용하여 똑같이 구현할 수 있다고 합니다.

     

    참고

    https://hmos.dev/how-to-cancel-at-axios

     

    How to cancel at axios | hmos.dev

    The article that how to use cancel logic on axios request.

    hmos.dev

    고민

    axios 요청 취소 가이드를 보면 다음과 같이 적혀있습니다.

    Axios의 취소 토큰 API는 중단된 proposal-cancelable-promises을 기반으로 하고 있습니다.

    “중단된” 것을 기반으로 동작한다니 굉장히 불안한 내용입니다. axios에서도 fetch와 같이 AbortController를 사용하여 처리하는 부분도 있습니다. 위 내용을 좀 더 조사해서 어떤 것을 사용해야할지 고민해봐야겠습니다.

    728x90

    'Front-end > React' 카테고리의 다른 글

    React Component debounce 적용  (1) 2023.03.05
    React CRACO 설정  (0) 2023.02.09
    현재 state와 동일한 값으로 업데이트해도 리렌더링되는 경우  (0) 2023.02.08
    React Production 환경 테스트  (0) 2023.01.28
    React Test  (0) 2023.01.18

    댓글

Designed by Tistory.