GS2-Gateway
GS2-Gateway는 게임 클라이언트와 서버 사이에서 WebSocket을 통한 상시 접속을 유지하고, 서버가 임의의 시점에 알림을 보낼 수 있도록 하는 기능을 제공합니다.
일반적인 게임 서버와의 통신은 클라이언트의 요청에 서버가 응답하는 형태이지만, GS2-Gateway를 사용하면 서버가 시작하는 알림(메시지 수신, 친구 신청, 길드로부터의 소집 등)을 실시간으로 클라이언트에 전달할 수 있습니다.
sequenceDiagram participant Client participant Gateway as GS2-Gateway participant Service as 각 마이크로서비스 Client->>Gateway: WebSocket 접속 Client->>Gateway: SetUserId(인증) Service->>Gateway: SendNotification Gateway->>Client: 알림 페이로드 전달
주요 기능
WebSocket 상시 접속
GS2-Gateway는 WebSocket 프로토콜로 클라이언트로부터의 접속을 받아들이고, 사용자별로 접속 정보를 보유합니다. 다른 마이크로서비스로부터 “이 사용자에게 알림을 보내고 싶다"는 요청이 오면, 접속 중인 클라이언트에 페이로드를 전달합니다.
주요 연계 대상은 다음과 같습니다.
- GS2-Inbox: 신규 메시지 수신 알림
- GS2-Friend: 친구 신청·승인 알림
- GS2-Guild: 길드 참가 신청, 길드 내 상황 변화 알림
- GS2-Matchmaking: 매칭 완료 알림
- GS2-Distributor: 트랜잭션 자동 실행을 위한 알림
- GS2-JobQueue: 신규 작업이 쌓였을 때의 알림
동시 접속 제어
네임스페이스 내의 사용자는 원칙적으로 동시에 하나의 세션만 보유할 수 있습니다.
SetUserId 실행 시 allowConcurrentAccess를 false로 설정하면, 이미 다른 세션이 접속 중인 경우 새로운 세션 측에서 동시 접속 오류로 감지할 수 있습니다.
true로 설정하면, 새로운 세션이 접속된 시점에 기존 세션이 끊어집니다.
이 기능을 이용하면 여러 기기에서의 동시 로그인을 억제할 수 있습니다. GS2-Account의 비밀번호 자동 변경 기능과 조합하면, 계정 공유나 인수인계 후 이전 기기의 접속 차단을 더욱 강력하게 수행할 수 있습니다.
Firebase Cloud Messaging 연계 (모바일 푸시 알림)
클라이언트가 실행되지 않은 (WebSocket이 접속되지 않은) 상태에서도 알림을 전달하고 싶은 경우, Firebase Cloud Messaging (FCM)과의 연계 기능을 이용할 수 있습니다.
사전에 네임스페이스의 firebaseSecret에 FCM의 서버 키(또는 서비스 계정 크리덴셜)를 등록해 두고, 각 사용자의 기기에서 취득한 FCM 토큰을 GS2-Gateway에 등록해 둡니다.
GS2-Gateway는 알림 전달 시 WebSocket 세션이 존재하지 않는 사용자에 대해서는, 등록된 FCM 토큰을 사용해 FCM을 통해 푸시 알림을 보냅니다. 이를 통해 앱이 실행되지 않은 상태에서도 사용자에게 알림을 전달할 수 있습니다.
알림 엔트리의 enableTransferMobileNotification을 활성화하면, 알림별로 모바일 푸시로의 전달 여부를 제어할 수 있습니다.
WebSocket API 설정
GS2의 클라이언트 SDK (Unity / Unreal Engine / Godot)에는 GS2-Gateway의 WebSocket 접속을 자동으로 확립·유지하는 유틸리티가 내장되어 있습니다.
로그인 시 GatewaySetting을 지정하면, 로그인 처리 흐름에 맞추어 WebSocket 접속과 SetUserId 호출을 자동으로 수행할 수 있습니다.
설정 항목은 다음과 같습니다.
gatewayNamespaceName: 사용할 GS2-Gateway의 네임스페이스 이름allowConcurrentAccess: 동시 접속을 허용할지 여부
트랜잭션 액션
GS2-Gateway에서는 트랜잭션 액션을 제공하지 않습니다.
마스터 데이터 관리
GS2-Gateway는 마스터 데이터를 가지지 않습니다. 네임스페이스 설정에서 Firebase 연계 정보나 로그 설정을 구성합니다.
구현 예제
로그인 시 WebSocket 접속을 확립
GatewaySetting을 지정하여 로그인하면, SDK가 자동으로 WebSocket 세션을 확립하고 SetUserId를 호출하여 사용자ID를 연결합니다.
var gameSession = await gs2.LoginAsync(
new Gs2AccountAuthenticator(
accountSetting: new AccountSetting {
accountNamespaceName = this.accountNamespaceName,
},
gatewaySetting: new GatewaySetting {
gatewayNamespaceName = "namespace-0001",
allowConcurrentAccess = false,
}
),
account.UserId,
account.Password
); const auto Future = Profile->Login(
MakeShareable<Gs2::UE5::Util::IAuthenticator>(
new Gs2::UE5::Util::FGs2AccountAuthenticator(
AccountNamespaceName,
KeyId,
"namespace-0001", // gatewayNamespaceName
false // allowConcurrentAccess
)
),
UserId,
Password
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError()) return false;
const auto Result = Future->GetTask().Result();var authenticator = Gs2AccountAuthenticator.new(
"account-namespace-0001",
"grn:gs2:{region}:{ownerId}:key:namespace-0001:key:key-0001",
"gateway-namespace-0001",
false
)
var game_session = Gs2GameSession.new(
authenticator, connection, account.user_id, account.password
)
var async_result = await game_session.login()
if async_result.error != null:
push_error(str(async_result.error))
return명시적으로 사용자ID를 설정
이미 접속되어 있는 WebSocket 세션에 사용자ID를 연결하고 싶은 경우나, 로그인 후에 동시 접속 허용 상태를 변경하고 싶은 경우에는 SetUserId를 호출합니다.
var domain = await gs2.Gateway.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).WebSocketSession(
).SetUserIdAsync(
allowConcurrentAccess: false
); const auto Future = Gs2->Gateway->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->WebSocketSession(
)->SetUserId(
false // allowConcurrentAccess
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError()) return false;var domain = ez.gateway.namespace_(
"$hash"
).me(game_session).web_socket_session(
)
var async_result = await domain.set_user_id(
true, # allow_concurrent_access
null # session_id
)
if async_result.error != null:
push_error(str(async_result.error))
return
var result = async_result.result보다 실전적인 정보
동시 접속 끊김 처리
allowConcurrentAccess: false 설정으로 접속 중일 때 다른 단말기에서 동일 사용자가 로그인을 수행하면, 현재의 WebSocket 세션이 끊어집니다.
클라이언트는 접속 끊김 이벤트를 감지하여, 재로그인을 유도하는 화면으로 전환하거나 “다른 단말기에서 로그인되었습니다"라는 메시지를 표시하는 등의 대응을 해야 합니다.
이를 통해 여러 단말기에서의 동시 플레이를 실질적으로 금지하는 운영이 가능해집니다.
버전 업데이트 시 전체 플레이어 접속 끊기
GS2-Version과 조합하여, 신규 버전 공개 시 모든 플레이어의 WebSocket 세션을 끊음으로써, 재접속 시점에 강제로 버전 체크를 통과시키는 운영이 가능합니다.
자세한 내용은 GS2-Version의 “버전 업데이트 운영 절차"를 참조하십시오.