<aside>
📌 로직 순서
</aside>
- 유저는 member에 로그인을 하고 member에서 jwt를 발급받는다.
- 이때 요청의 모든 header에는 jwt가 담겨있어서 recipe서버의 security는 이걸 확인해서 token이 유효하다면 기능이 동작해야 한다.
- 만약 recipe 조회를 하는 요청이 있다고 가정하면 이때 recipe서버는 jwtAuthorizationFilter를 통해서 요청에 담겨들어온 header 내부의 jwt토큰의 유효성을 검증하게 될거고 검증이 완료되면 SecurityContextHolder에 정보를 저장하게 될것이다.
- 기존에는 이렇게 SecurityContextHolder에 담긴 정보를 가져다 사용하려 했지만 jwt를 사용하는데 이 방식이 옳은건지 의문점이 생겨서 조사를 해봤다.
<aside>
📌 질문1
</aside>
- 질문:
- msa + springBoot + springSecurity + jwt에서 로그인 관련 로직을 구현해야하는데 시큐리티 context에 저장해서 공유하지말고 매번 jwt토큰으로 security 검증을 통과하면 그 claims정보를 메서드에서 꺼내서 사용하는게 좋은거야? 고민이야 security에 저장해서 계속 공유해서 사용하려했었거든
- 대답:
- Spring Security와 JWT를 사용하는 현재 아키텍처에서는, 매 요청마다 JWT 토큰으로 인증을 수행하는 것이 일반적이다. 이렇게 설계되면 Stateless한 특성을 유지할 수 있으며, 확장성과 유지보수성에 이점이 있다.
- Stateless Architecture:
- 각 요청이 독립적으로 인증되므로, 서버 측에서 상태를 유지할 필요가 없다. 이로 인해 확장성이 향상된다.
- Decoupling:
- 토큰 기반의 인증은 서비스간 결합도를 낮춘다. 각 서비스는 받은 토큰만 유효하면 처리할 수 있으므로,
member
서비스와의 통신을 최소화할 수 있다.
- Performance:
- 매번
member
서비스에게 사용자 정보를 요청하는 것은 네트워크 오버헤드를 발생시킬 수 있으므로, 필요한 정보는 토큰(Claim)에 미리 담아두는 것이 효율적이다.
- Security:
- 매 요청마다 토큰을 검증함으로써, 토큰이 탈취되거나 변조되는 것에 대한 리스크를 감소시킬 수 있다.
- 따라서 요청마다 JWT로 인증을 거친 후 필요한 정보를 Claim에서 꺼내어 사용하는 방식을 추천한다. 이 방식을 사용하면
SecurityContextHolder
를 통한 상태 공유는 필요하지 않을 것이다.
<aside>
📌 질문2
</aside>
- 질문:
- 그럼 매번 메소드에서 member관련 정보를 필요로한다면 jwt에서 계속 claim에서 꺼내서 저장하거나 그래야해?
- 대답:
- 그게 일반적인 접근 방식이다. JWT 토큰에 필요한 정보(예: 사용자 ID, 권한 등)을 Claim으로 저장해두면, 각 요청에서 해당 정보를 쉽게 추출할 수 있다. 이렇게 하면 별도의 네트워크 요청 없이도 필요한 정보를 빠르게 가져올 수 있다.
- 예를 들어, 서비스 로직 내에서 사용자 ID가 필요하다면, 요청에 포함된 JWT에서 사용자 ID를 추출할 수 있다. 이 정보는 보통
HttpServletRequest
객체, 혹은 Spring의 @AuthenticationPrincipal
어노테이션을 통해 접근할 수 있다.