메인 콘텐츠로 건너뛰기

세션 상태

게임 세션은 다음 상태를 순서대로 거칩니다.
상태설명
NONE유저 접속 전. LaunchData 확인 대기
VERIFYINGOTT 검증 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_EXHAUSTEDG-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분 유예 후 세션을 자동 종료합니다.

타임라인 예시

정상 종료

비정상 종료