개발놀이터

스프링 시큐리티 + JWT 인증 레이어 추가하기 (1) : 개요 본문

Spring/Spring Security

스프링 시큐리티 + JWT 인증 레이어 추가하기 (1) : 개요

마늘냄새폴폴 2023. 5. 20. 04:37

이번 포스팅에선 스프링 시큐리티에 JWT 인증 레이어를 추가하는 방법에 대해서 소개해드릴까 합니다. 

 

제가 이 프로젝트를 개발하면서 했던 고민들, 마냥 만사형통하지 않았던 험난한 과정들, 결국 내가 이 프로젝트를 통해 얻은 것들, 앞으로의 계획등은 아래의 링크에 자세히 기술되어있으니 참고해주시면 좋겠습니다. 

 

https://coding-review.tistory.com/381

 

온라인 쇼핑몰 ver.2 (3) : JWT 토큰으로 인증 레이어 추가하기

기존 프로젝트에선 스프링 시큐리티의 인증 + 세션 + Redis 이렇게 세 단계가 존재했습니다. 이번 개선으로는 JWT토큰을 도입해 인증에 새로운 레이어를 추가하는 것입니다. 하지만 따지고 보면 스

coding-review.tistory.com

 

아마 두개 내지 세개에 걸쳐 포스팅을 진행할텐데 이번 포스팅에선 개요에 대해서 작성해보도록 하겠습니다. 

 

위의 포스팅에서 적은 고민에 대해서 조금 설명하고 넘어가겠습니다. 

 

사실 이 프로젝트에 많은 고민이 있었습니다. 

 

  • 이미 스프링 시큐리티의 인증을 사용하고 있는데 굳이 다른 인증이 필요할까?
  • stateful한 session으로 인증을 구현하는게 stateless한 JWT에 비해 구현하기가 더 쉬운데...
  • JWT는 세션으로 인증을 안쓰려고 구현하는건데 스프링 시큐리티가 세션으로 인증을 진행한다고? 굳이 이 둘을 합쳐야할까?
  • 혹여 구현이 복잡해서 유지보수에 큰 영향을 끼치진 않을까? 

이런 크고작은 고민들이 있었습니다. 

 

사실 이런 고민을 한다는 것 자체가 저한텐 좋은 경험이었습니다. 아마 현업에서 개발하시는 분들이 겪는 고민들과 비슷한 느낌일 것이니까요. 

 

현업에선 많은 사람들끼리 회의를 통해 이런 기술을 도입할지 말지를 결정하겠지만 저는 회의할 사람이 없어서 챗 지피티한테 물어봤습니다. 

 

내가 스프링 시큐리티와 JWT를 결합해서 인증을 시도하려고 하는데 이렇게 둘을 합쳤을 때 장점이 있느냐

 

아주 청산유수더군요. 장점을 막 쏟아내는데 이 한문장 때문에 도입하기로 결정했습니다. 

 

"JWT는 MicroService의 준비단계다"

 

저는 제 프로젝트를 MicroService까지 구현할 생각입니다. 아직은 성능개선에 조금 초점을 두고 있지만 제 프로젝트의 종착지는 아마 마이크로서비스일 것입니다. 

 

이제 거두절미하고 본격적으로 포스팅 진행해보도록 하겠습니다. 

 

 

JWT로 인증

기본적으로 JWT로 인증을 구현했다고 하면 이런 구조를 떠올리실 것입니다. 

 

 

JWT가 구현하기가 뭐가 어려워? 라고 하시는 분들도 있을 것 같네요. 

 

그냥 JWT 빌더로 Access Token, Refresh Token 만들어서 쿠키에 넣어버리고 계속 검증하면 되는거 아냐?

 

그것도 물론 맞는 말이지요. 

 

하지만 그냥 스프링 시큐리티의 인증을 사용하는 것보다는 까다롭다고 생각합니다. 유지보수도 생각해야하구요. 

 

아마 그렇게 생각하신 분들도 있을텐데, JWT로 간단하게 구현하려면 얼마든지 간단하게 만들 수 있습니다. 

 

그렇지만 그렇게 간단하게 만들면 재미가 없지않겠습니까. 

 

제가 생각한 구조입니다. 

 

  1. 사용자가 로그인을 요청한다.
  2. JWTAuthenticationFilter로 요청을 인터셉트한다.
  3. Authentication 객체를 만들어서 SecurityContext에 집어넣는다.
  4. Access Token, Session Token을 발급해서 쿠키에 저장한다. 
  5. Session Token의 ID를 Redis에 저장한다. 
  6. 기본적인 HTTP 통신은 Filter에 의해 Access Token의 여부를 확인한다. 
  7. 이때 Access Token이 만료되면 
    1. SecurityContext에 들어있는 Authentication 객체의 isAuthenticated() 를 확인해서 true가 나왔다 = 웹 페이지를 벗어나지 않고 Access Token이 만료된 경우, 이런 경우엔 그냥 Access Token을 재발급
    2. Access Token이 null이고 = 쿠키가 만료되었고, Authentication 객체도 null 이다, 이런 경우엔 웹 페이지를 종료했다가 다시 들어온 사용자라는 얘기죠. 이럴땐 SESSION-TOKEN 쿠키를 확인해서 Redis에 있는 Refresh Token을 꺼내온다.
    3. Refresh Token을 검증한 뒤 Access Token을 재발급한다. 
  8. 모든 경우에서 SecurityContext에 Authentication 객체를 넣어서 스프링 시큐리티에게 인증을 위임한다.

 

이정도는 되어야 개발하는 맛이 있지 않겠습니까. 

 

정말 많은 삽질을 경험했구요. 

 

구현하는데 정말 까다로웠습니다. 험난했던 과정은 맨 처음에 올린 포스팅에서 확인해주세요! 

 

그래서 결국 JWT와 스프링 시큐리티를 이용한 인증을 구현했습니다. 

 

다음엔 주요 클래스 설명으로 이어집니다. 

 

https://coding-review.tistory.com/383

 

스프링 시큐리티 + JWT 인증 레이어 추가하기 (2) : 주요 클래스

https://coding-review.tistory.com/382 스프링 시큐리티 + JWT 인증 레이어 추가하기 (1) : 개요 이번 포스팅에선 스프링 시큐리티에 JWT 인증 레이어를 추가하는 방법에 대해서 소개해드릴까 합니다. 제가 이

coding-review.tistory.com