왼쪽 그림이 IOCP를 사용하는 서버의 일반적인 구조라고 생각된다.
이 그림에서 끊임없는 화제거리를 제공했던 주제는 worker thread의 N을 얼마로 해야하나 였고, 심심할때 가끔 나오는 주제는 worker thread가 얼마나 많은 일을 해야하나였다.
쓰레드 개수야 아직도 정답이 없고 worker thread가 하는 일은 시대에 따라 조금씩 변해왔다.
내가 처음 게임회사에 일을 시작했을때 대세는 worker thread에서 가능한 적은 일을 하는 것이었다. 그당시에 얻을 수 있는 거의 모든 소스(책, 해외 웹사이트 등등)에서 그렇게 하는게 정답이라고 말을 했고 주변에서도 그렇게 일을 했다.
그리 멀지도 않은 과거 그러니까 90년대로 돌아가보면 - 우리 모두가 스티븐스님의 책을 보면서 터미널에 다닥다닥 붙어 유닉스에서 네트워크 프로그램을 배우던 바로 그때 - 프로그램은 당연히 여러개의 프로세스로 이루어져 있었다. 포크(fork)를 통해서 새로운 프로세스를 만들어 일을 처리하는건 당연하면서도 훌륭한 방법이었으니까.
실제로 99년에 참가했던 산학협력 프로젝트에 교수님이 제안한 구조는 천개가 넘는 프로세스로 구성이 되어 있었고 그 결과물을 이상하게 생각하는 사람은 없었다. 그러나 시간이 흐르면서 21세기가 되자 분위기가 반전됐다. 과도한 context switching(쓰레드간의 작업 전환. 프로세스는 1개 이상의 쓰레드로 구성되므로 프로세스간의 전환도 결국 쓰레드 전환이다)이 인류의 적이 되어 버린 것이다.
적절한 쓰레드(프로세스) 개수를 유지해 쓰레드간의 전환없이 계속해서 일을 하는 프로그램을 만들어내는게 성능 문제의 한 주제가 돼버린 것이다. 이러한 추세에 탄력을 받았는지 어쩐지는 잘 모르겠지만 이즈음 슬슬 worker thread에서 하는 일도 변하게 된다. 버퍼에 단순히 데이터를 전달하는 입장에서 점점 더 많은 일을 하게 된 것이다. Worker thread가 IO처리만하고 잠드는 비용을 무시할 수 없었고 코어(그때는 프로세서였지)의 수도 늘어나면서 더 잘짜여진 쓰레드 전략이 필요해졌기 때문이다.
이 즈음의 가장 큰 이슈는 저 그림에서 Buffer(s)를 어떻게 처리하냐 하는 문제였던 것 같다(이 문제는 지금도 골치거리중 하나) 잘 만들어도 결국 버퍼에서 병목현상을 일으키게 되기 때문이다. 그때부터 지금까지도 서버 구조를 설계하면서 가장 신경 쓰는 부분중에 하나가 저 버퍼를 어떻게 처리하는가 하는 점이다. 일을 할때마다 조금씩 다른 구조로 설계를 했고 많은 변화가 있었던 부분이기도 하지만, 큰 그림은 저 위의 그림과 크게 다르지 않았다.
오늘 아침에 양치질을 하다가(드디어 이 글에서 진짜하고픈 말 등장이다) 문뜩 생각이 났는데 worker thread를 여러개 유지해야할 필요성이 있는가 하는 것이다(양치질 하면서 이런 생각을 왜 하는지는 묻지 말아주3). Worker thread가 여러개 필요한 가장 큰 이유는 worker thread가 블럭됐을 때 보다 효율적으로 일을 처리하기 위함이다. 그러나 내가 그동안 만들었거나 다른 사람들이 만들어 놓은 게임 서버의 구현을 생각해 볼때 worker thread가 블럭되는 경우는 사실상 없었다. 있다면 다수의 worker thread들이 저 buffer에 접근하면서 락을 걸어 서로를 괴롭히고 있을때 였다.
이렇게 생각해보자. 저 그림에서 worker thread를 1로 만들면 쓰레드간의 락이 일단 사라진다. 전체적으로 간결한 락 전략을 수립할 수 있고 쓰레드 개수 감소로 불필요한 문 전환도 근본적으로 생기지 않는다. 이러한 생각은 한 개의 worker thread를 사용해도 IO 성능에 문제가 생기지 않는다는 가정이 필요하다. IO의 성능에 차이가 없고 worker thread에서 살짝 다른 일을 하면서도 반응 속도에 영향이 없다면 훨씬 나은 구조가 될 수 있다. 물론 이렇게 되면 버퍼 뒤편에 있는 쓰레드들의 구성에도 변화를 줘야한다. 여러 쓰레드가 버퍼에 접근하면서 락을 사용하게 만들면 worker thread의 개수를 줄이면서 얻는 이익이 많이 날아가 버리니 말이다.
일이 좀 밀려 있기는 하지만 worker thread를 1개만 사용하는 구조를 테스트해봐야 겠다.