URL 입력부터 응답까지 — OSI 계층으로 이해하는 웹 통신
브라우저의 HTTPS 요청을 DNS·TCP·TLS·HTTP 순서로 따라가며 OSI 계층의 역할을 살펴봅니다. HTTP/3와 연결 재사용에 따른 차이를 구분하고, 개발자 도구와 오류 메시지로 지연·장애의 확인 범위를 좁히는 방법을 정리합니다.
들어가며
프론트엔드에서 요청이 느리거나 실패하면 먼저 개발자 도구의 Network 탭을 열게 된다. 같은 로딩 지연처럼 보여도 주소를 찾는 데 시간이 걸리는지, 연결을 만드는 중인지, 서버의 응답을 기다리는지에 따라 확인할 곳이 달라진다.
브라우저에 URL을 입력했을 때의 흐름을 다시 정리해보고 싶은 이유도 여기에 있다. DNS·TCP·TLS·HTTP라는 이름을 순서대로 외우는 데서 더 나아가, 각 단계가 담당하는 일과 문제가 생겼을 때 확인할 단서를 연결해보려 한다.
이번 글에서는 https://example.com/에 접속하면서 새 TCP 연결과 TLS 1.3 연결을 만들고 HTTP/2 요청을 보내는 경우를 기준으로 삼는다. 브라우저 캐시나 Service Worker에서 응답하는 경우, 기존 연결을 재사용하는 경우, HTTP/3를 사용하는 경우에는 일부 단계가 생략되거나 달라진다. 화면 렌더링은 범위에서 제외하고, 요청과 응답의 통신 과정에 집중한다.
1. OSI 모델을 실제 웹 통신과 연결하기
OSI(Open Systems Interconnection)는 통신 기능을 7개 계층으로 구분한 참조 모델이다. 계층을 나누면 응용 프로그램이 주고받는 메시지, 데이터를 전달하는 방식, 실제 신호 전송을 구분해 볼 수 있다. ITU-T X.200 — OSI 기본 참조 모델
| 계층 | 이름 | 구분해서 볼 역할 |
|---|---|---|
| L7 | 응용(Application) | HTTP·DNS처럼 응용 프로그램이 사용하는 통신 규칙 |
| L6 | 표현(Presentation) | 데이터 표현 형식과 변환 |
| L5 | 세션(Session) | 통신 당사자 사이의 대화 제어와 동기화 |
| L4 | 전송(Transport) | 종단 간 데이터 전달. TCP·UDP에 따라 제공 기능이 다름 |
| L3 | 네트워크(Network) | IP 주소와 네트워크 사이의 패킷 전달 |
| L2 | 데이터링크(Data Link) | Ethernet 등 링크 내부의 프레임 전달 |
| L1 | 물리(Physical) | 전기·광·전파 신호를 통한 비트 전송 |
다만 실제 인터넷 프로토콜이 이 표의 각 칸에 하나씩 대응하는 것은 아니다. 인터넷 프로토콜을 설명할 때는 응용·전송·인터넷·링크의 TCP/IP 계층 구분도 사용한다. RFC 1122 — 인터넷 프로토콜 계층
예를 들어 TLS의 암호화는 OSI의 표현 계층 역할과 연결해 설명할 수 있지만, 여기서 다룰 HTTPS 구현에서는 HTTP와 TCP 사이에 놓인다. HTTP/2의 스트림 관리 역시 HTTP/2 자체의 기능이다. 이를 별도의 OSI 세션 계층 프로토콜로 분류할 필요는 없다.
그래서 이 글에서는 실제 프로토콜의 흐름을 먼저 살펴보고, OSI 계층은 각 기능의 역할을 구분하는 기준으로 사용하려 한다.
캡슐화는 데이터를 다른 단위로 감싸는 과정
HTTP/2 데이터를 TLS로 보호한 뒤 TCP·IP·Ethernet으로 전송하는 구성을 단순화하면 다음과 같다.
HTTP/2 프레임
↓ TLS 레코드로 보호
암호화된 TLS 데이터
↓ TCP 바이트 스트림을 세그먼트로 전송
[TCP 헤더][TCP 페이로드]
↓ IP 패킷에 포함
[IP 헤더][TCP 세그먼트]
↓ Ethernet 링크에서 전달
[Ethernet 헤더][IP 패킷][FCS]
↓
전기·광 등의 신호
이런 식으로 상위 데이터를 하위 프로토콜의 전송 단위에 담는 것을 캡슐화라고 한다. 수신 측은 각 프로토콜을 처리하며 응용 데이터까지 복원한다. 모든 OSI 계층이 반드시 헤더 하나씩을 붙이는 구조는 아니다.
또한 HTTP/2 프레임 하나가 TLS 레코드 하나나 TCP 세그먼트 하나에 정확히 대응하지는 않는다. TCP는 바이트 스트림을 제공하므로, 애플리케이션 메시지의 경계와 실제 전송 단위의 경계를 구분해야 한다. RFC 9293 — TCP
2. URL을 해석하고 접속할 주소 찾기
네트워크 요청 전에도 처리할 일이 있다
주소창의 문자열을 URL로 볼지 검색어로 볼지는 브라우저의 판단과 설정에 따라 달라진다. 여기서는 입력이 https://example.com/이라는 URL로 해석된 이후부터 살펴본다.
브라우저는 스킴·호스트·포트·경로를 구분한다. 국제화 도메인은 IDNA 처리 과정에서 ASCII 호스트 표현으로 변환될 수 있다. 예를 들어 한국.kr의 ASCII 표현은 xn--3e0b707e.kr이다. 이런 변환은 URL 처리의 일부이며, 독립된 L6 통신 단계가 추가된다는 뜻은 아니다. WHATWG — URL과 IDNA
HTTP 주소를 입력했더라도, 이전 HTTPS 응답에서 저장한 HSTS 정책이나 preload 목록에 따라 요청 전에 HTTPS로 바뀔 수 있다. HSTS가 적용된 경우에는 해당 HTTP 요청을 먼저 보내고 리다이렉트를 받는 과정이 생략된다. MDN — Strict-Transport-Security
DNS 캐시는 고정된 일렬 구조가 아니다
연결에 사용할 주소를 아직 모른다면 이름 해석이 필요하다. 브라우저나 OS의 캐시, 로컬 이름 해석 설정, 재귀 리졸버의 캐시 등이 관여할 수 있다. 하지만 모든 환경이 브라우저 → OS → 공유기 → ISP 순서를 거치는 것은 아니다. 브라우저의 보안 DNS 설정이나 기업 네트워크 구성에 따라 사용하는 리졸버도 달라진다.
hosts 파일은 로컬 이름 매핑이며 DNS 캐시와는 구분된다. DNS 레코드의 TTL은 캐시 유효 시간을 판단하는 기준이지만, 로컬 매핑까지 같은 방식으로 만료되는 것은 아니다.
리졸버가 필요한 정보를 조회하는 과정
클라이언트는 보통 재귀 리졸버에 최종 답을 요청한다. 리졸버는 캐시를 활용하고, 필요한 경우 다른 DNS 서버를 조회한다. 캐시에 위임 정보도 없다고 단순화하면 다음 흐름으로 볼 수 있다.
클라이언트 → 재귀 리졸버: example.com의 주소 요청
재귀 리졸버 → 루트 서버: 질의
← .com을 담당하는 서버 정보
→ .com 서버: 질의
← example.com의 권한 있는 서버 정보
→ example.com의 권한 있는 서버: 질의
← A 또는 AAAA 레코드 등 응답
클라이언트 ← 재귀 리졸버: 조회 결과
클라이언트가 재귀 리졸버에 답을 요청하는 것과, 리졸버가 위임을 따라 서버들을 반복적으로 조회하는 것은 구분해야 한다. 이미 필요한 답이나 위임 정보가 캐시에 있다면 루트부터 다시 조회하지 않는다. CNAME이 반환되면 그 이름의 해석을 이어갈 수도 있다. RFC 1034 — 이름 해석과 캐시
CDN을 사용하는 서비스에서는 접속 주소가 원본 애플리케이션 서버 대신 CDN의 주소일 수 있다. 이후 연결의 상대가 어디인지 파악해야 서버 응답과 장애도 올바른 구간에서 해석할 수 있다.
DNS도 하위 전송 방식이 필요하다
DNS는 응용 계층 프로토콜이며, 메시지를 전달하는 방식은 하나로 고정되어 있지 않다.
| 방식 | 전송 형태 | 구분할 점 |
|---|---|---|
| 일반 DNS | UDP 또는 TCP, 보통 53번 포트 | UDP만 사용하는 프로토콜은 아님 |
| DNS over TLS(DoT) | TLS over TCP, 기본 853번 포트 | DNS 통신을 TLS로 보호 |
| DNS over HTTPS(DoH) | HTTPS | HTTP를 통해 DNS 질의·응답을 전달 |
전통적인 DNS의 UDP 메시지 크기 제한은 512바이트였지만, EDNS(0)를 사용하면 더 큰 UDP 응답을 수신할 수 있음을 알릴 수 있다. 응답이 잘렸음을 나타내는 TC 플래그를 받으면 TCP로 다시 질의하는 방식 등이 사용된다. 따라서 512바이트를 넘으면 무조건 TCP로 전환된다고 설명하면 현재 동작을 충분히 반영하지 못한다. RFC 6891 — EDNS(0), RFC 7766 — DNS over TCP
DoH·DoT를 사용한다면 DNS 질의 자체에도 보안 연결이 필요하며, 이미 열린 연결을 재사용할 수도 있다. DNS 다음에 웹 서버와 TLS 연결을 만든다는 순서는 목적지 웹 서버와의 연결에 관한 설명이다. RFC 7858 — DoT, RFC 8484 — DoH
3. TCP 연결과 그 아래의 패킷 전달
접속 주소를 확보하고 기존 연결을 재사용하지 않는다면 새 연결을 만든다. 이번 예제의 HTTPS 기본 목적지 포트는 443이며, 클라이언트는 보통 OS가 선택한 임시 포트를 사용한다.
TCP 연결 수립
TCP는 전송 계층에서 순서 있는 바이트 스트림과 재전송 등을 제공한다. 일반적인 연결 수립 흐름은 다음과 같다. RFC 9293 — 연결 수립
클라이언트 서버
│ │
│ ── SYN seq=x ────────────> │
│ <── SYN-ACK seq=y ack=x+1 ─ │
│ ── ACK ack=y+1 ──────────> │
│ │
└──────── 연결 수립 완료
SYN과 SYN-ACK을 통해 초기 시퀀스 번호를 교환한다. 클라이언트는 마지막 ACK와 함께 다음 단계의 데이터를 보낼 수도 있다. 이 TCP 연결이 성립했다고 해서 HTTPS 서버의 신원까지 확인된 것은 아니다. 인증서 검증은 뒤의 TLS 단계에서 수행한다.
다음 링크로 전달할 때 필요한 정보
TCP 세그먼트도 IP 패킷과 링크 프레임에 실려 이동한다. 여기서 IP 주소와 MAC 주소의 역할을 구분해두면 도움이 된다.
| 구분 | 이 예제에서의 역할 |
|---|---|
| 목적지 IP | 패킷을 어느 호스트 쪽으로 전달할지 결정하는 데 사용 |
| 다음 홉의 링크 주소 | 현재 링크에서 프레임을 누구에게 전달할지 지정 |
IPv4 Ethernet 환경에서 목적지가 다른 네트워크에 있다면 보통 게이트웨이로 프레임을 보낸다. 필요한 MAC 주소가 이웃 캐시에 없을 때 ARP로 확인할 수 있다. 목적지가 같은 링크에 있다면 해당 호스트의 주소를 확인한다. IPv6에서는 ARP 대신 Neighbor Discovery를 사용한다. RFC 826 — ARP, RFC 4861 — IPv6 Neighbor Discovery
라우터를 통과해 다른 Ethernet 링크로 나갈 때는 그 링크에 맞는 프레임으로 전달된다. 반면 같은 링크의 스위치를 통과할 때마다 출발지·목적지 MAC 주소가 모두 바뀌는 것은 아니다. 인터넷의 모든 구간이 Ethernet인 것도 아니므로, 전체 경로를 MAC 주소의 연속으로만 표현하기는 어렵다.
IP 주소도 항상 유지된다고 단정할 수는 없다. NAT가 있으면 주소나 포트가 변환될 수 있고, 프록시가 새 연결을 만들면 그 연결에는 다른 종단 주소가 사용된다. RFC 3022 — NAT
IPv4의 TTL과 IPv6의 Hop Limit은 라우터를 거치며 줄어든다. 단편화 규칙은 IP 버전에 따라 다르며, IPv6 라우터는 패킷을 단편화하지 않는다. 패킷이 너무 크면 송신 측이 대응할 수 있도록 Packet Too Big 메시지를 반환한다. RFC 8200 — IPv6
이 과정은 웹 서버와의 TCP 연결에만 필요한 것이 아니다. 앞의 DNS 메시지를 네트워크로 보낼 때도 그 메시지에 맞는 링크·IP·전송 계층 처리가 이루어진다.
4. TLS로 서버를 확인하고 데이터를 보호하기
TCP 연결 위에서는 TLS를 통해 통신 상대를 인증하고 데이터를 보호한다. 아래는 서버 인증서를 사용하는 일반적인 TLS 1.3 전체 핸드셰이크를 간략화한 흐름이다. 클라이언트 인증과 추가 협상은 생략했다.
클라이언트 서버
│ │
│ ── ClientHello ────────────> │
│ key_share, SNI, ALPN │
│ │
│ <── ServerHello ──────────── │
│ key_share │
│ │
│ <── EncryptedExtensions ──── │ 여기서부터 암호화
│ Certificate │
│ CertificateVerify │
│ Finished │
│ │
│ [인증서·서명·Finished 검증]
│ │
│ ── Finished ───────────────> │
│ ── Application Data ───────> │ 보호된 HTTP 데이터
클라이언트는 인증서 체인과 접속 호스트명, 유효 기간 등을 확인한다. 키 교환 결과를 바탕으로 양쪽이 사용할 암호화 키를 도출하며, 대칭키 자체를 그대로 전송하는 과정은 아니다. TLS 1.3에서는 ServerHello 이후의 핸드셰이크 메시지도 암호화된다. RFC 8446 — TLS 1.3 핸드셰이크
SNI와 ALPN이 전달하는 정보
SNI는 클라이언트가 접속하려는 서버 이름을 전달하는 확장이다. 서버는 이를 인증서나 가상 호스트 선택 등에 사용할 수 있다. 일반적인 ClientHello의 SNI는 관찰 가능하지만, ECH(Encrypted Client Hello)가 협상되어 적용되면 실제 서버 이름을 포함한 내부 ClientHello를 암호화할 수 있다. 따라서 SNI가 항상 평문으로 노출된다고 볼 수는 없다. Cloudflare — ECH 동작
ALPN은 같은 연결에서 사용할 응용 프로토콜을 협상하는 데 사용한다. 이번 예제에서는 h2가 선택되었다고 가정한다. http/1.1이 선택되면 그에 맞는 HTTP 메시지 형식을 사용한다. RFC 9113 — HTTPS에서 HTTP/2 시작하기
연결 비용을 볼 때의 전제
추가 협상이나 재전송이 없는 새 TCP + TLS 1.3 연결에서는, 클라이언트가 일반 HTTP 요청을 보내기 전까지 대략 TCP 1 RTT와 TLS 1 RTT가 필요하다. RTT는 데이터가 상대에게 갔다가 돌아오는 왕복 시간이다.
가령 RTT를 100ms로 가정하면 두 단계에 약 200ms가 필요하다는 계산이다. 이는 측정 결과가 아니며, DNS 조회·서버 처리·HTTP 응답이 돌아오는 시간은 포함하지 않는다.
TLS 세션을 재개한다고 항상 0-RTT가 되는 것도 아니다. 0-RTT early data는 이전 연결에서 얻은 정보와 서버의 허용이 필요하며, 재전송 공격에 대한 제약을 고려해야 한다. 서버가 early data를 거절할 수도 있다. RFC 8446 — 0-RTT
HTTP/3에서는 연결 방식이 달라진다
HTTP/3는 TCP 대신 QUIC을 사용한다. QUIC은 UDP 위에서 동작하지만, 자체적으로 신뢰성 있는 스트림·손실 복구·혼잡 제어 등을 제공한다. TLS 1.3의 핸드셰이크를 사용해 보안을 통합하므로 TCP 연결 후 별도 TLS 연결을 만드는 위 흐름과 다르다. RFC 9000 — QUIC, RFC 9001 — QUIC과 TLS
일반적인 최초 연결은 1 RTT로 진행할 수 있고, 조건이 맞는 재연결에서는 0-RTT 데이터를 사용할 수 있다. 다만 Retry나 추가 협상, 패킷 손실에 따라 시간이 늘어날 수 있다. HTTP/3를 사용한다고 모든 요청의 연결 시간이 같은 값으로 줄어드는 것은 아니다.
5. HTTP 요청과 응답이 실제로 오가는 구간
HTTP/2의 헤더와 프레임
HTTP/2에서는 HTTP/1.1처럼 GET / HTTP/1.1이라는 텍스트 요청 줄을 전송하지 않는다. 아래는 설명을 위해 풀어 쓴 헤더 목록이며, 실제 전송 바이트 형식은 아니다.
:method: GET
:scheme: https
:authority: example.com
:path: /
accept: text/html
accept-encoding: gzip, br
메서드·경로 등의 정보는 의사 헤더로 표현되며, 헤더 블록에는 HPACK 압축이 적용된다. 헤더와 본문은 HTTP/2 프레임으로 전달되고 스트림으로 구분된다. TLS를 사용하는 이 연결에서는 프레임이 TLS로 보호된 뒤 TCP를 통해 전달된다. RFC 9113 — HTTP/2 메시지
Accept-Encoding은 클라이언트가 수신할 수 있는 콘텐츠 인코딩을 알린다. 서버가 응답 본문에 Brotli를 적용했다면 Content-Encoding: br로 표시한다. 이는 TLS 암호화나 HTTP/2 헤더 압축과는 별개의 처리이며, Accept-Encoding을 보낸다고 요청 본문이 자동 압축되지는 않는다. RFC 9110 — Accept-Encoding
HTTPS는 경로·쿼리·헤더·본문을 TLS 연결 구간에서 보호한다. 그러나 IP 주소, 패킷 크기와 전송 시점 등의 메타데이터까지 모두 숨기지는 않는다. TLS를 종료하는 CDN이나 프록시는 복호화된 HTTP 내용을 처리할 수 있다.
브라우저가 연결한 서버와 원본 서버 구분하기
서비스 구성에 따라 요청은 여러 중간 지점을 거칠 수 있다. 아래는 가능한 구성의 한 예다.
[브라우저]
│ HTTPS 연결 A
↓
[CDN / 리버스 프록시: TLS 종료]
├─ 유효한 캐시가 있으면 여기서 응답
│ 별도의 연결 B
↓
[원본 서버 또는 로드밸런서]
↓
[애플리케이션] → [데이터베이스 등]
TLS 종료 지점에서는 데이터를 복호화하고 HTTP 요청을 해석한다. 원본으로 전달할 때는 별도의 연결을 사용할 수 있으며, 브라우저와 CDN 사이에서 사용한 HTTP 버전이 원본 연결에서도 같을 필요는 없다.
로드밸런서도 모두 L7에서 HTTP를 해석하는 것은 아니다. 주소와 포트를 기준으로 전달하는 L4 구성과 HTTP 내용을 활용하는 L7 구성을 구분해야 한다. TLS를 어느 장비에서 종료하는지도 구성에 따라 달라진다. AWS — 로드밸런서 유형과 동작
응답을 받은 브라우저는 TLS 복호화, HTTP 프레임 처리, 콘텐츠 디코딩 등을 거쳐 응용 데이터를 얻는다. TCP의 ACK는 TCP 데이터 수신에 관한 확인이며, 애플리케이션의 작업 성공을 의미하지 않는다.
응답이 끝나도 연결은 재사용할 수 있다
HTTP/1.1은 기본적으로 지속 연결을 사용하고, HTTP/2는 한 연결에서 여러 스트림을 처리한다. HTTP/2에서는 Connection: keep-alive 같은 연결 전용 헤더를 사용하지 않는다. 연결을 재사용하면 새 TCP·TLS 연결 비용을 피할 수 있다. RFC 9112 — 지속 연결, RFC 9113 — 연결 전용 헤더
TCP의 정상 종료는 양방향을 각각 닫는 FIN·ACK 교환으로 설명할 수 있지만, ACK와 FIN이 합쳐질 수 있어 항상 네 개의 패킷이 오가는 것은 아니다. RST나 타임아웃으로 종료되는 경우도 있다. RFC 9293 — 연결 종료
6. 오류를 계층 하나로 단정하지 않고 범위 좁히기
이 흐름을 정리한 뒤 실제 개발에 가져가고 싶은 부분은 오류를 읽는 방식이다. 메시지만 보고 원인을 확정하기보다, 어느 통신 구간에서 무엇까지 확인됐는지를 구분해보려 한다.
다음 표는 Chromium 계열의 오류 이름과 HTTP 상태 코드를 기준으로 한 점검 출발점이다. 오류 이름이나 표시는 브라우저에 따라 다를 수 있다.
| 증상 | 먼저 확인할 범위 | 확인할 후보 |
|---|---|---|
DNS_PROBE_FINISHED_NXDOMAIN, ERR_NAME_NOT_RESOLVED | 이름 해석 | 입력 호스트명, DNS 응답, 리졸버·로컬 설정 |
ERR_CONNECTION_REFUSED | 연결 시도 | 리스닝 포트, 명시적 연결 거부, 방화벽 정책 |
ERR_CONNECTION_TIMED_OUT | 연결 경로 | 패킷 드롭, 라우팅, 대상 장비의 응답 여부 |
ERR_CERT_COMMON_NAME_INVALID | 인증서의 호스트명 검증 | 접속 이름과 인증서 SAN의 일치 여부 |
ERR_CERT_DATE_INVALID | 인증서 시간 검증 | 만료·유효 시작 시각, 클라이언트 시계 |
ERR_SSL_PROTOCOL_ERROR | TLS 통신 | 협상 문제, TLS 포트·프로토콜 구성 오류 |
502 Bad Gateway | 게이트웨이와 upstream 사이 | 유효하지 않은 upstream 응답, 연결·TLS 실패 관련 로그 |
504 Gateway Timeout | 게이트웨이와 upstream 사이 | 제한 시간 내 응답 여부, 연결 지연·처리 지연 |
브라우저 오류는 가능한 원인을 좁히는 단서다. 예를 들어 인증서 날짜 오류는 서버 인증서의 만료뿐 아니라 클라이언트 시계 문제일 수도 있다. Chromium — 네트워크 오류 정의
502·504를 받았다고 전체 네트워크가 정상인 것은 아니다
502는 게이트웨이나 프록시가 upstream에서 유효하지 않은 응답을 받았음을, 504는 필요한 upstream 응답을 제시간에 받지 못했음을 나타낸다. RFC 9110 — 502·504
실제 네트워크를 통해 프록시의 504 응답을 받았다면 브라우저와 그 프록시 사이에서는 HTTP 응답을 수신한 것이다. 하지만 프록시와 원본 사이에서는 연결이 막혔거나 TLS 협상이 실패했거나 애플리케이션 처리가 지연됐을 수 있다. 제품별 상태 코드와 로그의 대응을 함께 확인해야 한다.
브라우저 <── 504 응답 ── 프록시
│
└─ 원본 연결 실패 또는 지연 가능
따라서 4xx·5xx를 모두 순수한 애플리케이션 문제로 분류하지 않는다. 어느 장비가 응답을 만들었는지 확인하고, 그 장비의 upstream 연결 로그와 서버 처리 로그를 이어서 살펴보는 편이 유용하다.
7. 개발자 도구와 명령어로 확인해보기
Network 탭에서 먼저 볼 항목
Chrome DevTools의 Timing에서는 DNS Lookup, Initial connection, SSL, Waiting(TTFB), Content Download 등을 구분해 볼 수 있다. 캐시와 연결 재사용 상태에 따라 일부 단계는 나타나지 않는다. Chrome DevTools — Timing
| 관찰한 내용 | 이어서 확인할 부분 |
|---|---|
| DNS Lookup이 길다 | 사용한 리졸버, 캐시, 질의 실패와 재시도 |
| Initial connection·SSL이 길다 | 새 연결 여부, RTT, 패킷 손실, TLS 협상 |
| Waiting(TTFB)이 길다 | 왕복 지연, 프록시·서버의 대기와 처리 시간 |
| Content Download가 길다 | 응답 크기, 전송 속도, 압축 적용 여부 |
TTFB에는 네트워크 왕복과 서버 응답 준비 시간이 함께 반영되므로 곧바로 백엔드 처리 시간으로 해석하지 않는다. Protocol 열에서 h2인지 h3인지, 응답이 캐시나 Service Worker에서 왔는지도 함께 확인한다.
브라우저 밖에서 확인하는 명령어
# DNS 응답과 질의에 응답한 리졸버 확인
dig example.com A
dig example.com AAAA
# TCP 443 포트 연결 시도
nc -zv example.com 443
# SNI를 지정해 TLS 연결과 인증서 정보 확인
openssl s_client -connect example.com:443 -servername example.com
# 요청·응답 및 연결 로그 확인
curl -v -o /dev/null https://example.com/
dig는 브라우저가 사용하는 DoH 리졸버와 다른 경로로 조회할 수 있다. nc의 TCP 연결 성공은 TLS나 HTTP의 성공까지 보장하지 않는다. openssl s_client의 -servername은 SNI 지정이며, 그 옵션만으로 호스트명 검증까지 수행하는 것은 아니다. OpenSSL — s_client 옵션
ping이나 traceroute도 경로를 살펴보는 보조 도구로 쓸 수 있지만, ICMP나 탐색 패킷이 차단될 수 있다. 응답이 없다는 이유만으로 HTTPS 접속도 불가능하다고 판단하지 않는다.
curl로 단계별 완료 시각 보기
아래는 측정 명령의 예시다. 실제 측정값은 환경과 실행 시점에 따라 달라진다.
curl -sS -o /dev/null \
-w 'dns=%{time_namelookup}\ntcp=%{time_connect}\ntls=%{time_appconnect}\nfirst_byte=%{time_starttransfer}\ntotal=%{time_total}\n' \
https://example.com/
각 값은 초 단위이며, 요청 시작을 기준으로 한 누적 시간이다. 프록시·리다이렉트·연결 재사용이 없는 HTTPS over TCP 요청이라면 다음처럼 구간을 대략 나눠볼 수 있다.
time_connect - time_namelookup: 이름 해석 이후 TCP 연결까지time_appconnect - time_connect: TCP 연결 이후 TLS 협상까지time_starttransfer - time_appconnect: 요청 전송과 응답 준비, 첫 바이트 수신까지
마지막 차이에는 네트워크 지연도 포함된다. 브라우저와 curl의 프록시·DNS·프로토콜 선택이 다를 수 있으므로 같은 조건인지 확인한 뒤 비교해야 한다. curl — verbose와 write-out
마치며
이번 정리에서 기억해두고 싶은 것은 프로토콜의 순서와 실제 연결 구간을 함께 보는 습관이다. 새 HTTPS over TCP 연결에서는 이름 해석, TCP 연결, TLS 협상, HTTP 교환을 따라갈 수 있지만, 캐시·연결 재사용·HTTP/3·프록시가 있으면 관찰되는 흐름이 달라진다.
OSI 모델은 그 과정에서 역할을 나누는 데 도움이 된다. 다만 오류 메시지 하나를 특정 계층의 원인으로 확정하기보다는, 연결과 응답 중 어디까지 확인됐는지를 기준으로 다음 점검 대상을 정하는 데 사용하려 한다.
프론트엔드에서도 Network 타이밍을 비교하고, 불필요한 새 연결을 줄일 수 있는지 살펴보며, 응답 크기와 압축을 점검할 수 있다. 서버 설정 변경이 필요한 문제라면 어느 구간에서 어떤 지연이나 오류가 관찰됐는지 함께 전달하는 것이 다음 조사를 시작하는 데 도움이 된다.