가끔 프로젝트에 필수적인 기능인 로그인은 쿠키, 세션, 토큰과 연관되어있습니다.
저번 프로젝트 때 로그인 기능에 대해서 어디까지가 백엔드의 역할인지, 또한 프론트 쪽에서 토큰과 같은 인증개념을
프론트에서 어느정도까지 다뤄야 보안적으로 안정적인지에 대한 고찰이 필요하다고 느꼈습니다.
따라서 토큰에 대한 개념을 접하기 이전, 쿠키와 세션에 대해서 톺아보고 토큰을 다뤄보고자 합니다.
개념들이 도출된 이유
쿠키를 알아보기 전에, 먼저 서버와 클라이언트가 통신할 때의 상황에 대해 알아야합니다.
우리는 인터넷간의 연결 중에도 웹통신을 할 때 HTTP
라는 것을 준수해서 통신을 하게 됩니다.
일종의 규칙인데요. 서로간의 소통을 하기위해 규칙을 지켜서 통신을 하게됩니다.
매번 클라이언트가 서버에게 HTTP
를 준수해 요청을 보낸다고 가정했을 때,
서버는 클라이언트가 늘 누구인지 기억하지 않습니다. 이를 stateless
라고 합니다.
이렇게만 이야기하면 이해하기 힘든데요. 아래의 가정된 상황을 보면 이해가 쉽습니다.
사용자가 브라우저 주소창에 네이버를 입력합니다.
Q.클라이언트 : 혹시 네이버라는 사이트 나한테 줄래?
A.서버 : 그래 여깄다.
--------------------------------------
사용자가 서버에게 다시 재요청을 합니다.
Q.클라이언트 : 혹시 저번에 줬던 사이트 나한테 좀 보내줄래?
A.서버 : 저번?? 뭔 사이트??
이처럼 서버는 매 요청마다 클라이언트가 누구인지 구별할 수 없으며, 기억하지 못합니다.
하지만 유저에 따라 누군가에게는 어떤 데이터로, 누군가에게 다른 데이터로 보이게 하고 싶은데,
이런 경우에는 유저를 구별하고 각 유저에 맞는 데이터들을 보여주어야합니다.
이런 경우 어떻게 유저를 구분할 수 있을까요?
정리해보자면, 쿠키와 세션은 서버에 요청한 유저를 기억하는 것에 대한 필요성에서 시작됩니다.
🍪 Cookie 쿠키
쿠키란 서버에서 클라이언트에 영속성이 있는 데이터를 저장하는 방법입니다.
앞으로 서버는 클라이언트를 기억하기 위해서 서버에게 요청을 보내는 클라이언트의 브라우저에 쿠키를 저장합니다.
즉, 쿠키에는 클라이언트 정보가 담긴 데이터가 저장되어 있습니다.
이후 쿠키는 자동적으로 클라이언트가 요청을 보낼 때마다 같이 서버에 보내집니다.
쿠키에는 여러 정보가 담겨있는데요, 아래와 같은 정보들이 담겨있습니다.
- Domain(도메인): 요청 서버의 도메인
- Path(경로): 도메인 뒤에 오는 경로
- MaxAge or Expires(만기시간): 쿠키의 유효기간
- Secure(보안): https만 요청가능한지 여부
- HttpOnly(접근여부): 자바스크립트로 쿠키 접근 가능여부 (기본적으로 false, 접근불가)
- SameSite(같은도메인만 가능하게할건지): Strict, Lax, None (자세한건 서칭)
따라서 서버는 클라이언트에게 쿠키에 여러 데이터를 담아 저장하게끔 하고, 매번 요청을 보낼때마다 쿠키를 받아 요청에 담긴 데이터를 확인하고 로그인이 가능하게 하거나 유저의 상태 데이터를 변동시킬 수 있습니다.
하지만 쿠키의 단점은 데이터가 공개적이기 때문에 노출되기 쉽고, 유효시간을 설정하지 않는 이상 서버가 쿠키를 삭제할 수 없습니다. 보안에 취약합니다.
정리
-
장점
- 쿠키에 데이터를 담아 클라이언트의 브라우저에 저장할 수 있다.
- 자동적으로 매 요청의 헤더에 담겨온다.
-
단점
- 데이터 공개적이라 쉽게 노출된다.
- 시간을 설정해놓지 않는 이상, 서버가 쿠키를 고의적으로 삭제할 수 없다.
- 장기적으로 유지해야하는 데이터가 필요한 경우, 보안상 유효기간을 설정해두면 데이터가 날아간다.
- 또한 앱 사용자들은 쿠키를 저장할 수 없다. (브라우저에 저장되므로.. 세션도 마찬가지입니다.)
프로젝트에 적용해본다면?
만약 쿠키에 로그인 관련 인증정보를 쿠키에 담아서 준다고 가정했을 시, 로그아웃을 해야한다면 쿠키 삭제를 서버가 할 수 없으니 보안을 위해 쿠키의 만료기한을 두는 것이 필수같아 보입니다.
또한 보안을 위해 HTTPS
설정인 Secure
을 true
로 해두는 것 또한 필수적이라고 생각이 드네요.
Session 세션
하지만 기억해야하는 유저가 많아지면서 쿠키가 공개적이고 보안에 취약한 점을 보완해야하는 방법이 필요해집니다.
세션은 이를 보완해줄 수 있습니다.
사용자의 로그인 상태, 장바구니 내용, 사용자 설정 등 이런 데이터들을 세션 데이터라고 합니다.
쿠키에 저장해둔다면 공개적이게 되므로, 사용자 데이터마다 아이디를 부여하고 이런 데이터들을 서버의 DB에 저장해둡니다.
만약 클라이언트가 로그인을 했다면, 서버는 인증 확인 이후 유저의 세션 데이터에 따라 세션 아이디를 부여합니다.
이후 세션 아이디를 쿠키에 담아 보냅니다.
클라이언트는 세션 ID가 담긴 쿠키가 자동적으로 전송되므로 서버가 아이디를 확인만 하고 이후 요청을 처리하게 됩니다.
따라서 데이터 보안의 취약점과, 데이터의 보존에 유리해집니다.
하지만 단점으로는 서버의 DB가 필요해진다는 점입니다. 또한, 매 요청마다 아이디를 확인해야하는 서버의 부담도 증가하게 됩니다.
정리
- 장점
- 데이터의 보안과 데이터 보존력이 좋아진다.
- 유저가 매요청마다 로그인 인증할 필요가 없다.
- 단점
- 서버가 세션 데이터를 관리해야하므로 서버의 부담이 증가한다.
- 사실 세션 아이디가 탈취당하면 어쩔수없다.
프로젝트에 적용해본다면?
로그인 할때는 인증을 통해서 서버가 쿠키에 세션ID를 넘겨주고, 로그아웃에 대해서 생각해보면 좋을 것 같습니다. 먼저 로그아웃 버튼을 누르게 된다면 브라우저에 있는 쿠키가 삭제되게끔 하는 것이 좋을 것 같습니다. 쿠키는 유효기간을 설정하지 않는 이상 계속 브라우저에 남아있게 되기 때문에, 브라우저 창을 껐을 때 쿠키가 삭제되게 하는건 어떨까란 생각을 해보았습니다. (결국 세션도 쿠키에 담기게 되니...)
짧은 정리
기본적으로 HTTP
를 준수하는 통신은 서로를 기억할 수 없습니다. 하지만 통신을 하면서 서버는 유저의 정보를 기억해야하는 기능들이 필수적입니다. 따라서 정보를 기억하기 위해 데이터를 사용하게 되었는데요, 그 데이터는 브라우저의 쿠키에 저장됩니다. 따라서 쿠키는 서버와 클라이언트가 주고받는 데이터이며 클라이언트의 정보들이 담길 수 있습니다. 하지만 쿠키는 공개적이기 때문에 보안에 취약하고 서버는 고의적으로 쿠키를 삭제할 수 없습니다. 따라서 이를 보완할 수 있는 점이 세션인데요. 세션은 유저관련 정보를 클라이언트 쪽에 저장하지 않고 서버의 DB에 저장하게 됩니다. 유저가 로그인을 하면 세션 데이터 부여된 ID를 쿠키에 담아보냅니다. 따라서 유저는 매번 로그인할 필요없이 쿠키에 담긴 세션 ID를 통해서 서버에게 여러 요청을 할 수 있습니다. 하지만 세션 데이터를 관리해야하는 서버의 부담이 증가됩니다. 또한 규모가 커지게 되고 여러 서버를 사용하게 된다면, 서버들간의 공유할 수 있는 세션 스토리지를 구축해야합니다.