P2P Server(Peer to Peer Server) -> 각각의 컴퓨터가 클라이언트이자 서버인 구조

Listen Server -> 클라이언트이자 서버인 방장(Host)이 있고, 나머지 참가자(Guest)는 모두 클라이언트 역할만 맡는 형태. (P2P의 일종이라고 볼 수 있음)

Dedicated Server -> 서버를 담당하는 컴퓨터가 따로 있음. 서버-클라이언트 구조.

 

Dedicated Server의 실행 흐름도

1. 서버 실행과 레벨 오픈

PIE든 Server.exe든, 서버 프로그램이 실행됨

실행 시 Open {Level이름}?Listen 인자가 전달됨

  • Open {Level이름} - 해당 레벨이 열림
  • ?Listen - 이 옵션 덕분에 다른 컴퓨터의 접속이 가능해짐 (리슨 서버가 됨)

레벨에는 WorldSettings가 있고, 여기 설정된 GameMode/GameState 정보를 바탕으로 서버가 GameMode와 GameState 액터를 생성함

 

2. GameMode = 서버 그 자체

가장 중요한 포인트

GameMode 액터는 전체 네트워크에서 오직 서버 한 곳에만 존재함

클라이언트에는 GameMode가 복제되지 않고 존재 자체가 없음

그래서 GameMode가 곧 서버를 대변한다고 봐도 무방함

 

3. Client1 접속 과정

  1. 클라이언트가 서버의 IP주소와 포트번호로 접속을 시도함
  2. 서버는 열어둔 Level 정보를 클라이언트에게 넘김
  3. 클라이언트도 해당 Level을 열고, 성공했다고 서버에게 알림
  4. Level 오픈에 성공한 Client1 전용 PlayerState, PlayerController, PlayerCharacter가 서버에 생성됨
  5. 이것이 다시 Client1에 복제됨
  6. GameState도 함께 복제됨

4. Client2 접속 과정

Client1과 동일한 흐름이 반복됨

  1. 다른 클라이언트가 접속을 시도함
  2. 서버가 Level 정보를 넘김
  3. 클라이언트가 Level을 열고 성공을 알림
  4. Client2 전용 PlayerState, PlayerController, PlayerCharacter가 서버에 생성됨
  5. Client2에 복제됨
  6. GameState도 복제됨

이때 Client1과 Client2의 PlayerState, PlayerCharacter도 서로에게 복제되면서, 두 클라이언트가 서로를 보게 됨

 

 


서버-클라이언트 구조의 핵심 특징

클라이언트와 클라이언트 간의 직접 통신은 불가능함

오직 서버와 클라이언트 사이의 통신만 가능함

모든 정보는 반드시 서버를 거쳐서 전달됨 (Client1 → Server → Client2 방식)

이 원칙이 앞으로 배울 RPC나 프로퍼티 레플리케이션 설계에 그대로 영향을 줌

 

  • GameMode = 판정을 내리는 심판 역할 : 플레이어 접속 처리, 승패 판정, 리스폰 로직, 룰 적용 같은 로직/권위(authority) 처리. 보안상 클라이언트한테 줄 필요 없고(치트 방지), 판정 과정 자체는 안 보여줘도 됨.
  • GameState = 전광판 역할 : 현재 스코어, 남은 시간 같은 모든 플레이어가 화면에 표시해야 할 정보. 클라이언트 UI에 띄워야 하니 복제 필수.

  • PlayerState: 점수, 이름 같은 공개 정보
  • PlayerController: 플레이어의 입력(키보드/마우스)을 처리하는 조종 장치
  • PlayerCharacter(Pawn): 게임 월드 안에서 실제로 보이는 캐릭터 몸

이 세 액터는 서버 메모리에 생성되지만 복제(Replication)를 통해 해당 클라이언트 컴퓨터에도 똑같이 복사됨.

 

  • PlayerController: 자기 자신의 클라이언트에게만 복제. 다른 사람의 컨트롤러가 내 컴퓨터에 복제되면 다른 사람 캐릭터를 조종할 수 있게 되는 보안 문제 발생
  • PlayerState, PlayerCharacter: 모든 클라이언트에게 복제 (다른 플레이어들도 보여야 하고 정보를 알아야 하므로)

 

  • 서버 → 클라이언트: Property Replication (변수 값이 바뀌면 자동 복제) 또는 Client RPC (Client_ 접두사 함수)
  • 클라이언트 → 서버: Server RPC (Server_ 접두사 함수)

클라이언트 A가 점프했을 때 클라이언트 B 화면에도 보이게 하려면?

  1. 클라이언트 A → 서버: A가 점프 키를 누르면 A의 PlayerController가 Server RPC를 호출해서 "점프했어요"라고 서버에 알림
  2. 서버 처리: 서버가 요청을 받아 판단하고, A의 PlayerCharacter 상태(애니메이션, 위치 등)를 실제로 변경
  3. 서버 → 모든 클라이언트(A, B 포함): 변경된 상태가 Property Replication을 통해 자동으로 모든 클라이언트에 복제 → B의 화면에서도 A의 점프가 보이게 됨

 

IsLocalController() 함수를 활용한 내 컴퓨터 확인

// CXPlayerController.cpp

...

void ACXPlayerController::BeginPlay()
{
	Super::BeginPlay();

	if (IsLocalController() == false)
	{
		return; // 내 컴퓨터가 아니라면, 아래 CreateWidget() 함수 호출을 막음.
	}

	...
}

...

 

+ Recent posts