c# 서버 제작하시는 분 있으신가요?
게임 코디에 올라온 c# 서버 제작하시는 분 있으신가요?라는 질문에 대해 나름대로 답변을 하고자 한다.
구글 검색, GPG 검색으로 c# 개발에 대해 부정적인 시각이 매우 많네요.
그런데 요즘 구인 글 보면 c# 서버 개발 가능자란 문구가 좀 보이는데요…
아직까지 캐주얼 게임에만 적용된 C#서버만 보였는데,
MMORPG 개발사인데 C#서버 개발 가능자를 뽑긴 하던데…
요즘엔 MMORPG에 C#서버로 돌리나요?
업계 동향 보니깐 아예 c#으로 가는 팀도 많아 보이던데….
혹시 경험 및 사례 있으시면 조금 공유 부탁 드려봅니다.
질문과 답변 형식으로 궁금증을 해소하는 편이 읽는 이가 이해하기에 나을 듯 싶다.
참고로 굳이 C#을 고려한 걸 보면 C#을 도입했을 때의 장점은 분명히 알리라 믿고 이 글에서는 성능 문제에만 초점을 맞춘다.
C#이 느리다던데요?
무엇과 비교하는냐에 달렸다. C/C++과 비교하면 느리다. 그런데 얼마나?
C# versus C++ versus Java performance comparison에서 가져온 이 자료에 따르면 Windows에서 C++은 C#보다 단지 15%가 빠를 뿐이다. 2009년도에 성능 차이가 이 정도였으니 현재는 격차가 더 적을 것이다. 물론 벤치마크의 방식과 샘플 데이터에 따라 결과는 달라진다. 하지만 대부분의 벤치마크에서 비슷한 수치를 보고한다.
그런데 왜 사람들은 C#이 느리다고 하죠?
C# 응용프로그램이 느리다고 느끼는 이유는 몇 가지 있다.
Just-in-time 컴파일
.NET Framework 는 JIT 컴파일을 한다. 여러분이 Visual Studio 에서 C#을 컴파일하면 바이너리 코드가 아닌 VM(가상머신) 언어로 결과가 나올 뿐이다. 나중에 응용프로그램을 실행할 때 .NET Framework 런타임이 VM 언어를 다시 네이티브 바이너리로 컴파일한다.
이런 까닭에 응용프로그램의 초기 구동시 반응이 느릴 수밖에 없다. 대부분의 프로그래머는 코드를 몇 줄 고치고 프로그램을 실행하고 닫는다. 이런 과정을 반복하기 때문에 장시간 운영되는 라이브 환경에서 나오는 성능보다 훨씬 낮은 체감 성능을 느낀다.
.NET Framework 에는 C# 코드를 바로 네이티브 코드로 컴파일하는 도구가 있긴 하다. 하지만 이런 도구를 사용하면 JIT가 제공하는 최적화를 놓치게 된다. 이러한 도구는 구동 시간이 중요한 클라이언트에 써야지 전체 처리량(Throughput)이 중요한 서버에 쓸 게 아니다.
가비지 컬렉션 방식
.NET Framework의 메모리 할당 방식은 간단히 말해 스택 할당이다. 따라서 할당 속도는 C++ 보다 빠르다. 물론 C++ 처럼 메모리 할당 전략을 프로그래머가 마음껏 바꿀 재량권은 상당히 박탈당한다.
빠른 할당에 비해 해제는 상당히 느린 편이다. 메모리가 부족하다 싶을 때 가비지 콜렉터가 한꺼번에 정리하기 때문이다. .NET Framework 의 런타임은 전체 처리량에 맞춰 최적화했다. 따라서 이러한 전략은 웹 서버와 같이 일시적인 느려짐이 크게 문제되지 않는 곳에 매우 적합하다. .NET Framework 초기에 ASP .NET 에 초점을 맞춰 마케팅이 이뤄진 점만 봐도 이러한 설계 철학이 이해가 된다.
따라서 C# 으로 서버를 개발한다면 소위 말하는 렉이 주기적으로 발생한다. 렉이 가끔 발생해도 문제되지 않는 서버에 쓰는 게 좋다. 렉이 발생해도 플레이어가 크게 불평하지 않는 캐주얼 게임이 아니라면 게임서버보다는 캐시서버 등에 적합하다고 보면 된다.
메모리 부족
같은 양의 데이터를 처리한다고 볼 때 C# 응용프로그램이 메모리 소모가 심하다. 몇 가지 이유가 있지만 무엇보다 가비지 콜렉션을 최후까지 미루는 탓도 크다.
이렇다 보니 메모리가 부족한 환경에서는 가비지 콜렉션을 자주 해야 한다. 그뿐 아니라 스왑도 자주 발생한다. I/O 가 서버 성능에 가장 큰 영향을 미치는 요소 중 하나라는 점을 생각해야 한다.
단, 라이브 환경에서는 값싼 메모리를 마구 투입하면 되므로 큰 문제가 되지 않을 수도 있다.
참고로 .NET Framework 는 COM 을 통해 메모리 할당 전략을 어느 정도 바꿀 수 있다. 다만 해제 전략과 관련된 어떠한 API 도 제공하지 않는다.
C# 으로 구현한 상용 게임이 있어요?
있다. 마비노기 영웅전! 그 외에도 개발 중인 MMORPG 도 있다. 단, 프로젝트마다 아키텍처와 문제해결 방식이 다르다. 고민 많이 해야 한다.
그렇게 좋다면 왜 C# 서버를 도입한 곳이 별로 없죠?
렉 문제와 설계의 어려움
앞서 말한 렉 문제가 게임 플레이에 크게 악영향을 주는 경우가 있다. 각 서버군 별로 나눠서 필요한 곳에만 C#을 적용해도 된다. 하지만 여러 개의 프로그래밍 언어를 개발팀이 익히고 유지보수해야 하는 문제가 있다. 또한 어떻게 아키텍처를 설계해야 C# 도입의 장점을 최대한 살리고 그 단점을 최소로 줄일 수 있는지 파악하기 힘들다.
느리다
어라, 방금 전까지 C#의 성능이 훌륭하다고 말하지 않았나? 아니, 그건 오해다. 15%? 작다면 작지만 어떤 경우에는 크다. 그게 핵심 엔진 코드라면 치명적일 수도 있다. 대체로 이러한 성능 차이는 분산 서비스로 설계하면 문제가 되지 않지만 단일 게임 서버에 하는 일이 몰린다면 심각한 문제가 야기될 가능성이 있다.
설계의 유연성이 부족하다
C++ 과 같은 네이티브 프로그래밍 환경이 주는 최대 장점은 설계의 유연성이다. 메모리 할당 및 해제 전략을 내 취미대로 고친다거나 무잠금 알고리즘을 적용한다던가(C#에서도 가능하지만, 그냥 해보면 안다) 초고성능을 추구하는 이에게 C# 환경은 답답한 면이 많다.
결론
여기까지 경험담을 정리했다. 잘 알고 잘 알아서 설계해서 알차게 살아보자. 어차피 내가 여러분의 프로젝트 책임자도 아니니 여기서부턴 나도 모르겠다.
뭔말이래 뭐가뭔말인지 하나다 몰겠다 ㅋㅋ c# Major랑 minor는 좀 아는데ㅠ
Violet Kim 네가 알아 들으면 난 실업자 돼 ㅋㅋㅋ
ㅋㅋㅋㅋㅋㅋ 명쾌하네
와 좋은정보 감사합니다.
최고의 장점인 컴파일타임 줄어드는 게 빠진듯 ㅎㅎ
장점은 아니까 검토를 하겠죠. 일일이 떠먹여 줄 수야 없죠. 컨설팅 비를 받는 것도 아닌데 ㅋㅋㅋㅋ
흥미로운 글 잘읽고 갑니다.
참고로 JIT, GC, 메모리 등 말씀 하신 사실과는 많이 다릅니다.
그리고
언어 태생과 목표 자체가 다른 부분이 있으나 설계의 유연성이 부족하진 않습니다.
어느 부분이 사실과 다른지 말씀해주시면 좋을 텐데요.
그리고 게임 개발시에는 메모리 할당 전략 등을 고쳐야 하는데 CLR에서는 이런 부분은 매우 한정적으로 수정이 가능합니다. CLR의 COM API 를 보면 그나마 메모리 할당은 수정이 어느 정도 가능해도 해제 부분은 전혀 손대지 못하게 되어 있습니다. TBB 등에서 구현한 바와 같이 고성능 메모리 할당 라이브러리 붙이거나 개발해 붙이는 것도 사실상 불가능합니다. .NET Framework 초기에 웹 서비스 개발에 맞춰 설계했기 때문에 반응성보다는 전체 처리량에 중점을 두었고 이런 설계가 반응성이 중요한 게임 또는 모바일 환경에 맞지 않기 때문에 최근에 마이크로소프트가 새로운 API 군을 내놓게 된 것이라고 생각합니다.
죄송합니다.
간단히 적는다는게 말이 단언하는걸로 보이게 적었네요
제가 적은 내용은 실제로 개발시에 jit의 초기 실행 속도가.
개발하는데 느낄 정도로 느리지 않다는 것 입니다.
그리고 jit는 실행시 전체를 최적화 하진 않습니다.
( 옵션 조정 가능합니다. 실행후 작동시 하도록.. )
gc가 생각보다 느리지 않다는점,
gc방식 이라고 무조건 훨씬 큰 메모리를 먹는건 아니라는점
메모리가 부족할때만 gc를 하는건 아닙니다. 그리고
메모리가 부족하다면 어떤 application 이건 문제가 생깁니다.
C#으로 서버를 개발한다면 렉이 주기적으로 발생하는것은
아니고 메모리가 임계점에 도달했을때라는 가정이 있어야 한다는것
메모리를 마구 투입해야 할정도로 메모리를 많이 먹지 않습니다.
네이티브 프로그래밍 에서 처럼 메모리 할당 해제 전략을 고치지못하지만 그건 메모리 관리에 대한 특정 부분이고 그것이 설계의 유연성이 없는것은 아니라는점을 이야기 하고 싶었습니다.
말씀하신 부분은 저도 동의하는데 게임 분야에 맞춰 생각할 곳도 있습니다.
최적화에 대해서는 미리 네이티브로 컴파일한 경우보다는 실시간으로 JIT 가 컴파일하는 경우가 최적화 기법을 더 활용할 가능성이 높다는 정도로 정리하고 싶습니다.
GC 가 게임에서 주로 문제가 되는 부분은… CLR은 할당 최적화 기법이라 한데 모아서 가비지 콜렉팅을 하는데 이때 순간적인 행이 걸리는 것처럼 보이고, 사용자가 게임을 떠나는 주요 원인이 될 가능성이 높다는 것입니다. 클라이언트와 게임 플레이에 직접적인 영향을 주는 서버군에 쓸 때는 주의해야겠지요. 서버에서 쓸 땐 사실상 임계점까지 갈 가능성이 매우 높습니다. 30분에 한번 정도라 해도 그때 사용자가 느끼는 불편함은 상당하거든요.
게임은 대부분 하드웨어 사양에 민감하기 때문에 할당 전략, 스레딩 전략 등도 손보지 못하면 곤란할 때가 많습니다. 이 둘을 수정 못한다는 이유 하나 만으로 .NET 을 채택하지 않을 곳이 많다고 생각합니다.
이 글은 게임 분야가 C++ 위주다 보니 게임 개발시 고려할 점 위주로 간단히 적은 것이고 만약 자세한 내용을 원하는 분이 계시다면 책을 여러 권 독파하셔야겠지요. ㅎㅎㅎ
c#은 제전공이 아니라 아쉽네요.
주제가 java로 게임서버를 만들면 어떨까 였다면 좀더 재밌는 이야기를
나눌수 있엇을텐데요 🙂
블로그 활동이 뜸했는데 오랜만에 댓글 달아준 분이 계셔서 즐거웠습니다. 언젠가 자바쪽 이야기도 들려주세요 ^^
오래전 포스팅인데 구글을 통해 흥미로운 내용을 이제 보게되었네요.
재미있는 내용이라 댓글 남기고 갑니다 =)
흥미로웠다니 다행이네요. 다른 의견이 있으면 공유도 해주세요 ^^
저도 구글 검색을 통해서 들어 왔습니다.
저는 웹 퍼블리셔로 일반적인 컴퓨터 언어와는 상관이 적지만, (HTML, CSS, javascript를 언어라곤 하지 않잖아요 ㅠㅠ)
최근에 서버에 대한 무한한 매력을 느껴서 이러 저리 네트웍에 대한 개념을 익히는 중입니다.
정말 좋은 글 잘보고 갑니다.
요즘 자바를 배워서 서버 개발을 해볼까… 생각 중입니다만. 언어 자체에 대한 개념도 없어서. 오락가락 하네요 ㅎㅎ
요새는 자바스크립트의 위상이 엄청나죠. node js 같은 서버측 자바스크립트를 모바일 게임 서버에 많이 적용하니까요.