인증(Authentication) 관련 개념 중 쿠키, 세션, 토큰, JWT에 대해 학습하며 간단히 정리한 글
서버는 쿠키를 사용하여 사용자의 브라우저에 데이터를 저장하고, 이를 통해 사용자 정보를 기억할 수 있다. 쿠키 주고 받기는 다음과 같은 방식으로 이루어진다.
- 사용자가 웹사이트에 접속하면, 브라우저는 서버에 사용자에게 보여줄 페이지를 요청한다.
- 요청을 받은 서버는 응답에 사용자에게 보여줄 페이지 정보를 담는데, 그 응답에 쿠키를 함께 보낸다.
- 브라우저는 응답을 받고, 응답에 쿠키가 들어있으면 쿠키를 저장한다.
- 이후 사용자가 이 웹사이트를 계속 이용하거나 또는 다음 번에 방문했을 때에도, 브라우저는 모든 요청에 위에서 받은 쿠키를 함께 보낸다.
세션과 토큰이 필요한 이유는 HTTP의 무상태성(Stateless) 때문이다. HTTP의 무상태성이란 모든 HTTP 요청이 이전 요청과 독립적임을 뜻한다. 그러므로 연속성을 가지려면 매 요청마다 사용자가 누구인지 다시 알려주어야 하고, 여기에 세션(및 토큰)이 쓰인다. 세션 기반 인증은 다음 같은 방식으로 진행된다.
- 브라우저에서 로그인을 위해 아이디 helloworld, 패스워드 ****를 서버에 보낸다.
- 서버는 아이디, 비밀번호를 확인한 뒤 문제가 없다면 세션 DB에 아이디 helloworld를 저장한다. 저장된 공간에는 고유 ID가 있는데, 이것이 세션 ID가 된다.
- 서버는 이 세션 ID를 쿠키에 담고, 쿠키를 포함한 응답을 브라우저에 보낸다.
- 브라우저는 응답을 받고, 세션 ID가 담긴 쿠키를 저장한다.
- 이제부터 이 웹사이트 내에서의 모든 요청에서 브라우저는 쿠키에 세션 ID를 담아 서버에 보낼 것이다.
- 요청을 받은 서버는 세션 ID가 들어있는 쿠키를 확인한다. 이 때 아직 사용자가 누구인지는 모른다.
- 이제 서버는 세션 DB를 확인하여 요청에 들어온 세션 ID과 매칭되는 사용자 이름을 찾는다. 사용자를 인지하면 브라우저에 응답을 보낸다.
- 이제 브라우저에서는 helloworld님 환영합니다. 라는 메시지를 띄울 수 있게 된다.
세션 기반 인증에서 중요한 점은 핵심 사용자 정보가 서버에 있다는 것이다. 사용자가 갖고있는 것은 세션 ID 뿐이다.
iOS, Andriod 앱을 만들 때 세션은 사용할 수 있지만, 쿠키는 브라우저에만 존재하므로 쿠키에 세션을 담아 보낼 수 없다. 그러므로 네이티브 앱을 만들 때는 토큰을 사용한다.
또한, 세션 기반 인증에서는 로그인한 모든 유저의 세션 ID를 DB에 저장해야 한다. 그러므로 일일이 쿠키, 세션 ID를 확인하고 DB에서 일치하는 사용자를 찾는 과정을 반복해야 하고, 유저가 늘어날수록 더 많은 DB 리소스가 필요하다. 이 문제를 해결하기 위한 것이 토큰 기반 인증이고, 그 중 가장 널리 쓰이는 표준이 JWT 기반 인증이다.
JWT는 토큰 포맷을 지니는 긴 문자열이다. JWT인증을 사용하면 세션 DB도 필요 없고, 유저 인증에 필요한 여러 과정이 생략된다.
- 브라우저에서 로그인을 위해 서버에 아이디, 패스워드를 보낸다.
- 서버는 DB를 거치지 않고, 사인 알고리즘을 통해 아이디에 'sign'을 하고, 이는 유저 인증에 필요한 signed information이 되어 JWT에 담겨 문자열 형태로 브라우저로 전송된다.
- 브라우저는 JWT를 저장하고, 이 후 모든 요청에 서버에 함께 보낸다.
- 서버는 이번에도 DB를 거칠 필요 없이, JWT이 유효한지만 체크하고 맞으면 사용자를 인증한다.
JWT 문자열은 일반적인 세션 ID보다 훨씬 길다. 세션 ID는 쿠키에 담기는데, 쿠키에는 공간 제약이 있기 때문이기도 하다. JWT는 길이 제한이 없다.
JWT는 암호화 된 것이 아니므로 누구나 볼 수 있다. 비밀 정보가 담겨서는 안 된다.
세션 기반 인증에서 서버는 로그인한 모든 유저의 정보를 DB에 저장한다.
이 때 장점은 유저 컨트롤 능력에 있다. 유저를 쫓아내려면 세션을 삭제하면 된다. 인스타그램이나 왓챠에서처럼 원하지 않는 디바이스에서 강제 로그아웃을 하는 경우이다. 넷플릭스처럼 계정 공유 수를 컨트롤 할 수 있는 것도 같은 맥락이다.
단점은 세션 DB 비용을 지불하고 관리해야 한다는 것인데, 보통 세션 관리용 DB에는 빠르고 저렴한 redis를 사용한다.
JWT 기반 인증 시, 서버는 토큰이 유효한지 아닌지만 확인하면 된다.
발급이 매우 간편하며, 코로나 이후 시설 입장 시 QR 체크인에 사용하는 것도 토큰이다.
그러나 DB가 없으므로 세션 기반 인증처럼 사용자를 컨트롤하는 기능은 사용할 수 없다. 토큰은 만료되기 전까지는 계속 유효하다.