profile image

L o a d i n g . . .

쿠키와 세션 등을 사용하는 이유?

- HTTP프로토콜의 특징이자 단점인 비연결성을 보완하기 위해 사용

- 서버-클라이언트 모델을 따르는 HTTP는 Connectionless, stateless 특성을 가진다.

  Connectionless(비연결성): 클라이언트가 서버에게 요청을 한 후 응답을 받으면 연결이 끊긴다. 즉, 클라이언트와 서버가 연결되어있지 않아 리소스가 계속 사용되지 않고 일회성으로 발생한다. 다만 이러한 특징때문에 매번 요청에 대해 새로운 연결을 해야하므로 '오버헤드(처리를 위해 들어가는 간접적인 처리시간&메모리)'가 발생하는 단점 또한 존재한다

 

  Stateless(무상태): 상태를 가지고 있지 않다. 즉, 서버는 클라이언트를 식별할 수 없기때문에 클라이언트의 상태 또한 알 수 없다. 예) 쇼핑몰 접속 -> 로그인 -> 상품클릭 -> 상세화면으로 이동 -> 로그인 -> 장바구니 -> 로그인 -> 주문 -> 로그인 

 

HTTP가 지닌 특성들의 단점 중 상태를 기억하지못하는 점을 보완하기위해 상태를 기억하기위한 다양한 데이터 저장방식이 등장했다.

 


쿠키: 브라우저에 저장되는 정보

스택오버플로우

웹 서핑을 하다보면 위와같이 쿠키를 설정할거냐는 문구를 본 적이 있을것이다. 이 쿠키덕분에 사이트에 로그인하지않아도 검색기록에서 이전에 입력했던 검색어들이 남아있게 된다.

 

쿠키는 크롬이나 사파리 등의 브라우저에 저장되는 작은 텍스트 조각이다. 브라우저는 사용자의 컴퓨터에 설치된 소프트웨어이므로 쿠키는 사용자(클라이언트)가 가지고 있는 정보라고 할 수 있다. HTTP응답 시 헤더에서 Set-Cookie로 사용자의 브라우저에 전송할 수 있다. 

 

 

위의 쿠키 허용을 누른 후 개발자도구(F12 또는 커멘드+옵션+J)를 눌러서 네트워크에 들어가보면

이렇게 애플리케이션에서 쿠키를 확인할 수 있다.

 

이 말인 즉슨, 쿠키는 브라우저에서 확인하고 추가, 편집, 삭제가 가능하기 때문에 당사자 뿐 아닌 제3자에게 노출될 위험이 있다. 따라서 개인정보나 보안상 민감한 정보를 저장하는데에는 적합한 저장장소가 될 수 없다. 

 

그렇다면 쿠키는 어떤 경우에 사용하는게 가장 좋을까?

- 자동로그인

- 쇼핑몰 장바구니

- 검색 내역

- 팝업 "오늘 더 이상 이 창을 보지 않음" 

 

쿠키의 특징 및 구성요소

- 쿠키는 클라이언트에 300개까지 저장 할 수 있으며, 하나의 도메인 당 20개의 값만 가질 수 있다.

- 하나의 쿠키값은 4KB까지 저장된다.

- 사용자인증 유효시간을 정할 수 있으므로 시간 내에는 브라우저가 종료되어도 쿠키가 유지된다는 특징이 있다.

- 쿠키 구성요소(Key-Value): 이름 / 값 / 유효시간 / 도메인 / 경로

 

 

 

 


세션: 서버가 나를 알아보는 방법

쿠키가 사용자(클라이언트)에 저장되는 정보라면, 세션은 쿠키를 기반으로 하지만 쿠키와는 달리 정보를 서버에 저장하고 관리한다. 세션은 로그인 여부등 사용자와 서버의 관계가 기억되어 보존되고 있는 상태를 말한다.

 

세션 동작방식: 사용자가 로그인 하면 브라우저 종료 전 까지 상태를 기억한다.

사용자가 사이트에 올바른 아이디와 비밀번호로 로그인 하면 서버는 유니크한 세션ID라는 데이터를 만든다. 유일한 값인 '98as2nj5gd'와 같은 해싱된 값을 사용자에게 전달한다. 사용자는 서버로부터 받은 세션ID를 쿠키로 저장한 후 이후 웹 사용에 필요한 요청들에 함께 전달한다. 댓글 작성, 마이페이지, 상품내역 등 다양한 요청마다 서버에게 세션아이디를 보내게 된다.

서버는 사용자에게서 요청에 담긴 세션아이디를 확인한 후 서버가 보관하고 있는 세션아이디와 매칭하게되고, 해당되는 세션 아이디에 맞춘 정보를 담아 응답한다.

 

세션의 단점

세션은 안전하고 효과적이지만 단점또한 존재한다. 서버는 요청마다 함께 오는 세션ID를 바로바로 확인할 수 있도록 메모리에 올려둔다. 메모리에 올려둔 데이터를 빠르게 확인할 수 있다는 장점이 있지만 메모리는 한정적인 공간이기때문에 사용자가 많아질 수록 서버 메모리를 많이 차지하게되고, 동시 접속하는 사용자가 많아지면 메모리 공간이 부족해져 서버에 부하가 걸리고 화면이 멈추는 등의 문제가 발생할 수 있다.

 

 

 


토큰: 세션과는 또 다른 로그인 유지방식

메모리 공간을 많이 차지하는 세션 대신 토큰이라는 방식이 있다. 토큰은 특수한 수학적 원리가 적용되어 있어 위조방지 장치가 있는 지폐처럼 해당서버만의 방식으로 암호화된 문자열을 발행한다. 때문에 토큰을 받은 사용자는 이를 쿠키에 저장해두고 필요할 때마다 제시하면 서버는 메모리에 저장해 둘 필요없이 그때그때 자기가 발급한 토큰인지 알아보고 사용자의 요청을 허가해준다. 대표적으로는 OauthJWT가 있다

 

토큰의 단점

토큰또한 한계가 존재한다.

- 토큰의 길이가 길어 인증요청이 많아질 수록 네트워크 부하가 심해질 수 있다.

- 여러기기에서의 로그인을 제한하기 위해 서버는 강제로 기기 로그아웃을 시킬 수 있어야 하지만 토큰 방식에서는 불가능하다. 말인 즉슨, 특정 토큰을 강제로 만료시키기 어렵다는 뜻이다. 토큰은 유효기간이 끝나기 전까지 통제할 방법이 없다. 만료될 때까지 계속 사용이 가능하므로 중간에 공격자로부터 토큰이 탈취당하기 전에 만료시간을 짧게 지정해두는게 좋다. 

 

 

JWT(Json Web Token)

인증에 필요한 정보들을 암호화 시킨 후 JWT토큰을 HTTP 헤더에 싣는다. 서버는 헤더에 추가된 토큰을 디코딩하여 사용자를 인증한다. 

 

//header      signature
aaaaaa.bbbbbb.cccccc
     //payload

 

헤더, 내용, 서명으로 이루어져 있으며 각 언어의 라이브러리에서 자동으로 인코딩 밋 해싱작업을 해준다. 

헤더: JWT토큰의 유형이나 HMAC SHA256 또는 RSA와 같이 해시알고리즘 중 무엇으로 사용했는지의 정보가 담김

내용: 토큰에 담을 클라이언트에 대한 정보다 메타데이터 등이 담김

서명: 헤더에서 지정한 알고리즘과 비밀키, 서명으로 payload와 header를 담음. 위변조 여부 확인 가능

 

JWT는 자체적으로 모든 정보를 가지고 있기때문에 클라이언트가 해독해서 정보를 볼 수 있다. 따라서 민감한 정보는 payload에 담지않는게 좋다. 다만, 토큰정보를 수정하기위해서는 비밀키를 알고있어야 한다

 

 


캐시: 전송량은 줄이고 속도는 높이고

 

쿠키/세션은 캐시와 다르다. 캐시는 이미지나 css, js등을 브라우저나 서버 앞단에 저장해놓고 사용하기때문에, 반복적으로 사용하는 콘텐츠를 빠르게 이용할 수 있고 데이터 사용량도 줄일 수 있다. 쿠키와 캐시 모두 정보를 저장하여 재활용 하는 기술이지만, 쿠키는 클라이언트의 수고를 덜어주는 목적에 가깝고 캐시는 데이터의 전송량을 줄이고 서비스 이용 속도를 높이는게 주 목적이다. 

한번 캐시에 저장되면 브라우저를 참고하기 때문에 서버에서 변경이 되어도 사용자는 변경되지 않게 보일 수 있다. 이런 부분은 캐시를 지워주거나 서버에서 클라이언트로 응답을 보낼 때 헤더에 캐시 만료시간을 명시하는 방법등으로 보완할 수 있다.

 

 

 

예) css 수정 후 화면에 바로 반영되지 않는 경우: 해결을 위해선 개발자도구-네트워크-캐시 사용 중지를 체크해주어야 한다.

 

웹서버 캐싱과정

캐싱? 캐싱은 주어진 리소스의 복사본을 저장하고 있다가 요청 시에 그것을 제공하는 기술

- 웹에 요청을 호출하면, 요청은 웹브라우저로부터 하드디스크의 파일 시스템에 있는 정적 리소스를 제공하는 웹서버로 전달한다.

 

- 이때 성능을 고려하여 캐싱 시스템을 잘 활용하고있는 시스템 환경이라고 한다면 웹서버로 첫 요청 시, 하드 디스크는 캐시를 확인 후 "캐시미스(캐시 메모리에 찾는 데이터가 존재하지 않을 때)"를 발생시킨다. "캐시미스"가 발생하면 메모리 저장소로부터 필요한 데이터를 찾아 캐시 메모리에 로드한다. 그리고 다시 요청받을 수 있다고 하면 캐시를 하드디스크에 저장한다. 

 

- 이후 요청부터는 캐시를 사용할 수 있는 경우 "캐시히트(캐시메모리에 찾는 데이터가 존재할 때)"를 발생시키고, 캐시미스가 발생하기 전까지 버퍼에서 캐시를 제공한다.

 

- 데이터베이스 캐싱의 경우도 시스템 성능에 있어 매우중요하다. DB쿼리의 경우 DB서버에서 수행되기 때문에 사용자가 급격히 증가함에 따라 속도가 매우 느리고 부하가 생길 수있다. 이런 쿼리들이 반복될 때 그 결과값을 데이터베이스에 캐싱하면 응답시간 향상 및 서버부하 감소가 가능해진다. 특히 다수의 머신이 동일한 데이터베이스에 동일한 쿼리를 사용할수록 그 효과는 커지게 된다.

 

응답 캐싱

WAS: DB 조회 혹은 다양한 로직 처리를 요구하는 동적 컨텐츠를 제공하기 위해 만들어진 Application 서버. HTTP 프로토콜을 기반으로 사용자 컴퓨터나 장치에 애플리케이션을 수행해주는 미들웨어로서, 주로 데이터베이스 서버와 같이 수행.  WAS는 DB 조회나 다양한 로직을 처리하고, 단순한 정적 컨텐츠는 웹 서버에서 처리하며 서버부하 분산. 

Redis: 

Key-Value 구조의 비정형 데이터를 저장하고 관리하기위한 오픈소스기반 DBMS. DB, Cache, Message Broker로 사용되며 인메모리 데이터 구조를 가진 저장소 

- 웹서버는 응답을 캐싱하도록 구성하여 유사요청이 애플리케이션 호스트로 전달되지 않도록 할 수 있다

- 위와 비슷한 방식으로, 애플리케이션 호스트는 비용이 높은 데이터베이스 쿼리나 자주 요청되는 파일들에 대한 응답을 캐싱할 수도 있다.

- 웹서버의 응답은 메모리에 캐싱하고, 애플리케이션 캐시는 로컬 인메모리에 저장하거나 캐시서버 위에서 실행되는 레디스와같은 인메모리 데이터베이스에 저장할 수 있다.  

 

HTTP헤더를 통한 브라우저 캐싱

모든 브라우저는 HTML, CSS, JS 및 이미지 등의 웹문서 임시저장을 위해 HTTP캐시(웹캐시)구현을 제공하고 있다.

 

- 브라우저는 서버에 index.html 파일을 요청후, 서버는 index.html 파일을 찾아보고 존재할 경우 파일 내용을 브라우저에게 header와 함께 응답한다. 

- 브라우저는 응답받은 내용을 브라우저에 표시하고 응답 헤더의 내용에 따라 캐시정책을 수행한다. 

- HTTP헤더를 제공하여 브라우저가 응답을 캐싱할 수 있는 방법, 시기, 지속시간을 지시할 때 사용한다.

- 리소스가 로컬캐시로부터 빠르게 로드되기 때문에 하드웨어 성능이 급격하는 시기에 잘 이요한다면 강력한 속도향상을 제공한다.

- 요청이 네트워크를 통해 전송되지 않기 때문에 왕복시간(RTT, Round Trip Time)이 발생하지 않는다.

- 캐시 설정을 통해 브라우저 응답으로 온 HTML, JSON등의 전송 데이터를 통해 서버에 요청을 보내지 않고도 사용할 수 있다. 

- 일반적으로 캐싱은 GET요청에서 처리한다

    > 200, 206(부분 컨텐츠 응답), 301(리다이렉트 후 가져옴), 404 상태코드로 응답들을 캐싱할 수 있다. 

 

 

귀여운 깃헙 404 페이지

- 가장 흔하게 볼 수 있는 캐싱페이지는 오류페이지이다. 어떤 오류가 발생 시 그사이트 특색에 맞게 오류 페이지를 보여주도록 해둔 사이트들이 많다. 

 

 

캐시관련 헤더종류

  HTTP 1.0 (1996) HTTP 1.1 (1999)
  REQUEST RESPONSE REQUEST  RESPONSE
파일이 이전과 비교하여 변경되었는가 
(validation)
If-Modified-Since Last-Modified If-None-match Entity Tag (Etag)
캐시의 만료 여부 체크
(freshness)
Pragma Expires Cache-control Cache-control

HTTP 1.1에선 하위 호환되므로 1.0의 헤더를 사용하여도 정상 동작하지만 중복으로 선언된다면 1.1에 정의된 것이 우선순위를 가지게 된다

 

1) Cache-Control (모든 브라우저에서 지원)

- 캐싱 정책을 정의

- 응답을 캐시할 수 있는 사용자, 해당 조건 및 기간제어

- 응답-요청헤더 모두 사용가능

- 프론트 - 중개 서버 - 서버와 같은 구조인 경우 중개 서버에 있는 캐시를 가져오지 않도록 하려면 요청 시 Cache-Control을 헤터로 넣어 해결하기도 한다.

 

2) no-cache / no-store

- no-cache: 캐시를 쓰기 전에 서버에 이 캐시를 진짜 써도 되냐고 물어보라는 뜻 (캐시를 사용하지 말라는 뜻이아님)

- no-store: 아무것도 캐싱하지 않을때 사용

 

3) public / private

<!-- 사용자 클라이언트에만 10분간 유효한 캐시저장 -->
'Cache-Control': 'private, max-age=600'

- public: 공유캐시(또는 중개서버)에 저장해도 된다는 뜻 ex)public, max-age=3600

    >> max-age로 캐시유효시간을 초단위로 줄 수 있다. 대부분의 경우 명시적 캐싱정보가 응답이 어떠한 경우든 캐시가 가능하다고 나타내므로 퍼블릭이 필요하지 않다

- private: 브라우저 같은 특정 사용자 환경에만 저장, 단일 사용자 대상으로 중간 캐시가 이 응답을 캐싱할 수 없다.

    >> 비공개 사용자 정보가 포함된 HTML페이지는 사용자의 브라우저가 캐시할 수 있지만, CDN은 캐싱불가

 

4) must-revalidate / max-age

<!-- 브라우저가 10분 이전의 데이터를 가지고 있다면, 서버에 요청하지 않는다. -->
Cache-Control: must-revalidate, max-age=600

- 만료된 캐시만 서버에 확인을 받도록 한다.

- 브라우저는 최초 응답시 받은 Cache-Control 중 max-age값을 GMT와 비교해 기간 이내라면 서버를 거치지 않고 캐시에서 페이지를 로드, 만약 기간이 만료되었다면 validation 작업을 수행한다.

 

5) Age 

- 캐시 응답 때, max-age 시간 내에서 얼마나 흘렀는지 초 단위로 알려준다.

 

6) Expires

Expires: Wed, 11 Jan 2023 13:44:23 GMT

- Cache-Control과 동시에 동작하진 않으나, Expires라는 헤더를 지정해 응답 컨텐츠 만료시간을 나타낼 수 있다.

- Cache-Control의 max-age가 있는 경우 무시된다.

- 유효 수명: Expires 헤더에서 Date 헤더의 값을 뺀 결과

- 브라우저는 최초 응답시 받은 Expires시간을 비교해 기간 이내라면 서버를 거치지 않고 바로 캐시에서 페이지를 로드하고, 기간이 만료 되었다면 validation 작업을 수행한다.

 

7) ETag 

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4

- 특정 버전의 리소스를 식별하는 식별자로써 ETag로 캐시된 응답에 대한 유효성 검사를 수행 (HTTP컨텐츠가 바뀌었는지 검사)

- Etag는 서버마다 생성하는 값이 다르며 파일마다 고유한 값을 가진다.

- 서버는 ETag 헤더를 사용해 유효성 검사 토큰을 전달. 유효성 검사 토큰을 사용해 리소스 업데이트를 검사하며 리소스가 변경되지 않은 경우 데이터가 전송되지 않는다. 

- Expires 나 max-age 등을 사용하여 특정 시간동안만 캐시를 사용한다고 했을 때 특정 시간, 시점이 지나야 브라우저가 새 요청을 발송하고 전체 새 응답을 가져온다. 리소스가 변경되지 않은 경우엔 이미 캐시에 있는 동일한 정보를 다운로드할 이유가 없으므로 이렇게 시간을 지정하여 캐시를 갱신하는 작업은 비효율적이다. 

- ETag 헤더에 지정된 유효성 검사 토큰은 바로 이 문제를 해결하기 위해 고안되었다. 서버는 일반적으로 파일 콘텐츠의 해시나 기타 일부 지문인 임의 토큰을 생성하고 반환한다. 클라이언트는 다음 요청 시 지문을 서버에 전송하기만 하면 된다. 지문이 여전히 동일한 경우 리소스가 변경되지 않고 이 다운로드를 건너뛸 수 있다.
ex) 클라이언트에 최대 120초 동안 캐시하도록 지시하고, 응답이 만료된 후 리소스가 수정되었는지 확인하는 데 사용할 수 있는 유효성 검사 토큰(‘x456dff’)을 제공한다.

 

8) If-None-Match

If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

- 서버를 보며 Etag가 달라졌는지 검사 후 Etag가 다를 경우에만 컨텐츠를 새로 받는다

- Etag가 같다면 서버는 304 Not Modified를 응답하고 캐시를 그대로 사용한다.

- Etag가 다르다면 200 OK와 함께 새로운 Etag 값을 응답 헤더에 전송한다.

 

 

 

 

 

캐시에 관한 헤더를 상황에 맞게 선택할 수 있도록 도와주는(Cache-Control flowchart)

https://web.dev/http-cache/#defining-optimal-cache-control-policy

 

 

 

 


CDN: 서버 부담은 줄이고 사용자와는 가깝게

캐시를 사용하지 않고 매번 정보가 전송되는 것은 사용자로서도, 서버에게도 큰 부담이다.

이런 문제를 해결하기위해 사용하는것이 바로 CDN(콘텐츠 전송 네트워크)이다.

CDN은 지리적으로 분산된 여러 서버를 이용해 웹 콘텐츠를 사용자와 가까운 서버에서 전송함으로써 전송 속도를 높인다

 

- 여러 지역에 설치된 캐시 서버들을 사용해 본 서버로 들어오는 요청들을 분산처리하는 서비스

- 대량의 데이터를 전송하는 서비스, 특히 유튜브나 넷플릭스 같은 동영상 서비스에 CDN은 필수

- AWS의 CloudFront, CloudFlare, Akamai등이 전세계 캐시 서버를 운영하는 대표 CDN 업체

- 한국에서도 GS네오텍, SKB, KT 등 한국 서비스에 최적화된 CDN 업체가 있다.

- 서비스특성, 사용자 규모, 대상지역에 따라 호스팅 업체와는 별개의 CDN서비스를 선택하여 이용할 수 있다.

 

 

참고: 

- 혼자 공부하는 얄팍한 코딩지식(고현민 저) 한빛미디어

- http://egloos.zum.com/rousalome/v/10143695

- https://victorydntmd.tistory.com/286

- https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Set-Cookie

반응형

'개발 > CS' 카테고리의 다른 글

[CS] CPU, 프로세스, 스레드  (2) 2023.02.04
[Network] IP, DNS, HTTP, HTTPS  (1) 2023.01.26
[혼공단 9기] 혼공얄코 커리큘럼  (0) 2023.01.01
SSR? CSR? SEO?  (1) 2023.01.01
[Network] 데이터 링크 계층의 역할과 이더넷  (2) 2022.12.07
복사했습니다!