본문 바로가기
Computer science/Network

Cookie, Session, Token

by developerDoorold 2022. 11. 30.

들어가며

 현재 저는 간단한 근태 관리 게시판을 만들고 있습니다. Node.js를 활용해 CRUD를 구현했고(RESTFul 하게 개발하고 있는지는 잘 모르겠습니다...) 추가로 로그인 기능을 구현하고자 합니다.

 서버가 클라이언트 인증을 확인하는 대표적인 방식인 Cookie, Session, Token에 대해서 알아보도록 하겠습니다.


인증 방식 종류(Cookie & Session & Token)

1. Cookie

Cookie는 Key-Value 형식의 문자열 덩어리입니다. 클라이언트가 어떤 웹사이트를 방문할 경우, 그 사이트가 사용하고 있는 서버를 통해 클라이언트의 브라우저에 저장되는 작은 기록 정보 파일입니다. 각 사용자의 브라우저에 정보가 저장됨으로 고유 정보 식별이 가능합니다. 또한 쿠키는 인증 뿐만아니라 여러 가지 정보를 저장할 수 있습니다. 예를 들면 웹사이트 언어 설정을 변경하면 서버는 쿠키를 통해 사용자가 선택한 언어를 저장합니다.

1-1. Cookie 인증 방식

  1. 브라우저(클라이언트)가 서버에 요청(접속)을 보냅니다.
  2. 서버는 클라이언트의 요청에 대한 응답을 작성할 때, 클라이언트 측에 저장하고 싶은 정보들을 응답 헤더의 Set-Cookie에 담습니다.
  3. 이후 해당 클라이언트는 요청을 보낼 때마다, 매번 저장된 Cookie를 요청 헤더의 Cookie에 담아 보냅니다. 서버는 Cookie에 담긴 정보를 바탕으로 해당 요청의 클라이언트가 누구인지 식별하거나 정보를 바탕으로 추천 광고를 띄웁니다.

1-2. Cookie 방식의 단점

  • 가장 큰 단점은 보안에 취약하다는 것 입니다. 요청 시에 Cookie의 값을 그대로 보내기 때문에 유출 및 조작당할 위험이 존재합니다.(수정이 불가능한 중요 정보들을 쿠키에 저장하기에는 부적절합니다.)
  • Cookie에는 용량 제한이 있어 많은 정보를 담을 수 없습니다.
  • 웹 브라우저마다 Cookie에 대한 지원 형태가 달라 브라우저간 공유가 불가능합니다.
  • Cookie의 사이즈가 커질수록 네트워크에 부하가 심해집니다.

2. Session

위와 같은 Cookie의 보안적인 한계를 이유로 Session은 지워지거나 유출되서는 안되는 민감한 정보들을 브라우저가 아닌 서버 측에서 저장하고 관리합니다. 서버의 메모리에 저장하기도 하고, 서버의 로컬 파일이나 DB에 담아 저장하기도 합니다. 핵심은 민감한 정보는 클라이언트에 보내지 않고 서버에서 모두 관리한다는 것입니다.(사용자가 임의로 데이터를 직접 수정할 수 없습니다.)

 

참고. Session 객체는 어떤 형태로 이루어져 있을까?

Session 객체는 Key에 해당하는 Session ID와 이에 대응하는 Value로 구성되어 있습니다.

Value에는 Session 생성 시간, 마지막 접근 시간 및 사용자가 저장한 속성 등이 Map 형태로 저장됩니다.

2-1. Session 인증 방식

  1. 클라이언트가 웹사이트에서 로그인을 하면 Session이 서버 메모리(혹은 데이터베이스) 상에 저장됩니다. 이때, Session을 식별하기 위한 Session ID를 기준으로 정보를 저장합니다.
  2. 서버에서 브라우저의 쿠키에 Session ID를 저장합니다.
  3. 쿠키에 정보가 담겨있기에 브라우저는 해당 웹사이트에 대한 모든 요청에 Session ID를 쿠기에 담아 전송합니다.(사용자가 가지고 있는 정보는 Session ID 뿐이며 Cookie는 그저 Session ID를 전달하기 위한 매개체일 뿐입니다.)
  4. 서버는 클라이언트가 보낸 Session ID와 서버 메모리로 관리하고 있는 Session ID를 비교하여 인증을 수행합니다. 

2-2. Session 방식의 단점

  • Cookie를 포함한 요청이 외부에 노출되더라도 Session ID 자체는 유의미한 개인정보를 담고 있지 않습니다. 하지만 해커가 Session ID 자체를 탈취해 클라이언트인척 위장을 할 수 있다는 한계가 존재합니다.(이는 서버에서 IP특정을 통해 해결할 수 있긴 하다고 하네요~)
  • 서버에서 Session 저장소를 사용함으로 요청이 많아지면 서버에 부하가 심해집니다.
  • 현재 로그인한 사용자들의 모든 Session ID를 메모리 혹은 로컬 저장소, DB에 저장해야 합니다. 즉 요청이 들어올 때 마다 서버는 Cookie를 받아서 Session ID를 확인하고 서버가 가지고 있는 Session ID 일치하는 유저를 찾고 그제야 다음 작업을 수행할 수 있습니다.(메모리에 저장하는 경우 사용자가 많으면 메모리가 부족해질 수 있습니다. 그리고 로컬 저장소 혹은 DB에 저장하는 경우는 메모리에 저장하는 경우보단 성능면에서 느립니다. 이를 해결하기 위해 Redis나 MemCached와 같은 메모리형 데이터베이스 서버에 올려두기도 합니다.)

3. Token

Token 기반 인증 시스템은 클라이언트가 서버에 접속을 하면 서버에서 해당 클라이언트에게 인정되었다는 의미로 'Token'을 부여합니다. 이 Token은 유일하며 Token을 발급받은 클라이언트는 서버에 다시 요청을 보낼 때 요청 헤더에 Token을 첨부해 보냅니다. 그러면 서버에서는 클라이언트로부터 받은 토큰을 서버에서 제공한 토큰과의 일치 여부를 체크해 인증 과정을 처리하게 됩니다. 

 

기존의 Session 기반의 인증은 서버가 파일이나 DB에 Session 정보를 가지고 있어야하며 이를 조회하는 과정이 필요하기에 많은 오버헤드가 발생합니다. 하지만 Token은 Session과는 달리 서버가 아닌 클라이언트에 저장되기 때문에 메모리나 스토리지 등을 통해 Session을 관리했던 서버의 부담을 덜 수 있습니다.(Token 자체에 데이터가 들어있기 때문에 클라이언트에서 받아 위조되었는지 판별만 하면 되기 때문입니다.)

 

Token은 앱과 서버가 통신 및 인증할 때 가장 많이 사용됩니다.(Session을 활용해 IOS, Android App을 만들 수 있지만 Cookie를 사용할 순 없습니다. Cookie는 네이티브 앱에는 없다고 합니다.)

 

참고. Session 기반 vs Token 기반

Session 기반 인증 시스템

서버의 Session을 사용해 사용자 인증을 하는 방법으로 서버측(메모리 or DB)에서 사용자의 인증 정보를 관리하는 것을 의미합니다. 그러다 보니 클라이언트로부터 요청을 받으면 클라이언트의 상태를 계속해서 유지해놓고 사용합니다.(Stateful)

이는 사용자가 증가함에 따라 성능의 문제를 일으킬 수 있으며 확장이 어렵다는 단점이 있습니다.

 

Token 기반 인증 시스템

이러한 단점을 극복하기 위해서 "Token 기반 인증 시스템"이 나타났습니다. 인증받은 사용자에게 Token을 발급하고, 로그인이 필요한 작업일 경우 헤더에 Token을 함께 보내 인증받은 사용자인지 확인합니다. 이는 Session 기반 인증 시스템과 달리 상태를 유지하지 않음으로 Stateless 한 특징을 가집니다.

 

3-1. Token 인증 방식

  1. 클라이언트가 아이디와 비밀번호로 로그인 합니다.
  2. 서버 측에서 클라이언트에게 유일한 토큰을 발급합니다.
  3. 클라이언트는 서버 측에서 전달받은 토큰을 쿠키나 스토리지에 저장해 두고, 서버에 요청을 할 때마다 해당 토큰을 HTTP 요청 헤더에 포함시켜 전달합니다.
  4. 서버는 전달받은 토큰을 검증하고 요청에 응답합니다. 토큰에는 요청한 사람의 정보가 담겨있기에 서버는 DB를 조회하지 않고 누가 요청하는지 알 수 있습니다.

 

3-2. Token 방식의 단점

  • Cookie / Session과 다르게 Token 자체의 데이터 길이가 길어 인증 요청이 많아질수록 네트워크 부하가 심해질 수 있습니다.
  • Payload 자체는 암호화되지 않기 때문에 클라이언트의 중요한 정보는 담을 수 없습니다.
  • Token 자체를 탈취당하면 대처하기 어렵습니다.(사용 기간을 설정하는 방식으로 극복할 수 있습니다.)
  • 인스타그램의 기기별 강제 로그아웃과 같은 기능을 구현할 수 없습니다.(생성된 토큰을 추적하지 않으며 해당 토큰이 만료되기 전까지는 유효하기 때문입니다.)

마치며

 로그인 기능 구현에 필요한 이론적인 내용들을 한번 정리해봤습니다. 코드로 구현하면서 겪는 애로사항들도 추후에 포스팅하도록 하겠습니다. 혹여 잘못된 내용이 있다면 따끔한 지적 부탁드리겠습니다. 바로 수정할 수 있도록 하겠습니다. 감사합니다.


References

- https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC

- https://www.youtube.com/watch?v=OpoVuwxGRDI

- https://www.youtube.com/watch?v=tosLBcAX1vk

- https://www.youtube.com/watch?v=1QiOXWEbqYQ

 

제 공부에 도움을 주셔서 감사드립니다:) 특히 이번 포스팅에 많은 도움을 받은 인파_님께 다시 한번 감사인사 올립니다.(꾸벅)

댓글