[팀 프로젝트] 2026-04-01 | Steam Session Subsystem 기획

2026. 4. 1. 21:45·언리얼 게임개발

Steam Session Subsystem 기획서

프로젝트: SagoMagic
작성 기준: UE5 + Steam + AWS EC2 데디케이티드 서버
세션 방식: Steam 친구 초대 전용 (불특정 다수 매칭 없음)


1. 개요

1.1 목표

  • 최대 4인(최소 1인)이 Steam 친구 초대를 통해 같은 서버에 모여 디벤스 게임을 진행
  • 모든 게임 로직의 권위는 AWS 데디케이티드 서버가 가진다.
  • 방장(호스트)은 게임 서버 역할을 하지 않으며, Steam 세션 등록과 UI 진행만 담당한다.

1.2 핵심 용어 정리

용어 설명
데디케이티드 서버 AWS EC2에서 24시간 실행되는 게임 서버 프로세스. 게임 로직의 단일 권위자
Steam 세션 Steam 서버 목록에 등록되는 메타데이터. 접속 주소(AWS IP) 포함
방장 (Host) 로비를 생성하고 Steam 세션을 등록하는 클라이언트 플레이어
SeamlessTravel 클라이언트 연결을 유지한 채 레벨을 전환하는 UE5 기능
CopyProperties SeamlessTravel 시 PlayerState 데이터를 새 레벨로 복사하는 UE5 함수

2. 전체 흐름

[L_Main] 방장이 Host 클릭
    │
    │ ClientTravel (AWS 고정 IP)
    ▼
[L_Lobby / AWS 데디서버] 방장 접속
    │
    │ 방장 클라이언트가 Steam 세션 등록
    │ Steam 친구 초대
    │ 친구들1 ClientTravel (AWS IP) 로 합류
    │ PlayerState에 캐릭터/장비 저장
    │ 전원 Ready + 방장 Start
    │
    │ ServerTravel + SeamlessTravel
    ▼
[L_Play / AWS 데디서버] 게임 시작
    │
    │ CopyProperties → PlayerState 데이터 유지
    │ GameMode가 PlayerState 읽어 Pawn 스폰
    ▼
게임 진행

3. 레벨 구조

3.1 레벨 목록

레벨 실행 위치 GameMode
L_Main 플레이어 로컬 PC 없음 (기본값)
L_Lobby AWS 데디케이티드 서버 ASMLobbyGameMode
L_Play AWS 데디케이티드 서버 ASMGameMode

3.2 레벨별 역할

L_Main

  • 플레이어의 로컬 PC에서만 동작하는 오프라인 화면
  • 게임 실행 시 Steam에 자동으로 온라인 연결됨 (코드 불필요)
  • 세션 없음. Host 버튼 클릭 시 AWS 서버로 ClientTravel

L_Lobby

  • AWS 데디서버에서 실행
  • 플레이어 슬롯 (1~4) 표시 및 준비 상태 관리
  • Steam 친구 초대 진행
  • 캐릭터/장비 선택 및 PlayerState 저장
  • 전원 Ready 확인 후 방장이 Start → L_Play로 ServerTravel

L_Play

  • AWS 데디서버에서 실행
  • SeamlessTravel로 L_Lobby에서 전환됨
  • GameMode가 PlayerState를 읽어 Pawn 스폰
  • 디펜스 게임플레이 진행

4. Steam 세션 동작 방식

4.1 세션 등록 주체

데디케이티드 서버가 직접 Steam에 세션을 등록하려면 Steam Game Server API 연동이 필요하여 구현 복잡도가 높다. 따라서 방장 클라이언트가 세션을 등록하는 방식을 채택한다.

방장은 Listen Server 역할을 하지 않는다.
Steam 세션 등록은 단순히 "이 AWS 서버에 이런 게임이 열려있다"는 메타데이터를 Steam에 알리는 행위이며, 게임 트래픽은 방장 PC를 경유하지 않고 AWS 서버로 직접 전달된다.

4.2 세션 등록 시점

  1. 방장이 Host 클릭 → AWS 서버로 ClientTravel
  2. L_Lobby 진입 완료
  3. 방장 클라이언트의 USMSessionSubsystem.CreateSession() 호출
  4. Steam 세션 등록 완료 → InviteButton 활성화

4.3 세션 설정값

설정 값 이유
NumPublicConnections 4 최대 4인
bIsDedicated false 방장 클라이언트가 등록 주체
bUsesPresence true Steam 친구 초대에 필요
bUseLobbiesIfAvailable true Steam Lobby 활용
bShouldAdvertise true 초대 가능 상태로 노출
bAllowJoinInProgress false 게임 시작 후 합류 불가

4.4 친구 초대 흐름

  1. 방장 → Steam 오버레이 → 친구 초대 전송
  2. 친구 → 초대 수락
  3. Steam → AWS 서버 IP 반환
  4. 친구 클라이언트 → ClientTravel(AWS IP) → L_Lobby 진입

4.5 게임 외부에서 초대 수락 시

  1. 친구가 Steam에서 초대 수락 → 게임 자동 실행
  2. 게임 실행 → USMSessionSubsystem.Initialize()에서 InviteAccepted 콜백 발동
  3. 자동으로 AWS 서버 접속

5. 레벨 전환 및 데이터 전달

5.1 L_Main → L_Lobby

  • 방장: ClientTravel(AWS_ELASTIC_IP:7777)
  • 게스트: OnSessionUserInviteAccepted() → GetResolvedConnectString() → ClientTravel

5.2 L_Lobby → L_Play

// ASMLobbyGameMode.TryStartGame()
GetWorld()->ServerTravel("/Game/Maps/L_Play?listen?MaxPlayers=N");
  • bUseSeamlessTravel = true 상태에서 ServerTravel 호출
  • 연결된 모든 클라이언트가 자동으로 L_Play로 전환
  • ASMPlayerState::CopyProperties() 자동 호출 → 데이터 유지

5.3 PlayerState 데이터 유지 조건

PlayerState는 레벨 전환 시 파괴 후 재생성된다. 데이터 유지를 위해 아래 두 조건이 반드시 충족되어야 한다.

조건 설정 위치 내용
SeamlessTravel 활성화 ASMLobbyGameMode 생성자 bUseSeamlessTravel = true
CopyProperties 오버라이드 ASMPlayerState.cpp 커스텀 변수 직접 복사

 

UPROPERTY(Replicated) 는 서버→클라이언트 동기화 용도이며, 레벨 전환 후 데이터 유지와 무관하다.

5.4 L_Play에서 데이터 수신

  • ASMGameMode.BeginPlay()에서 GetGameInstance<USMGameInstance>()->GetLobbyInfo() 호출
  • ASMGameMode.PostLogin()에서 PlayerState 직접 읽기 (캐릭터·장비 정보)
  • Pawn 스폰 및 빙의(Possess)

6. GameMode별 PlayerState 클래스 지정

두 GameMode 모두 동일한 PlayerState 클래스를 지정해야 CopyProperties가 정상 동작한다.

// ASMLobbyGameMode 생성자
PlayerStateClass   = ASMPlayerState::StaticClass();
bUseSeamlessTravel = true;

// ASMGameMode 생성자 (게임플레이 팀)
PlayerStateClass   = ASMPlayerState::StaticClass();
bUseSeamlessTravel = true;

 

7. 테스트 전략

단계 방법 목적 Steam 필요
1단계 PIE + NULL Subsystem 로직·Replication 검증 불필요
2단계 PIE + Steam Steam 초기화·세션 생성 확인 필요 (단일 클라이언트)
3단계 Standalone + Steam 팀원과 실제 Steam 초대 테스트 필요 (각 PC별 계정)
4단계 패키징 빌드 + AWS 최종 통합 테스트 필요

PIE에서 클라이언트 2개 이상 + Steam 동시 연결은 불가능하다. (Steam 계정 1개당 1인스턴스 제한)
Steam 초대 기능은 반드시 Standalone 단계에서 팀원 PC와 함께 검증한다.


8. Build.cs 의존 모듈

PublicDependencyModuleNames.AddRange(new string[]
{
    "Core",
    "OnlineSubsystem",
    "OnlineSubsystemSteam",
    "UMG",
    "Slate",
    "SlateCore"
});

PrivateDependencyModuleNames.AddRange(new string[]
{
    "CoreUObject",
    "Engine",
    "Slate",
    "SlateCore"
});

9. DefaultEngine.ini 설정

; 개발 중 (PIE 테스트)
[OnlineSubsystem]
DefaultPlatformService=NULL

; Steam 연동 시 (Standalone 이후)
[OnlineSubsystem]
DefaultPlatformService=Steam

[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
bInitServerOnClient=true

; SeamlessTravel 활성화
[/Script/Engine.GameMapsSettings]
bUseSmoothTravel=true

10. 문제점

동시에 여러개의 session 생성 불가능.

반응형

'언리얼 게임개발' 카테고리의 다른 글

[팀 프로젝트 회고] 2026-04-24 | 팀 프로젝트 회고  (0) 2026.04.27
[TIL] 2026-04-16 | GameplayCueNotify에서 무기 소켓 위치 올바르게 가져오기  (0) 2026.04.16
[TIL] 2026-04-13 | UE5 멀티플레이 로비 - 캐릭터 외형 커스터마이징 시스템 설계  (0) 2026.04.13
[TIL] 2026-04-06 | UnrealEngine에서의 Null체크: IsValid(Thing), Thing.IsValid, !Thing의 차이점  (0) 2026.04.06
[TIL] 2026-04-02 | UnrealEngine에서의 TObjectPtr과 Raw포인터의 사용  (0) 2026.04.02
'언리얼 게임개발' 카테고리의 다른 글
  • [TIL] 2026-04-16 | GameplayCueNotify에서 무기 소켓 위치 올바르게 가져오기
  • [TIL] 2026-04-13 | UE5 멀티플레이 로비 - 캐릭터 외형 커스터마이징 시스템 설계
  • [TIL] 2026-04-06 | UnrealEngine에서의 Null체크: IsValid(Thing), Thing.IsValid, !Thing의 차이점
  • [TIL] 2026-04-02 | UnrealEngine에서의 TObjectPtr과 Raw포인터의 사용
개발근육체육관원
개발근육체육관원
개발 근육 단련 체육관 입니다.
  • 개발근육체육관원
    개발근육체육관
    개발근육체육관원
  • 전체
    오늘
    어제
    • 분류 전체보기 (24)
      • 언리얼 게임개발 (13)
      • AlgorithmCodekata (9)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    c++
    AlgorithmCodekata
    Til
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
개발근육체육관원
[팀 프로젝트] 2026-04-01 | Steam Session Subsystem 기획
상단으로

티스토리툴바