쿠키(Cookie)와 세션(Session)
HTTP 프로토콜 특징
- 클라이언트 서버 구조- 클라이언트가 서버에 요청(request)을 보내면, 서버는 그에 대한 응답(response)를 보냄 
 
- 비연결 지향(Connectionless)- 클라이언트의 요청에 응답한 후에는 연결을 끊음(연결 유지 X) 
- 최소한의 자원으로 서버 유지 
 
- 무상태(Stateless)- 연결을 끊는 순간 클라이언트와 서버의 통신이 끝나고, 서버는 클라이언트의 상태 정보를 보존하지 않음 
- 클라이언트가 요청할 때 필요한 데이터를 추가적으로 담아서 전송해야 함 - 항상 같은 서버를 유지하지 않아도 됨 
- 응답 서버를 쉽게 바꿀 수 있어서 서버 확장성이 높음(무한한 서버 증설 가능) 
 
 
쿠키와 세션의 필요성
- HTTP 프로토콜의 특징으로 모든 요청 간에는 의존관계가 없음 - 현재 접속한 사용자가 이전에 접속했던 사용자와 같은 사용자인지 아닌지 알 수 있는 방법 존재 X 
 
- 통신할 때마다 새로 연결하기 때문에 클라이언트는 매 요청마다 인증을 해야 함 - 로그인을 진행한 후, 다른 서비스를 사용하기 위해 매번 로그인(인증)을 하는 상황 발생 
 
- 클라이언트의 상태 정보를 유지할 필요가 있을 경우, - 쿠키와- 세션을 활용해서 Stateful한 동작 구현 가능- 무상태를 지향하기 위해 매 요청마다 필요한 정보를 담아 서버와 통신하는 경우, 비용과 부하가 커질 수 있음 
 
쿠키(Cookie)
- 개념 - 클라이언트 로컬에 저장되는 키와 값이 들어있는 파일 
- 사용자 인증이 유효한 시간 명시 가능(유효시간이 정해지면 브라우저가 종료되어도 인증 유지) 
- 클라이언트의 상태 정보를 브라우저(로컬)에 저장하여 참조 
 
- 구성 요소 - 쿠키의 이름(name) 
- 쿠키의 값(value) 
- 쿠키의 유효시간(Expires) 
- 쿠키를 전송할 도메인 이름(Domain) 
- 쿠키를 전송할 요청 경로(Path) 
 
- 동작 방식 - 웹브라우저가 서버에 요청 
- 상태를 유지하고 싶은 값을 쿠키(cookie)로 생성 
- 서버가 응답할 때 HTTP 헤더(Set-Cookie)에 쿠키를 포함해서 전송 
- 전달받은 쿠키는 웹 브라우저가 관리, 다음 요청 때 쿠키를 HTTP 헤더에 자동으로 넣어서 전송 
- 서버에서 쿠키 정보를 읽어 이전 상태 정보를 확인 후 응답 
 
- 사용 예 - 아이디, 비밀번호 저장 
- 쇼핑몰 장바구니 
 
세션(Session)
- 개념 - 일정 시간 동안 같은 브라우저로부터 들어오는 요청을 하나의 상태로 보고 그 상태를 유지함 - 웹 브라우저를 통해 서버에 접속한 이후부터 브라우저를 종료할 때까지 유지되는 상태 
 
- 쿠키를 사용하여 값을 주고 받으며 클라이언트의 상태 정보를 유지함- 사용자 정보 파일을 쿠키는 브라우저에 저장하고, 세션은 서버측에서 관리 
 
- 사용자에 대한 정보를 서버에 두기 때문에, 사용자가 많아질수록 서버 메모리 많이 차지 
- 보안 면에서 쿠키보다 우수 - 쿠키는 클라이언트 측에서 쉽게 탈취 가능 - 쿠키는 클라이언트 측에서 변경이 가능한 반면, 세션은 서버에서만 변경 가능 
 
- 세션ID값 탈취는 적극적인 해킹공격으로 쿠키보다 어려움 
 
 
- 동작 방식 - 웹브라우저가 서버에 요청 
- 서버가 해당 웹브라우저(클라이언트)에 유일한 ID(Session ID)를 부여함 
- 서버가 응답할 때 HTTP 헤더(Set-Cookie)에 Session ID를 포함해서 전송 
- 웹브라우저는 부여된 Session ID를 쿠키에 저장해두고, 다음 요청 때마다 해당 쿠키를 HTTP 헤더에 넣어서 전송 
- 서버는 Session ID를 확인하고, 해당 세션에 관련된 정보를 확인한 후 응답 - 로그인을 하는 경우, 해당 Session ID의 로그인 상태를 유효한 값으로 바꿔 저장 
- 이후 요청에서 해당 Session ID를 가진 클라이언트는 로그인 상태가 유효하므로 별도의 로그인 없이 서비스 이용 가능 
 
 
- 사용 예 - 로그인 
 
다중 서버 환경에서 세션 관리
서버를 다중화했을 경우, 세션 불일치 이슈 발생
- Sticky Session (스티키 세션) - 클라이언트의 요청이 항상 해당 클라이언트의 세션이 저장된 서버로만 전달됨 - 로드밸런서에서 요청 쿠키(Session ID)를 읽고 지정된 서버(세션이 있는)로만 요청을 전달함 
- 세션 정보가 없을 경우, 로드밸런서의 기본 알고리즘대로 요청 전달 
 
 
- Session Clustering (세션 클러스터링) - 클러스터링: 병렬 처리해서 여러 대의 서버를 하나의 서버처럼 운영 
- 세션을 서버 각각에 복사해서 모든 서버가 모든 세션을 보유하고 있음 
- 특정 서버에서 세션이 생성될 때 다른 서버로 세션을 전파하여 복제 
 
- Session Storage (세션 스토리지) - 세션만 관리하는 별도의 DB 서버를 두고, 모든 서버가 해당 서버를 참조함 
 
토근 기반 인증 방식
- 세션은 사용자의 수 만큼 서버 메모리를 차지하기 때문에, 최근에는 이를 보완하는 토근 기반의 인증방식을 많이 사용함( - stateless)
- ex) - JWT(JSON Web Token)
쿠키와 세션의 차이
저장 위치
클라이언트의 웹 브라우저가 지정하는 메모리 or 하드디스크
서버 메모리
저장 형식
Text
Object
만료 시점
쿠키 저장 시 설정
정확한 시점 알 수 없음
보안
클라이언트에 저장되므로 취약
Session ID만 저장하고, 이 값에 따라 서버에서 처리하므로 비교적 보안성 좋음
속도
클라이언트에 저장되어 서버에 요청 시 빠름
정보가 서버에 저장되어 있어 서버 처리가 필요해 쿠키보다 느림
용량 제한
한 도메인 당 20개, 한 쿠키당 4KB
제한없음
➕ 토큰
- 개념 - 메모리 공간을 많이 차지하는 세션 방식의 대안으로 사용자에게 - 세션 아이디대신- 토큰을 발급
 
- 동작 방식 - 클라이언트가 서버에 접속 시, 서버는 클라이언트에게 인증되었다는 의미로 - 토큰부여 (해당 토큰은 유일함)- 클라이언트는 전달받은 토큰을 쿠키나 스토리지에 저장함 
 
- 토큰을 발급받은 클라이언트는 다시 서버에 요청을 보낼 때 헤더에 토큰을 심어보냄 
- 서버의 토큰 일치여부 체크로 인증과정 처리 - 클라이언트로부터 받은 토큰과 서버에서 제공한 토큰의 일치여부 체크 
 
 
- 특징 - 적은 서버의 부담 - 토큰은 클라이언트에 저장 됨 → 세션을 관리했던 서버의 부담을 덜 수 있음 
- 해당 서버만이 만들 수 있는 토큰 발급 → 상태를 저장하지 않고도 사용자의 정보 파악 가능 
 
 
- 한계 - 한 번 발행한 토큰은 유효기간 만료시 까지 통제 불가 - 여러 기기에서 로그인 제한 불가 
- 세션에 비해 토큰 정보 탈취 당할 가능성 높음 - 해결 방법으로 - 만료 시간이용
 
 
- 토큰 자체 데이터 길이가 긺 - 인증 요청이 많아질 수록 네트워크 부하가 심해짐 
 
 
JWT (JSON Web Token)
- 개념 - 인증에 필요한 정보들을 - 암호화시킨 JSON 토큰
- JWT토큰을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식 
 
- 특징 - JWT는 JSON 데이터를 Base64 URL-safe_Encode를 통해 인코딩을 직렬화한 것 
- Self-contained- 필요한 정보를 자체적으로 지니고 있음 
 
- Signature- 전자서명을 통한 위변조 체크 
- 토큰 내부에 위변조 방지를 위해 개인키를 통한 전자서명이 들어감 - 사용자가 JWT를 서버로 전송시 서버는 서명을 검정하는 과정을 거침 
- 검증 완료 시 요청한 응답을 돌려줌 
 
 
- Calim- JSON 데이터 구조로 표현한 토큰 
- 표준규약(RFC-7519)에 따라 생성된 암호화된 문자열(토큰) 
 
- URL-safe- 두 개체 사이에서 손쉽게 전달되며, 사용되는 JSON 데이터는 URL에 포함될 수 있는 문자만으로 생성 
 
- HMAC 알고리즘 사용으로 비밀키 또는 RSA를 이용한 Public Key / Private Key 쌍으로 서명 가능 
 
- 구조  - .을 구분자로 나누어지는 세가지 문자열의 조합- Header- 알고리즘과 토큰 타입을 포함 
- "alg" : 정보를 암호화할 해싱 알고리즘 지정 
- "typ" : 토큰의 타입 지정 
 
- Payload- 토큰에 저장할 정보를 가짐 
- Claim형태(key, value로 이루어진 한쌍의 정보)로 이루어짐 - Registered Claim - 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기위하여 이름이 이미 정해진 클레임 
- 해당 클레임의 사용은 전부 선택적 
 
- Public Claim - 충돌이 방지된 이름을 가지고 있어야함 
- 충돌을 방지하기 위해 클레임 이름을 URI형식으로 생성 
 
- Private Claim - 서버와 클라이언트, 서비스와 서비스간에 협의하에 사용되는 클레임 
- 공개 클레임과 달리 이름이 중복되어 충돌 발생 가능 
- 민감한 정보는 불포함 또는 암호화 처리가 필요 
 
 
 
- Signature- 인코딩된 Header와 Payload를 더한 뒤 비밀키로 해싱하여 생성 
- 토큰의 위변조 여부 확인 시 사용 - Header 및 Payload는 단순 인코딩된 값으로 해커가 복호화와 조작 가능 
- Signature는 서버 측에서 관리하는 비밀키가 유출되지 않는 이상 복호화할 수 없음 
 
 
 
- 토큰 인증 과정 - 클라이언트가 서버로 로그인 요청을 보냄
- 서버는 검증 후 클라이언트 고유 ID등의 정보를 Payload에 담고, 암호화할 비밀키를 사용해 Access Token(JWT) 발급
- 클라이언트는 전달받은 토큰을 저장해두고, 서버에 요청할 때마다 토큰을 요청 헤더 Authorization에 포함시켜 함께 전달
- 서버는 토큰의 Signature 을 비밀키로 복호화한 다음, 위변조 여부 및 유효 기간 등을 확인 후 유효한 토큰이라면 요청에 응답
 
AccessToken
- 클라이언트에서 요청한 로그인이 성공한 경우, 서버는 AccessTocken 발급 
- 사용자 - 발급받은 토큰 정보를 기억하고 있음 
- 서버 호출시 헤더에 해당 토큰을 담아 호출 
 
- 서버 - AccessToken을 DB나 파일에 저장하지 않았으므로 미리 정의된 비밀키를 이용해 비교하여 인증 처리 
 - 이와 같은 이유로 서버는 특정 사용자의 접속을 강제로 만료시키기 어려움 
RefreshToken

- 개념 - 한번 발급되면 만료기간까지 계속 사용가능하므로 탈취시 위험하다는 단점을 해결하기 위해 사용 
- Access Token, Refresh Token으로 이중으로 나누어 인증 진행 
- Access Token의 유효기간을 짧게 만들고, 유효기간이 만료될 때마다 Refresh Token을 통해 새로운 Access Token을 만듦 
 
- 특징 - 클라이언트에서 로그인을 요청을 하고 성공을 할 경우, 기존 AccessToken 외에 추가로 RefreshToken을 발급 
- AccessToken 에 비해 긴 만료시간을 갖도록 설정 
 
- 클라이언트 측 - AccessToken이 만료되었을 시 추가로 받았던 RefreshToken을 사용하여 재발급 요청 진행 
 
- 서버 측 - 유효한 RefreshToken이 오면 추가로 AccessToken 과 RefreshToken을 다시 발급 
- RefreshToken의 경우 서버 Storage에 따로 저장하며 이후 검증에 사용 - 이로인해 추가적인 I/O작업 필요하며 이는 별도의 I/O작업이 없다는 JWT의 빠른 인증처리의 특징에 상반되는 부분임 
 
 
- 장점 - 토큰이 탈취되더라도 제한된 기간만 접근 가능 
- RefreshToken에 대한 만료 강제 설정 가능 
 
- 단점 - 클라이언트는 AccessToken 만료시 갱신하는 로직을 구현해야 함 
- 서버는 별도의 storage 필요 
 
Ref
Last updated