서버 권한 모델에서는 서버가 전체 게임 상태의 단일 진실의 출처이며 클라이언트는 자신의 입력을 보고하는 것만 신뢰됩니다. 이 아키텍처는 클라이언트가 자신의 위치나 상태를 보고할 때 신뢰하지 않으므로 플라이핵이나 스피드핵과 같은 여러 종류의 치트를 방지하여 공정하고 경쟁적인 게임의 핵심 넷코드 기초가 됩니다.
장점
단순한 서버 소유 시스템에서는 클라이언트가 자신의 입력을 서버에 보내고 서버가 다시 보낸 게임 결과를 표시합니다. 기술적으로는 올바르지만, 모든 플레이어 행동이 서버로 이동하고 처리되며 결과가 클라이언트로 다시 전송되기 때문에 상당한 입력 지연이 발생합니다. 대부분의 게임, 특히 빠른 게임에서는 이 왕복 지연이 게임플레이를 느리게 하고 반응이 없으며 플레이할 수 없다고 느끼게 합니다.
Roblox의 서버 권한 모델에서는 클라이언트가 그 입력을 서버에 보내는 것 외에도 즉시 예측하여 입력의 효과를 보상합니다. 예를 들어, 플레이어가 키를 누르면 클라이언트는 서버의 응답을 기다리지 않고 마지막으로 알고 있는 서버 상태의 몇 프레임 앞으로 예측합니다. 이렇게 하면 클라이언트는 입력 행동의 결과를 즉시 표시할 수 있으며, 이는 네트워크 지연을 숨기고 게임을 반응성이 뛰어난 느낌을 줄 수 있게 합니다.
때때로 클라이언트는 예측을 잘못 하게 되고 (오예측) 네트워크 지연으로 인해 몇 프레임 동안 실수를 인지하지 못합니다. 예를 들어:
오예측이 감지되면 클라이언트는 서버의 권위 있는 상태에 따라 자신의 예측을 수정해야 합니다. 권위 있는 상태가 클라이언트의 예측 상태와 다르다면, 클라이언트는 롤백 및 다시 시뮬레이션해야 합니다. 클라이언트 측 예측, 롤백 및 다시 시뮬레이션 시스템은 "지연 보상"으로 알려져 있으며, 서버 권한 다중 플레이어 게임이 매끄럽고 반응성이 뛰어난 느낌을 주도록 돕습니다.
설정
서버 권한 모델은 올바르게 작동하기 위해 특정 다른 엔진 기술이 필요합니다. Explorer에서 Workspace 객체의 다음 속성 설정을 확인하십시오.
- Workspace.AuthorityMode는 Server여야 합니다 (이 설정은 다음 다섯 가지를 자동으로 설정합니다).
- Workspace.NextGenerationReplication이 활성화되어야 합니다.
- Workspace.PlayerScriptsUseInputActionSystem이 활성화되어야 합니다.
- Workspace.SignalBehavior는 Deferred여야 합니다.
- Workspace.UseFixedSimulation이 활성화되어야 합니다.
- Workspace.StreamingEnabled가 활성화되어야 합니다.
개념
서버 권한 시스템은 다음과 같은 몇 가지 핵심 개념을 기반으로 실행됩니다.
클라이언트 예측
클라이언트 예측을 통해 클라이언트는 마지막으로 알려진 서버 상태보다 몇 프레임 앞서 시뮬레이션을 수행하여 플레이어 입력의 효과를 즉시 예측합니다. 이는 입력 지연을 숨기지만, 예측이 나중에 잘못된 것으로 판명될 수 있으며 (클라이언트 오예측) 수정이 필요할 수 있습니다. 클라이언트는 마지막으로 알려진 권위 있는 서버 상태보다 충분히 앞서 시뮬레이션을 수행하여 입력이 서버에 의도된 프레임에서 도착하도록 하려고 합니다. 클라이언트가 알고 있는 서버 상태 앞에서 예측하는 프레임 수는 클라이언트와 서버 간의 지연에 따라 결정됩니다.
클라이언트 오예측
클라이언트가 서버에서 권위 있는 상태를 받을 때, 그 상태를 그 프레임에 대해 로컬에서 예측했던 기록과 비교합니다. 클라이언트가 예측한 것과 서버가 실제로 한 것 사이에 차이가 있을 경우, 이는 오예측입니다. 오예측은 네트워크 지연의 변화, 클라이언트가 예상하지 못한 방식으로 행동하는 다른 플레이어, 서버에서만 특정 로직이 실행되는 경우 등 여러 이유로 발생할 수 있습니다.
권위 있는 상태가 클라이언트의 예측 상태와 다르면, 클라이언트는 롤백 및 다시 시뮬레이션해야 합니다.
롤백 및 다시 시뮬레이션
클라이언트가 오예측을 감지하면, 서버의 권위 있는 상태로 재설정하고, 예측된 프레임으로 점프하기 위해 다시 시뮬레이션해야 합니다. 네트워크 지연을 기반으로 클라이언트는 입력이 서버에 의도된 프레임에서 도착하도록 마지막으로 알려진 권위 있는 서버 상태보다 충분히 앞서 시뮬레이션을 시도합니다.
요약하자면, 클라이언트는 다음과 같이 수행합니다:
- 서버로부터 권위 있는 상태를 받고, 이를 자신의 예측 상태와 비교합니다.
- 클라이언트의 예측이 잘못된 경우:
- 클라이언트는 서버로부터 받은 마지막 알려진 권위 있는 상태로 롤백합니다.
- 클라이언트는 권위 있는 상태에서 예측 상태로 다시 시뮬레이션하며, 모든 로컬 입력을 다시 적용합니다.
구현
네트워크 소유권 및 예측
서버 권한 모델에서는 핵심 게임 플레이 개체를 서버 소유로 유지하면서 일반적으로 서버 소유와 관련된 입력 지연 비용을 발생시키지 않도록 할 수 있습니다. 자동차, 플레이어 캐릭터 또는 다른 게임 플레이에 중요한 개체와 같은 것들은 다른 플레이어와 상호작용할 때도 서버 소유로 유지될 수 있습니다.
기본적으로 Roblox는 로컬 플레이어 Character 근처의 시뮬레이션 접근이 가능하도록 속성을 자동으로 예측합니다. 그러나 더 세밀한 제어가 필요한 경우에는 RunService:SetPredictionMode()를 사용하여 인스턴스의 예측을 강제로 켜거나 끌 수 있습니다.
시뮬레이션 동기화
서버 권한 모델에서는 클라이언트와 서버가 모두 핵심 시뮬레이션을 실행해야 하며, 클라이언트의 시뮬레이션은 롤백 및 다시 시뮬레이션할 수 있어야 합니다. 이를 활성화하려면 ModuleScript의 RunService:BindToSimulation()를 통해 바인딩된 함수 안에 핵심 로직을 작성하십시오. 이 모듈 스크립트는 클라이언트와 서버 모두에서 초기화해야 합니다.

다시 시뮬레이션하는 동안 Roblox는 BindToSimulation()을 통해 simulation에 바인딩된 함수를 다시 실행합니다. 플레이어 입력을 처리하고, 동기화된 물리 개체와 상호작용하며, 핵심 게임 상태를 업데이트하는 것은 이러한 바인딩된 함수 내에 있어야 합니다.
ModuleScript 이름이 Simulation인 ReplicatedStorage 내의 스크립트:
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Simulation = {}
Simulation.Initialize = function()
RunService:BindToSimulation(function(deltaTime)
-- 플레이어 입력 읽기
-- 게임 상태 업데이트
end)
end
return Simulation속성으로 상태 동기화
Roblox는 예측된 인스턴스에서 시뮬레이션 접근이 가능한 모든 속성을 자동으로 동기화합니다. 사용자 데이터의 경우, 속성은 예측된 것으로 표시된 인스턴스를 동기화하는 주요 방법입니다; 이러한 인스턴스에서 서버의 진실 출처와 클라이언트의 예측 간의 속성 값 불일치는 전체 롤백 및 다시 시뮬레이션을 촉발합니다.
속성 한계
속성이 복제되려면 다음 모든 기준을 충족해야 합니다:
- 속성은 그 Instance의 처음 64개 속성 중 하나여야 합니다.
- 이름은 최대 50자를 포함해야 합니다.
- 문자열 유형의 속성이라면 값은 최대 50자를 포함해야 합니다.
시뮬레이션 접근
엔진 API 참조의 많은 속성과 메서드는 시뮬레이션 접근 레이블이 있습니다. 예를 들어, BasePart.CFrame와 같은 속성입니다. 이 레이블이 있는 속성은 서버 권한 시스템에 의해 예측됩니다. 또한 이 레이블이 있는 속성과 메서드만 RunService:BindToSimulation()으로 바인딩된 함수 내에서 접근할 수 있습니다.
입력 동작
서버 권한 게임에서는 클라이언트가 게임 상태에 영향을 미치는 주요 방법이 입력 동작 시스템을 통해 이루어집니다. 이러한 입력은 서버로 전송되며 다시 시뮬레이션 중 클라이언트에서 재생됩니다. 따라서 InputActions는 핵심 시뮬레이션에 영향을 미치는 모든 입력에 대해 사용해야 하며, 처리되기 전에 건전성을 확인해야 합니다.
InputContexts는 엔진이 InputContext에 대한 소유권을 알 수 있도록 Player의 자식이어야 합니다. 한 가지 방법은 ReplicatedStorage 하위 폴더에 InputContexts를 추가하고 ServerScriptService 하위의 Script를 사용하여 플레이어마다 InputContexts를 복제하는 것입니다:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local InputsFolder = ReplicatedStorage:WaitForChild("Inputs")
local function onPlayerAdded(player)
local clone = InputsFolder:Clone()
clone.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end이 패턴을 사용하면 RunService:BindToSimulation() 내에서 클라이언트와 서버 모두에 대해 모든 플레이어의 InputActions를 읽어 지정된 프레임에 대한 동일한 데이터를 수신하고 이전 프레임의 입력을 속성에 기록할 수 있습니다. 예를 들어, RunAction 입력 동작이 트리거될 때 캐릭터가 달리기를 시작하도록 할 수 있습니다.
원격 이벤트
원격 이벤트는 클라이언트와 서버 간의 명확한 통신을 촉진하기 위해 서버 권한 모델 내에서 여전히 사용할 수 있습니다. 예를 들어, 서버는 점수를 얻거나 객체를 집는 것에 대해 데이터를 방송하기 위해 원격 이벤트를 사용할 수 있으며, 클라이언트는 버튼 눌림이나 3D 세계에서 객체를 탭하는 것과 같은 서버에 입력을 보내기 위한 대체 API로 원격 이벤트를 사용할 수 있습니다.
애니메이션, 소리 및 효과
클라이언트 측 효과인 애니메이션 및 소리는 클라이언트 시뮬레이션이 단순히 권위 있는 서버 상태의 예측임을 알고 작성해야 합니다. BindToSimulation()은 바인딩된 함수 내에서 호출될 수 있는 속성과 메서드의 범위를 제한하여 동기화된 시뮬레이션 상태에만 쓰도록 가이드합니다. 이 시뮬레이션 결과를 표시하고, 효과 및 소리를 트리거하는 등의 작업은 시뮬레이션의 결과를 읽고 원하는 효과를 트리거하는 RenderStepped에 연결된 별도의 함수에서 수행해야 합니다.
예측된 시뮬레이션을 렌더링하는 데 관한 추가적인 안내는 고급 기술 가이드에 설명되어 있습니다.
예제 프로젝트
이 문서 외에도 다음 템플릿들이 시작하는 데 도움이 될 수 있습니다:


