❗❗
해당 게시글은 session 과 jwt를 이용한 사용자 인증의 차이점에 대해서만 다룹니다.❗❗
session 및 jwt에 대한 개념 정리는 다른 포스팅에서 다룹니다. (아니 다룰 예정입니다)
회사에서 일하는 약 1년에 가까운 시간동안, 로그인과 접근권한에 대해 직접 만져볼 일이 없었다.
사실상 내가 하는 일들이 게시판 찍어내기, 기존 플젝 유지보수가 전부였고, 설령 플젝 전체를 혼자 맡게 되더라도 로그인 로직은 기존 플젝에서 복사해 수정해서 썼기 때문...
그러던 중 친구가 jwt 관련 질문을 하는데 아무런 대답을 해줄 수 없었고 그 사실이 부끄러워 정리해보고자 한다.🤦♂️
Stateless
사실 웹개발을 하면서 이 개념을 모르진 않을거라 생각해서 간단하게만 적자면,
HTTP는 비연결성과 상태없음이란 특징을 지닌다. 어떠한 상태(state)를 계속 지니고 있지 않는다.
요청(request)를 보내고 응답(response)를 받으면 그것으로 끝이란 얘기
이러한 특성때문에 같은 데이터를 똑같이 불러오고 싶어도 매번 요청을 해야한다.
근데 여기에 인증이 필요하다면? 웹은 어떤 상태를 유지하고 있지 않기 때문에 계에에에에속 인증을 해줘야 응답을 받아볼수 있는것이다.
만약 내가 네이버에서 메일을 보려고 한다면 메일 하나를 클릭할때 마다 권한이 있다는 것을 알려줘야 한다는 것.
-> 즉 페이지 이동마다, 데이터 조회때마다 로그인을 새로 해줘야 한다는 소리가 된다.
로그인 유지는 어떻게 하는가?
사실 누군가의 접근을 통제하기 위해 쓰이는 방법은 간단하다.
군대를 예로 들어보자. 부대에는 아무나 들락날락 할 수 없다. 신임 소대장이 저녁에 약속이 있어서 시내로 나갔다. 오늘 밤 위병초소에 근무하는 모 상병은 휴가를 갔다오느라 신임 소대장의 얼굴을 모른다.
소대장이 부대로 복귀할때 위병근무자는 소대장의 신원이 파악되지 않아 접근하는 사람이 부대 사람인지 확인해야한다.
근무자는 신임 소대장에게 문어를 던진다. 다행히 신임소대장은 오늘의 암구호를 숙지하고 나갔다. 문어에 알맞은 답어를 얘기하고 이를 확인한 위병근무자는 소대장을 들여보낸다. (현실은 '어 나 몇소대 소대장인데~' 하면 들어보내준다.)
위의 예시에서 해당 근무자는 신임 소대장과의 상태가 없다고 봐도 무방하다. 얼굴도 이름도 모르니까. 그래도 그를 들여보내줄 수 있었던 건 암구호라는 암묵적인 약속이 있었기 때문에 가능했다.
군대에선 이 암구호를 매일매일 바꾼다. 적, 혹은 부대 외 인물이 암구호를 숙지해 들어올 가능성이 있기 때문이다. 사용자 인증과 보안도 이와 유사하다.
Session을 통한 인증 및 유지
세션을 통한 사용자 인증 및 유지는 위 그림과 같은 절차를 따른다.
인증 절차
- 사용자가 로그인할시 ID와 PASSWORD를 보내 인증을 요청한다.
- DB에서 사용자의 계정 정보를 조회해 맞는지 확인한다.
- 만약 ID와 PASSWORD가 동일하면 서버는 세션을 생성하고 이 때 생성된 Session ID를 세션 저장소에 저장한다.
- 사용자에게 응답과 함께 Session ID를 보낸다. 이 때 Session ID는 쿠키에 저장된다.
인증 이후
- 사용자가 특정 정보를 요청할 때 쿠키에 저장된 Session ID를 함께 보낸다.
- 서버는 세션저장소에 Session ID가 존재하는지, 또 해당 세션이 유효한것인지 확인한다.
- 맞다고 확인되면 DB에서 사용자가 원하는 정보를 조회한다.
- 사용자가 요청한 정보를 응답한다.
Session을 이용한 인증의 장단점
그럼 간딴하게 session을 이용해서 인증을 진행하면 뭐가 좋은지, 또 뭐가 나쁜지 알아보자
장점
- 사용자는 Session ID만 지니게 된다. 이 말인 즉, 중요한 정보들은 서버가 지니고 있다는 뜻이다. 이렇게 Session ID 만 지니게 되면, 도중에 요청을 탈취당해도 Session ID 밖에 없다는 뜻.
- Session ID 는 특정 유저에게 고유하게 할당 된다. 그렇기 때문에 Session ID에 매칭된 회원정보를 바로 확인할 수 있고, 이를 토대로 해당 회원과 관련된 정보를 DB에서 확인하기에 용이하다.
- 서버단에서 session에 대한 통제가 가능하다.
단점
- 장점이었던 서버의 session에 대한 통제권 때문에 서버가 터지면 전체가 다 터져버린다.
- 추후 트래픽이 늘고, 회원수가 늘고 하면 세션저장소에 대한 관리가 추가된다. 이 때 서버 증설과 세션저장소의 크기가 비례해서 늘지 않으므로 이 경우 골치가 아프다.
- 또 서버를 증설해 A서버와 B서버가 있다고 가정할 경우, A서버와 B서버에서의 session 정보가 일치하지 않는다. (이 경우 별도의 session db를 하나 만들어 동시에 관리하는 방법이 있긴 하다.)
- 서버에 걸리는 부하가 심하다.
JWT(Json Web Token)를 이용한 인증 및 인증 유지
인증 절차
- 일단 사용자가 로그인을 시도하고
- DB에서 사용자의 ID와 PASSWORD가 정확한 것인지 확인한다. (여기까진 session과 동일)
- 사용자의 정보가 맞는것이 확인되면 ACCESS TOKEN(JWT)을 발급한다.
- ACCESS TOKEN을 응답한다. 이 때 쿠키에 저장할 수도 있고 local storage에 저장할 수도 있다.
인증 이후
- 요청과 함께 발급받은 ACCESS TOKEN을 서버에 전달한다.
- 이게 유효한 토큰인지 확인을 한다.
- 만일 이 토큰이 유효하지 않다면, 사용자에게 다시 인증을 요구하고 REFRESH TOKEN을 발급한다.
- 유효한 토큰일 경우 정보를 조회한다.
- 사용자에게 요청한 정보를 응답한다. 이때 REFRESH TOKEN이 발급되었으면 같이 보내준다.
JWT를 이용한 인증의 장단점
장점
- 우선 이 녀석은 세션을 사용할때의 문제점에 대비할 수 있다. 서비스 확장에 자유로우며 서버에 대한 의존성도 낮다.
- 또한 세션저장소와 같은 인증을 위한 별도의 저장소가 필요하지 않다.
- 이것 또한 세션의 한계 중 하난데, 세션의 경우 쿠키에 Session ID를 저장해 정보를 지속적으로 확인하지만, 브라우저 의외의 환경(이를테면 앱)에서는 쿠키활용이 안된다. 하지만 jwt의 경우 다양한 플랫폼에서의 활용이 가능하다.
- 위에서 세션의 경우 서버를 여러개 둔다면, 각각의 서버가 서로의 Session ID를 검증하기 힘들다는 단점이 있지만, 이 친구의 경우 Secret key만 일치한다면, 어느 서버에 사용자가 접속하건 동일하게 서비스를 이용할 수 있다.
단점
- 이 자체에 담긴 정보가 너무 많다.
- 얘를 풀어보면 알겠지만 무진장 길다. 근데 jwt에 정보를 이것저것 담다보면 트레픽 데이터의 크기가 커질수도 있다.
- 세션의 경우 문제가 발생(이를테면 부적절한 접근이라던지, 사용자를 차단하고 싶다던지하는)하면 그냥 session DB에서 해당 정보를 날리면 그만이다. 하지만 jwt의 경우 이를 통제할 수 없는 수단이 없다. 이미 발급된 토큰은 사용자가 갖고있고 서버에선 그게 맞는지만 확인하기 때문이다.
- jwt의 사이닝(signing)은 Base64로 인코딩하는데, 이 토큰의 유효기간이 길 경우 외부에서 이를 decode해 접근할 수 있다.
결론
- 더 자세히 적기에는 지식도 부족하고 배도 고프고 해서 무리지만, 추후에 보안 관련에서 추가로 정리가 필요할 듯 싶다.
- 둘 중 낫다 뭐가 뒤쳐진다 하기 어렵다. 어느샌가부터 특정 라이브러리, 특정 방식이 유행처럼 자주 사용되면 그 외의 선택지가 폄하되거나 구리다는 식의 뉘앙스를 풍기는 글 혹은 댓글들을 본 적이 있다. 물론 그 외 선택지들의 문제점이 크리티컬하다면 갈아타는 것이 올바른 길이겠지만, 정답은 없다고 생각한다.
- 나는 세션으로 구현하는게 더 편하다. 다중 플랫폼을 이용하는 경우가 거의 없고, 서버를 확장할 만큼의 트래픽이 발생한다던지, 이용자가 늘어난다던지 하는 일도 거의 없다. 또 이에 대비할 해결책도 알고 있다. 하지만 공부삼아 jwt를 이용한 인증을 구현하긴 할 예정. 언제가 될진 모르겠으나... 그 언제가 되면 정리해서 올려야겠다.
- 저녁은 짜파게티와 만두다.