Velog
여기까지 어떻게 온 걸까?
브라우저가 어떤 서버에 연결할 때 *왜 그 경로* 인가는 ICMP TTL, BGP 피어링, AS(자율 시스템) 의 합작이다. 인터넷은 *개방형 네트워크* 가 아니라 계약으로 묶인 네트워크들의 네트워크 다.
핵심 요약
패킷이 라우터를 지날 때마다 ICMP 의 TTL(time-to-live) 이 1 씩 감소하고, 0 이 되면 라우터가 Time Exceeded 메시지를 발신지로 돌려보낸다. traceroute 는 TTL 을 1, 2, 3… 로 키워가며 보내 각 홉의 IP 를 수집하는 트릭이다. 각 IP 는 어느 AS(자율 시스템) 에 속하며, AS 들은 BGP 로 내가 도달 가능한 prefix 목록 을 광고한다. 두 AS 가 피어링 계약 을 맺으면 서로의 광고를 받아들이고, 라우터는 라우팅 테이블에서 최단 AS path + 정책 휴리스틱 으로 다음 홉을 고른다. 즉 인터넷 토폴로지는 물리적 케이블 이 아니라 비즈니스 계약 이 그린다. 본 글의 데모는 추가로, 자바스크립트 없이 HTTP 응답을 stream 으로 천천히 흘려보내고 CSS display: none 트릭으로 점진적으로 나타나게 만들어 streaming SSR 의 본질을 직관적으로 보여준다.
인터넷을 '전 지구적 단일 공용 네트워크' 가 아니라 'AS(Autonomous System)들이 서로 BGP 피어링 계약으로 연결된 사기업 네트워크의 그래프' 로 본다. 패킷의 경로는 물리적 거리 가 아니라 어떤 AS 가 어떤 AS 와 피어링되어 있는지 로 결정된다. traceroute 는 그 그래프를 내 패킷이 어느 노드를 거쳐 갔는지 로 시각화하는 도구다.
이 그림이 머릿속에 있으면 프런트엔드 성능/장애 디버깅이 다르게 보인다.
- 왜 한국 → 유럽 latency 가 안정적이지 않은가 — 중간 AS 의 라우팅 정책이 시간대마다 바뀌기 때문
- 왜 같은 CDN 인데 지역마다 hit 율이 다른가 — Anycast IP 가 BGP 광고 범위 안의 가까운 PoP 으로만 라우팅됨
- 왜 ISP 장애가 내 사이트를 죽이는가 — 그 ISP 의 AS 가 BGP 광고를 잃으면 내 origin 으로 가는 경로 자체가 사라진다
- 본 글은 서버에서 클라로 흐르는 동안 응답 본문을 청크로 stream 하는 트릭(노란 텍스트가 점진적으로 나타나는 효과)도 보여줘 HTTP streaming + 점진적 렌더링 의 감각도 함께 키운다.
학습 포인트
면접 답변으로 연결할 학습 포인트입니다.
TTL 은 시간이 아니라 *홉 카운터* 다
TTL 은 time 이라는 이름과 달리 라우터를 한 번 지날 때마다 1 씩 감소하는 홉 카운터. 0 이 되면 패킷은 폐기되고 라우터가 ICMP Time Exceeded 를 돌려준다. traceroute 는 이 동작을 역이용한다.
TTL=1 → 첫 라우터에서 폐기 + ICMP 응답 → 1번 홉 IP 획득
TTL=2 → 두 번째 라우터에서 폐기 + ICMP 응답 → 2번 홉 IP 획득
...
네트워크 이름과 동작이 어긋나는 대표 예. 면접에서 자주 나오는 트리비아.
TTL 을 밀리초 단위 시간 제한 으로 오해하는 것. 실제로는 지나간 라우터 수 다.
BGP 는 *가장 짧은 경로* 가 아니라 *정책 우선* 이다
라우터가 BGP 라우팅 테이블에서 다음 홉을 고를 때 사용하는 우선순위는 대략:
- Local Preference (사내 정책)
- AS Path 길이 (짧을수록 선호)
- Origin type, MED, eBGP > iBGP, IGP 거리
즉 가장 짧은 경로 가 항상 선택되는 게 아니라 AS 운영자의 비즈니스 정책 이 먼저 작용한다.
| 시나리오 | 결과 |
|---|---|
| 무료 피어 vs 유료 transit, AS path 동일 | 무료 피어 선호 (Local Pref 높음) |
| 짧지만 비싼 transit vs 긴 무료 피어 | 정책에 따라 긴 경로가 선택됨 |
트래픽 흐름 = 비즈니스 계약 이 인터넷의 실제 모습이다.
'인터넷은 항상 최단 경로로 라우팅된다' 고 가정하는 것. CDN 미스 원인의 상당수가 이 오해에서 나온다.
JS 없이 streaming 렌더링하는 트릭
본 글의 페이지는 자바스크립트 0줄 로 traceroute 결과를 점진적으로 표시한다. 핵심은 두 가지.
<!-- 1. HTTP 응답을 닫지 않고 청크로 흘려보낸다 -->
<!-- 2. 새 청크가 오면 이전 hop 을 숨기는 CSS 를 *덮어쓴다* -->
<style>.hop1 { display: block; }</style>
... 첫 번째 hop 텍스트 ...
<style>.hop1 { display: none; } .hop2 { display: block; }</style>
... 두 번째 hop 텍스트 ...
브라우저는 청크가 도착하는 즉시 CSS/HTML 을 파싱해 화면을 업데이트한다. streaming SSR 도 이 원리를 그대로 쓴다 — <Suspense> 가 풀릴 때마다 inline <script> 가 placeholder 를 진짜 콘텐츠 로 swap.
'streaming 은 React 18 에서 처음 나온 신기능' 으로 오해. 실제로는 1990년대 HTTP/1.1 chunked encoding 위에서 동작한다.
읽는 순서
- 1이론
ICMP TTL 동작과 BGP 의 path-vector 알고리즘 한 페이지 요약. prefix advertisement 와 peering 의 차이를 적는다.
- 2구현
Node 로 3초마다 한 청크씩 보내는 HTTP 핸들러를 만들고, 브라우저 Network 탭에서
Transfer-Encoding: chunked를 확인한다. - 3실무
현재 프로젝트에서 외부 API 한 곳을 traceroute 로 추적하고, 각 홉의 AS 를 bgpview.io 에서 조회해 본다.
- 4설명
팀에 'CDN 의 latency 가 안정적이지 않을 때 어디서 어떻게 진단하나' 5분 설명. 축: traceroute → AS path → BGP 광고 변화.
면접 연결 질문
[감점 답변] '네트워크가 느려서'. [좋은 답변] (1) 중간 transit AS 가 피어링 계약을 변경 해 더 긴 AS path 로 우회되고 있을 수 있음. (2) origin AS 가 BGP 광고를 prefix 단위로 좁혀 일부 지역 라우터가 다른 PoP 로 보내고 있을 수 있음. traceroute 의 AS path 변화 를 비교해 확인.
[감점 답변] '완전히 다르다'. [좋은 답변] 둘 다 HTTP chunked transfer 위에서 동작한다. 차이는 swap 메커니즘. 본 글은 CSS display 토글로 청크를 갈아끼우는 반면, React 18 은 <template> + inline <script> 로 placeholder DOM 을 실제 노드로 교체. 후자는 hydration 까지 포함해야 해서 추가 JS 가 필요.
자기 점검
'localhost 에서 traceroute 는 의미 없다'. 클라이언트가 어떤 ISP/AS 를 거쳐 첫 PoP 에 도달하는지가 latency 디버깅의 출발점이다.