ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Web] 세션과 HTTP, 연결(커넥션)에 관하여
    programing/Network 2021. 5. 16. 15:42

    발단

    쿠키와 세션에 관한 질문에 대해 고찰하던 중, 세션 인증 방식을 위해서는 필수불가결하게 쿠키를 사용해야 한다는 사실을 깨닳았습니다. 왜냐하면

    1. HTTP 프로토콜은 기본적으로 매 요청마다 연결(커넥션)을 맺고 끊기 때문입니다.
    2. HTTP 프로토콜은 기본적으로 stateless 하기 때문입니다.

    그렇다면 1번의 이유에 대해, 세션이라는 단어가 내포하고 있는 "클라와 서버의 연결이 끊기지 않음" 이랑 모순되지 않나? 라는 생각이 들었습니다.

    HTTP

    HTTP의 레이어

    위 사진은 HTTP 레이어를 나타내고 있습니다. 브라우저는 어플리케이션이고, 여기서부터 네트워크 요청이 만들어지므로, 응용 계층(7, application layer)에는 웹 브라우저가 관여하게 됩니다.

    연결은 전송 계층(4, transport layer)에서 담당하므로, HTTP 영역 밖의 일입니다. 따라서 연결을 맺는 일은 전송 계층 프로토콜에게 위임합니다.

    기본적으로 HTTP는 대부분 TCP를 기반으로 하며, HTTP 요청 전에 TCP 핸드셰이크를 실행합니다. 그리고 HTTP 요청은 TCP를 통해 전송되므로 직렬화되어야 합니다. 핸드셰이크를 통해 연결을 맺고 끊는 방식 때문에, #커넥션이 끊기지 않고 유지될 때 더 효율적입니다.

    HTTP Connection Model

    HTTP 커넥션에 대해 찾아보니 다음 세가지 모델이 있습니다.

    HTTP 연결의 세가지 모델

    단기 커넥션

    HTTP/1.0 의 기본 모델입니다. (Connectoin 헤더가 존재하지 않거나 close 로 설정된 경우)

    🚨 HTTP/1.1 에서는 Connection 헤더가 close로 설정된 경우에만 이 모델이 사용됩니다.

    TCP 핸드셰이킹이 끝나면 TCP 커넥션이 구성됩니다. 요청에 대한 응답을 전송할 때, close connection을 같이 보내서 TCP 커넥션을 끊습니다. 이러한 특성 때문에 TCP의 성능을 제대로 활용하지 못하는 모델입니다.

    영속적인 커넥션

    해당 모델은 커넥션을 일정 기간 동안 열어두고, 요청 및 응답을 해당 커넥션을 통해 주고받습니다. 따라서 매 요청마다 새로운 커넥션을 구성할 필요가 없어, 성능이 향상되었습니다.

    💡 Keep-Alive 헤더를 통해 커넥션의 유지 시간을 설정할 수 있습니다.

    다만 해당 모델도 다음과 같은 단점이 있습니다.

    • 비활성 상태에서도 서버의 리소스를 사용합니다.
    • 과부하 상태에서 DoS 공격을 당할 수 있습니다.

    HTTP/1.0 에선 기본적으로 영속적이지 않습니다. HTTP/1.1 에서는 기본적으로 영속적이며, 별도의 헤더 설정도 필요없습니다.

    파이프라이닝

    🚨 HTTP 파이프라이닝은 몇가지 이유 때문에, 기본적으로 활성화되어 있지 않습니다. 그래서 파이프라이닝은 더 나은 알고리즘인 멀티플렉싱으로 대체되었고, 이는 HTTP/2 에서 사용됩니다.
    자세한 내용은 링크를 참고해주세요.

    기본적으로, 흐름제어를 위해 HTTP 요청은 순차적입니다. 현재의 요청에 대한 응답을 받고 나서야 다음 요청을 실시합니다. 네트워크 지연과 대역폭 제한에 걸려 다음 요청을 보내는 데까지 상당한 딜레이가 발생할 수 있습니다.

    파이프라이닝이란 동일한 영속적인 커넥션을 통해서, 응답을 기다리지 않고 요청을 연속적으로 보내는 기능입니다. 이것은 응답을 기다리는 시간을 줄이기 위한 방법입니다.

    모든 종류의 HTTP 요청이 파이프라인으로 처리될 수 있는 것은 아닙니다: GET, HEAD, PUT, DELETE 메서드같은 멱등적인(idempotent) 메서드만 가능합니다. 따라서 실패가 발생한 경우에는 단순히 파이프라인 컨텐츠를 다시 반복하면 됩니다.

    오늘날, 모든 HTTP/1.1 호환 프록시와 서버들은 파이프라이닝을 지원해야 하지만, 실제로는 많은 프록시와 서버들은 제한을 가지고 있습니다. 모던 브라우저가 이 기능을 기본적으로 활성화하지 않는 이유입니다.

    HTTP 버전

    0.9

    생략

    1.0

    • 버전 정보가 각 요청 사이내로 전송되기 시작했습니다. (HTTP/1.0GET 라인에 붙은 형태로)
    • 상태 코드 라인 또한 응답의 시작 부분에 붙어 전송되어, 브라우저가 요청에 대한 성공과 실패를 알 수 있고 그 결과에 대한 동작(특정 방법으로 그것의 로컬 캐시를 갱신하거나 사용하는 것과 같은)을 할 수 있게 되었습니다.
    • HTTP 헤더 개념은 요청과 응답 모두를 위해 도입되어, 메타데이터 전송을 허용하고 프로토콜을 극도로 유연하고 확장 가능하도록 만들어주었습니다.
    • 새로운 HTTP 헤더의 도움으로, 평이한 HTML 파일들 외에 다른 문서들을 전송하는 기능이 추가되었습니다([Content-Type](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Type) 덕분에).

    1.1 (표준)

    • 커넥션이 재사용될 수 있게 하여, 탐색된 단일 원본 문서 내로 임베드된 리소스들을 디스플레이하기 위해 사용된 커넥션을 다시 열어 시간을 절약하게 하였습니다.
    • 파이프라이닝을 추가하여, 첫번째 요청에 대한 응답이 완전히 전송되기 이전에 두번째 요청 전송을 가능케 하여, 커뮤니케이션 레이턴시를 낮췄습니다.
    • 청크된 응답 또한 지원됩니다.
    • 추가적인 캐시 제어 메커니즘이 도입되었습니다.
    • 언어, 인코딩 혹은 타입을 포함한 컨텐츠 협상이 도입되어, 클라이언트와 서버로 하여금 교환하려는 가장 적합한 컨텐츠에 대한 동의를 가능케 했습니다.
    • [Host](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Host) 헤더 덕분에, 동일 IP 주소에 다른 도메인을 호스트하는 기능이 서버 코로케이션을 가능케 합니다.

    2.0

    구글의 SPDY 프로토콜을 기반으로 함.

    • 그것은 텍스트 프로토콜이라기 보다는 이진 프로토콜입니다. 더 이상 읽을 수도 없고 수작업을 만들어낼 수 없습니다; 이런 결점에 대한 보상으로, 새로운 최적화 기술이 구현될 수 있습니다.
    • 병렬 요청이 동일한 커넥션 상에서 다루어질 수 있는 다중화 프로토콜로, 순서를 제거해주고 HTTP/1.x 프로토콜의 제약사항을 막아줍니다.
    • 전송된 데이터의 분명한 중복과 그런 데이터로부터 유발된 불필요한 오버헤드를 제거하면서, 연속된 요청 사이의 매우 유사한 내용으로 존재하는 헤더들을 압축시킵니다.
    • 서버로 하여금 사전에 클라이언트 캐시를 서버 푸쉬라고 불리는 메커니즘에 의해, 필요하게 될 데이터로 채워넣도록 허용합니다.

    HTTPS

    HTTP Secure. HTTP의 암호화 버전입니다.

    비대칭 키 암호화 및 대칭 키 암호화를 이용하는 SSL(이후 TLS로 바뀜)라는 계층을 HTTP 위에 얹은 모델입니다.참고로, TLS 또한 HTTP 처럼 프로토콜입니다.

    TLS 1.0과 1.1은 2020년부터 대부분의 브라우저에서 지원 종료했으며, 현재 1.2 혹은 1.3을 주로 사용합니다.

    HTTPS 연결 구성 과정은 HTTPS를 알아보자를 참고해주세요.

    결론

    쿠키와 세션은 서로 mutex 한 개념이 아닙니다. 쿠키는 HTTP에 상태를 부여하는 기술이며, 세션은 서버에서 유저 정보를 보관하고 쿠키를 통해 검증하는 기술입니다.

    따라서 "클라와 서버의 연결이 끊기지 않음" 이라는 말은 애초에 틀린 말입니다. 아마도 "세션 유지" 라는 말을 자주 하기 때문에, 이런 잘못된 인식을 가지게 된 것 같습니다.

    올바른 비교를 한다면 쿠키 + 세션 vs 쿠키 + 토큰 을 비교하는 게 더 적절합니다.

    세션

    • 세션 아이디는 자가수용적(self-contained)이지 않기 때문에 별도의 DB를 통해 유효성 검증을 해야 한다.
    • 따라서 서버에 별도의 저장소가 필요하며, 서버의 OC(open close)를 방해하는 요소로 작용하며, 서버의 확장을 방해한다.
    • 하지만 악의적인 쿠키에 대한 빠른 대응이 가능하다.
    • 민감한 정보를 서버에 저장하므로, 보안성이 좋다.

    토큰

    • 토큰은 자가수용적이기 때문에 그 자체로써 유효성 검증이 가능하다.
    • 따라서 서버에 별도의 저장소가 필요하지 않으며, 서버의 OC(open close)에 알맞는 요소로 작용하며, 서버의 확장에 방해되지 않는다.
    • 하지만 한번 발행된 토큰은 서버측에서 임의로 폐기할 수 없기 때문에, 악의적인 쿠키에 대한 대응이 느리다. (refresh token을 이용해 대응 시간을 최소화 할 수는 있다.)
    • payload를 누구나 볼 수 있기 때문에, 민감함 정보를 담을 수 없다.
      • 쿠키 헤더 : 브라우저가 자동으로 요청에 담아줘서 편하다. httpOnly 및 secrure 옵션을 통해 XSS 공격 방어 가능. CSRF 공격은 방어 불가. (단, CORS 를 이용해 어느정도 방어 가능)
      • 인증 헤더 : 매 요청마다 일일이 담아줘야 하며, 상태를 저장하기 위해 web storage api를 사용해야 한다. XSS 공격과 CSRF 공격 방어 가능.
      • 보통 쿠키 헤더를 많이 쓰는 듯.

    참고

    HTTP 자습서

    HTTP/1.x의 커넥션 관리

    HTTPS

    전송 계층 보안 (TLS)

    쉽게 알아보는 서버 인증 1편(세션/쿠키 , JWT)

    HTTPS를 알아보자

    Access Token 저장 위치에 대한 고찰

    댓글

Designed by black7375.