첫 번째 스프린트는 로그인/회원가입 기능을 구현하는 것이다. 먼저 인증/인가의 개념을 이해하고, 세션 방식이 아닌 JWT를 적용한 이유에 대해 정리해보았다.
<인증>
: 쉽게 말해 로그인이라고 생각하면 된다.
내가 이 사이트에 사용자임을 아이디와 패스워드를 통해서 인증을 받는 것이다.
<인가>
: 쉽게 말해 로그인이 유지되는 상태라고 생각하면 된다.
한 번 인증을 받은 사용자가 이후 서비스의 여러 기능을 사용할 때 서비스가 그 기능들을 사용할 수 있도록 허가를 해주는 것
로그인 기능을 구현할 때, 보안을 강화하기 위해 JWT 방식을 채택한다.
먼저 세션 방식의 로그인 과정을 보면
- 사용자가 로그인을 하면 서버에서 세션 ID를 생성하고 이를 쿠키에 담아 클라이언트에게 전달한다.
- 클라이언트는 이후 요청 시 세션 ID가 담긴 쿠키를 함께 보낸다.
- 서버는 세션 ID를 확인하여 사용자의 인증 상태를 확인하고 권한을 부여한다.
즉, 세션 방식은 서버 메모리에 세션 ID를 올려놓기 때문에 휘발성이고, 사이트가 커질 경우 메모리 부족 문제가 발생할 가능성이 높아진다는 것을 알게되었다.
세션 방식의 문제점
→ 사용자 인증 정보를 클라이언트가 아닌 서버가 관리해서 보안상 안정적일 수 있지만 서버 부하가 치명적이다.
- 세션 정보를 서버 메모리에 저장하므로 사용자 수가 늘어나면 서버 메모리 부족 문제가 발생할 수 있다.
- 세션 정보가 서버에 저장되므로 동기화 문제가 발생할 수 있다.
- 세션 ID가 탈취되면 돌이킬 수 없다.
따라서, 이런 세션 방식의 문제점을 해결하고, 인가 과정의 보안을 강화하기 위해 구현된 방식이 토큰 기반의 JWT이다.
그러나 암호화된 토큰 방식으로 보안을 강화한 JWT도 Base64로 인코딩 되어 있고, 수명이 길어 제 3자에게 탈취당할 위험이 있어 안전하다고 할 수 없다.
이를 보완한 방법으로 AccessToken과 RefreshToken을 사용하는 방식인데,,
JWT 방식의 보안 강화
- AccessToken: 유효기간 짧음, 서비스 접근에 사용
- RefreshToken: 유효기간 길음, AccessToken 재발급에 사용
- RefreshToken 재발급으로 AccessToken 유출 위험 감소
즉, 정리하면 JWT 토큰은 서버 메모리에 저장되는 방식이 아닌, 클라이언트에 저장되어 부담이 줄어들고, 암호화 방식으로 토큰이 구현되어 있기 때문에 탈취 시에도 위변조가 어려운 장점이 있다. 그러나 인코딩 방식에서 탈취 시 보안을 강화하기 위해 AccessToken과 RefreshToken을 사용하였다.
그러나 이도 완벽한 방법은 아니기에 JWT 방식이 세션 방식보다 정말 좋은 방식일까에 대한 고민은 계속하였다.
현재 프로젝트 특성상 완벽한 보안까지 필요없고, 세션에서 좀 더 편한 방식인 디바이스별 로그아웃 기능 등을 구현하지 않을 것이기에 비지니스 적이나 리소스 측면에서 JWT를 사용하는 것이 더 적절하다고 판단했다. 즉, 만약 보안이 정말 중요했다면 세션 방식을 사용했을 것 같다.
...
이제 이어서 JWT를 활용한 로그인/회원가입 기능을 구현할 것이다.
참고