로그인은 성공했다고 뜨는데, 세션 관련 API가 전부 이상하게 동작함

LogTemp: [EOS] AutoLogin 요청 (서브시스템: NULL)
LogTemp: [EOS] 로그인 성공: BRD-E68F528241AF811B9A9B2E99E2B2B6CC

 

IOnlineSubsystem::Get()이 EOS가 아니라 NULL 서브시스템(언리얼의 오프라인용 더미 구현체)을 반환하고 있었음

(일종의 가짜로그인)

Project Settings -> Plugins -> Online Subsystem EOS의 GUI로 크리덴셜을 채웠는데

GUI는 [/Script/OnlineSubsystemEOS.EOSSettings] 섹션만 만들고

[OnlineSubsystem] DefaultPlatformService=EOS는 안 건드린다는 걸 알게됨

 

ini를 직접 열어서 수정

[OnlineSubsystem]
DefaultPlatformService=EOS

[OnlineSubsystemEOS]
bEnabled=true

 

근데 수정을 하고 나니 EOS SDK는 초기화되는데 백엔드 통신이 403으로 계속 거절됨

HttpStatus=[403], ErrorCode=[errors.com.epicgames.common.invalid_product]
ErrorMessage=[E:생략, A:생략]
SDK Config Product Update Request Failed, Result Code: EOS_Invalid_Product

 

에러 메시지의 E가 내가 보낸 ProductId,

A가 Application ID인데 두 값이 바뀌어있었음

 

포털 화면에 제품 ID 와 애플리케이션 ID 가 나란히 있어서 헷갈렸음

Product 게임 한 개의 최상위 식별자
Application 그 안의 EAS(에픽 계정 서비스) 앱 식별자

 

포털의 제품 ID를 ProductId에 넣어야 함

 

근데 크리덴셜을 다 채웠는데도 못 읽음

DefaultArtifactName=Client                          ← "Client"를 찾는데
+Artifacts=(ArtifactName="2e1e1f4d87ab...", ...)    ← 실제 이름은 해시값

 

엔진은 DefaultArtifactName과 같은 이름의 Artifact를 찾아서 크리덴셜을 읽음

GUI가 ArtifactName에 해시를 자동으로 넣어버린 게 원인

 

둘 다 같은 값으로 통일 (이름 자체는 아무거나 상관없음)

DefaultArtifactName=FunnyorDie
+Artifacts=(ArtifactName="FunnyorDie", ...)

 

이거 해결하고 나니

또 다른 문제상황 발생 

StartButton을 누르면 세션 패널이 열리는 동시에 로비 맵으로 날아감

 

코드를 아무리 봐도 문제 상황을 모르겠어서 난감하던 찰나에 

문득 WBP Graph에 노드가 설정되어있나? 싶어서 확인해보니 

팀원이 임시로 붙여둔 노드가 남아있었음

 

C++의 AddDynamic으로 바인딩한 핸들러와 블루프린트 이벤트가 둘 다 실행되는 상황이었던 것

 

OpenLevel은 네트워크와 무관하게 단순 레벨이 로드되는 거기 때문에 여기서 쓸 수 없음

(로비맵은 네트워크 넘어서 열려야 함)

-> 블루프린트 노드 삭제

OpenLevel(맵) 네트워크와 무관한 단순 레벨 로드. 혼자 맵만 갈아끼움
ServerTravel("맵?listen") 서버가 맵을 열며 리슨 서버 개시
ClientTravel(주소) 클라가 특정 서버로 접속

 

이후 팀원들과 같이 Dev Auth Tool 켜고 한명이 방을 만들고 나머지가 참여하기 눌러서 같이 실행해보려고 하는데

방은 만들어지는데, 참여하기를 누르면 열린 방이 없습니다가 뜸

LogEOSLobby: Error: Search query is empty, search invalid.
LobbySearch_Find not successful. Finished with EOS_EResult EOS_InvalidParameters
LogTemp: Warning: [EOS] 찾은 방 없음

 

코드를 다시 보니 클라이언트의 검색 조건이 이것뿐이었음

SearchSettings->QuerySettings.Set(SEARCH_LOBBIES, true, EOnlineComparisonOp::Equals);

 

SEARCH_LOBBIES는 로비 방식으로 검색하겠다는 모드 지정이지 검색 조건이 아님

호스트는 SEARCH_KEYWORDS에 값을 넣어뒀는데 클라가 그걸로 검색을 안 한 것

 

문서를 보고 따라서 만드느라 몰랐음

// 모드 지정
SearchSettings->QuerySettings.Set(SEARCH_LOBBIES, true, EOnlineComparisonOp::Equals);

// 실제 검색 조건
SearchSettings->QuerySettings.Set(SEARCH_KEYWORDS, FString("FunnyorDie"),
                                  EOnlineComparisonOp::Equals);

 

호스트 쪽의 이것과 문자열이 정확히 일치해야 함

Settings.Set(SEARCH_KEYWORDS, FString("FunnyorDie"),
             EOnlineDataAdvertisementType::ViaOnlineService);

 

이제 참가자가 방을 찾고, JoinSession도 성공하는데

실제 접속에서 실패하고 StartMaps로 튕겨나옴

호스트 로그엔 참가자 입장 기록이 없음 (현재 인원 1에서 멈춤)

 

팀원과 로그 공유

 

참가자:

LogSockets: Warning: GetAddressInfo failed to resolve host with error SE_HOST_NOT_FOUND [11001]
LogNet: Driver: Name:PendingNetDriver Def:GameNetDriver IpNetDriver_0
LogNet:  - Result=AddressResolutionFailed
LogNet: Error: Your connection to the host has been lost.

 

호스트:

LogNet: Created socket for bind address: 0.0.0.0:7777
LogNet: Name:GameNetDriver Def:GameNetDriver IpNetDriver_0 IpNetDriver listening on port 7777

 

양쪽 다 IpNetDriver 를 타고 있었음

EOS 넷드라이버가 아니라 기본 IP 넷드라이버

  • 호스트: 7777 포트로 평범한 IP 서버를 열었음 -> 외부에서 접근 불가
  • 참가자: GetResolvedConnectString이 돌려준 EOS 고유 주소를 받았는데 IP 넷드라이버가 그걸 호스트네임으로 착각하고 DNS 조회를 시도 -> 그런 도메인은 없으니 SE_HOST_NOT_FOUND

원인이 뭔지 로그를 찍어보고 함수를 들여다봐도 모르겠어서 

문서를 다시 읽다가 문득 문서에 작성된 버전이랑 지금 내 버전이 달라서 문제가 되나? 하고

문제가 되는 netdrive 쪽을 집중적으로 보다가

ini 파일에서 SocketSubsystemEOS.NetDriverEOSBase로 되어있는데

문서에는 OnlineSubsystemEOS.NetDriverEOSBase로 적혀있는걸 발견함 

 

문서를 참고해서 코드를 작성했으니 버전이 달라서 클래스 경로가 다른가? 하고 바꿔봄

 

가이드에 나온 대로 이렇게 썼는데:

DriverClassName="OnlineSubsystemEOS.NetDriverEOSBase"

 

이렇게 바꿈

DriverClassName="SocketSubsystemEOS.NetDriverEOSBase"

 

그러니까 해결됨

정상 작동되고 팀원들끼리도 다같이 모일 수 있었음

 

UE 5.5에서 NetDriverEOSBase는 SocketSubsystemEOS 모듈에 있었어서

클래스를 못 찾았던 것이 문제였던 것 같음 (추측)

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="SocketSubsystemEOS.NetDriverEOSBase",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")

[/Script/SocketSubsystemEOS.NetDriverEOSBase]
bIsUsingP2PSockets=true

 

로그를 다시 보니

LogEOSSDK: LogEOSP2P: A new connection request listener has been bound. SocketId=[GameNetDriver]
LogEOSSDK: LogEOSP2P: A new connection closed listener has been bound. SocketId=[GameNetDriver]

 

정상 작동

 

이외에도 알게된 것

Epic Account Services의 Application이 초안 모드일때는 조직 멤버만 로그인할 수 있음

  • 포털 -> Organization -> Members에서 팀원을 초대

카테고리

LogEOSSDK EOS SDK 내부 (인증, 로비, P2P)
LogOnline / LogOnlineSession 언리얼의 OSS 레이어
LogNet / LogSockets 실제 네트워크 연결

 

보안 - 크리덴셜 관리 방침

리포가 public이라 ClientSecret/EncryptionKey를 커밋하면 안 됨

 

적용한 방식:

  1. Config/DefaultEngine.ini를 .gitignore에 추가
  2. Config/DefaultEngine.ini.template 만들어서 크리덴셜 자리만 <입력>으로 비워두고 커밋
  3. 실제 값은 DM으로 채널로 팀원에게 전달
  4. 팀원은 본인 로컬에 직접 입력

히스토리 정리: git rm --cached Config/DefaultEngine.ini로 추적만 해제 (로컬 파일은 유지)

git log --all -p 로 과거 커밋에 크리덴셜이 실제로 박힌 적 없었음을 확인 후 진행

 

<근데 이렇게 하면 문제점>

이 방식은 DefaultEngine.ini 통째로를 버전 관리에서 빼는 거라 렌더링, 맵 설정까지 전부 커밋에서 사라짐

그래서 나중에 프로젝트 세팅을 바꾸면 그 변경이 자동으로 팀에 공유되질 않고 누군가 template도 같이 갱신해줘야 반영됨

+ Recent posts