핵심 인사이트 (3줄 요약)
- 본질: TCP NewReno(뉴레노)와 SACK 옵션은 구형 Reno가 "한 창문(Window) 안에서 2~3개의 패킷이 동시에 유실되었을 때 속도를 반의반으로 계속 깎아 먹다 뻗어버리는 멍청한 자멸 현상"을 완벽하게 치료하기 위해 도입된 현대 TCP 혼잡 제어의 필수 구원투수다.
- NewReno의 진화 (Partial ACK의 눈치): NewReno는 잃어버린 10번을 다시 보내줬는데, 수신자가 "고마워! 근데 20번도 잃어버렸었어!"라며 찔끔 대답(Partial ACK)하는 걸 듣고, "아~ 이거 아까 10번 날아갔을 때 같이 날아갔던 놈이구나!"라고 귀신같이 눈치채고 속도(CWND)를 두 번 깎지 않는 관대함을 발휘한다.
- SACK (Selective ACK)의 마법: NewReno보다 한술 더 떠서, 아예 처음부터 수신자가 영수증 밑 빈칸(TCP 옵션)에다가 "나 10~19번 잘 받았고, 21~30번 잘 받았어! (즉, 가운데 20번만 쏙 빠졌어!)"라고 정답(유실 번호)을 핀셋으로 콕 집어주어, 송신자가 묻지도 따지지도 않고 딱 20번만 0.1초 만에 재전송하게 만드는 현대 초고속 인터넷의 무적 치트키다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
-
개념: 단일 윈도우 내 다중 패킷 손실(Multiple Packet Loss) 발생 시 TCP Reno의 성능 저하(다중 Fast Recovery로 인한 CWND 급감 및 Timeout)를 방지하기 위해 개선된 혼잡 회피 알고리즘(NewReno)과 확장 TCP 헤더 옵션(SACK).
-
필요성: 1Gbps 초고속망이 되니까 한 번에 쏘는 윈도우 크기가 1,000개가 넘었다. 해저 케이블에서 노이즈가 살짝 튀면 1,000개 중 5개가 듬성듬성 유실된다. Reno는 이 5개를 잃어버릴 때마다 속도를 1/2, 1/4, 1/8, 1/16, 1/32로 미친 듯이 깎아 먹다가 아예 뻗어버렸다(Timeout). "야! 1,000개 보낸 것 중에 5개 잃어버린 건 '한 번의 사고'잖아! 왜 속도를 5번이나 깎아! 그리고 잃어버린 것만 딱딱 집어서 알려주면 내가 한 방에 다 다시 쏴줄 텐데 굳이 누적 ACK로 사람 숨 막히게 할 거야?!" 이 절규가 SACK과 NewReno를 탄생시켰다.
-
💡 비유:
- Reno (구형): 택배 100개를 시켰는데 10번과 20번이 안 왔습니다. 고객은 "10번 안 왔어!"라고 1차 클레임을 겁니다(속도 삭감). 회사가 10번을 보내줍니다. 그제야 고객은 "20번도 안 왔어!"라고 2차 클레임을 겁니다(속도 또 삭감). 배송 회사는 암 걸립니다.
- SACK (신형): 고객이 택배를 받자마자, "1~9번 오케이, 11~19번 오케이, 21~100번 오케이!"라고 영수증에 형광펜으로 칠해서(SACK 블록) 보냅니다. 배송 회사는 영수증을 딱 보고, **"아 10번이랑 20번 2개가 비었네? 한 번에 퀵으로 쏴줄게! (속도 삭감은 1번만)"**라며 눈부신 처리를 보여줍니다.
📢 섹션 요약 비유: SACK(선택적 확인 응답)은 시험지 채점을 할 때 "너 3번 틀렸어 다시 풀어와" 하고 다시 풀어오면 "7번도 틀렸어 다시 풀어와" 하는 꼰대 선생님(Reno)의 방식을 부수고, 처음부터 "너 3번이랑 7번 틀렸어!"라고 한 번에 채점표를 쥐여주는 1타 강사의 명쾌한 족집게 과외입니다.
Ⅱ. Partial ACK와 SACK 블록의 해부 (Deep Dive)
1. NewReno의 융통성 (Partial ACK 판별법)
SACK 옵션이 켜져 있지 않은 낡은 PC들 사이에서도 다중 유실을 막기 위해 커널 코드를 살짝 고친 것이 NewReno다.
- Reno의 바보짓: 유실된 10번을 재전송하고, 수신자가
ACK 20을 보내면 "오 10번 잘 갔네! Fast Recovery 끝! 정상 주행!" 하고 샴페인을 터뜨렸다. 그런데 바로 다음 순간20번이 없다고 징징대면 "헐? 새 사고 터졌네? 또 절반 깎자!" - NewReno의 눈치: 수신자가
ACK 20을 보냈다 치자. NewReno는 샴페인을 안 터뜨린다. "잠깐만. 내가 아까 창문(Window) 하나에 100번까지 꽉꽉 채워 보냈는데, 쟤가 왜 100번을 불렀다 안 하고 20번을 부르지? 아! 아까 10번 날아갈 때 20번 놈도 같이 바다에 빠진 거구나 (Partial ACK 감지)!!" - 조치: NewReno는 이 상황을 '새로운 사고'로 안 보고, **'아까 난 사고 수습 중(Fast Recovery 진행 중)'**으로 간주하여 속도(CWND)를 깎지 않고 20번을 부드럽게 재전송해 준다.
2. 궁극의 치트키 SACK (Selective Acknowledgment)
TCP 통신을 처음 맺을 때(SYN 패킷 교환), Options 구역에 "나 SACK 지원함!"이라고 합의를 마친다.
- SACK Block의 구조: 수신자는 기본 영수증(
ACK=10)을 보내면서, 헤더 꼬리표(Option)에 4개의 블록을 더 적어 보낼 수 있다.- "기본적으로 10번까지 받았어. (근데 11번이 안 왔어)"
- "[SACK Option]: 근데 나 15~20번은 받았고, 25~30번도 받았어!"
- 송신자의 광속 재전송: 이 엽서를 받은 송신자는 머리를 1초도 안 굴리고, 뻥 뚫려있는 빈 공간인 11~14번과 21~24번 패킷만 핀셋으로 쏙쏙 뽑아내어 한 방에 재전송해 버린다.
- 결과적으로 타임아웃(Timeout) 따위는 절대 구경할 수 없는 무적의 다운로드 속도가 유지된다.
┌─────────────────────────────────────────────────────────────┐
│ 와이어샤크(Wireshark)에서 SACK 블록 훔쳐보기 │
├─────────────────────────────────────────────────────────────┤
│ │
│ [ 일반 TCP 헤더 영역 ] │
│ Acknowledgment number: 1000 ◀─ "나 999까지 받았어! 1000번 내놔!" │
│ │
│ [ Options 영역 (SACK 켜짐) ] │
│ TCP SACK Option: │
│ - SACK Left Edge: 1500 │
│ - SACK Right Edge: 2000 ◀─ "근데 1500~1999번은 잘 도착해 있어!" │
│ │
│ ▶ 송신자의 행동: "오케이! 너 1000번부터 1499번까지만 잃어버렸구나! │
│ 내가 그 구간만 핀셋으로 뽑아서 지금 당장 쏴줄게!!" │
└─────────────────────────────────────────────────────────────┘
📢 섹션 요약 비유: SACK은 치과 의사가 쓰는 **"충치 파노라마 엑스레이"**입니다. 환자(수신자)가 "이빨 아파요(기본 ACK)"라고 징징댈 때, 의사(송신자)가 이빨을 하나하나 두드려가며 아픈 곳을 찾는 게(Reno) 아니라, 엑스레이(SACK 블록) 사진 한 장 딱 보고 "아, 왼쪽 어금니 두 개 썩었네" 하고 정확히 그 두 곳만 0.1초 만에 핀셋 치료(재전송)를 끝내버리는 현대 의학의 기적입니다.