문제 발생

RTR 적용 중 발생한 문제입니다. 하지만 RTR 에 국한된 문제가 아니라서 따로 포스팅하려고 합니다.

RTR 을 local 에서 확인하던 중 다음과 같은 문제가 발생했습니다.

한번씩 Redis 에 저장된 refreshToken 값이 갑자기 바뀜

  • 바뀌는 이유를 모르겠음. debug 를 찍어봐도 refreshToken 값이 특정 메서드에서가 아니라 특정 구간 사이에서 랜덤하게 갑자기 변경됨
  • 두 번 실행하면 한번은 성공함. 하지만 두번 다 실패하는 경우도 있음

이 문제 때문에 2시간 정도 고생했습니다.

문제 원인

처음에는 문제의 원인이 당연히 서버에 있는줄 알았는데요. 그게 아니라 프론트쪽이었습니다. (그래서 TIL-react 입니다… ㅎ)

다음 코드가 문제였습니다.

...
const [nickname, setNickname] = useState('');
let isLogin = authCtx.isLoggedIn;
let isGet = authCtx.isGetSuccess;

const callback = (str) => {
    setNickname(str);
  }

  useEffect(() => {
    if (isLogin) {
      authCtx.getUser();
    } 
  }, [isLogin]);

  useEffect(() => {
    if (isGet) {
      callback(authCtx.userObj.nickname);
    }
  }, [isGet]);

여기서 authCtx.getUser()"/member/me" 로 user 정보를 요청해서 받는 함수입니다. 위 코드가 MainNavigation 에서 선언되어 있어서 모든 페이지에서 login 시 호출되게 되어있습니다.

이때 authCtx.isLoggedIn 는 localStorage 의 accessToken 여부로 판단하게 되는데, 있으면 true, 없으면 false 입니다.

중요한 건 AccessToken 을 호출할 때 발생하는데요. AccessToken 이 만료될 때마다 새로 LocalStorage 에 저장하는 과정에서 isLogginedIn 이 true -> false -> true 로 변경됩니다.

이렇게 변경되면 isLogin 이 변경되면서 authCtx.getUser() 를 다시 호출하게 됩니다.

문제점

  1. "/player/list" 호출하면서 "member/me" 함께 호출
  2. 두 요청이 비동기로 처리되면서 server 로 동시에 호출됨
  3. server 에서는 다음과 같이 동작됨
    1. /player/list 호출에 대해 /refreshToken 으로 token 갱신 요구
    2. /refreshToken 갱신하면서 Redis 에 있는 refreshToken 을 갱신함
    3. 해당 refreshToken 이 도착하기 전에 member/me 호출에 대한 token 갱신도 시작됨
    4. member/me 에 대한 갱신도 cookie 안의 refreshToken 으로 이루어지는데, 해당 refreshToken 은 이미 /player/list 에 대한 갱신으로 인해 변경된 상태임
    5. 따라서 refreshToken 이 맞지 않으므로 401 에러를 반환
  4. 클라이언트는 401 에러를 받고 재로그인 요구

글로 설명하기가 어렵네요. 결론적으로 server 로 호출을 2번하면서 refreshToken 갱신도 2번 요구하게 되고, 첫번째 갱신과 두번째 갱신이 동시에 이루어지다보니 Redis 에 저장된 값과 맞지 않게 된 겁니다.

해결

해결 방법은 useEffect 에서 isLogin 값이 아닌 다른 값을 사용하거나, cookie 에 userObj 를 저장하는 방법 등이 있겠지만 결론적으로 navigation 에서 member/me 호출을 뺐습니다.

그 이유는 어쨋든 실행 페이지의 호출과 navigation 의 호출이 겹칠 위험이 있고, 한 동작에서 호출이 2번 일어나면 안되기 때문입니다.(사실 제 생각입니다 ㅎㅎ)

다음에 react, typescript 를 좀 더 배우면 ui/ux 를 제대로 변경해보겠습니다.

태그: ,

카테고리:

업데이트:

댓글남기기