로그인(일반/소셜) 기능 구현을 완료하고 나서 로그아웃 구현을 시작하였다. 로그아웃 기능은 사용자의 인증 세션을 종료시키고, 서비스 내에서 비로그인 상태로 전환되도록 처리하는 기능이다. 구체적으로는 다음 기능들을 포함한다.
즉, 그저 “토큰을 지우는 버튼”이 아니라 서버/클라이언트 상태를 함께 정리해서 인증 흐름을 안전하게 끊어주는 세션 종료 기능이다.
앞에서 로그인 방식을 대대적으로 개편하면서 어떠한 흐름으로 로그인이 완료되는지 이해가 꽤나 됐다고 생각한 나는 로그아웃은 크게 어려울 것이 없다고 생각이 들었다. 나는 바뀐 인증 구조(AccessToken + RefreshToken httpOnly 쿠키) 에 맞춰 아래 2가지 기준으로 로그아웃을 구현하였다.
서버 세션도 함께 종료한다
이미 refreshToken이 httpOnly 쿠키로 내려오는 구조였기 때문에, 프론트가 임의로 refreshToken을 지우는 방식은 불가능했다. 따라서 로그아웃은 반드시 서버 로그아웃 API를 호출해서 refreshToken을 무효화/삭제하고, 브라우저 쿠키도 서버 응답으로 정리되는 흐름이 되도록 하였다.
클라이언트 상태를 즉시 ‘비로그인’으로 만든다
로그아웃 직후 화면이 즉시 바뀌고 Protected 페이지 접근이 막혀야 했기 때문에, API 성공 여부와 관계없이 프론트에서는 accessToken 제거 + 인증 관련 캐시/상태 초기화를 통해 “지금 이 순간부터 비로그인” 상태가 되도록 설계했다.
온보딩 마지막 페이지인 ‘온보딩 완료 페이지’를 어느 가드에 둘지가 애매했다… 처음에는 당연하게도 온보딩이 완료된 페이지이기에 OnboardingCompleteGuard 아래에 두었다가 온보딩이 미완료인 상태로 진입하기에 가드에 의해 온보딩 시작으로 튕겼다. 그렇다고 온보딩이 아직 미완료된 OnboardingOnlyGuard에 두자니 온보딩이 완료되는 페이지가 들어가기에 적합하지 않았다.

우선 온보딩 완료 페이지 자체가 어떤 식으로 온보딩 유무를 처리하는지를 먼저 살폈다. 이 페이지에 들어가게 되면 api호출을 통해 온보딩 완료를 확정하게 된다. 그러나 그 전에 상위에 걸린 가드가 먼저 판단을 내리게 된다. 결과적으로 이 페이지는 온보딩 미완료에서 완료가 되는 전환 페이지의 역할을 해야 하는데 그 전에 가드가 존재하면 선제적으로 리다이렉트를 하기에 흐름이 꼬이게 되는 것이었다.
중요한 것은 이 페이지가 온보딩 유와 무가 둘 다 존재할 수 있는 전환페이지였기에 어떠한 가드에 두는것도 적합하지 않다는 것이었다. 대신 앞에서 로그인 여부를 따진다면 비로그인 유저는 접근가능하면 안되기에 AuthGuard 아래에 단독 라우트로 배치를 하였다. 그러나 이렇게 되면 로그인과 온보딩을 모두 진행한 유저가 억지로 접근할 수 있고 필요없는 온보딩 완료 api를 한번 더 호출할 수 있기에 라우트가 아닌 페이지 레벨에서 이미 온보딩이 완료된 유저는 기기추천 페이지로 리다이렉트하게 처리를 하였다.