[네트워크] 요청을 보내면 서버는 어떻게 응답할까?

한강섭·2025년 11월 25일

네트워크

목록 보기
8/8
post-thumbnail

썸네일 출처

필수 학습 목표

  • HTTP 요청/응답 구조 (Method, Header, Body) 이해
  • HTTP 상태 코드: 2xx, 3xx, 4xx, 5xx 이해
  • HTTPS: SSL/TLS를 통한 보안 연결 이해
  • HTTP/2, HTTP/3 차이점 및 효율성

선택적 학습 목표

  • 웹 보안: SSL/TLS 핸드셰이크, 인증서 관리
  • HSTS (HTTP Strict Transport Security)


HTTP 요청

Request Line + Headers + Body


Request Line (요청 라인)

GET /api/users HTTP/1.1

요청이 어디로 어떤 방식으로 갈 지를 정해준다.

HTTP Methods (GET, POST, DELETE, FETCH, PUT) 중 GET 요청을 할 것이다.
/api/users 로 가세요.
HTTP/1.1 버전의 프로토콜로 가겠습니다.

Headers (헤더)

Host: example.com // 요청을 보낼 서버의 도메인 이름 (or IP 주소)
Content-Type: application/json // json 형식으로 보내겠음
Authorization: Bearer token123 // JWT 토큰 인증 방식이라면 여기에 token을 담는다. 
User-Agent: Mozilla/5.0 // 클라이언트의 정보, 브라우저 호환성 체크 용도로 사용
Accept: application/json // 받고 싶은 형식, json으로 응답해주삼~~

Body (본문)

선택적으로 Body를 넣어서 보낼 수 있다. 실제 요청 데이터!

{
  "id": 1,
  "username": "john",
  "email": "john@example.com"
}

HTTP 응답

Status Line + Headers + Body


Status Line (상태 라인)

HTTP/1.1 200 OK

Headers (헤더)

Content-Type: application/json
Content-Length: 348
Set-Cookie: sessionId=abc123
Cache-Control: no-cache

Body (본문)

{
  "id": 1,
  "username": "john",
  "email": "john@example.com"
}

주요 상태 코드

2xx (성공): 200 OK, 201 Created, 204 No Content
3xx (리다이렉션): 301 Moved Permanently, 302 Found
4xx (클라이언트 오류): 400 Bad Request, 401 Unauthorized, 404 Not Found
5xx (서버 오류): 500 Internal Server Error, 503 Service Unavailable


HTTPS : SSL/TLS를 통한 보안 연결

HTTP + Secure = HTTPS


HTTPS 란 HTTP 에 SSL/TLS 암호화 계층을 추가한 프로토콜이다. 기본 포트는 443을 사용한다.

SSL : Secure Socket Layer 으로 초기 보안 프로토콜이다.
TLS : Transport Layer Security 로 SSL의 후속버전이고 현재 표준이다.

TLS Handshake

HTTPS가 통신할때도 악수 과정을 거친다.

Client Hello : 클라이언트가 서버에 연결 시도, 지원하는 TLS 버전, 암호화 방식 목록 전송
Server Hello : 서버가 사용할 TLS 버전과 암호화 방식 선택 서버의 SSL 인증서 전송
인증서 검증 : 클라이언트가 인증서의 유효성 확인, CA를 통해 신뢰할 수 있는 인증서인지 검증
세션 키 생성 : 클라이언트가 대칭키(세션 키)를 생성
암호화 통신 시작 : 이후 모든 데이터는 세션 키로 암호화되어 전송된다.

이런 방식을 통해 진행하여

암호화, 무결성, 인증이 보장된 통신이 가능해진다!

HTTP/2

HTTP/1.1 의 한계를 극복


HTTP/1.1 에서는 한 번에 하나의 요청만 처리할 수 있어서 여러 리소스를 받으려면 여러 TCP 연결을 맺어야 했다. 이를 HOL(Head Of Line) Blocking 문제라고 한다.

이 문제를 해결하기 위해 멀티플렉싱, 헤더 압축, 서버 푸시, 바이너리 프레임을 통해 업그레이드 한 것이 HTTP/2 이다.

멀티플렉싱: 하나의 TCP 연결에서 여러 요청과 응답을 동시에 처리할 수 있다. 스트림 단위로 데이터를 나눠서 보내기 때문에 하나의 요청이 느려도 다른 요청에 영향을 주지 않는다.

헤더 압축: HTTP/1.1에서는 매 요청마다 비슷한 헤더를 반복해서 보냈지만, HTTP/2는 HPACK 압호화를 사용해서 중복되는 헤더를 압축하고, 이전에 보낸 헤더 정보를 재사용 한다.

서버 푸시: 클라이언트가 요청하지 않아도 서버가 필요할 것 같은 리소스를 미리 보낼 수 있다. HTML을 요청하면 서버가 필요한 CSS, JS 파일을 함께 푸시하는 방식이다.

바이너리 프레임: HTTP/1.1은 텍스트 기반 프로토콜이었지만, HTTP/2는 바이너리 형식으로 데이터를 전송한다. 파싱 속도가 빠르고 오류가 적다.

HTTP/3

근본 프로토콜의 변화


하지만 여전히 TCP 기반이라 TCP 자체의 HOL Blocking 문제가 남아있다. 하나의 패킷이 손실되면 그 뒤의 모든 패킷이 대기해야 하는 구조인 것이다.

그래서 UDP 기반의 QUIC(Quick UDP Internet Connections) 프로토콜을 사용한다.
UDP에 신뢰성과 보안 기능을 추가한 프로토콜이다.

독립적인 스트림: 각 스트림이 독립적으로 동작해서 한 스트림에서 패킷 손실이 발생해도 다른 스트림에는 영향을 주지 않는다. TCP 레벨의 HOL Blocking이 완전히 해결된다.

빠른 연결: TCP는 3-way handshake로 연결을 맺고, 그 위에 TLS handshake를 또 해야한다. 하지만 QUIC는 연결과 암호화를 하나의 핸드셰이크로 처리해서 지연 시간이 크게 줄어든다.

연결 마이그레이션: 모바일 환경에서 WIFI에서 LTE로 전환되면 IP가 바뀌면서 TCP 연결이 끊어진다. 하지만 QUIC는 Connection ID로 연결을 식별해서 네트워크가 바뀌어도 연결이 유지된다.

SSL/TLS 핸드셰이크와 인증서

웹 사이트 신원 증명


TLS는 Transport Layer Security의 약자로, 네트워크 통신을 암호화하는 프로토콜이다. 과거에는 SSL(Secure Sockets Layer)가 사용되었지만, 보안 취약점으로 인해 완전히 폐기되었고 현재는 TLS 1.2, 1.3만 사용된다.

TLS 가 핸드셰이크 할 때 클라이언트가 먼저 Client Hello를 통해 먼저 TLS 버전과 암호화 방식 목록을 전송한다. 난수값도 함께 보내는데, 나중에 세션 키를 생성할 때 사용한다.

그 후 서버가 Server Hello를 통해 클라이언트가 제시한 목록 중에서 사용할 TLS 버전과 암호화 방식을 선택한다. 그리고 서버의 TLS 인증서를 클라이언트에게 전송한다.

클라이언트는 받은 TLS 인증서의 유효성을 확인한다. 인증서가 신뢰할 수 있는 CA(Certificate Authority)에서 발급되었는지, 도메인이 일치하는 지, 유효 기간이 지나지 않았는지 검증한다.

검증이 되었다면, 대칭키(세션 키)를 생성한다. 이 키를 공개키로 암호화해서 서버에 전송한다. 서버는 자신의 개인키로 복호화해서 세션 키를 얻는다. 이제 클라이언트와 서버 둘 다 같은 세션 키를 얻게된다.

이후 모든 데이터는 세션 키로 암호화되어 전송된다. 대칭키 암호화는 공개키 암호화 보다 훨씬 빨라서 성능도 훨씬 좋다.

그렇게 이 handshake를 거친 후에 하는 통신은 모두 암호화, 무결성, 인증을 보장하는 통신이 된다.

캠퍼스 페이 프로젝트에서는 Let's Encrypt 인증서를 통해서 발급을 받았고, certbot 도구를 사용해서 인증서를 갱신하였다.

Corazy Arcade 에서는 Kubernetes 환경이라서 cert-manager를 통해 인증서 라이프사이클을 관리하였다. Ingress 리소스에 어노테이션을 추가하여 cert-manager가 자동으로 Let's Encrypt에서 인증서를 발급받고, 만료 전에 갱신한다. Secret으로 저장되어 Pod에 자동으로 마운트 된다.

HSTS (HTTP Strict Transport Security)

HTTP 절대 금지


나는 이전에 HTTP 요청에 들어오면 Nginx에서 HTTPS로 리다이렉트해서 보안에 신경쓴 줄 알았는데, 이는 중간자 공격에 취약한 구조였다.

HSTS를 설정하면 브라우저가 자동으로 HTTPS로 변환해서 요청을 하기 때문에 이런 공격을 방지할 수 있다.

HSTS Preload List에 등록하면 사용자가 처음 방문할 때부터 HTTPS를 사용한다. 주요 브라우저들이 공유하는 리스트이고, hstspreload.org에서 등록할 수 있다.

하지만 만약 인증서 문제가 발생하면 사용자가 사이트에 완전히 접근할 수 없게 되므로 인증서 관리가 굉장히 중요해진다.

profile
기록하고 공유하는 개발자

0개의 댓글