TIL

TIL 8/27

nbcssw 2024. 8. 27. 21:40

스탠다드반 강의 - 게임 서버

게임 서버의 역할

게임 서버의 역할에 대해 알아보기 전에, 1인용 게임에서 어떠한 일이 일어나고 있는지 살펴보자.

1. Inputs (입력받기): 사용자가 키보드, 마우스 등을 누르는 것으로 컴퓨터가 정보를 획득하는 과정

2. Simulate (로직 처리하기): 게임 정보를 담고 있는 상태인 Session이 상태 변화를 처리하고 계산하는 과정

3. Render (렌더링하기): 변화된 상태를 화면에 표현하는 과정

4. Wait (대기): 다음 Input이 있을 때까지 대기

이것을 반복하는 것을 Game Loop라고 한다.

 

1인용 게임에서는 모든 입출력과 연산 처리가 사용자의 컴퓨터에서만 일어나지만, 온라인 게임이 되면 이야기가 달라진다. 사용자가 여러 명이 되고 사용자끼리의 상호작용이 일어나기 때문에, 로직을 처리하는 과정에서 차이가 발생한다. Simulate 과정이 사용자의 컴퓨터가 아니라 다른 컴퓨터나 서버에 있다.

 

게임 서버와 클라이언트의 상호 작용

온라인 게임에서, 사용자가 사용 중인 컴퓨터를 클라이언트라고 한다. 대부분의 온라인 게임에서는 클라이언트에서 게임 로직을 처리하는 역할 일부는 서버에서 처리한다. 그리고 클라이언트와 서버 간에는 컴퓨터 네트워크를 통해 서로 데이터를 주고 받는다.

 

클라이언트가 서버에 데이터, 즉 메세지를 보내면 서버는 메세지의 내용에 따라 특정한 행동을 하고, 서버가 클라이언트에 메세지를 전달하면 클라이언트는 그 내용에 따라 특정한 행동을 한다. 이렇게 메세지가 오가는 것을 상호작용이라고 한다. 클라이언트와 서버의 상호 작용은 크게 네 가지로 분류된다.

  1. 연결
  2. 요청과 응답
  3. 능동적 통보
  4. 연결 해제

 연결을 통해 최초로 클라이언트가 서버와 데이터를 주고받을 준비를 한다. 클라이언트가 서버에 연결을 요청하면 서버가 이를 수락해서 연결을 한다. 그 후에는 클라이언트가 서버에 메세지를 보내면 서버는 메세지에 따른 행동을 취한다. 이를 요청과 응답이라고 한다. 하지만 연결을 했다고 해서 모든 행동이 허락되는 것은 아닌데, 클라이언트가 서버와 연결되있으면 클라이언트는 서버에 '내가 누구인지' 알려주고, 서버는 클라이언트의 신원을 확인해서 연결을 유지할지 말지 판단해야 한다.

 또한, 모든 메세징이 요청과 응답의 형식을 취할 필요는 없다. 클라이언트가 서버에 어떤 상황을 통보하고, 그에 대한 서버의 반응을 굳이 받지 않아도 되는 상황도 있고, 서버가 클라이언트에게 능동적으로 통보해야 할 상황도 있다. 이것은 온라인 게임의 유저가 한명뿐이 아니기 때문이다. 그리고 클라이언트와 서버 간의 통신을 차단하거나 해제해야하는 경우 서버에서 연결을 해제하기도 한다.

 

게임 서버가 하는 일

  1. 클라이언트와 상호 작용
  2. 보안 처리
  3. 상태 관리

 온라인 게임의 사용자는 한명뿐이 아니기 때문에, 여러 플레이어 간의 행동을 중앙에서 관리하여 결과를 판정하는 역할을 서버에서 수행한다. 이를 서버에서 수행해야 하는 이유는 클라이언트에서 수행하는 경우 문제가 발생할 수 있기 때문이다.

 

 클라이언트에서 행동의 결과를 관리하게 된다면 다음과 같은 문제가 발생하게 된다: 예를 들어, 플레이어 1과 2가 있고, 1이 2를 공격하는 상황을 가정해보자. 플레이어 1은 본인의 공격력과 상대의 hp, 방어력 등을 알고 있기 때문에 플레이어 1의 클라이언트에서 결과를 계산해 서버에 통보하고, 서버는 그 결과를 그대로 플레이어 2에게 보내주면 된다. 하지만, 플레이어 1이 해킹을 통해 클라이언트에서 자신의 공격력을 높게 해버리면 비정상적인 결과가 나와버려 공정성을 해치게 된다.

 하지만 서버에서 수행할 경우, 플레이어 1의 클라이언트는 서버에 자신이 플레이어 2를 공격했다는 사실만 알려주고, 서버에서 결과를 처리하기 때문에 위와 같은 상황이 발생하지 않게 된다.

 

 그렇다면 모든 게임 플레이 판정을 서버에서 처리하면 부정행위를 막을 수 있을까? 가능은 하지만, 다른 문제를 일으키게 된다. 극단적으로 게임 판정뿐만 아니라 모든 로직을 서버에서 처리하게 된다면, 사용자의 행동 하나하나가 전부 네트워크르 통해 서버에 전달되고, 서버가 클라이언트에게 데이터를 보내는 행동이 이루어져야 하는데, 이는 게임 플레이의 쾌적함을 해칠 수 있게 된다. 이건 Latency(대기 시간) 때문이다. 현대 네트워크의 레이턴시는 몇 밀리초에서 수백 밀리초로 다양한데, 사용자의 입력이 서버에 도달하는 시간, 서버에서 이를 판정하여 클라이언트에게 보내는 시간이 제각각 달라지게 되어 게임 진행 속도에 영향을 주게 되기 때문이다. 결국, 모든 로직을 서버에서 처리할 순 없고, 서버에서 수행할 로직과 클라이언트에서 수행할 로직을 잘 타협해서 구분하는 것이 중요하다.

 

 이러한 역할들을 수행하는 서버가 중간에 꺼져 버리면 플레이어간의 상호 작용이 중단되고, 정상적인 게임 플레이가 불가능해진다.

 

게임 서버의 목표

  1. 안정성
  2. 확장성
  3. 성능

 안정성이란 게임 서버가 얼마나 죽지 않는가를 의미한다. 게임 서버는 365일 24시간 항상 켜져있어야 하는 컴퓨터이기 때문에 고장이 나면 안된다. 구조적으로 설계가 잘못되었거나, 코딩 실수가 서버의 안정성을 위협한다. 또한, 서버가 오작동을 해서 결과가 이상하게 나와도 사용자가 현금으로 구매한 아이템이 사라지거나 하는 등의 문제가 일어나기도 한다.

 

 확장성이란 서버를 얼마나 많이 설치할 수 있느냐를 의미한다. 게임의 사용자가 늘어나더라도, 서비스의 품질이 떨어지지 않고 유지되는가를 결정한다. 확장성이 확보된 서버는 사용자 수가 어마어마하게 많아지더라도 서버가 죽거나 느려지지 않고 쾌적한 게임 환경을 제공한다.

 서버 확장성을 올리는 방법에는 크게 수직적 확장과 수평적 확장이 있다. 수직적 확장은 서버의 하드웨어를 더 좋은 것으로 바꾸는 것이고, 수평적 확장은 서버의 컴퓨터 수를늘리는 것이다. 수직적 확장은 단위 성능과 구조 측면에서 유리하지만 확장성에 한계가 있고, 수평적 확장은 그 반대이지만 확장성을 결국 해결한다. 이 둘을 잘 조절하여 확장성을 확보하는 것이 중요할 것이다.

 

 성능은 확장성과 비슷해 보이지만 다른 요소이다. 성능은 서버의 처리 속도를 의미한다. 게임의 장르마다 요구되는 성능이 다르다. 플레이어가 순서대로 한 명씩 행동을 취하는 게임(예를 들어 턴제 게임)은 처리 속도가 제법 느려도 괜찮다. 하지만 다수의 인원이 동시에 행동을 취하는 게임(예를 들어 슈팅 게임)은 처리 속도가 굉장히 중요하다. 게임 서버의 성능을 높이는 기본적인 원칙은 서버의 단위 처리 속도를 높이는 것이다.

 

 

데일리 루틴 47번 - 문자열 내 마음대로 정렬하기

https://school.programmers.co.kr/learn/courses/30/lessons/12915

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

function solution(strings, n) {
    const newArr= [];
    for(let i=0; i<strings.length; i++)
        newArr.push(...strings[i][n]);

    for(let i=0; i<strings.length; i++)
        strings[i] = newArr[i].concat(strings[i]);

    strings.sort();

    for(let i=0; i<strings.length; i++)
        strings[i] = strings[i].substring(1);

    return strings
}

'TIL' 카테고리의 다른 글

8/29 TIL  (0) 2024.08.29
TIL 8/28  (0) 2024.08.28
8/26 TIL  (0) 2024.08.26
8/23 TIL  (0) 2024.08.23
8/22 TIL  (0) 2024.08.22