문제상황
새로운 서비스의 카카오 로그인 기능을 구현하던 중, 인가 코드를 통해 카카오 서버로부터 액세스 토큰을 받아오는 과정에서 다음과 같이 KOE320 에러가 발생했다.

KOE320에 대해 검색해보니, 이미 발급된 인가코드를 다시 사용하여 발생하는 문제라고 한다.
현재 로그인 관련 로직은 다음과 같이 구현되어 있다.
- 카카오 계정으로 로그인
- 카카오 콜백 url(클라이언트측으로 설정)에서 인가코드를 받아오고, 이를 담아 서버측으로 API 요청
- 서버 API에서 인가코드를 통해 액세스 토큰을 받아온 후 회원가입or로그인 처리
- 클라이언트로 액세스 토큰 response body에 담아서 보냄 & refresh token은 httpOnly 쿠키에 저장
- 클라이언트에서 토큰 받아와서 axios.defaults.headers에 저장(axios 요청시 항상 헤더에 토큰을 포함하도록)
2번에서 문제가 있는 것 같다.
해결
리액트를 아직 완벽히 숙달하지 못해서 평소에도 불필요한 렌더링이 발생하는 경우가 종종 있었다.
인가코드를 중복 사용했다는 것 또한 반복 렌더링 문제 때문일 것이라 추측하고, 렌더링이 중복될 수 있는 부분들을 체크했다.
→ React.StrictMode를 사용하여 생긴 문제였다.
CRA로 리액트 프로젝트를 생성하게 되면 React.StricMode가 디폴트로 설정되는데,
이는 javascript의 strict mode와 유사하게 리액트 애플리케이션 내의 잠재적 문제를 방지하기 위한 도구이다.
React.StrictMode를 사용하면, 부작용 문제를 진단하기 위해 렌더링 단계의 메서드를 두 번씩 호출하게 된다.
...
const authCode = searchParams.get("code");
const getToken = async () => {
await axios({
method: "GET",
url: `${process.env.REACT_APP_BASE_URL}/auth/kakao/callback`,
params: {
authCode,
},
withCredentials: true,
})
.then((res) => {
onLoginSuccess(res).then(() => {
setIsLogin(true);
});
})
.catch(onLoginFail);
};
useEffect(() => {
getToken()
}, [])
...
위 코드를 통해 서버에 인가코드를 전달하는데, React.StrictMode로 인해 getToken이 두 번 호출되었다.
따라서 동일한 인가코드로 카카오 서버에 토큰 요청을 두 번 중복하여 보내게 되므로, KOE320 에러가 발생하였다.
index.js에서 React.StrictMode를 제거하는 것으로 우선 해결하였다.
...
root.render(
// <React.StrictMode>
<RecoilRoot>
<Suspense
fallback={
<>
<ClipLoader />
</>
}
/>
<App />
</RecoilRoot>
// </React.StrictMode>
);
(strct mode를 사용하는 것이 안정성 측면에서 좋다고 하는데, 이를 사용하면서 인가코드 문제가 발생하지 않는 방향을 추후에 연구해볼 예정이다.)
References
https://jeonghwan-kim.github.io/2022/05/20/react-strict-mode
리액트 StrictMode
거의 사용해 보지 못했다. create-react-app에서 잠깐 봤는데 이걸로 프로젝트를 해본 경험이 없으니 정말 거의 사용한 적이 없었다. React의 Strict 모드가 무엇인지 문서 위주로 정리해 보자. 역할 자
jeonghwan-kim.github.io