핵심 인사이트 (3줄 요약)
- 본질: 앞 장의 '어리석은 윈도우 증후군'을 송신자 입장에서 막아주는 기술로, 내가 키보드를 한 글자 칠 때마다 1바이트짜리 패킷을 낭비하며 쏘는 짓을 막기 위해, **"택배 상자(MSS)가 꽉 차거나, 앞서 보낸 패킷의 영수증(ACK)이 올 때까지 1바이트짜리 짐들을 출발 안 시키고 모아두었다가(Batching) 한 방에 발사하는 지연 전송 알고리즘"**이다.
- 대역폭의 구원자: "h", "e", "l", "l", "o" 다섯 글자를 보내기 위해 40바이트 헤더를 5번(200바이트 낭비) 씌워 날리던 미친 짓을, 상자에 5글자를 꾹꾹 모았다가 40바이트 헤더 딱 한 개만 씌워서 보내게(45바이트) 만들어 네트워크망의 찌꺼기 패킷들을 완벽히 청소해 주었다.
- 실시간 게임의 적 (비활성화 필수): 스타크래프트나 롤에서 마우스를 0.1초 움직이면 그 즉시 데이터가 날아가야 하는데, 네이글 알고리즘은 "야! 택배 상자 찰 때까지 0.5초만 숨 참고 기다려!"라며 딜레이를 유발한다. 따라서 반응 속도가 생명인 온라인 게임이나 터미널 서버 개발자들은 무조건 소켓 옵션에서
TCP_NODELAY를 선언하여 네이글 알고리즘의 목을 비틀어 강제 종료시켜야만 렉을 없앨 수 있다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
-
개념: 작은 크기의 데이터 세그먼트가 네트워크 상에 과도하게 발생하여 대역폭을 낭비하는 것을 막기 위해, 미확인된 데이터(Unacknowledged data)가 있는 경우 작게 생성된 데이터들을 버퍼에 지연/모아서 한꺼번에 전송하는 송신 측 트래픽 최적화 알고리즘. (John Nagle, RFC 896).
-
필요성: 내가 미국 구글 서버에 텔넷(원격 접속)을 켰다.
l키를 눌렀다. 1바이트가 40바이트 헤더를 달고 태평양을 건넌다.s키를 눌렀다. 또 41바이트가 날아간다. 미국 왕복에 200ms가 걸리니까, 나는 타자를 칠 때마다 내 글씨가 화면에 찍히기까지 0.2초씩 기다려야 한다. 게다가 쓸데없이 41바이트짜리 조무래기 패킷들이 해저 케이블을 꽉 막아버려 거대한 영화 파일(FTP)들이 길을 비켜주느라 인터넷이 느려졌다. "야!! 너 지금 방금 'l' 보낸 거 영수증(ACK) 아직 안 왔지? 그럼 핑퐁 도는 동안 키보드에서 쳐진 글씨들은 버퍼 창고에 좀 모아놔!! 영수증이 딱 도착하는 순간, 그동안 모아둔 글씨 10개를 상자 하나에 묶어서 한 방에 던져!" -
💡 비유: 네이글 알고리즘은 버스 회사의 **"만차 출발 룰"**과 같습니다.
- 네이글 끄기: 승객이 1명 탈 때마다 무조건 45인승 버스를 1대씩 출발시킵니다. 도로에 텅 빈 버스가 미친 듯이 깔려 교통지옥이 됩니다. (대역폭 낭비).
- 네이글 켜기: 버스 기사님은 "좌석 45개가 꽉 차거나(MSS 도달), 아니면 앞서 출발한 1호 버스가 종점에 무사히 도착했다는 무전(ACK)이 올 때까지" 무조건 문을 안 닫고 승객을 모아서 기다립니다. 버스는 꽉꽉 차서 효율적으로 운행되지만, 1번째 탄 승객은 출발할 때까지 버스 안에서 5분을 멍때리며 기다려야(Delay) 합니다.
📢 섹션 요약 비유: 네이글은 쌀알 1톨이 생길 때마다 배송 트럭을 보내던 멍청한 송신자에게, **"트럭이 꽉 차거나 앞 트럭이 무사 귀환할 때까지 쌀알들을 창고에 쓸어 담아(Batching) 한 번에 보내라!"**는 효율성 지침을 내린 전설적인 최적화 법칙입니다.
Ⅱ. 네이글 알고리즘의 동작 룰과 치명적 부작용 (Deep Dive)
현대의 모든 윈도우/리눅스 OS는 기본적으로 TCP 소켓을 열 때 네이글 알고리즘이 강제로 켜져(Enabled) 있다. (대역폭 보호를 위함).
1. 송신 허락의 2가지 절대 조건
네이글이 켜져 있을 때 송신자 버퍼(창고)의 짐이 밖으로 출발하려면 아래 조건 중 딱 하나만 만족하면 된다.
- 조건 1 (양 채우기): 앱이 들이부은 데이터가 패킷의 최대 수용량(MSS, 1460바이트)을 꽉 채웠는가? -> "오케이, 박스 꽉 찼네 냅다 쏴라!"
- 조건 2 (영수증 받기): 박스가 안 차서 1바이트밖에 없어도, 방금 전 쐈던 패킷에 대한 상대방의 영수증(ACK)이 도착했는가? -> "오케이 앞차 무사히 도착했네! 그럼 1바이트 찌꺼기라도 안 묶고 그냥 바로 쏴버려!"
┌─────────────────────────────────────────────────────────────┐
│ 네이글(Nagle) 켜짐 vs 꺼짐의 패킷 발송 시나리오 │
├─────────────────────────────────────────────────────────────┤
│ │
│ * 사용자가 키보드로 H, E, L, L, O 를 0.1초 간격으로 타닥타닥 친다. │
│ * 이전 패킷의 ACK가 미국에서 날아오는 데 0.5초가 걸린다 가정! │
│ │
│ [ 네이글 알고리즘 OFF (게임 환경) ] │
│ H 누름 ──▶ 발사! (ACK 안 기다림) │
│ E 누름 ──▶ 발사! (ACK 안 기다림) ──▶ (해저 케이블 쓰레기로 꽉 참) │
│ L 누름 ──▶ 발사! │
│ │
│ [ 네이글 알고리즘 ON (기본 환경) ] │
│ H 누름 ──▶ (첫 패킷은 무조건 발사!) │
│ E 누름 ──▶ (버퍼에 가둠) │
│ L 누름 ──▶ (버퍼에 가둠) │
│ L 누름 ──▶ (버퍼에 가둠) │
│ 0.5초 뒤, 미국에서 "H 잘 받았어(ACK)!" 도착!! │
│ OS: "오예! 가둬놨던 ELL 3글자 묶어서 하나의 40바이트 헤더에 싸서 발사!!"│
└─────────────────────────────────────────────────────────────┘
2. 게임 개발자의 적 (TCP_NODELAY 옵션)
FPS(총 쏘기) 게임이나 롤(LOL)을 하는데, 내 마우스 클릭 정보(1바이트)가 네이글 알고리즘에 걸려서 공유기 버퍼에 0.1초 동안 갇혀서 묶였다고 상상해보라. 그 0.1초 사이에 내 캐릭터는 이미 죽어있다 (극강의 반응 지연).
- 그래서 게임이나 주식 트레이딩 시스템(HFT)을 만드는 개발자는 파이썬이나 C로 네트워크 코딩을 할 때, 무조건
setsockopt(TCP_NODELAY)라는 마법의 주문을 걸어서 소켓에 붙어있는 네이글 알고리즘의 스위치를 꺼버린다. - 망 대역폭(쓰레기 패킷)을 희생해서라도 극한의 반응 속도(Low Latency)를 쥐어짜 내는 실무 프로그래밍의 가장 위대한 팁이다.
📢 섹션 요약 비유: 네이글을 켜는 것은 연비를 극대화하기 위해 차가 꽉 찰 때까지 출발 안 하는 **"시골 합승 택시"**이고, 네이글을 끄는 것(
TCP_NODELAY)은 요금(대역폭)이 얼마나 나오든 손님 1명만 타면 미친 듯이 밟고 출발하는 **"VIP 콜택시"**입니다. 목적에 맞게 골라 써야 합니다.