한양과학기술고등학교

에듀테크 프로젝트 대시보드

MTU와 IP 단편화

MTU와 IP 단편화

네트워크 링크마다 한 번에 실어 나를 수 있는 최대 크기가 정해져 있다. 이를 MTU (Maximum Transmission Unit, 이더넷 기본값 1500 bytes)라 부른다. 보낼 데이터가 MTU보다 크면 라우터는 IP 데이터그램을 여러 조각으로 단편화(Fragmentation)한다. 아래에서 데이터 크기와 MTU를 직접 바꿔가며 조각이 어떻게 나뉘는지 확인해 보자.

1. 단편화 시뮬레이터

4028 B
1500 B
원본 데이터그램

2. Path MTU Discovery — 미리 알아내기

라우터가 매번 단편화를 대신 해주면 CPU 부담이 크고, 조각 하나만 유실돼도 전체를 재전송해야 한다. 그래서 현대 TCP/IP 스택은 DF (Don't Fragment) 플래그를 켜고 미리 가장 작은 MTU를 알아낸 뒤, 처음부터 그 크기 이하로만 보낸다.

💻 송신 호스트
🌐 중간 라우터 (MTU 1400)
🖥️ 수신 호스트
① 1500B 패킷 전송, DF=1
② 라우터: 1500 > MTU(1400) 이고 DF=1 → 버림!
③ ICMP Type 3 Code 4 "Fragmentation Needed" (MTU=1400) 회신
④ 송신 호스트: 캐시된 PMTU=1400으로 재전송 → 목적지 도착!
// "다음 단계" 버튼을 눌러 진행하세요
주의: PMTUD 블랙홀
일부 방화벽이 보안을 이유로 ICMP를 통째로 차단하면, 라우터가 패킷을 버리고도 알려줄 방법이 없어진다. 송신 호스트는 응답 없이 계속 같은 크기로 재전송하다가 결국 타임아웃 — 이것이 PMTUD 블랙홀 문제다.

3. 단편화 필드 계산 (Python)

# IPv4 헤더의 Identification / Flags(DF,MF) / Fragment Offset 필드로 # 수신측은 조각을 원래 순서와 위치대로 재조립한다 def fragment(data_len: int, mtu: int, header: int = 20): max_data = ((mtu - header) // 8) * 8 # offset 단위 8B에 맞춰 내림 fragments, offset = [], 0 while offset < data_len: chunk = min(max_data, data_len - offset) more = offset + chunk < data_len # MF 플래그 fragments.append({ "offset_units": offset // 8, # 8바이트 단위로 기록 "data_bytes": chunk, "MF": int(more), }) offset += chunk return fragments # 모든 조각은 같은 Identification 값을 공유 → 재조립 시 묶는 기준 # 마지막 조각만 MF=0, 나머지는 MF=1로 "더 올 조각 있음"을 표시
핵심 3가지
① 단편화는 Identification(같은 원본 식별) + Fragment Offset(8바이트 단위 위치) + MF 플래그(마지막 조각 여부) 세 필드만으로 재조립된다.
② 조각 하나만 사라져도 전체 데이터그램이 폐기된다 — 단편화가 비효율적인 근본 이유.
③ 그래서 실무에서는 라우터의 즉석 단편화 대신 Path MTU Discovery로 미리 안전한 크기를 찾아 보낼 때부터 쪼개지 않는 것을 선호한다.