HTTP와 HTTPS

Series: 네트워크

네트워크contains 4

HTTP와 HTTPS

들어가며

웹 브라우저를 열고 주소창에 URL을 입력하는 순간, 우리는 아주 자연스럽게 어떤 웹 페이지를 받아본다. 이 과정은 너무 익숙해서 단순히 요청을 보내고 응답을 받는 정도로만 생각하기 쉽지만, 실제로는 그 안에 여러 단계의 통신 과정과 중요한 설계가 포함되어 있다. 특히 이 통신이 어떤 방식으로 이루어지는지, 그리고 그 과정에서 데이터가 얼마나 안전하게 보호되는지는 웹을 이해하는 데 있어 핵심적인 요소이다. HTTP와 HTTPS는 바로 이 통신의 중심에 있는 프로토콜이며, 두 프로토콜의 차이를 이해하는 것은 단순한 개념 학습을 넘어 실제 서비스의 동작과 보안을 이해하는 데 중요한 출발점이 된다. 이 글에서는 단순한 정의를 나열하는 것이 아니라, 실제 요청이 어떻게 흐르는지를 따라가면서 HTTP와 HTTPS를 자연스럽게 이해해보려고 한다.

1. HTTP

좋다. 지금 문단은 핵심은 잘 잡혀 있는데, 흐름이 약간 “설명 요약” 느낌이라서
→ 실제 요청 흐름을 끼워 넣어서 풀어주면 훨씬 자연스럽고 깊어진다.

같은 내용인데 한 단계 더 풀어서 다시 작성해보면 아래처럼 가져가는 게 좋다.


1.1 HTTP의 개념

HTTP는 웹에서 데이터를 주고받기 위한 프로토콜이다. 우리가 브라우저에 주소를 입력하고 특정 웹 페이지에 접속할 때, 내부적으로는 이 HTTP를 이용해 서버와 통신이 이루어진다. 여기서 중요한 점은 HTTP가 단독으로 데이터를 전송하는 역할까지 모두 담당하는 것이 아니라, 데이터를 어떤 형식으로 주고받을지를 정의하는 역할에 집중한다는 것이다. 조금 더 구체적으로 보면, HTTP는 '무엇을 요청할지'와 '어떤 형태로 응답할지'를 결정하는 규칙이다. 반면, 실제 데이터를 네트워크를 통해 전달하는 역할은 HTTP가 아니라 TCP가 담당한다. 즉, HTTP는 메시지의 내용과 구조를 정의하고, TCP는 그 메시지를 안전하게 전달하는 역할을 맡는다. 이 둘은 서로 분리된 역할을 가지면서도 함께 동작한다.

이 구조를 이해하려면 실제 요청이 어떻게 이루어지는지를 한 번 흐름으로 보는 것이 좋다. 사용자가 브라우저에 https://choewy.github.io과 같은 주소를 입력했다고 가정해보자. 이때 브라우저는 바로 HTTP 요청을 보내는 것이 아니라, 먼저 서버와의 연결을 만들어야 한다. 이 연결이 바로 TCP 연결이다.

sequenceDiagram
    participant Client as 브라우저
    participant Server as 서버

    Client->>Server: TCP 연결 요청
    Server-->>Client: 연결 수락
    Client->>Server: HTTP 요청
    Server-->>Client: HTTP 응답

이 과정에서 중요한 점은 HTTP 요청은 항상 TCP 연결이 만들어진 이후에 전송된다는 것이다. TCP 연결이 먼저 생성되어야만, 그 위에서 HTTP 메시지를 주고받을 수 있다. 즉, HTTP는 TCP 위에서 동작하는 상위 프로토콜이라고 볼 수 있다. 그렇다면 왜 굳이 TCP 위에서 HTTP를 동작시키는 걸까? 이유는 TCP가 제공하는 특징 때문이다.

TCP는 데이터를 전송할 때 몇 가지 중요한 보장을 제공한다. 데이터를 보낸 순서대로 받을 수 있도록 순서를 보장하고, 전송 중 데이터가 손실되면 이를 감지해서 다시 보내도록 한다. 또한 데이터가 중간에 손상되었는지도 확인할 수 있다. 이 덕분에 HTTP는 데이터가 제대로 도착할지에 대해서는 크게 신경 쓰지 않고, 어떤 데이터를 주고받을지에 집중할 수 있다. 예를 들어 서버가 HTML 문서를 응답으로 보낸다고 했을 때, HTTP 입장에서는 그 문서가 정확히 전달되는지까지 관리하지 않는다. 그 역할은 TCP가 대신 수행한다. 이처럼 HTTP와 TCP는 역할이 명확하게 나뉘어 있다. HTTP는 요청과 응답의 구조를 정의하고, TCP는 그 데이터를 신뢰성 있게 전달한다. 이 구조 덕분에 웹 통신은 비교적 단순한 방식으로 설계되면서도 안정적으로 동작할 수 있게 된다.

1.2 HTTP의 구조

HTTP는 요청과 응답이라는 매우 단순한 구조를 가진다. 브라우저는 서버에게 요청(Request)을 보내고, 서버는 이에 대한 응답(Response)을 반환한다. 이 과정은 하나의 대화처럼 반복된다. 요청에는 어떤 자원을 원하는지에 대한 정보가 포함되며, 응답에는 요청 결과와 실제 데이터가 담긴다.

sequenceDiagram
    participant Client as 브라우저
    participant Server as 서버

    Client->>Server: HTTP 요청
    Server-->>Client: HTTP 응답

요청에는 단순히 경로만 포함되는 것이 아니라, 어떤 방식으로 요청하는지도 함께 전달된다. 이를 HTTP Method라고 하며, 대표적으로 GET, POST, PUT, DELETE 등이 있다. 예를 들어 GET은 데이터를 조회할 때 사용되고, POST는 데이터를 생성할 때 사용된다. 서버는 이 Method를 기반으로 요청의 의도를 판단한다. 또한 응답에는 상태 코드가 포함되는데, 이는 요청이 정상적으로 처리되었는지, 오류가 발생했는지를 나타낸다. 200(Success)은 성공, 404(Not Found)는 자원을 찾을 수 없음, 500(Internal Server Error)은 서버 내부 오류를 의미한다. 이처럼 HTTP는 단순한 문자열 기반 프로토콜이지만, 요청과 응답 구조를 통해 다양한 상황을 표현할 수 있도록 설계되어 있다.

1.3 HTTP의 특징 (Stateless)

HTTP를 이해할 때 반드시 짚고 넘어가야 하는 특징 중 하나가 Stateless라는 점이다. Stateless는 말 그대로 상태를 저장하지 않는다는 의미인데, 이걸 단순히 기억하지 않는다고 이해하기보다는 실제 요청 흐름 속에서 생각해보는 것이 훨씬 이해하기 쉽다. 예를 들어 사용자가 어떤 서비스에 로그인한다고 가정해보자. 사용자는 아이디와 비밀번호를 입력하고 로그인 요청을 보낸다. 서버는 이 요청을 처리하고, 로그인에 성공했다는 응답을 반환한다. 여기까지는 일반적인 흐름이다. 그런데 그 다음에 사용자가 다른 페이지를 요청한다고 해보자. 이때 서버는 이 요청만 보고는 이 사용자가 방금 로그인했던 사용자라는 사실을 알 수 없다.

sequenceDiagram
    participant Client as 사용자
    participant Server as 서버

    Client->>Server: 로그인 요청
    Server-->>Client: 로그인 성공

    Client->>Server: 사용자 정보 요청
    Server-->>Client: (누군지 모름)

이유는 HTTP가 각 요청을 완전히 독립적인 것으로 처리하기 때문이다. 이전 요청에서 어떤 일이 있었는지, 사용자가 어떤 상태였는지에 대한 정보는 자동으로 이어지지 않는다. 모든 요청은 항상 처음 보는 요청처럼 처리된다. 이 구조는 서버를 단순하게 만든다는 장점이 있다. 서버는 특정 사용자의 상태를 계속 기억할 필요가 없기 때문에, 구조가 복잡해지지 않고 확장하기도 쉬워진다. 여러 대의 서버로 요청을 분산시키는 환경에서도 별도의 상태 동기화가 필요 없기 때문에 대규모 서비스에서 유리한 구조라고 볼 수 있다.

하지만 동시에 명확한 한계도 있다. 로그인 상태 유지, 장바구니, 사용자 맞춤 정보처럼 이전 상태를 기반으로 동작해야 하는 기능을 구현하기가 어려워진다. 그래서 실제 서비스에서는 HTTP 위에 별도의 상태 관리 방법을 추가로 얹어서 사용한다. 대표적인 것이 쿠키, 세션, 토큰이다. 클라이언트가 요청을 보낼 때마다 자신의 상태를 식별할 수 있는 정보를 함께 전달하고, 서버는 그 정보를 기반으로 사용자를 구분하게 된다. 결국 HTTP 자체는 상태를 전혀 관리하지 않는 프로토콜이고, 우리가 흔히 사용하는 “로그인 유지” 같은 기능은 모두 그 위에 추가된 구조라고 이해하는 것이 정확하다.

1.4 HTTP의 취약점

HTTP의 가장 큰 문제는 데이터가 아무런 보호 없이 전달된다는 점이다. 이 문제는 단순히 암호화가 안 되어 있다라는 수준에서 끝나는 것이 아니라, 실제 통신 구조를 이해해보면 훨씬 더 심각하게 느껴진다. 사용자가 브라우저에서 어떤 요청을 보낸다고 하면, 그 요청은 서버로 바로 전달되는 것이 아니라 여러 네트워크 경로를 거쳐 이동한다. 집에서 사용하는 공유기를 지나고, 통신사의 네트워크를 통과하고, 여러 중간 장비를 거쳐서 목적지 서버에 도달한다. 이 과정에서 HTTP 요청과 응답은 그대로 노출된 상태로 이동한다. 예를 들어 로그인 요청을 보낸다고 가정해보자.

POST /login

id=admin&password=1234

이 데이터는 암호화되지 않은 상태로 네트워크를 통해 전달된다. 만약 이 경로 중간에 있는 누군가가 패킷을 확인할 수 있다면, 요청에 포함된 정보는 그대로 읽을 수 있다. 즉, 아이디와 비밀번호 같은 민감한 정보도 그대로 노출될 수 있다. 문제는 여기서 끝나지 않는다. 단순히 데이터를 읽는 것뿐만 아니라, 변경하는 것도 가능하다는 점이 더 위험하다. 예를 들어 중간에서 요청 내용을 수정하거나, 서버의 응답을 바꿔버리는 상황도 이론적으로 가능하다.

sequenceDiagram
    participant Client as 사용자
    participant Attacker as 중간 공격자
    participant Server as 서버

    Client->>Attacker: HTTP 요청
    Attacker->>Server: 변조된 요청
    Server-->>Attacker: 응답
    Attacker-->>Client: 변조된 응답

사용자는 정상적으로 서버와 통신하고 있다고 생각하지만, 실제로는 중간에서 변조된 데이터를 주고받고 있을 수도 있다. 이런 공격을 흔히 중간자 공격(Man-in-the-Middle Attack)이라고 한다. 이처럼 HTTP는 데이터 전달이라는 기능 자체는 충실히 수행하지만, 보안이라는 관점에서는 거의 아무런 보호 기능을 제공하지 않는다. 그래서 로그인, 결제, 개인정보 처리처럼 민감한 데이터를 다루는 환경에서는 HTTP만으로는 안전한 서비스를 만들 수 없고, 반드시 추가적인 보안 계층이 필요하게 된다. 이 지점에서 등장하는 것이 HTTPS이다.

2. HTTPS

2.1 HTTPS의 등장 배경

HTTP의 구조를 그대로 두고 생각해보면, 결국 하나의 문제로 귀결된다. 데이터를 주고받는 방식은 잘 정의되어 있지만, 그 데이터가 안전하게 전달되는지에 대해서는 전혀 보장하지 않는다는 점이다. 초기 웹 환경에서는 단순한 정보 조회가 대부분이었기 때문에 큰 문제가 되지 않았지만, 웹이 발전하면서 상황이 완전히 달라졌다. 로그인 기능이 추가되고, 사용자 계정이 생기고, 결제와 같은 민감한 기능들이 웹 위에서 동작하기 시작하면서 단순한 평문 통신으로는 더 이상 서비스를 운영할 수 없는 수준에 이르게 된다.

예를 들어 사용자가 온라인 쇼핑몰에서 결제를 진행한다고 생각해보자. 카드 정보나 개인 정보가 HTTP를 통해 그대로 전달된다면, 이 데이터는 네트워크를 지나가는 모든 구간에서 노출될 수 있다. 단순히 데이터를 볼 수 있다는 문제를 넘어서, 중간에서 데이터를 바꾸는 것도 가능해진다. 사용자는 정상적으로 결제를 진행했다고 생각하지만, 실제로는 전혀 다른 정보가 전달될 수도 있다. 이러한 문제를 해결하기 위해 등장한 것이 HTTPS이다.

HTTPS는 기존 HTTP를 완전히 대체하는 것이 아니라, HTTP 위에 보안 계층을 하나 더 추가한 구조이다. 즉, HTTP의 요청/응답 구조는 그대로 유지하면서, 그 데이터를 안전하게 전달할 수 있도록 보호 장치를 추가한 것이다. 여기서 중요한 점은 단순히 데이터를 숨기는 것이 아니라, 통신하는 상대가 실제로 신뢰할 수 있는 대상인지까지 검증한다는 것이다. 이 과정을 통해 데이터의 기밀성뿐만 아니라, 무결성과 신뢰성까지 함께 확보하게 된다.

2.2 HTTPS의 암호화 방식

HTTPS를 이해할 때 가장 중요한 개념은 결국 암호화이다. 하지만 여기서 단순히 '데이터를 암호화한다'라고만 이해하면, HTTPS의 핵심 구조를 놓치게 된다. 실제로 HTTPS는 하나의 암호화 방식만 사용하는 것이 아니라, 서로 다른 특징을 가진 두 가지 방식을 조합해서 사용한다. 이 구조를 이해하려면 먼저 암호화가 실제 통신에서 어떤 문제를 만드는지부터 생각해볼 필요가 있다.

2.2.1. 대칭키 방식

데이터를 암호화하려면 결국 송신자와 수신자가 동일한 기준으로 데이터를 풀어낼 수 있어야 한다. 즉, 암호화에 사용된 키를 양쪽이 모두 알고 있어야 한다. 여기서부터 문제가 시작된다. 이 키를 어떻게 안전하게 공유할 것인가라는 문제가 생기기 때문이다. 가장 단순한 방법은 하나의 키를 만들어서 서로 공유하는 것이다. 이 방식이 바로 대칭키 방식이다. 하나의 키로 데이터를 암호화하고, 같은 키로 복호화한다. 구조가 단순하기 때문에 처리 속도가 빠르고, 실제 데이터 통신에 매우 효율적이다. 그래서 대량의 데이터를 처리해야 하는 상황에서는 이 방식이 적합하다.

하지만 이 방식은 시작부터 한계를 가지고 있다. 데이터를 보내기 전에 반드시 동일한 키를 공유해야 하는데, 이 키를 전달하는 과정이 안전하지 않다면 암호화 자체가 무의미해진다. 예를 들어 네트워크를 통해 키를 전달하는 도중 누군가가 이를 가로챘다면, 이후 통신 내용은 그대로 노출될 수밖에 없다. 즉, 대칭키는 빠르고 효율적이지만, '키를 어떻게 안전하게 전달할 것인가?'라는 문제를 해결하지 못한다.

2.2.2. 비대칭키 방식

대칭키 방식이 갖고 있는 문제를 해결하기 위해 등장한 방식이 비대칭키 방식이다. 비대칭키는 공개키(Public Key)와 개인키라(Private Key)는 두 개의 키를 사용한다. 공개키는 누구에게나 공개할 수 있고, 개인키는 소유자만 가지고 있는다. 중요한 특징은 공개키로 암호화된 데이터는 반드시 해당하는 개인키로만 복호화할 수 있다는 점이다. 이 구조 덕분에 키를 직접 전달하지 않고도 안전한 통신을 시작할 수 있다. 예를 들어 서버는 자신의 공개키를 클라이언트에게 전달하고, 클라이언트는 이 공개키를 이용해 데이터를 암호화해서 보낸다. 이 데이터는 오직 서버가 가진 개인키로만 복호화할 수 있기 때문에, 중간에서 누군가 데이터를 가로채더라도 내용을 해석할 수 없다. 이 방식은 키 교환 문제를 해결해준다는 점에서 매우 중요한 역할을 한다.

하지만 비대칭키 방식 역시 단점이 있다. 연산 과정이 복잡하기 때문에 처리 속도가 느리고, 대용량 데이터를 지속적으로 처리하기에는 비효율적이다. 즉, 안전하게 시작할 수는 있지만, 계속해서 이 방식으로 통신하기에는 부담이 크다.

2.2.3. 대칭키와 비대칭키 결합

HTTPS는 바로 이 두 방식의 장단점을 결합한다. 처음 연결을 설정할 때는 비대칭키 방식을 사용하여 안전하게 키를 교환한다. 이 과정에서 실제 통신에 사용할 대칭키가 생성되고, 이 키는 비대칭키를 이용해 안전하게 전달된다. 이후 실제 데이터 통신에서는 이 대칭키를 사용하여 빠르게 암호화와 복호화를 수행한다.

sequenceDiagram
    participant Client as 브라우저
    participant Server as 서버

    Client->>Server: 공개키 요청
    Server-->>Client: 공개키 전달

    Client->>Server: 대칭키 전달 (공개키로 암호화)
    Server-->>Client: 대칭키 설정 완료

    Note over Client,Server: 이후 대칭키로 빠르게 암호화 통신

이 구조를 보면 HTTPS의 암호화는 단순히 데이터를 숨긴다는 개념이 아니라, 처음에는 안전하게 연결을 만들고, 이후에는 효율적으로 데이터를 주고받는 방식이라고 이해하는 것이 더 정확하다. 결국 HTTPS는 하나의 암호화 기술이 아니라, 여러 방식을 조합해서 만든 설계라고 볼 수 있다.

2.3. HTTPS 연결 과정

HTTPS 통신은 단순히 요청을 보내는 것으로 시작되지 않는다. 우리가 브라우저에서 어떤 주소를 입력했을 때, 바로 HTTP 요청이 전송되는 것이 아니라 그 전에 반드시 두 단계의 준비 과정이 선행된다. 이 과정을 이해하지 못하면 HTTPS를 단순히 “암호화된 HTTP” 정도로만 이해하게 되지만, 실제로는 훨씬 더 복잡한 흐름을 가지고 있다.

먼저 브라우저는 서버와 데이터를 주고받기 위해 기본적인 통신 경로를 만들어야 한다. 이때 사용되는 것이 TCP이며, 이 연결을 생성하는 과정이 바로 3-Way Handshake이다. 이 과정은 단순히 연결을 만든다는 의미를 넘어서, 클라이언트와 서버가 서로 통신이 가능한 상태인지 확인하는 단계라고 볼 수 있다.

2.3.1. 3-Way Handshake

TCP 연결은 세 번의 메시지 교환을 통해 이루어진다.

클라이언트가 먼저 서버에게 연결을 요청하고, 서버가 이를 수락한 뒤, 마지막으로 클라이언트가 확인 응답을 보내면서 연결이 완성된다. 이 과정을 통해 양쪽 모두 이제 데이터를 주고받을 준비가 되었다는 상태가 된다.

sequenceDiagram
    participant Client as 브라우저
    participant Server as 서버

    Client->>Server: SYN (연결 요청)
    Server-->>Client: SYN + ACK (요청 수락)
    Client->>Server: ACK (확인)

    Note over Client,Server: TCP 연결 완료

이 단계까지는 HTTPS가 아니라, 단순히 통신을 위한 길을 만든 것에 가깝다. 아직 데이터는 암호화되지 않았고, HTTP 요청도 보내지지 않았다. 즉, 이제 막 대화를 시작할 수 있는 상태가 된 것이다.

2.3.2 TLS Handshake

TCP 연결이 완료되면, 그 다음 단계로 TLS Handshake가 진행된다. 이 과정이 바로 HTTPS에서 핵심적인 부분이다. 이 단계에서는 단순히 연결을 만드는 것이 아니라, 이 연결을 안전하게 만들기 위한 준비가 이루어진다.

sequenceDiagram
    participant Client as 브라우저
    participant Server as 서버

    Client->>Server: TLS 연결 요청
    Server-->>Client: 인증서 + 공개키 전달

    Client->>Client: 인증서 검증
    Client->>Server: 대칭키 전달 (공개키로 암호화)

    Server-->>Client: 설정 완료

    Note over Client,Server: 이후 통신은 대칭키 기반 암호화

먼저 서버는 자신의 인증서를 클라이언트에게 전달한다. 이 인증서에는 서버의 공개키와 도메인 정보가 포함되어 있으며, 클라이언트는 이 정보를 바탕으로 서버가 실제로 신뢰할 수 있는 대상인지 검증한다. 이 과정은 단순히 데이터를 확인하는 것이 아니라, 현재 접속한 서버가 진짜인지, 혹은 중간에서 누군가 위장하고 있는 것은 아닌지를 판단하는 단계이다. 검증이 완료되면, 클라이언트는 이후 통신에 사용할 대칭키를 생성하고, 이를 서버에게 전달한다. 이때 앞서 설명한 비대칭키 방식이 사용된다. 서버가 전달한 공개키로 대칭키를 암호화해서 보내고, 서버는 자신의 개인키로 이를 복호화한다. 이 과정을 통해 양쪽은 동일한 대칭키를 안전하게 공유하게 된다. 이 단계가 끝나면 비로소 HTTPS 통신을 위한 준비가 완료된다. 그 이후에야 우리가 흔히 알고 있는 HTTP 요청과 응답이 오가게 되는데, 이때의 데이터는 모두 암호화된 상태로 전달된다.

이 전체 과정을 하나의 흐름으로 보면 다음과 같이 이해할 수 있다.

sequenceDiagram
    participant Client as 브라우저
    participant Server as 서버

    Client->>Server: TCP 연결 (3-Way Handshake)
    Server-->>Client: 연결 완료

    Client->>Server: TLS Handshake 시작
    Server-->>Client: 인증서 전달
    Client->>Server: 키 교환

    Client->>Server: HTTPS 요청 (암호화)
    Server-->>Client: HTTPS 응답 (암호화)

이 구조에서 중요한 점은 HTTPS가 단순히 HTTP 요청을 암호화하는 것이 아니라, 그 이전 단계에서 통신 자체를 안전하게 만들기 위한 준비 과정을 반드시 거친다는 것이다. 즉, 우리가 사용하는 HTTPS는 암호화된 HTTP라기보다, 안전한 연결 위에서 동작하는 HTTP라고 이해하는 것이 더 정확하다.

2.4 SSL/TLS란?

앞에서 HTTPS 연결 과정에서 TLS Handshake가 등장했는데, 여기서 자연스럽게 이런 질문이 생긴다. 결국 TLS는 정확히 무엇을 하는 프로토콜일까. 단순히 암호화한다라는 설명만으로는 이 역할을 충분히 이해하기 어렵다. SSL과 TLS는 클라이언트와 서버 사이의 통신을 보호하기 위한 보안 프로토콜이다. 과거에는 SSL(Secure Sockets Layer)이 사용되었지만, 여러 보안 취약점이 발견되면서 이를 개선한 TLS(Transport Layer Security)가 등장했고, 현재는 TLS가 표준으로 사용된다. 실무에서는 여전히 SSL이라는 용어가 관습적으로 사용되기도 하지만, 실제로 HTTPS 통신에서 동작하는 것은 TLS라고 이해하는 것이 맞다. 이 프로토콜의 역할을 단순히 '데이터를 암호화한다'라고만 보면 중요한 부분을 놓치게 된다. TLS는 단순히 내용을 숨기는 것을 넘어서, 통신 과정에서 반드시 해결해야 하는 세 가지 문제를 동시에 처리한다.

  • 기밀성: 네트워크를 통해 전달되는 데이터는 여러 경로를 거치기 때문에, 중간에서 누군가 내용을 볼 수 있는 가능성이 존재한다. TLS는 데이터를 암호화하여 이러한 상황에서도 내용을 해석할 수 없도록 만든다.
  • 무결성: 데이터가 전달되는 과정에서 누군가 내용을 수정하거나 손상시킬 수 있는데, TLS는 이를 감지할 수 있는 구조를 포함하고 있다. 즉, 수신 측에서는 데이터가 중간에서 변경되지 않았다는 것을 확인할 수 있다.
  • 인증: 클라이언트는 자신이 접속한 서버가 진짜 서버인지 확인해야 한다. 만약 이 과정이 없다면, 공격자가 가짜 서버를 만들어 사용자를 속이는 것도 가능해진다. TLS는 인증서를 기반으로 서버의 신원을 검증하는 과정을 포함하고 있다.

이 세 가지를 함께 보면 TLS는 단순한 암호화 도구가 아니라, 통신 자체를 신뢰할 수 있게 만드는 프로토콜이라고 볼 수 있다. 앞에서 살펴본 TLS Handshake 과정도 결국 이 역할을 수행하기 위한 준비 단계이다. 인증서를 통해 서버를 검증하고, 안전하게 키를 교환한 뒤, 이후 통신에서는 암호화를 통해 데이터를 보호한다. 즉, Handshake는 TLS의 기능을 실제로 적용하기 위한 초기 설정 과정이라고 이해할 수 있다. 이 구조를 전체적으로 보면 HTTPS는 단순히 HTTP를 암호화한 것이 아니라, HTTP 위에 TLS를 얹어서 통신 자체를 보호하는 형태라고 볼 수 있다. HTTP가 어떤 데이터를 주고받을 것인가를 정의한다면, TLS는 그 데이터를 어떻게 안전하게 전달할 것인가를 담당한다. 이 두 계층이 결합되면서 현재 우리가 사용하는 안전한 웹 통신 구조가 만들어진다.

2.5 CA 인증서와 인증 과정

앞에서 TLS Handshake 과정에서 서버가 인증서를 전달한다고 했는데, 여기서 한 가지 중요한 질문이 생긴다. 서버가 '나는 이 도메인의 주인이 맞다'라고 주장한다고 해서 클라이언트는 그 말을 그대로 믿어도 되는 걸까? 만약 아무 검증 없이 이를 신뢰한다면, 공격자가 가짜 서버를 만들어 동일한 방식으로 응답하는 것도 충분히 가능해진다. 이 문제를 해결하기 위해 등장한 개념이 바로 CA(Certificate Authority)와 인증서이다. HTTPS에서 인증서는 단순히 공개키를 담고 있는 파일이 아니라, 이 서버가 실제로 해당 도메인의 소유자라는 것을 제3자가 보증한 증명서라고 보는 것이 더 정확하다.

CA는 이러한 보증을 담당하는 신뢰 기관이다. 서버 운영자는 자신의 도메인에 대한 소유권을 증명하고, CA는 이를 검증한 뒤 인증서를 발급한다. 이 인증서에는 서버의 공개키와 도메인 정보, 그리고 이를 발급한 CA의 정보가 포함된다. 중요한 점은 이 인증서가 CA의 개인키로 서명되어 있다는 것이다. 이 서명을 통해 인증서의 위변조 여부를 확인할 수 있게 된다. 이제 클라이언트가 실제로 서버에 접속하는 상황을 생각해보자. TLS Handshake 과정에서 서버는 자신의 인증서를 클라이언트에게 전달한다. 클라이언트는 이 인증서를 단순히 받아들이는 것이 아니라, 여러 단계를 거쳐 검증을 수행한다.

sequenceDiagram
    participant Client as 브라우저
    participant Server as 서버
    participant CA as 인증기관

    Server-->>Client: 인증서 전달
    Client->>CA: 인증서 서명 검증 (내장된 CA 목록 사용)
    Client->>Client: 도메인, 유효기간 확인
    Client->>Server: 신뢰 여부 결정

먼저 이 인증서가 신뢰할 수 있는 CA에 의해 발급된 것인지 확인한다. 브라우저나 운영체제는 기본적으로 여러 CA의 공개키를 미리 가지고 있기 때문에, 인증서에 포함된 서명을 검증할 수 있다. 이를 통해 해당 인증서가 위조되지 않았는지를 판단한다. 다음으로 인증서에 포함된 도메인이 현재 접속하려는 주소와 일치하는지 확인한다. 예를 들어 choewy.github.io에 접속했는데 인증서에는 다른 도메인이 적혀 있다면, 이는 신뢰할 수 없는 연결로 판단된다. 마지막으로 인증서의 유효 기간이 지나지 않았는지도 검사한다. 이 검증이 모두 통과되면, 클라이언트는 현재 연결된 서버를 신뢰할 수 있는 대상으로 판단하고 이후 통신을 계속 진행한다. 반대로 이 과정 중 하나라도 실패하면 브라우저는 경고를 표시하거나 연결을 차단한다.

이 구조의 핵심은 신뢰를 직접 확인하지 않고, 신뢰할 수 있는 제3자를 통해 검증한다는 점이다. 클라이언트는 서버를 직접 알지 못하지만, 이미 신뢰하고 있는 CA를 통해 간접적으로 서버를 신뢰하게 된다. 만약 이 과정이 없다면, 공격자가 가짜 서버를 만들어도 이를 구분할 방법이 없어지고, HTTPS의 보안 모델 자체가 무너진다. 결국 HTTPS에서 인증서는 단순한 데이터가 아니라, 통신의 출발점에서 신뢰를 형성하는 가장 중요한 요소라고 볼 수 있다.

2.6 HTTPS 성능과 오해

HTTPS에 대해 이야기할 때 빠지지 않는 이야기가 하나 있다. 'HTTPS는 HTTP보다 느리다'는 인식이다. 이 말은 완전히 틀린 말은 아니지만, 현재 기준에서는 거의 맞지 않는 이야기라고 보는 것이 더 정확하다. 이 인식이 왜 생겼는지부터 이해해보는 것이 중요하다.

과거에는 실제로 HTTPS가 HTTP보다 느린 것이 맞았다. 이유는 구조적으로 추가되는 과정이 있었기 때문이다. 먼저 TCP 연결 이후에 TLS Handshake 과정이 한 번 더 필요했고, 이 과정에서 인증서를 주고받고 키를 교환하는 단계가 추가되었다. 즉, 단순히 요청을 보내기 전에 한 번 더 준비 과정이 들어가기 때문에 초기 연결 시간이 늘어날 수밖에 없었다. 여기에 더해 데이터 자체를 암호화하고 복호화하는 연산도 필요했기 때문에, CPU 부담 역시 증가했다. 특히 서버 성능이 지금보다 좋지 않았던 시기에는 이 비용이 꽤 크게 체감될 수 있었다.

하지만 현재는 상황이 많이 달라졌다. 먼저 하드웨어 성능이 크게 향상되면서 암호화 연산 자체가 큰 부담이 되지 않게 되었다. 또한 TLS 프로토콜 자체도 지속적으로 개선되면서 Handshake 과정이 최적화되었고, 불필요한 왕복 횟수를 줄이는 방향으로 발전해왔다. 예를 들어 한 번 연결했던 서버와 다시 통신할 때는 이전 세션 정보를 활용하여 Handshake 과정을 줄이는 방식도 사용된다. 여기에 더해 HTTP/2와 같은 기술이 도입되면서 전체적인 통신 효율은 오히려 더 좋아진 경우도 많다. 하나의 연결로 여러 요청을 동시에 처리할 수 있고, 헤더 압축이나 서버 푸시 같은 기능을 통해 네트워크 사용 효율이 개선되었다. 이런 변화들은 HTTPS 환경에서 함께 사용되면서 단순히 암호화 비용 이상의 성능 개선을 만들어냈다.

결국 지금 시점에서 중요한 것은 단순한 속도 비교가 아니다. 보안 위협은 계속 증가하고 있고, 네트워크 상에서 데이터가 노출되거나 변조될 가능성은 현실적인 문제로 존재한다. 이런 상황에서 HTTPS를 사용하지 않는 것은 성능 문제가 아니라 보안 리스크를 그대로 방치하는 것에 가깝다. 이러한 흐름을 반영하듯, 현재 대부분의 브라우저는 HTTP로 제공되는 사이트에 대해 '안전하지 않음'이라는 경고를 표시하고 있다. 또한 주요 서비스들은 기본적으로 HTTPS를 사용하도록 강제하고 있으며, 검색 엔진 역시 HTTPS를 사용하는 사이트를 더 신뢰하는 방향으로 정책을 운영하고 있다. 이제 HTTPS는 선택적으로 적용하는 기능이 아니라, 웹 서비스를 구성할 때 가장 기본적으로 고려해야 하는 요소가 되었다고 보는 것이 자연스럽다.

마치며

HTTP와 HTTPS를 처음 접했을 때는 단순히 “암호화 여부의 차이” 정도로만 이해했던 기억이 있다. 하지만 실제로 흐름을 따라가면서 정리해보니, 단순한 차이 이상의 구조적인 설계가 들어가 있다는 것을 느끼게 되었다. 특히 HTTP가 TCP 위에서 어떻게 동작하는지, 그리고 HTTPS에서는 그 사이에 TLS라는 계층이 어떻게 끼어들어 통신을 보호하는지를 이해하고 나니, 단순한 요청과 응답 뒤에 어떤 과정이 숨어 있는지 조금 더 명확하게 보이기 시작했다.

처음에는 대칭키, 비대칭키 같은 개념도 각각 따로 떨어져 있는 기술처럼 느껴졌는데, 실제로는 '키를 어떻게 안전하게 공유할 것인가?'라는 하나의 문제를 해결하기 위해 함께 사용된다는 점이 인상적이었다. 또한 인증서를 통해 서버의 신뢰를 검증하는 구조를 보면서, 네트워크 통신에서 ‘보안’이라는 것이 단순히 데이터를 숨기는 것이 아니라, 통신 자체를 믿을 수 있게 만드는 과정이라는 것도 다시 한 번 정리할 수 있었다.

이번 글을 정리하면서 느낀 점은, 네트워크를 이해할 때 결과만 보는 것이 아니라 그 사이의 과정을 따라가야 한다는 것이다. 브라우저에서 요청 하나를 보내는 단순한 행동 뒤에도 TCP 연결, TLS Handshake, 인증서 검증 같은 여러 단계가 존재하고, 이 각각이 역할을 나누어 동작하고 있다는 점이 꽤 흥미롭게 느껴졌다. 다음 글에서는 HTTP와는 다른 방식으로 통신이 이루어지는 WebSocket에 대해 정리해보려고 한다. 요청과 응답 구조가 아닌, 연결을 유지하면서 데이터를 주고받는 방식이라는 점에서 HTTP와 비교해보면 이해가 더 잘 될 것이라고 생각한다.