[Unity] 게임 서버/네트워크 라이브러리 Mirror & Mirage 소개

JongHa Shin (John)
Ward Games
Published in
11 min readMar 30, 2021

Jong Ha Shin (John)

  • 들어가며 ::
  • 게임 서버를 만드려면 무엇이 필요할까?
  • Mirror & Mirage network library 소개
  • ZOOPORTS 프로젝트에서 Mirror & Mirage를 적용하게 된 계기 (feat. PUN2)
  • 마치며 ::

들어가며 ::

안녕하세요! Ward Games의 소프트웨어 엔지니어 John입니다. 게임 개발자라면 한 번쯤은 재미있는 온라인 게임을 만들어서 서비스하는 생각을 해봤을 것입니다. 멋진 싱글플레이 게임들도 많지만, 멀티플레이 게임만이 줄 수 있는 재미를 제공해 줄 수는 없기 때문이겠죠. 하지만 이제 막 게임 제작에 입문하신 개발자분들이나 새롭게 멀티플레이 게임을 만들고 싶은 분들에게는 가장 막연하고 부담스러운 것이 바로 서버/네트워크 프로그래밍입니다. 하지만 이미 제작된 서버 API를 잘만 이용한다면 누구든지 쉽게 온라인 게임을 만들 수 있는 세상이 되었습니다. 이번 포스팅에서는 게임 서버의 인사이트와 함께, 여러분들의 게임 서버 구현을 보다 쉽게 만들어줄 Mirror, Mirage 네트워크 라이브러리를 간략하게 소개해드리고자 합니다.

게임 서버를 구현하려면 무엇이 필요할까?

일반적으로 서버/클라이언트 모델의 온라인 게임을 만들고 운영하려면 게임 서버 빌드를 만들고 호스팅해야 합니다. 그 서버 빌드에는 서버 엔진 파트와 게임 컨텐츠 파트가 구현되어야 합니다. 엔진 파트는 Transport 설계, 소켓 통신, API 등 전반적인 네트워킹과 관련된 것들을 구현하며 컨텐츠 파트는 말그대로 게임의 온라인 컨텐츠 기능을 구현하는 부분입니다. 그렇다면 엔진 파트는 어떻게 구현할 수 있을까요?

먼저 성능과 필요한 기능 등을 고려해 서버 엔진을 팀에서 자체적으로 제작하는 방법이 있습니다. 이 방법의 장점은 서버 기능의 확장, 유지 보수가 용이합니다. 구현하고자 하는 게임에 최적화도 가능합니다. 그리고 구현 방식을 자유롭게 선택할 수 있습니다. 하지만 서버 엔진을 구현하기 위해 필요한 네트워크 지식을 모두 알아야 되며 제작에 드는 시간과 비용을 고려하면 결코 쉬운 작업이 아닐 수 있습니다. 그래서 소규모 팀에서는 그다지 추천하지 않는 방식입니다.

또 다른 방법은 이미 만들어진 게임 서버 라이브러리와 제공되는 API를 이용하는 방법이 있습니다. 이미 많은 솔루션이 있으며 각 솔루션마다 각기 다른 특징을 가지고 있기 때문에 구현하고자 하는 게임에 맞게 선택을 해서 사용하면 됩니다. 이 방법의 장점은 서버 엔진을 구현하는 시간과 비용을 절약할 수 있다는 것, 경우에 따라서는 네트워크 프로그래밍에 관한 지식이 없어도 API 사용 방법만 익히면 멀티플레이를 구현할 수 있다는 것입니다. 단점은 라이브러리 내에 구현된 서버 엔진에 따라서 원하는 기능의 추가나 성능 최적화가 제한될 수 있다는 점입니다. 예시로 Unity 엔진에서는 Unet이라고 불리는 네트워킹 전용 고수준 API (HLAPI)와 네트워크 라이브러리를 자체적으로 지원하며 이를 이용해서 멀티플레이 게임을 구현할 수 있습니다. (다만 Unet은 유니티에서 제거될 예정이기 때문에, 새로운 프로젝트는 Unet으로 구현하지 않는 것을 추천합니다.)

Mirror & Mirage 네트워크 라이브러리 소개

다행히도 우리는 Unity에 이용할 수 있는 좋은 네트워크 라이브러리가 이미 많이 만들어져있는 시대에 살고 있습니다. 개발자들은 단지 제작하려는 게임에 어떤 것이 좋을지 게임 제작 초기에 신중하게 결정만하면 됩니다. 그 중에서도 Unet으로부터 포크(fork)해 다수의 개발자들이 오픈 소스로 참여하고 제작한 Mirror 와 Mirror에서 포크하여 전문 서버 개발자들이 새롭게 제작 중인 Mirage를 소개해드리고자 합니다.

Mirror의 특징

  1. Mirror는 Unet에서 포크되었기 때문에 마찬가지로 HLAPI 입니다. Mirror를 사용하는 개발자들은 서버 엔진 단의 작동 방식을 몰라도 API만 잘 활용하면 손쉽게 멀티플레이를 구현할 수 있습니다.
  2. Mirror는 Low level의 Transport를 지원합니다. Mirror는 초기에 TCP 베이스로 탄생했으나 게임에 맞는 다른 Transport를 사용하면 자동으로 성능 최적화가 가능합니다. 예를 들어 보다 빠른 페이스의 게임(액션 등)에서는 TCP보다는 UDP를 이용하는게 좋은데, 원하는 Low level의 Transport를 Mirror에서는 쉽게 적용할 수 있습니다.
  3. Server/Client의 서버 모델을 지원합니다. 데디케이티드 서버(Dedicated Server), 권한 서버 (Authority Server) 라고도 하는 이 방식은 실제로 게임 플레이의 핵심 로직을 담당하는 전용 서버 + 클라이언트로 구성됩니다. 특히 경쟁 요소가 있는 게임들에는 보안 이슈를 다루는 것이 무척이나 중요한데, 이를 서버 쪽에서 처리할 수 있게됩니다. 추가로 리슨 서버(Listen Server) 방식도 지원하여 한 명의 플레이어가 서버 역할을 대신하고 호스트(방장)가 되는 것도 가능합니다.
  4. 네트워크의 전반적인 기능은 NetworkBehaviour라는 상위 오브젝트에 구현된 메서드를 override해서 구현합니다.
  5. 오픈 소스 기반 라이브러리입니다. 다수의 멋진 개발자들이 꾸준히 Github에 업데이트를 하고 있으며 많은 온라인 게임 프로젝트들이 Mirror로 개발 & 서비스되고 있습니다. Mirror 전용 Discord 채널에는 개발 내용을 공유하고 질문을 할 수 있는 커뮤니티가 잘 구축되어 있습니다.
  6. 오랜 기간 개발되어 API 문서와 튜토리얼이 잘 되어있습니다. 특히 제가 처음 Mirror의 API를 익힐 때는 유니티 서버 프로그래밍 관련 컨텐츠를 제작하는 First Gear Games 의 영상을 많이 참고하였습니다. 무료 컨텐츠도 있지만 First Gear Games의 patreon에서 유료 구독을 하면 이 분이 개발한 Mirror 튜토리얼 컨텐츠를 받아볼 수 있습니다.
  7. 모든 API 메뉴얼이 영어입니다.

Mirage의 특징

  1. Mirror에서 포크한 오픈 소스 라이브러리입니다. 많은 특징이 Mirror와 비슷합니다. Mirage는 개발이 시작된지 오래되지는 않았지만 Mirror보다 전문적인 서버 개발자들이 꾸준히 개발을 진행하고 있습니다.
  2. Mirror는 태생이 TCP 베이스인 반면, Mirage는 UDP 베이스입니다.
  3. Unity 2019부터 도입된 fast domain reload를 지원합니다.
  4. Mirage는 Mirror에 비해 더 세부적인 기능들로 모듈화가 잘 되어있습니다. 따라서 사용이 좀 더 쉽습니다. 저는 둘 다 사용해봤는데, Mirage가 확실히 좀 더 적응하기가 편했습니다.
  5. UPM(Unity Package Manager)를 통해 업데이트 됩니다. 코드의 직접적인 수정에는 제한이 있지만, 오픈 소스가 업데이트될 때마다 쉽게 받아서 적용할 수 있습니다.
  6. API가 전반적으로 event 기반으로 작동합니다. Mirror 보다 직관적입니다.
  7. 유저와 오브젝트 숫자가 많아도 최적화가 잘 되어 있어서 서버가 CPU와 메모리 사용량을 적게 먹습니다.
  8. 같은 프로세스 내부에 다수의 클라이언트 + 다수의 서버를 구현할 수 있도록 지원합니다.
  9. Error Handling을 자체적으로 지원합니다.
  10. Mirror와 마찬가지로 모든 API 메뉴얼이 영어입니다.

여러모로 Mirage가 Mirror보다 좋아보이는데 아무래도 Mirror 보다는 비교적 최근에 개발이 진행이 되고 있어서 그렇습니다. 다만 그만큼 Mirror에 비해서 Mirage는 메뉴얼이 잘 되어 있지는 않습니다. 필요한 내용은 모두 있지만 업데이트가 느려서 최신 변경을 반영하고 있지는 않습니다. 최신 변경이 반영된 튜토리얼은 거의 없다시피 합니다.

Mirror 컨텐츠를 개발하는 First Gear Games 디스코드 커뮤니티에서 한 달 전에 Mirror vs Mirage 관련해 개발자들이 열띤 토론 시간을 가졌었는데요, 결론적으로 많은 분들이 Mirage의 손을 들어줬습니다. 하지만 아직 Mirage는 개발 단계에 있는 만큼 API가 바뀔 여지가 많다는게 중론이었고(Mirror에서 포크한 기능들을 Mirage 전용 API로 변경하는 것을 포함) First Gear Games 개발자님은 Mirage 튜토리얼 컨텐츠를 꾸준히 업데이트하기에는 불안정하다는 이유로 개발을 연기하셨습니다.

따라서 Mirage를 사용하기 위해서는 이전 API 문서를 보면서 로직을 익히고 최신 라이브러리 코드를 분석해 가며 개발을 진행해야 되는 번거로움이 있습니다. 새로 시작하는 프로젝트에 둘 중 하나를 써야한다면 Mirage를 추천하지만, 서버 프로그래밍에 익숙하지 않다면 문서와 튜토리얼이 잘 되어 있는 Mirror를 선택하시는 것이 좋습니다.

ZOOPORTS 프로젝트에서 Mirror & Mirage를 적용하게 된 계기 (feat. PUN2)

저희 Ward Games의 온라인 게임 프로젝트인 ZOOPORTS에서는 현재 Mirage로 게임 서버를 개발하고 있습니다. 그 전 알파버전까지는 Photon의 PUN2를 사용했었는데 ZOOPORTS 게임과는 맞지 않아서 베타버전부터는 Mirage로 변경하게 되었습니다.

Phton PUN2의 장점과 단점

프로토타입부터 알파까지 사용했던 PUN2의 장점은 다음과 같습니다.

  1. API 문서와 튜토리얼이 잘 되어 있음
  2. 서버와 클라이언트 로직을 분리하지 않아도 됨. (사실상 클라이언트만 구현하면 멀티플레이가 가능한 느낌)
  3. 개발 속도가 빠름
  4. 별도의 서버 호스팅을 하지 않아도 PUN2 제품 자체에서 클라우드 서버, 스케일링, 게임 룸, 매칭 등을 지원해줌

PUN2는 이처럼 유니티에서 멀티 플레이 게임을 개발하는 데에 좋은 솔루션입니다. 하지만 몇몇 게임 장르에서는 다음과 같은 단점 때문에 사용에 한계가 존재합니다.

  1. Relay Server 로직을 사용합니다. PUN2에서는 지정된 클라이언트 (마스터 클라이언트)가 게임 서버의 데이터를 게임 룸의 다른 플레이어에게 전송하는 방식을 사용하는데 보안에 취약합니다.
  2. 사실상 게임 로직을 전부 클라이언트에서 처리합니다. 따라서 네트워크가 좋지 않은 플레이어가 있다면 경우에 따라서 게임 진행이 원활하지 못할 수 있습니다.
  3. 데이케이티드 서버를 사용할 수 없습니다. 서버의 역할을 비슷하게 해주는 마스터 클라이언트가 있습니다. 다만 마스터 클라이언트가 처리하는 로직이 있는데 연결이 끊겨버리면 게임에 문제가 발생할 수 있습니다.

PUN2는 이러한 점들 때문에 장르가 한정됩니다. 특히 PC보다 네트워크 속도가 좋지 않은 모바일에서는 빠른 페이스의 게임을 제작하기 힘듭니다. 저희 ZOOPORTS 또한 빠른 페이스의 액션/스포츠 게임이기 때문에 상기 단점들이 치명적이었구요. 그래서 베타 버전부터는 Mirror를 사용하기 시작했습니다. Mirror 포팅을 시작한지 얼마 되지 않아 Mirage를 알게되어 검토한 뒤, 지금은 Mirage로 전부 포팅한 상태입니다.

서버 솔루션은 신중히 고민하는 것이 좋습니다. 제작 중간에 바꾸게 되면 경우에 따라 시간이 꽤 걸릴 수 있습니다. 각 솔루션마다 어떤 장단점이 있는지 기획 단계에서 꼭 확인해보시고 게임에 적합한 것을 선택하시면 좋을 것 같습니다.

마치며 ::

Mirror & Mirage 처럼 잘 만들어진 네트워크 라이브러리를 사용한다면 멀티 플레이 게임을 쉽게 만드실 수 있습니다. 생각해두었던 온라인 게임이 있다면 이 두 가지의 라이브러리를 이용해 보시길 추천드립니다!

그리고 서버 프로그래밍과 관련해서 여유가 된다면 한 번 정도는 게임 서버의 엔진 파트를 바닥부터 만들어보시는 것을 추천드립니다. 단순히 API를 사용하는 것 이상으로 네트워크 라이브러리에 대한 분석력과 이해도가 높아지기 때문입니다.

이상으로 Mirror와 Mirage 네트워크 라이브러리 소개에 관한 포스팅을 마치도록 하겠습니다. 기회가 된다면 Mirage 튜토리얼도 블로그에서 다뤄보도록 하겠습니다.

읽어주셔서 감사드립니다.

레퍼런스

--

--