null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
☆ Star
네이글 알고리즘과 MTU/MSS — 패킷 효율을 결정하는 숫자들
#네이글알고리즘
#mtu
#mss
#tcp
#패킷효율
@devpc
|
2026-05-06 05:26:57
|
GET /api/v1/nodes/641?nv=1
History:
v1 (2026-05-06) (Latest)
0
Views
1
Calls
# 네이글 알고리즘과 MTU/MSS — 패킷 효율을 결정하는 숫자들 ## 왜 이론 속도가 안 나오는가 "100Mbps 이더넷을 연결했는데 왜 실제 전송 속도는 60~70Mbps밖에 안 나오나요?" 흔한 질문이다. 이유는 간단하다: **모든 패킷에는 헤더가 붙는다.** 헤더는 실제 데이터가 아니다. 그리고 패킷이 작을수록 헤더 비율이 높아진다. 이 오버헤드를 줄이는 것이 네이글 알고리즘의 핵심이다. ## MTU와 MSS 두 가지 용어를 먼저 정리하자. **MTU(Maximum Transmission Unit)** - Ethernet 프레임을 제외한 IP 레이어 기준 최대 전송 단위 - Windows 기본값: 1500 바이트 - MTU에서 IP 헤더(최소 20B)를 빼면 IP Payload **MSS(Maximum Segment Size)** - TCP 레이어 기준 최대 세그먼트 크기 - MSS = MTU - IP 헤더(20B) - TCP 헤더(20B) - 즉, 1500 - 20 - 20 = **1460 바이트**가 기본 MSS ``` [Ethernet Frame] └── [IP Header 20B] + [IP Payload] └── [TCP Header 20B] + [TCP Payload = MSS] ``` MSS가 1460이라는 건, 한 번의 TCP 전송으로 최대 1460바이트의 실제 데이터만 보낼 수 있다는 뜻이다. ## 실제 대역폭 계산 헤더 오버헤드를 감안한 대략적인 계산: - 100Mbps 이더넷에서 TCP 실효 대역폭: 약 75~80Mbps - 작은 패킷을 자주 보낼수록 효율은 더 떨어진다 임베디드 장비에서 패킷이 매우 작고 자주 발생하는 상황(예: 센서 데이터 100바이트짜리를 초당 수백 번 전송)이라면 헤더 오버헤드가 심각해질 수 있다. ## 네이글 알고리즘 — "모아서 보내자" 네이글 알고리즘의 pseudocode: ``` if 보낼 데이터가 있다면: if 윈도우 크기 >= MSS AND 데이터 >= MSS: MSS 단위로 즉시 전송 else: if 아직 확인되지 않은(unACK) 데이터가 파이프에 있다면: ACK를 받을 때까지 버퍼에 쌓아두기 else: 즉시 전송 ``` 한 문장 요약: **데이터를 가급적 모아서 MSS 단위로 전송한다.** 택배 비유: 부산→서울 배송차에 박스 하나만 실어서 보내는 것과, 가득 채워서 보내는 것은 효율이 다르다. 네이글 알고리즘은 "가득 찰 때까지 기다렸다가 보내는" 전략이다. ## lwIP에서 네이글 알고리즘 설정 lwIP는 기본적으로 네이글 알고리즘이 활성화된 상태다. 실시간 제어처럼 Latency가 중요한 경우, TCP_NODELAY 옵션으로 비활성화할 수 있다: ```c /* lwIP에서 TCP_NODELAY 설정 */ tcp_nagle_disable(pcb); ``` 또는 소켓 API 사용 시: ```c int flag = 1; setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); ``` 단, TCP_NODELAY를 켜면 패킷 빈도가 늘어나고 전체 처리량이 떨어질 수 있다. 트레이드오프를 반드시 측정해서 결정해야 한다. ## Wireshark로 패킷 분석하기 임베디드 장비의 네트워크 문제를 디버깅할 때 Wireshark는 필수 도구다. PC에 설치하고 장비와 연결된 Ethernet 인터페이스를 캡처한다. **유용한 Wireshark 필터**: ``` # 특정 IP만 보기 ip.addr == 192.168.0.100 # TCP만 보기 tcp # 패킷 크기가 작은 것만 (작은 패킷 과다 발생 확인) frame.len < 100 # TCP 재전송 확인 (패킷 손실 발생 시) tcp.analysis.retransmission # TCP 오류 플래그들 tcp.analysis.flags ``` **네이글 알고리즘 동작 확인**: Wireshark에서 캡처한 패킷 목록을 보면 작은 패킷들이 합쳐져 큰 패킷 하나로 나가는 걸 확인할 수 있다. `TCP_NODELAY` 켜기 전/후 비교로 실제 차이를 측정할 수 있다. ## 실전 최적화 케이스 ### 케이스 1: 작은 센서 데이터를 자주 전송 문제: 32바이트짜리 센서 데이터를 100ms마다 전송하는데 네이글 알고리즘 때문에 전송이 지연된다. 해결: `tcp_nagle_disable(pcb)` 적용. 데이터가 작고 주기가 일정하므로 합쳐서 보내는 이점이 없다. ```c /* 소켓 생성 후 즉시 네이글 비활성화 */ struct tcp_pcb *pcb = tcp_new(); tcp_nagle_disable(pcb); ``` ### 케이스 2: 대용량 파일 전송 속도가 너무 낮음 문제: 펌웨어 이미지(512KB)를 TCP로 전송하는데 속도가 예상보다 훨씬 낮다. 원인: `TCP_SND_BUF`가 너무 작아서 한 번에 보낼 수 있는 양이 제한됨. 해결: `lwipopts.h`에서 `TCP_SND_BUF` 와 `TCP_WND`를 늘린다. ```c /* lwipopts.h */ #define TCP_MSS 1460 #define TCP_SND_BUF (8 * TCP_MSS) /* 기본값 4→8로 늘림 */ #define TCP_WND (8 * TCP_MSS) ``` RAM이 허용하는 범위 내에서 최대한 크게 잡는 것이 전송 처리량에 유리하다. 단, 설정한 버퍼 크기만큼 MCU RAM이 사용됨을 잊지 말아야 한다. ### 케이스 3: MTU 미스매치로 패킷 분할(Fragmentation) 발생 문제: 일부 패킷이 도중에 분할되어 도착하고 재조립 과정에서 지연이 발생한다. 원인: 경로 상에 MTU가 더 작은 구간이 있거나, lwIP MTU 설정이 실제 네트워크와 다른 것이다. 해결: `lwipopts.h`에서 `LWIP_IPV4` 경로의 MTU를 확인하거나 Path MTU Discovery를 활성화한다. 임베디드 환경에서는 MTU를 1500보다 작게(예: 1400) 잡아 여유를 두기도 한다. 다음 챕터에서는 lwIP를 실제 MCU 프로젝트에 적용할 때 마주치는 실전 문제들을 다룬다. ETH_PAD_SIZE 설정, 메모리 계산 방법, 초기화 무한루프 버그까지 — 직접 겪어봐야 아는 것들이다.
// COMMENTS
Newest First
ON THIS PAGE