# 확장성을 위한 모델링

**URL:** https://heroiclabs.com/docs/kr/nakama/concepts/storage/modeling/
**Summary:** 게임을 만들 때 특히 진행 기반 메커니즘의 경우 플레이어의 경험을 직접 본받아 서버 코드를 모델링하고 싶을 것입니다.

---


# 확장성을 위한 게임 역학 모델링

게임을 만들 때 특히 진행 기반 메커니즘의 경우 플레이어의 경험을 직접 본받아 서버 코드를 모델링하고 싶을 것입니다. 그러나 이렇게 하려면 큰 문제가 있습니다.

플레이어가 경험치를 획득하고 일주일 동안 매일 작업을 완료하면 보상을 주는 가상의 롤플레잉 게임을 생각해 보십시오. 두 가지 시스템을 만들 수 있습니다. 하나는 플레이어가 보상을 받기 위해 충분한 경험치를 획득하는 순간 수준을 올려주는 시스템이고 다른 하나는 매일 자정에 플레이어의 일일 작업 진행 상황을 확인(또는 cron 작업을 사용)하는 시스템입니다.

이 두 시스템을 판단하기는 쉽지만 시간이 지나면서 게임에 추가 시스템이 추가될 가능성이 높습니다. 바로 이 때 이 접근의 문제점이 드러납니다.  비용이 폭발적으로 증가하고 더욱 복잡해지며 취약점은 가려집니다.

**새로운 플레이어가 있을 때마다 처리가 선형적으로 증가하기 때문에 비용이 많이 발생합니다.** 야간 cron 작업을 완료하는 데 시간이 점점 더 오래 걸리거나 서버를 저하시키는 야간 부하 뿐만 아니라 충분히 빠르게 실행하기 위해 값비싼 컴퓨팅 성능이 추가로 필요해집니다.

**새로운 역학, 타이머 또는 이벤트마다 시스템을 새로 구축해야 하기 때문에 복잡해집니다.** 수준 진행 시스템의 경우 일일 작업 시스템의 코드를 쉽게 재사용할 수 없으며 그 반대의 경우도 마찬가지입니다.

**서버 코드를 클록에 연결시킬 수 있으므로 취약합니다.** 자정에 일일 진행 상황 확인을 완료하지 않으면 게임 플레이가 중단되거나 야간 해결 작업을 요구할 수 있습니다. 더 나쁜 것은 플레이어 리소스의 지속적인 고갈 또는 축적과 같은 일부 주기적 시스템이 완전히 유지 불가능해질 수 있다는 것입니다. 해당 cron 작업은 매초 모든 플레이어에 대해 합리적으로 실행될 수 없습니다.

그렇다면 게임 개발자는 어떻게 해야 하나요?

## 순진한 접근 방식에서 벗어나는 방법: 플레이어 중심 처리

좋은 소식은 많은 게임 시스템에서 작동하는 일반화된 방식으로 서버 코드를 모델링하는 방법이 있다는 것입니다. 로그인, 로그아웃, 대결 종료 등과 같은 플레이어 이벤트에 반응 등.

특정 플레이어, 팀 또는 항목에 적용될 수 있는 변경 사항을 주기적으로 확인하는 대신 실제로 발생한 이벤트를 기다리고 대응합니다. 어떤 면에서 이것은 *이벤트 중심 프로그래밍* 패러다임과 비슷합니다. 서버는 콜백 함수를 트리거하는 메인 루프처럼 작동합니다.

이 접근 방식의 경우 다음과 같은 이유로 서버 비용을 줄이고 복잡성을 최소화하며 더 강력한 게임을 만들 수 있습니다:

- 진행 코드는 플레이어에게 직접적인 영향을 끼치는 경우에만 서버에서 실행됩니다.
- 서버 부하는 시간에 따라 더 고르게 분산됩니다.
- 이벤트 처리는 예약된 cron 작업을 기다리는 대신 플레이어 활동에 가까운 시간에 발생합니다.
- 진행 코드는 게임 메커니즘 사이에서 더 쉽게 재사용할 수 있습니다.

이 접근 방식의 개략적인 개요를 확인하고 실제 예를 살펴보겠습니다.

## 구현 패턴: 진행 템플릿

이 모델을 구현하기 위한 하나의 패턴은 세 부분으로 나뉘어 작동합니다:

1. 정적 진행 정의: 시스템 진행을 위한 이정표, 보상 및 기본값을 정의하는 템플릿을 작성합니다.
2. 진행 시작: 진행이 시작되면 템플릿을 플레이어의 데이터에 복사합니다.
3. 플레이어 행동 시 업데이트: 관련 이벤트가 발생할 때마다 플레이어의 진행 상황 사본을 업데이트합니다.

## 템플릿 및 이벤트 처리로 일일 연속 실행 구현

예를 살펴보겠습니다. 가상의 게임에서 연속적으로 매일 게임에 로그인하는 플레이어에게 보상을 주려고 합니다. 플레이어가 24시간마다 한 번 이상 로그인을 7회하면 완료 보상과 3일 차의 작은 보상을 함께 받게 됩니다.

이를 설정하기 위해 JSON 형식의 정적 진행 템플릿을 생성합니다(JSON은 여기에서 하나의 옵션일 뿐입니다. 다른 형식이나 데이터 구조를 사용할 수 있지만 이 개념은 계속 적용됨).

```json
{
  "title":"7-day check-in challenge",
  "progress":0,
  "next_login_after":"1602092170",
  "rewards": [
    {}, {},
    { "gold":300 },
    {}, {}, {},
    {
      "gold":1000,
      "items":[
        "item374"
      ]
    }
  ]
}
```

플레이어가 로그인할 때마다 해당 플레이어가 활성 연속 기록이 있는지 확인하기 위해 일부 코드가 실행됩니다. 활성 연속 실행이 없는 경우(또는 기존 연속 실행이 중단된 경우), 해당 플레이어의 데이터에 템플릿이 복사됩니다:

```
function onLoginEvent(player)
  if (player.streak == undefined or streakIsExpired(player.streak))
    player.streak = copyNewStreakFromTemplate()
```

플레이어가 이미 활성 연속 실행을 갖고 있고 적시에 로그인한 경우, 연속 실행 잠금 해제를 통해 플레이어 진행이 계속될 수 있습니다:

```
if (time.now() > next_login_after and time.now() < next_login_after + ONE_DAY)
    player.streak.progress += 1
    awardUnlock(player, player.streak.rewards[player.streak.progress])
    setTimeForNextUnlock(player.streak)
```

연속 실행의 끝에 도달한 후, 다시 시작하려면 몇 가지 추가 논리가 필요합니다(더 정교한 템플릿은 승수를 지원하고 연속 실행을 반복할 수 있음).

다른 이벤트도 연속 실행에 대한 작업을 트리거할 수 있습니다. 예를 들어, 플레이어는 연속 실행을 취소할 수 있습니다(다른 진행을 시작하기 위해서 등). 이 경우에는 자체 이벤트 핸들러가 있을 것입니다.

## Nakama의 이벤트 후크

Nakama에서는 이 패턴을 [사후 후크](../../../server-framework/introduction/#hooks)로 구현할 수 있습니다. 서버에서 각 메시지를 수신한 후 실행되는 기능을 등록할 수 있습니다. 해당 기능에서 보다 구체적인 이벤트 핸들러에 전달하여 플레이어의 수준을 올리거나 트로피를 수여하거나 이 예에서는 연속 실행을 업데이트할 수 있습니다.

이 경우 클라이언트가 연속 실행에 대한 대역 외 알림을 보내는 `getAccount()` 기능을 호출할 때마다 플레이어의 연속 실행 진행을 업데이트하는 사후 후크를 작성할 수 있습니다.

![getAccount 기능이 호출될 때 플레이어의 연속 실행 진행을 업데이트하는 사후 후크](images/after-hook.png) 이 경우 Nakama가 이미 제공하고 어쨌든 여러분이 사용할 가능성이 있는 API에서 이벤트 트리거를 얻습니다. `getAccount()` 클라이언트 측에서는 연속 실행 업데이트를 트리거하기 위한 추가 코드가 필요하지 않습니다.

## 하나의 패턴, 많은 애플리케이션

이 접근 방식은 다음을 포함하여 수많은 진행 스타일 게임 메커니즘에 작동합니다.

- 플레이어, NPC, 항목 수준 향상
- 항목 분해, 에너지 충전 등 리소스 소모 및 재생
- 도전, 퀘스트 및 달성
- 연속 실행 및 일일 보상과 같은 유지 인센티브

끝없는 cron 작업으로 인한 고통을 덜어주고 이벤트 중심의 게임 메커니즘 모델링을 생각해 보십시오.

## 자세한 내용

[Nakama에서 후크 등록 방법을 알아 보세요](../../../server-framework/introduction/#hooks)
