세션 상태
게임 세션은 다음 상태를 순서대로 거칩니다.
| 상태 | 설명 |
|---|
NONE | 유저 접속 전. LaunchData 확인 대기 |
VERIFYING | OTT 검증 API 호출 중 |
ACTIVE | 검증 성공. 하트비트 루프 실행 중 |
ENDING | 세션 종료 API 호출 중 |
ENDED | 세션 종료 완료 |
세션 생성
유저가 PlayWave 런처를 통해 게임에 접속하면 LaunchData에 OTT가 포함됩니다.
-- 서버에서 OTT 추출
local joinData = player:GetJoinData()
local ott = joinData.LaunchData -- OTT UUID 문자열
OTT가 있으면 POST /v1/game/session/verify를 호출하여 검증합니다. 검증 성공 시 game_session_id를 받고 세션이 ACTIVE 상태가 됩니다.
PlayWave 런처 없이 접속한 유저는 LaunchData가 비어있습니다. 이 경우 검증을 건너뛰고 일반 유저로 처리합니다.
하트비트
세션이 ACTIVE 상태가 되면 2분(120초) 간격으로 하트비트를 전송합니다.
-- 하트비트 루프
while activeSessions[userId] do
task.wait(120) -- 2분 대기
apiRequest("PATCH", "/game/session/heartbeat", {
game_session_id = gameSessionId,
provider_user_id = providerUserId,
})
end
하트비트 응답 처리
| result | 의미 | 처리 |
|---|
OK | 정상 | 다음 하트비트까지 대기 |
CHARGE_EXHAUSTED | G-coin 소진 | 유저에게 안내. 서버가 2분 유예 후 자동 종료 |
SESSION_REPLACED | 같은 PC에서 다른 세션 시작됨 | 하트비트 중지. 세션 종료 API 호출 불필요 |
하트비트 에러 처리
| HTTP 상태 | 의미 | 처리 |
|---|
| 404 | 세션 없음 (만료/삭제) | 하트비트 중지, 유저 킥 |
| 410 | 세션 이미 종료 | 하트비트 중지, 유저 킥 |
| 5xx | 서버 오류 | 다음 주기에 재시도 |
하트비트가 4분 이상 수신되지 않으면 서버에서 세션이 자동 종료됩니다. 2분 간격을 유지하세요.
세션 종료
세션은 다음 6가지 경우에 종료됩니다.
1. 정상 종료 (normal)
유저가 게임을 나가면 PlayerRemoving 이벤트에서 세션 종료 API를 호출합니다.
Players.PlayerRemoving:Connect(function(player)
endPlayerSession(player.UserId)
end)
2. 서버 종료 (BindToClose)
Roblox 서버가 종료될 때 모든 활성 세션을 정리합니다.
game:BindToClose(function()
for userId in pairs(activeSessions) do
endPlayerSession(userId)
end
end)
3. 하트비트 타임아웃 (heartbeat_timeout)
4분간 하트비트가 수신되지 않으면 서버에서 자동 종료합니다. PC 강제 종료, 네트워크 장애 등의 경우에 해당합니다.
4. 세션 교체 (session_replace)
같은 PC에서 다른 게임을 실행하면 기존 게임 세션이 자동 종료되고 새 세션이 생성됩니다. 기존 세션의 하트비트에 SESSION_REPLACED가 반환됩니다.
5. 런처 하트비트 타임아웃
게임 서버 하트비트 처리 시 서버는 런처의 생존도 확인합니다. 런처가 4분 이상 하트비트를 보내지 않으면 서버가 게임 세션을 종료합니다 (HTTP 410 반환). PlayWave 런처가 크래시되거나 강제 종료된 경우 발생합니다.
6. G-coin 소진 (charge_exhausted)
하트비트 응답에서 CHARGE_EXHAUSTED를 수신하면 서버가 2분 유예 후 세션을 자동 종료합니다.
타임라인 예시
정상 종료
비정상 종료