SSR 환경에서 로그인 유지하기

In9_9yu·2023년 7월 12일
1

mobae

목록 보기
9/9

🚪 들어가기 전

해당 PR 과 관련이 있습니다.

⚠️ 문제의 발생

이전 글에도 나와있지만, 로그인을 하면 다음과 같은 응답을 내려줍니다.

  • accessToken
  • user 정보 (id, email, gender, rank etc...)

이와 함께 서버에서 refresh token을 쿠키로 전달해주고, 서버에 요청을 보낼때 마다 refresh token도 같이 전달하는 방식을 취하고 있습니다.

실제 배포 환경에서 기능을 테스트 해보기 위해 로그인 이후 새로고침을 해보았습니다.

역시나 한 번에 성공하는 경우가 없어서 매우 슬픕니다.

❓ 문제의 원인

가장 근본적인 원인은, 서버로부터 refresh token이 브라우저에 저장되지 않는 문제였습니다.

그렇다면 왜 refresh token이 쿠키로 저장되지 않았을까요?

바로 도메인이 달랐기 때문입니다.

로컬 환경에서는 프론트엔드와 백엔드 모두 localhost 에서 돌아가기 때문에 발견하지 못했던 문제였습니다.

문제를 마주친 당시 프론트엔드와 백엔드의 도메인은 다음과 같았습니다.

환경도메인
프론트엔드example.vercel.app
백엔드example.xyz

다른 도메인간 쿠키 전송 이라는 주제로 글을 검색해보면, 꽤나 많은 자료들이 나옵니다.

여러 글들을 찾아보면서 해결책으로 제시한 다양한 방법을 시도했지만, 원하는 결과는 얻을 수 없었습니다.

해당 문제는 쿠키와 관련하여 따로 해보도록 하겠습니다.

🎊 해결한 방법

이미 해결하는 방법은 위에서 언급했듯이, 프론트엔드와 백엔드의 도메인을 일치시키면 됩니다.
과도한 호기심 + 오기 때문에 많은 시간을 다른 곳에 허비한 느낌이라 좀 아쉽긴 하네요

도메인은 다음과 같이 바꾸었습니다.

환경도메인
프론트엔드example.xyz
백엔드api.example.xyz

이렇게 하면 서브도메인만 달라지기 때문에, sameSite 옵션을 strict로 설정할 수 있다는 장점도 있습니다.

서브도메인을 설정하는 방법은 이 글에서 다룹니다.

🤦‍♂️ 또 다른 문제

서브도메인만 다르게 설정하여 배포한 결과는 성공적이었습니다.
로그아웃을 하기 위해 로그아웃 버튼을 눌렀는데도, 로그인이 유지되는 문제가 발생하였습니다. 이건 또 뭐야

분명 브라우저 상에서는 refresh token이 사라진 것을 볼 수 있었는데, 서버 로그에는 이전에 로그인 했던 refresh token이 계속 넘어오는 것을 볼 수 있었습니다.

내가 모르는 어디선가 캐싱이되나? 싶어서 해당 키워드를 가지고 검색을 해도 원하는 결과를 얻을 수 없었습니다.

계속된 디버깅 끝에 다음 코드에서 문제가 발생하는 것을 찾을 수 있었습니다.

export const silentLogin = async (
  cookie: string | undefined,
): Promise<null | ILoginResponse> => {
  // 아래의 조건문에서 발생하는 문제
  if (cookie) {
    axios.defaults.headers.Cookie = cookie;
  }
  ...
};

로그인 되어있는 상태
위 상황에서 Next 서버에서 곧바로 request를 요청하게 되면, 401 응답을 받게 됩니다.

왜냐하면 브라우저에는 쿠키 값으로 refresh token을 가지고 있지만, Next 서버에서는 해당 값을 가지고 있지 않기 때문입니다.

따라서 위의 코드와 같이 cookie를 전달 받는 경우, axios의 헤더에 추가하는 과정을 거치게 됩니다.

로그아웃 이후의 상태

문제는 로그아웃을 수행 한 뒤 브라우저에서 다시 새로고침을 하게 되면, cookie가 undefined 값이 되어버려 조건문을 거치지 않게됩니다.

그러면, 이전에 설정해 놓은 쿠키가 담긴 헤더 값으로 계속 요청을 보내게 됩니다.

이런 문제를 해결하기 위해, 해당 조건문을 삭제하였습니다.

그 이후 null 병합 연산자를 이용하여 전달 받은 쿠키가 존재한다면, 그 값을 그대로 할당하고, 없는 경우는 빈 문자열을 할당하여 문제를 해결하였습니다.

  axios.defaults.headers.Cookie = cookie ?? "";

📚 참고 문헌

RFC 6265
web.dev - SameSite 쿠키 설명
이현섭 개발자님의 글

profile
FE 임니다

0개의 댓글