구글·애플 소셜 로그인 뒤에, 왜 내 JWT를 다시 발급하나

앱에 구글·애플 로그인을 붙일 때 흔한 오해가 있다. “소셜 로그인 됐으니 그 토큰으로 API를 부르면 되지 않나?” 나는 소셜 로그인 뒤에 내 서버의 JWT를 다시 발급하는 구조로 짰다. 그 이유와 흐름, 그리고 실제 얻은 이점을 정리한다.

인증 흐름

  1. 모바일 앱에서 구글/애플 로그인 → 소셜 제공자의 토큰을 받는다.
  2. 그 토큰을 백엔드로 보내 서버가 검증한다(제공자에게 유효성 확인).
  3. 검증되면 서버가 사용자를 찾거나 새로 만들고, 내 서버의 JWT(액세스 + 리프레시)를 발급한다.
  4. 이후 모든 API는 이 JWT로 인증한다. 푸시용 FCM 토큰도 이때 함께 저장한다.

왜 소셜 토큰을 그대로 안 쓰나

  • 클라이언트를 믿지 않는다. 소셜 토큰 검증을 서버에서 해야 위조를 막는다. 앱이 보낸 “나 로그인했어요”를 그냥 믿으면 조작된 요청에 뚫린다. 검증은 반드시 서버 몫이다.
  • 인증을 하나로 통일한다. 구글이든 애플이든, 검증 후엔 전부 동일한 내 JWT로 수렴한다. API·미들웨어는 소셜 제공자를 신경 쓸 필요가 없다. 나중에 카카오·네이버 같은 로그인을 추가해도 검증 어댑터만 하나 더 붙이면 API 계층은 그대로다.
  • 수명·갱신을 내가 통제한다. 액세스 토큰은 짧게 두고 리프레시 토큰으로 갱신한다. 소셜 제공자의 토큰 정책에 종속되지 않고, 필요하면 서버에서 즉시 무효화도 할 수 있다.

미들웨어 한 곳에서 검증

발급한 JWT는 인증 미들웨어 한 곳에서 검사하고, 통과하면 요청 컨텍스트에 사용자 정보를 주입한다. 각 라우트는 “이미 인증된 사용자”만 받으면 되니, 인증 로직이 컨트롤러마다 흩어지지 않는다. 라우트·서비스는 비즈니스 로직에만 집중하고, 인증·검증은 미들웨어가 책임진다. 여기에 요청 제한(rate limit)과 보안 헤더를 함께 걸어, 인증 계층에서 남용도 막는다.

토큰 수명 설계

액세스 토큰을 길게 두면 탈취 시 피해가 크고, 너무 짧으면 사용자가 자주 튕긴다. 그래서 짧은 액세스 + 리프레시 갱신 조합을 쓴다. 앱은 액세스가 만료되면 리프레시로 조용히 새 토큰을 받아, 사용자는 로그인 상태가 끊기지 않는다. 소셜 제공자에 매번 다시 묻지 않아도 되니 로그인 흐름도 빨라진다.

정리

소셜 로그인은 “신원 확인”까지만 쓰고, 그 뒤 세션은 내 JWT로 가져간다. 이렇게 하면 보안(서버 검증)·확장(로그인 수단 추가)·통제(토큰 수명)를 한 번에 잡을 수 있다. 소셜 로그인을 “편리한 회원가입 버튼”으로만 보면 놓치기 쉬운 설계인데, 실제 서비스에선 이 한 겹이 보안과 유지보수를 크게 좌우한다.

실수하기 쉬운 지점

이 구조에서 흔히 걸리는 함정이 있다. 리프레시 토큰을 안전하지 않은 곳에 저장하면 탈취 시 갱신까지 뚫린다 — 모바일에선 보안 저장소를 써야 한다. 또 애플과 구글의 토큰 검증 방식이 달라, 각 제공자에 맞는 검증 로직이 필요하다(애플은 발급 정보가 최초 로그인에만 오는 등 특이점이 있다). 마지막으로 로그아웃·계정 삭제 시 서버의 리프레시 토큰과 FCM 토큰을 함께 정리해야 유령 세션·유령 푸시가 안 남는다. 인증은 “발급”보다 “폐기·정리”에서 사고가 난다.

댓글 남기기

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.ㅇ