이번 프로젝트에서 인증, 로그인 기능을 맡은 것은 아니지만, 웹 개발자라면 꼭 알아야하는 쿠키, 세션, 토큰이 무엇인지 알아보고 싶었다. 추가적으로 jwt가 무엇인지도 알아보겠다.
8.24 내가 썼던 내용을 다시 읽었다. 나는 쿠키, 세션, 토큰의 개념이 이상했다... 다시 작성해 보는 인증 인가에 대한 지식..! 커맨드 + a를 눌러 전부 지우고 다시 작성했다.
auth는 두 가지 의미를 가진다. 스펠링을 찾지 않고 쓰려고 하니 authorization, authentication이 기억이 나지 않았다.
인가와 인증 이 둘의 차이는 무엇일까
일단 내가 벨로그에 글을 쓸 수 있는 이유에 대해서 인증, 인가 개념을 적용해 보겠습니다.
사실 벨로그 로그인을 OAuth를 사용했지만 아니라고 생각하고, 회원가입을 하고 로그인에 성공했다고 가정하겠습니다.
로그인에 성공하면 서버에서 내가 회원임을 '인증'했기 때문에 오른쪽 상단에 내 프로필이 나오게 됩니다. 너는 우리 회원이라는 것을 벨로그가 인증했기 때문에 나는 자랑스러운 벨로거가 되었다!
그래서 글을 쓰고 싶어서 글쓰기를 눌렀더니, 벨로그에서는 너는 우리 회원이니 글을 쓸 수 있게 권한을 '인가'해줄게 라며 글을 쓸 수 있게 되었고 또 다른 사람에게 좋아요를 누를 수도 있고, 내 이름으로 댓글도 달 수 있게 권한을 '인가'해주었다.
다만 다른 사람 이름으로 글을 쓸 수 있는 권한은 주지 않았다.
아주 간단한 예시를 통해 인증과 인가를 알게 되었다. 그렇다면 이러한 과정을 클라이언트와 서버는 어떻게 통신을 하고 있을까
돈이 없는 시절 창업을 시작해 서버가 단 하나만 있는 시절...
일단 유저가 인증 요청을 하게 되면 서버에 저장된 id와 password, 즉 식별 가능한 정보를 req header에 넣어 서버에 요청을 보낸다. 확인이 완료되면 res값으로 ok를 보내주면 로그인에 성공한다.
하지만 이렇게만 하면 유저는 매번 로그인 요청을 보내줘야 한다. 다른 일을 할 때도 로그인을 해야하고 반복적으로 로그인을 해야하기 때문에 너무 번거롭다. 그래서 브라우저에 있는 스토리지를 사용하기로 마음을 먹었다.
그래서 쿠키를 사용했다. 이전과 같은 과정을 거쳐 요청을 보내지만 쿠키라는 브라우저 스토리지에 유저 정보를 담아 로그인 요청을 보낼 때 보내주면 얼마나 편한가!
나도 편하고 내 정보를 호시탐탐 노리고 있는 사람들도 너무 편한 문제가 있다. 쿠키에 데이터를 그대로 담았기 때문에 보안 상에 큰 문제가 있다.
그래서 쿠키에 로그인 정보를 담는 행위는 매우 위험한 행위이다.
아까와 같은 문제가 있어 돈을 좀 더 써서 세션을 하나 추가를 했다. 이제 로그인한 유저에게 res값으로 sessionId값을 줄 수 있어서 쿠키에 유저정보를 저장하던 방식보다 훨씬 안전한 방식을 제공할 수 있어서 매우 기쁘다.
그렇게 서비스가 승승장구를 하던 중 예상치 못한 문제를 겪게 되는데, 유저 수가 많아져 세션을 늘리고, 이를 분배하기 위한 로드 밸런서도 설치를 했더니 유저 식별이 불가능해지는 문제가 발생했습니다.
session에 id와 sessionId를 저장해서 인가를 진행하고 있었지만, 여러 개의 session이 생겨서 항상 같은 session을 확인할 수 없게 되는 문제가 생겨버린 것입니다. 그렇다고 인가마다 모든 session을 탐색하는 일은 있을 수 없는 일이기에 새롭게 도입한 session storage!
세션에 저장한 데이터를 하나의 세션 스토리지에 저장해서 값을 찾을 수 있도록 설계를 했더니 안심이 되었다.
그렇게 더 많은 유저를 모을 수 있었는데 어머나... 세션 스토리지가 터져버렸다..
하지만 이 문제는 유저가 많아져서 생긴 문제만이 아니다. 기본적으로 http 통신의 기본 원칙에는 무상태성을 유지해야 한다. 클라이언트와 서버간 통신에 있어 서로 상태를 공유하지 말아야 한다. 그런데 지금 방식은 어떠한지 생각해보면 서버, 클라이언트, 세션, 세션스토리지들이 상태를 가지고 있는 문제를 발견하게 된다.
이는 기본적인 원칙, 패러다임이 충돌하고 있기 때문에 우리는 다른 방법을 생각해 봐야한다.
통신 간, 무상태성을 유지하기 위해 토큰 개념을 도입하게 되었다. 우리는 토큰 중에서 JWT를 사용했다. jwt는 'json web token' 이다.
jwt의 스트링 값은 세 부분으로 나뉘어져 있다.
header, payload, signiture.
header은 두 가지 정보가 들어있다.
토큰의 타입, 사용된 해싱 알고리즘 정보가 담겨있다.
payload는 정말 중요한 데이터는 담겨있지 않고, 유저를 식별할 수 있는 해커가 알아도 될 정도의 데이터를 담고 있다. 이는 jwt에 담길 때 'Base64Url'로 변환된다.
마지막 signiture를 통해 jwt가 편리하게 사용이 되는 것인데, 서버에 저장된 key값을 통해 header와 payload에 있는 데이터를 식별해서 인가가 가능해진다.
이 글을 처음 썼을 때 결론은 세션을 사용하면 더 좋을 것이다 라고 했었다. 하지만 지금은 모르겠다. 토큰만 가지고 유저관리를 전부 할 수 있을까? 그것도 확신이 서지 않는다.
공부에는 끝이 없지만.. 개발에는 정답이 없는 것도 너무 괴롭다. 하지만 이 괴로움이 즐거운 마음.. 답을 정확히 내릴 수 없지만 실제 일을 하다보면 깨우치는 게 있지 않을까??
관심있는 주제인데 재밌게 잘 적어주셔서 이해가 잘됐어용!! 👍