Cookie와 Session
Cookie
사용자의 방문한 웹페이지에서 이용된 환경설정, 이용정보 등을 사용자의 로컬스토리지에 저장한 것을 말한다.
- 즉, 클라이언트의 웹 브라우저가 지정한 메모리/하드디스크에 저장을 한다.
그러므로 서버의 리소스를 활용하여 저장하지 않는다는 장점이 존재한다.
- 인증뿐만 아니라, 여러가지 정보를 주로 저장한다. (i18n 같은 것들도 저장한다고 한다.)
- 저장할 때, expires 속성을 활용하여 삭제, 만료될 시간을 지정할 수 있다.
- 클라이언트도 모르게 접속되는 사이트 들에 의해서 설정이 될 수 있기 때문에, 쿠키로 인해 문제가 발생하는 것을 막고자 한 도메인 당 20개, 하나의 쿠키당 4KB의 제한이 존재한다.
(그래서 사실 요즘 사용하는 사이트들은 접속하면 Allow Cookies 팝업을 통해 물어보곤 하는 것을 볼 수 있다.)
Session
쿠키에서 언급한 사용자의 정보를 서버에 저장을 하면 세션이 된다.
- 서버의 메모리, DB에 저장을 한다.
그러므로 세션이 생길 때 마다 서버의 리소스를 차지한다.
- 일반적으로 설정하지 않으면, 클라이언트가 로그아웃, 설정시간동안 반응이 없으면 무효화 되기 때문에 정확한 시점을 알 수 없다. 서버의 default 설정마다 다르긴하다고 한다.
이렇게 되면 무한정 서버에서 세션을 보관해 메모리가 초과하거나, 무한정 보관하는 세션이 탈취당할 경우 보안에 취약해지기 때문에, 다양한 방식을 통해 세션 만료기간을 두거나 로그아웃 시 세션 비활성화 요청을 보내는 식으로 구현을 할 수 있다.
Stateless (무상태성)
웹에서 사용하는 HTTP 프로토콜은 기본적으로 stateless하다.
이 말이 무슨 뜻이냐 하면...
- Server↔Client 구조에서 Server가 Client의 상태를 가지고 있지 않는 것을 말한다.
- Server로 가는 모든 request가 이전 request와 독립적으로 다뤄진다.
- 즉, Server는 메모리가 없어, 요청이 끝나면 Client가 누구인지 알지 못한다.
그러므로, 요청마다 서버에게 누구인지 알려주기 위해 사용하는 것이 Session이다.
이에 반대로, 서버에서 클라이언트의 이전 상태를 기록하는 방식이다 Stateful 방식이다.
Session과 Token
Session의 작동방식
앞서 말했듯이, HTTP의 stateless함을 stateful한 방식으로 해결하는 것이 session 방식이다.
출처
- 서버는 "session DB" 를 가지고 있고, 해당 각 세션에는 session ID가 존재한다.
- 해당 session ID는 쿠키를 통해 브라우저로 돌아와서 저장된다.
- 같은 웹사이트의 다른 페이지로 이동하면, 브라우저는 가지고 있던 "session ID를 포함한 쿠키" 를 서버에 전송한다.
- 서버는 해당 쿠키를 통한 요청이 있다는 것을 발견한다. 하지만 이때까지도 서버는 클라이언트가 누구인지 판별할 수 없다.
- 서버는 해당 session ID를 통해 세션이 담긴 session DB를 확인하고, 일치하는 세션을 찾아 그제서야 클라이언트가 누구인지 알게 된다.
- 해당 요청이 끝나고 다른 페이지로 클라이언트가 이동하면, 위 프로세스가 반복적으로 수행된다.
위와 같은 방식으로 서버는 클라이언트가 누구인지 인지하고, 그에 맞는 인증이나 권한을 부여할 수 있다.
- 그러므로, 중요한 클라이언트의 정보는 일반적으로 모두 서버에 존재한다.
- 클라이언트가 가지고 있는 것은
session ID 뿐이다.
- 해당 작동과정을 보면 알 수 있듯이, 쿠키는 session ID를 전달하기 위한 매개체로만 사용된다.
- 뒤에서 설명할 토큰 역시, 쿠키를 매개체로 사용한다.
Session 방식의 한계점?
- 현재 로그인 된 유저들의 모든 session ID를 DB에 보유하고 있어야 한다.
(즉, 리소스 차지)
- 새 request마다 쿠키를 받고, session ID를 확인하고, DB를 탐색하여... 일치하는 유저를 찾는 과정을 반복한다.
(리소스 차지 22)
- 요청이 있을 때 마다 DB를 탐색하므로, 유저가 많을수록 DB 사용 리소스가 많아진다는 단점이 존재한다.
(사실 이 탐색 문제를 개선한 DB들이 이제는 있다고 한다.. redis..?)
아무튼, 이러한 문제를 해결하기 위해 JWT가 등장하게 된다.
Token
그냥 랜덤한 문자열의 형태이다. (ex. 9dkgj.a02jh67.21lg6)
- 네이티브 앱 환경에서도 세션자체는 활용이 가능한데, 브라우저와 같은 쿠키가 없음.
- 이럴 경우에 토큰을 보내서 활용 할 수 있다.
- 작동방식은 세션과 동일하나, session ID를 가진 쿠키를 주고 받는게 아닌, 토큰을 주고 받는 형식이다.
- 이후에 session DB에서 토큰으로 일치하는 유저를 찾는 방식이다.
- 이론상으론 '토큰 자체'를 주고 받는 방식이나, 웹에서 구현할 때는 세션처럼 주로 쿠키안에 토큰을 담아 활용하긴 한다...
- 암호화 되지 않았기 때문에 누구나 토큰 내용을 열람할 수 있다.
- 위처럼 랜덤한 문자열의 해싱 알고리즘만 알고 있다면, 디코딩하여 내용을 볼 수 있다.
- 그렇기 때문에 비밀번호와 같은 크리티컬한 비밀 정보는 주로 토큰에 담지 않고, 세션 처럼 ID, 유저이름 정도만 담아 활용하는 편이다.
Session vs. Token
Session
장점
- session DB 정보를 활용하여 새로운 기능을 추가하기 용이하다.
ex.) 특정유저 강제 로그아웃/밴, Netflix의 계정 공유 수 제한 등
- DB를 통한 서버에서의 총괄적인 관리를 한다는 것 자체가 장점이다.
- 보안이 뚫렸을 때 세션을 만료시켜 추가적인 피해를 막을 수 있다.
단점
- 세션관리 자체를 위한 DB를 가지고 있어야하고, 지속적인 유지 및 보수를 해야한다.
- 유저가 많을수록 session DB가 커진다.
Token
장점
- 세션을 위한 DB가 필요없고, 토큰을 추적하지 않아도 된다.
- 단지, 서버가 해야할 것은 요청이 들어온 토큰에 대한 유효성 검증만 하면 된다.
단점
- 토큰을 추적하지 않기 때문에, 토큰이 만료되기 전까지 계속 유효하다. 즉, 강제 로그아웃 등의 특정 유저를 추적/특정화하는 기능 구현이 힘들다.
- 서비스가 더 커지고, 유저를 더 엄격하게 관리하기 위해서는 세션이 더 유리하다.
- 토큰 자체가 암호화가 되어있지 않고, 보안이 뚫린다면 별도의 작업이 불가능하다.
정리하자면,
- 세션형식의 발급은 DB를 사용하므로 무겁지만, 그만큼 보안성이 보장된다.
- 토큰형식의 발급은 단일토큰 자체가 수많은 인증정보를 저장하지 않기 때문에 가볍고 확장성이 좋다.
토큰 방식에 대한 구체적인 내용은 현재 많이 활용하는 JWT를 통해 설명할 것이다.