JWT와 세션 방식의 오해
해당 포스팅은 개발하는 과정에서 생긴 고민을 작성한 글입니다.
작성한 내용은 정답을 제시한 것이 아닌 작성자 본인이 고민한 내용과 생각을 작성하였으므로 다양한 의견을 제시해 주시면 감사합니다.
🔖 주제
해당 포스팅은 회원 도메인의 인증/인가 방식에 대해 개발하며 생긴 고민을 소개합니다.
포스팅에서 중점으로 바라보는 것은 JWT 방식과 세션 방식의 차이점과 서비스에 어떤 방식을 도입하는 것이 적합한지에 대해 설명합니다.
📓 설명
JWT 방식
인가 정보를 암호화하여 사용자에게 위임하는 방식.
기본적으로 AT(Access Token)만 존재하는 것이고, RF(Refresh Token)은 AT의 특징을 변형하기 위해 만들어진 개념입니다.
AT를 클라이언트에 위임하는 것으로 서버는 인가 상태를 저장할 필요가 없어 stateless 상태를 유지할 수 있습니다.
세션 방식
인가 정보를 서버에 저장하는 방식.
세션 아이디를 기준으로 인가 정보를 찾을 수 있도록 구성하여, 중요 정보가 외부로 노출되지 않도록 구현합니다.
상태를 저장하기 때문에 stateful으로 표현할 수 있습니다.
Q&A
ℹ️ 제 스스로 궁금했던 점이나 고정관념에 의해 착각하고 있던 점을 기술합니다.
Q. JWT 방식은 AT를 주기적으로 갱신하니 세션 방식에 비해 보안이 좋지 않나요?
JWT가 AT를 주기적으로 갱신하는 이유는 탈취를 걱정하기 때문입니다.
오히려 JWT 방식의 취약성을 우려하여 대처를 해둔 것일 뿐이지 단순히 갱신한다 해서 보안이 더욱 좋아졌다 생각하면 안 됩니다.
또한 갱신이 중점이라면 세션 아이디 또한 갱신을 통해 주기적으로 교체할 수 있습니다.
Q. 세션 방식은 회원 검증 과정으로 인해 JWT 방식에 비해 비효율적이지 않나요?
회원을 검증하는 과정은 선택이라 생각합니다.
JWT 방식을 구현한다면 전 주로 AT를 복호화하여 회원 ID를 획득하는 프로세스를 적용했습니다.
세션도 동일합니다.
세션 아이디를 기준으로 회원 ID를 찾습니다.
이 두 과정의 차이는 복호화 프로세스 동작과 스토리지 색인의 차이입니다.
질문의 중점인 검증이 회원이 존재하는지, 회원의 상태가 정상인지 판단하는 것이라면 이는 비교가 잘못되었습니다.
세션 방식이 스토리지를 통해 색인하다 보니 자연스럽게 회원 조회로 착각할 수 있지만 이 방식은 서비스 구성 과정의 선택입니다.
JWT 방식 또한 복호화한 회원 ID를 기준으로 회원을 검증할 수 있는 것은 동일합니다.
굳이 세션 방식에만 회원 상태 검증을 강제할 필요는 없다 생각합니다.
Q. 세션 방식은 확장에 제한이 있지 않나요?
메인 서버의 메모리에 저장한다면 분명 확장에 제한이 있습니다.
특히 서버의 트래픽 처리를 분산하기 위한 스케일 아웃에 로드밸런싱 기술을 검토해야 할 수 있습니다.
다만, 외부 서버를 스토어로 구성했을 경우 이야기는 달라집니다.
예시로 Redis가 존재합니다.
메인서버 s는 외부 서버에 세션 정보를 기록하고 갖고 오는 형태를 구현한다면 확장에 제한을 줄일 수 있습니다.
이는 JWT 방식과 주요한 차이점을 갖고 있습니다.
JWT 방식은 검증 위치가 상관없으므로 확장성이 용이하며, 외부 저장소에 의존성 또한 낮습니다.
또한 세션 방식은 외부 서버와 통신으로 인해 네트워크 지연을 받을 수 있다는 특징이 있습니다.
다만 Access Token 자체의 위험성인 “유효기간 내에 탈취”라는 보안 취약성이 존재하니 이를 비교하여 어떤 방식을 선택할지 고려할 수 있습니다.
Q. Access Token 또한 블랙리스트, 화이트 리스트를 검증하면 탈취 위험도 없어지지 않나요?
본질을 배제한 질문입니다.
Access Token은 상태를 관리하지 않는 stateless라는 고유한 특징이 있습니다.
매 요청마다 블랙리스트, 화이트리스트 처리를 한다는 것은 Access Token 상태를 관리한다는 의미이며, 이는 세션 방식과 전혀 다르지 않습니다.
이 점을 이해하고 있기 때문에 Refresh Token을 적용한다 생각합니다.
완벽하게 stateless를 유지할 수는 없더라도 최대한 적은 상태를 관리하여 보안을 일부분 적용하기 위함입니다.
Q. Refresh Token은 어떤 값을 저장해야 하나요?
질문의 대답 이전 짚고 넘어가야 하는 점이 있습니다.
Refresh Token을 어떤 방법으로 생성하고 있나요? 질문의 요지는 “Refresh Token을 JWT 방식으로 생성하고 있는지”입니다.
어떤 방법이던 상관없지만 Refresh Token은 보안을 위해 만들어진 토큰입니다.
즉 Access Token과 동일한 방법을 적용하면 보안에 악역향이 있을 수 있습니다.
또한 JWT 방식은 Payload가 Base64로 Encoding 되어 있기 때문에 중요 정보를 저장하는 것도 지양해야합니다.
보안을 고려할 것이라면 두 Token의 생성 방식을 다르게 적용하는 것을 권장합니다.
이제 답변을 하자면 필요한 값을 저장하면 됩니다.
Refresh Token을 세션 방식으로 취급하면 됩니다.
세션 방식에서 저장하는 값은 사용자 식별 아이디 또는 찾을 수 있는 값입니다.
📚 정리
Q. 그럼 대체 어떤 방법을 선택해야 하나요?
저는 서비스 규모를 기준으로 고려하는 게 좋다 생각합니다.
모든 서비스에 완벽이 부합하는 기능은 없다 생각하는데, 이 점을 바탕으로 이야기하겠습니다.
세션 방식은 현재 담당한 서비스의 규모가 작고, 보안관련 설정이 미흡하다 생각할 경우 선택을 고려할 수 있습니다.
https 설정, 중요정보 외부 노출 차단, 사용자 고유 정보 logging 제외 정도만 하더라도 작은 규모의 서비스는 문제 없다 생각합니다.
반대로 토큰 탈취에 대한 방지, 권한 세분화(회원탈퇴, 상품 구매 등등을 별도 권한)에 대해 염두해두었고, 대규모 트래픽 발생이 예상된다면 JWT 방식을 고려해보는게 좋다 생각합니다.
중요한 점은 어떠한 방식을 선택하는 것 보다 현재 상황에 맞추어 선택하는 것이 좋다 생각합니다.
서비스 규모는 점진적으로 커지는 것이 당연합니다.
이를 고려해 처음부터 큰 규모로 작성하는 것 보다 서비스 과정에서 발생하는 다양한 이슈를 "수집"하여 분석하고 무엇을 변경할지 백로그로 작성하는 과정이 중요하다 생각합니다.
'Backend' 카테고리의 다른 글
나만의 서버 구성기 (0) | 2024.05.16 |
---|---|
광고 시스템 이해를 위한 기초 지식 (0) | 2024.05.07 |