본문 바로가기
컴퓨터/Server

네이글 알고리즘(Nagle Algoritm)

by 김짱쌤 2015. 3. 27.

네이글 알고리즘



1. 네이글 알고리즘이란?

IP 네트워크에서 데이터는 몇 곂의 헤더로 캡슐화되어 목적지로 보내진다. 이 헤더들의 용량도 제법 커서, 적은 데이터를 보내게되면 배보다 배꼽이 커지는 경우가 발생한다. 고의로 작은 단위의 데이터를 전송하는 경우도 있겠지만, 의도치 않게 네트워크 상황상 비효율적인 송신을 해야하는 경우가 있다. 

예를 들면 전송해야될 데이터가 있는데, 상대방의 윈도우 크기(전송 받을 수 있는 크기)가 매우 작은 경우. 내가 의도한 바는 아니지만 보낼 수 있는 패킷의 크기 자체가 작기 때문에 따로 지연 설정을 하지 않으면, 작은 크기의 패킷이 만들어질 수 밖에 없다.

보낼 수 있는 데이터를 바로 패킷으로 만들지 않고, 가능한 모아서 더 큰 패킷으로 만들어 한번에 보내면 이런 문제는 발생하지 않을 것이다. 네이글 알고리즘은 이 대안을 실제로 구현한 네트워크 전송 알고리즘이다. 


2. 동작원리

#define MSS "maximum segment size"

if there is new data to send if the window size >= MSS and available data is >= MSS send complete MSS segment now else if there is unconfirmed data still in the pipe enqueue data in the buffer until an acknowledge is received else send data immediately end if end if end if

위 의사코드는 http://en.wikipedia.org/wiki/Nagle's_algorithm에서 가져온 네이글 알고리즘이다. 

요약하자면 아래와 같다.

1. 상대방이 받을 수 있는 사이즈(window size)와 내가 보낼 데이터가 MSS보다 크다면 문제없이 바로 전송한다. 

2. 더 이상 SEND 처리할 데이터가 없다면 현재 있는것 그대로 보낸다.

3. 둘다 아니라면, 아래의 그림 (Nagle On) 처럼 동작한다.


네이글이 최대한 작은 크기의 패킷 전송을 지연시키는 기능을 할 수 있는 것은 3번 경우에 대한 처리 덕분이다. 기존의 네트워크 환경에서는 데이터가 버퍼에 조금씩 쌓이게 되면, Nagle off의 그림처럼 상대방의 ACK를 기다리지 않고 바로바로 작은 패킷을 전송한다. 네이글은 이런 작은 패킷을 가능한 지연시키기 위하여, ACK가 올때까지 전송을 중지하고 ACK가 도착한 시점에, 지금까지 버퍼에 모인 데이터를 패킷으로 만들어서 전송한다. 

ACK를 기다리는 지연방식으로 네이글은 작은 패킷을 연속해서 보내는 네트워크의 비효율을 극복하였다. 하지만 이런 지연방식을 사용하면 위 그림처럼 데이터 전송속도가 더 늦다. 


3. 네트워크 게임에서 네이글 알고리즘

게임은 반응성을 중요시한다. 게임을 하는데 내 입력에 대한 피드백이 바로바로 오지 않는다면, 그리고 그 결과 원치않은 결과를 얻었다면, 유저들은 불편함과 부당함을 느끼고 게임을 빠르게 삭제해버릴 것이다. 네트워크 게임에서 네이글을 적용시켰을 때, 반응성과 효율성 두가지를 모두 얻을 수 있을까? 게임 서버와 클라이언트에서 네이글을 사용했다는 상상실험을 통해 그 결과를 유추해보자.

온라인 게임의 네트워크 상황을 생각해보자. 클라이언트의 경우 서버로 유저의 입력을 전송한다. 이 입력신호의 경우데이터 양 자체가 작고, 또 반복적으로 여러 입력이 요청될 수 있기 때문에, 쉽게 위 3번의 경우에 빠지기 쉽다. 하지만 이 입력 패킷이 크기가 작다는 이유로 지연된다면, 사용자의 반응성에 큰 영향을 미치게된다. 입력 패킷은 크기는 작아도 게임에 있어 그 의미는 매우 크다. 뿐만아니라 PC 클라이언트의 입장에서 네트워크의 효율 문제는 큰 이슈가 아니다. 어느정도의 트래픽 효율을 포기하더라도 빠른 반응성을 얻는것이 유저 입장에서도 좋은 거래가 될 것이다.따라서 클라이언트 네트워크의 경우에는 네이글 알고리즘을 사용하지 않는 것이 유리하다고 생각한다.

서버의 경우는 클라이언트와 다르다. 서버는 클라이언트에게 현제 유저가 처한 게임 상황의 결과를 지속적으로 보내줄 것이다. 이 정보는 패킷 크기에 비해 헤더 크기가 비대해 보이지 않을 정도로 충분히 큰 양의 데이터일 것이며, 지속적으로 갱신해서 보내주는 데이터가 될 것이다. 이러한 데이터가 네이글 알고리즘에 의해 지연되는 경우는 클라이언트의 가용 윈도우 사이즈가 충분히 크지 않은 경우가 될 것이다. 클라이언트의 처리 능력이 원활하지 않은 경우 계속해서 데이터를 잘라서 우겨넣는것이 유저가 체감하는 반응성에 큰 영향을 미칠 것이라 생각하지 않는다. 또한 동시에 여러 클라이언트가 사용하는 서버에서 트래픽이슈는 민감한 부분이기 때문에, 네이글 알고리즘을 사용했을때 얻는 이득이 더 크지 않을까 생각해본다.


4. C++ Socket에서 Nagle 옵션 On / Off방법

int option = TRUE;               //네이글 알고리즘 on/off
setsockopt(m_Socket,             //해당 소켓
           IPPROTO_TCP,          //소켓의 레벨
           TCP_NODELAY,          //설정 옵션
           (const char*)&option, // 옵션 포인터
           sizeof(option));      //옵션 크기

setsockopt를 통해서 사용 소켓 옵션을 TCP_NODELAY로 설정하면, 네이글 알고리즘을 사용하지 않을 수 있다. 기본적인 소켓은 네이글 알고리즘을 사용하도록 세팅되어 있으므로, 네이글을 수동으로 설정하지 않으면, 자동으로 네이글 알고리즘이 동작한다.