React-query, SWR을 사용해야하는 이유. 엄격 모드

카카오 로그인을 구현하기 위해서 코드를 작성하고 있는데, 예상치 못한 부분에서 오류가 났습니다.

카카오톡 로그인은 위와 같은 과정으로 구현할 수 있습니다.

카카오 로그인에 대한 자세한 내용은 아래 공식문서를 참조하세요!

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

오류가 왜 났는지 결론부터 말씀드리자면, 인가코드로 토큰을 요청하는데 Strict-Mode 때문에, fetch 요청이 두 번 이루어 지게 되면서 오류가 난 것이었습니다.

const Auth = () => {
  const params = useSearchParams();
  const code = params.get("code");
  const router = useRouter();

	useEffect(()=>{
            const asyncRequest = async () => {
	    const res = await (
	      await fetch("/api/kakaoToken", {
	        method: "POST",
	        body: JSON.stringify({ code }),
	      })
	    ).json();
	
	    if (res.ok) {
	      router.push("/message");
	    }
	    if (res && !res.ok) {
	      router.push("/");
	      toast.error(res.error);
	    }
	  };
	
	  asyncRequest();
	},[])
  

	return (
            <div className="py-5 px-10 flex flex-col gap-2 items-center backdrop-blur-lg rounded-lg">
              <p className="text-lg font-semibold ">로그인 중입니다...</p>
              <RiLoader2Line size={30} className="animate-spin" />
            </div>
	);
};

위 코드는 제가 인가코드를 이용하여 로그인을 요청하는 부분을 짠 코드입니다.

보시면 fetch API를 이용하여 서버에 인가코드를 보냈고, 서버에서 외부 서버인 카카오 서버로 토큰을 요청하게 되어 로그인을 완료하게 합니다.

하지만 위 코드로는 로그인이 정상적으로 이루어지지 않게 되었습니다.

❓ 로그인에 실패한 이유?

서론에서 말씀 드렸다시피, 로그인에 실패한 이유는 바로 React 환경에서는 기본적으로 Strict Mode가 적용되어 있기 때문입니다. Strict 모드 즉 엄격 모드는 두 번 실행하는(Double-Invoke) 방식으로 부작용을 방지합니다.

따라서 렌더링 시 함수가 두 번 실행되는 Double-Invoke 때문에, 인가 코드를 보내는 요청이 두 번 발생하게 되면서 오류가 발생했던 것입니다.

카카오 서버의 인가 코드는 1회만 사용할 수 있는데, 두 번 요청하게 되면서 서버에서 예상치 못한 Error 혹은 예상치 못한 값을 응답받게 됩니다.

React-query, SWR 라이브러리를 사용하여 서버 데이터를 요청하게 되면, 엄격 모드에서도 한 번 작동하게 됩니다.

따라서 서버데이터를, 특히나 외부 서버 데이터를 다루는 경우에는 필수적으로 React-query, SWR과 같은 서버 데이터 관리 툴을 사용하는 것이 필수적이겠네요!

❓Strict Mode를 해제하면 되지 않을까?

Strict 모드를 사용하지 않는다는 것은 굉장히 위험합니다.

Strict 즉 엄격 모드를 사용하지 않는다면, 실수의 가능성이 매우 높아지고, 사용하지 않을 경우 의도하지 않은 결과를 낳을 수 있습니다. 특히나 유연성이 높은 JS의 경우에는 더더욱 그렇겠지요.

아래는 리액트의 Strict 모드 공식 문서입니다.

 

Strict 모드 – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

따라서 Strict Mode를 사용하지 않는 것 보다, React-query, SWR과 같은 라이브러리를 사용하는 것이 좋겠네요!

다음은 수정 코드 입니다.

const Auth = () => {
  const params = useSearchParams();
  const code = params.get("code");
  const router = useRouter();

  if (!code) {
    router.push("/");
    toast.error("something wrong");
  }

  const { data } = useSWR(["kakaoToken"], () => getToken(code!));

  useEffect(() => {
    if (data && data.ok) {
      router.push("/message");
    }
    if (data && !data.ok) {
      router.push("/");
      toast.error(data.error);
    }
  }, [data, router]);

  return (
    <div className="py-5 px-10 flex flex-col gap-2 items-center backdrop-blur-lg rounded-lg">
      <p className="text-lg font-semibold ">로그인 중입니다...</p>
      <RiLoader2Line size={30} className="animate-spin" />
    </div>
  );
};