4. 서버 토폴로지: 단일 vs 분산, 존/샤딩, 매치메이킹, 부하분산
난이도 상모범답안 — 서버 토폴로지: 단일 vs 분산, 존/샤딩, 매치메이킹, 부하분산
난이도: 상
핵심 답변
- 단일 vs 분산 / scale-up vs scale-out: 단일 서버는 개발·운영·디버깅이 단순하고 상태 공유 비용이 없지만, 한 머신 성능이 천장이고 단일 장애점(SPOF)이다. 분산은 확장성·장애 격리를 얻는 대신 통신·상태 동기화·운영 복잡도가 커진다. **Scale-up(수직 확장)**은 더 좋은 한 대로 키우는 것(한계·비용 급증), **Scale-out(수평 확장)**은 여러 대로 늘리는 것(상태 분배가 관건).
- 존(zone) 분할: 하나의 거대한 월드를 지리적 영역으로 쪼개 영역별로 다른 서버/스레드가 담당. 공간 부하를 분산. 같은 월드 안에서 영역만 다름.
- 채널/샤드(shard) 분할: 같은 콘텐츠(같은 월드)를 통째로 복제한 평행 인스턴스(채널1, 채널2…). 인원이 많으면 채널을 늘려 분산. 다른 채널 플레이어는 서로 보이지 않음.
- 매치메이킹: 대기시간 ↔ 매칭 품질(실력/핑) 사이의 균형 문제. 대기열에서 비슷한 실력·낮은 핑을 묶되, 너무 엄격하면 못 찾고 너무 느슨하면 불공정/고핑.
- 부하분산: 신규 접속/룸을 여유 있는 인스턴스로 배분하고, 디스커버리로 클라이언트를 올바른 서버로 라우팅.
깊이 있는 설명 (왜, 트레이드오프)
존 vs 샤드는 해결하는 문제가 다르다. 존 분할은 "한 월드 안 공간 부하"를 다룬다(넓은 맵을 영역으로 나눠 각 서버가 일부만 시뮬레이션). 샤드/채널은 "같은 공간에 사람이 너무 많음"을 다룬다(월드를 통째로 복제). 핵심 차이: 존은 경계를 넘는 상호작용(시야/전투가 경계를 가로지름)을 처리해야 하고, 샤드는 서로 다른 샤드 간엔 상호작용이 아예 없어 단순하지만 "친구와 다른 샤드"가 생긴다. 실무에선 둘을 섞는다(샤드로 큰 인원을 나누고, 각 샤드 내부를 존으로 시뮬레이션).
존 경계의 어려움(seamless world). 플레이어가 존 경계를 넘으면 담당 서버가 바뀐다. 경계 부근에서 양쪽이 보이게 하려면 인접 존 서버가 경계 영역(AOI, area of interest) 엔티티를 교환·중계해야 하고, 핸드오프(상태 이관) 중 패킷 누락·중복·끊김을 막아야 한다. 그래서 경계를 겹치게(overlap) 두거나, 핸드오프 동안 양쪽이 잠시 동시에 인지하는 설계를 쓴다.
매치메이킹의 트레이드오프. 보통 MMR/Elo 같은 실력 점수로 비슷한 사람을 묶되, 대기 시간이 길어질수록 매칭 허용 범위(실력 차, 핑)를 점진적으로 넓힌다(expanding search window). 지역 매칭은 핑을 낮추지만 인구가 적은 지역은 대기가 길어진다. "공정성 vs 속도 vs 핑"은 동시에 최적화 불가라 게임 성격에 맞춘 정책이 필요하다.
분배 키의 선택. scale-out에서 플레이어를 어느 서버에 둘지는 "분배 키"로 결정한다. 무작위/라운드로빈은 균등하지만 친구를 흩뜨린다. 길드/파티/지역 기준으로 묶으면 함께 플레이가 쉽지만 핫스팟이 생긴다. 일관 해싱(consistent hashing)을 쓰면 노드 추가/제거 시 재배치를 최소화한다.
응용/실무 연결 (게임서버에서)
(a) 도시 몰림 해소: 마을 광장은 "같은 공간에 인원 과밀" 문제이므로 **채널/샤드(또는 인스턴스 분할)**가 적합 — 광장을 채널1·채널2로 복제해 인원을 나눈다. 동시에 넓은 필드는 존 분할로 영역별 부하를 나눈다. 존 이동은 핸드오프로 처리: 목적지 존 서버에 플레이어 상태를 이관하고, 경계 구간은 AOI 중계로 끊김 없이 전환. 채널 이동은 더 단순(현재 채널 떠나 대상 채널 입장, 같은 캐릭터 데이터 사용).
(b) 동접 한계 돌파 + 친구 문제: 분배 키로 월드/샤드를 나눈다. 친구가 흩어지는 문제는 (1) 파티/길드 단위로 같은 샤드에 배정, (2) "친구 따라가기"로 친구가 있는 샤드를 선택, (3) 샤드 간에도 파티/채팅/거래는 글로벌 서비스로 분리해 샤드 경계와 무관하게 동작하게 설계. 데이터는 캐릭터를 샤드에 종속시키지 말고 계정 단위 글로벌 저장 + 샤드는 런타임 배치만 담당하는 편이 유연하다.
(c) 디스커버리/라우팅: 게임 서버 인스턴스들이 자신의 주소·부하·여유를 서비스 레지스트리(예: Redis/Consul/etcd)에 등록. 클라이언트는 게이트웨이/디렉터리 서버에 "입장할 곳"을 물어보고, 디렉터리가 부하·지역·샤드를 고려해 적절한 인스턴스 주소 + 입장 토큰을 발급. 오토스케일로 인스턴스가 뜨고 죽어도 클라이언트는 항상 디렉터리를 통해 라우팅되므로 직접 주소를 알 필요가 없다. 죽은 인스턴스는 헬스체크로 레지스트리에서 제거.
흔한 오답·함정
- 존과 샤드를 혼동: 존=한 월드의 공간 분할, 샤드/채널=월드 복제. 해결 문제가 다르다.
- "처음부터 분산이 정답": 동접이 작으면 단일이 더 빠르고 싸다. 분산은 필요할 때 도입.
- 존 경계 핸드오프를 무시: 경계에서 끊김/중복/시야 단절이 가장 까다로운 부분이다.
- 무작위 분배로 친구 분리: 소셜 게임에서 치명적 UX. 파티/길드 기준 배정 필요.
- 클라이언트에 서버 주소를 하드코딩: 오토스케일/장애조치가 불가능해진다.
꼬리질문 대비
-
Q: 인스턴스 던전(파티 전용 공간)은 샤드와 무엇이 다른가요? A: 인스턴스 던전은 특정 파티만을 위한 일회성 격리 공간(필요 시 생성·종료). 샤드는 다수가 공유하는 평행 월드. 둘 다 격리지만 수명·공유 범위가 다르다.
-
Q: 일관 해싱이 단순 모듈러 해싱보다 나은 이유는? A: 단순 mod N은 노드 수가 바뀌면 거의 전부 재배치된다. 일관 해싱은 링 구조로 노드 추가/제거 시 인접 일부만 이동해 재배치 비용·캐시 미스가 작다.
-
Q: 부하분산을 연결 단위로만 하면 안 되는 이유는? A: 게임은 연결 수보다 "그 연결이 만드는 CPU/시뮬레이션 부하"가 중요하다. 한 도시에 몰린 적은 연결이 더 큰 부하일 수 있어, 부하 메트릭 기반 배치가 필요하다.