SYDESYDE
SYDESYDE
  • 피드
  • 쇼케이스
  • 블로그
  • 모임
SYDESYDE© 2026 SYDE. All rights reserved.
SYDE 소개문의하기
Kakao
SYDE 오픈채팅
Instagram
Instagram
Threads
Threads
커뮤니티 가이드라인협업문의이용약관개인정보처리방침
커뮤니티 가이드라인협업문의이용약관개인정보처리방침

© 2026 SYDE. All rights reserved.

멀티플레이를 만들었다 — SAME DECK #3

멀티플레이를 만들었다 — SAME DECK #3

mmustardoo· 8일 전· 해프닝·회고
목차
  • 두 컴퓨터가 같은 전투를 보게 하려면
  • 전투 결과는 누가 결정해야 할까?
  • 같은 결과를 받았다고 같은 화면을 보고 있는 건 아니다
  • 잘못된 행동 하나 때문에 게임이 멈췄다
  • 실제 두 컴퓨터를 연결해보니
  • 이제 연결은 된다. 그런데…

목차

  • 두 컴퓨터가 같은 전투를 보게 하려면
  • 전투 결과는 누가 결정해야 할까?
  • 같은 결과를 받았다고 같은 화면을 보고 있는 건 아니다
  • 잘못된 행동 하나 때문에 게임이 멈췄다
  • 실제 두 컴퓨터를 연결해보니
  • 이제 연결은 된다. 그런데…

두 컴퓨터가 같은 전투를 보게 하려면

SAME DECK을 만들면서 처음부터 넣고 싶었던 기능 중 하나가 친구와의 대전이었다.

혼자서 컴퓨터를 상대하는 것도 좋지만, 서로 같은 덱에서 카드를 뽑는 게임이라면 실제 사람을 상대로 플레이하는 게 더 재미있을 것 같았다.

기본적인 전투 시스템을 구현한 뒤 멀티플레이 작업을 시작했다.

턴제 게임이니 서로의 행동만 주고받으면 되지 않을까 싶었지만, 실제로 구현해야 할 부분은 생각보다 많았다.

특히 신경 써야 했던 것은 서로 다른 컴퓨터에서 같은 전투가 진행되도록 만드는 것이었다.


전투 결과는 누가 결정해야 할까?

가장 먼저 고민했던 것은 전투를 어느 컴퓨터에서 처리할지였다.

두 컴퓨터가 각각 전투를 계산하도록 만들 수도 있다. 같은 행동을 전달받고 같은 규칙으로 계산한다면 결과도 같아야 할 것이다.

그런데 SAME DECK에는 한 가지 문제가 있었다.

다음에 뽑힐 카드의 순서는 어느 플레이어도 미리 알아서는 안 된다.

두 컴퓨터가 완전히 같은 덱 순서와 난수 상태를 가지고 있다면, 상대에게 알려지면 안 되는 정보까지 전달해야 할 수 있었다.

반대로 서로 독립적으로 카드를 뽑고 전투를 계산한다면 결과가 달라질 위험이 있었다.

그래서 게임을 생성한 Host가 실제 전투 상태와 덱 순서를 관리하고, 참가한 Client는 공개되어야 하는 정보만 전달받도록 구성했다.

Client가 공격을 요청하면 Host가 행동할 수 있는 상황인지 확인하고, 실제 전투 결과를 계산한 뒤 양쪽 화면에 반영하는 방식이다.

이렇게 하면 두 컴퓨터가 서로 다른 결과를 계산하는 상황을 방지하면서, 비공개 정보도 Host에 남겨둘 수 있다.

하지만 전투 결과를 일치시키는 것만으로는 충분하지 않았다.


같은 결과를 받았다고 같은 화면을 보고 있는 건 아니다

예를 들어 내가 상대 영웅을 공격했다고 해보자.

Host에서는 이미 공격 결과가 계산되어 상대 영웅의 체력이 줄어들었지만, Client에서는 아직 공격 애니메이션이 재생되고 있을 수 있다.

SWAP으로 두 진영이 교환되거나 REVERSE로 이전 전투 상태가 복구되는 상황이라면 이런 차이가 더 눈에 띌 수 있다.

카드를 뽑을 때도 마찬가지였다.

실제 카드의 종류가 이미 결정됐더라도, 화면에서는 카드를 뒤집는 연출이 끝나기 전까지 결과가 드러나서는 안 된다.

전투 상태를 일치시키는 것과 플레이어가 그 결과를 확인하는 시점은 별개의 문제였다.

그래서 전투의 판정과 화면의 연출을 분리했다.

Host는 명령을 받아 전투 결과를 계산하고, 양쪽 컴퓨터는 전달받은 결과를 정해진 순서대로 화면에 재생한다.

그리고 양쪽 모두 결과를 표시했다고 확인한 뒤에야 다음 행동을 허용하도록 했다.

전체 흐름을 단순하게 정리하면 다음과 같다.

[Client] 행동 요청
          │
          ▼
[Host] 행동 검증 및 전투 판정
          │
          ├─ 거부 → 오류 응답
          │         전투 상태는 그대로 유지
          │
          ▼ 승인
[Host] 전투 결과 전달
          │
          ▼
[Host / Client]
각자 공격·카드 공개 등 연출 재생
          │
          ▼
[양쪽] 표시 완료 확인 (ACK)
          │
          ▼
[Host] 양쪽 ACK 확인
          │
          ▼
다음 행동 허용 (Grant)

여기서 ACK는 상대 컴퓨터가 정해진 결과를 표시했다는 확인 메시지다.

핵심은 두 화면의 애니메이션이 정확히 같은 프레임에 시작하고 끝나도록 만드는 것이 아니다.

한쪽 화면에서는 아직 이전 행동을 보고 있는데, 다른 쪽에서는 이미 다음 행동을 시작하는 상황을 막는 것이다.

또한 ACK를 받았다고 해서 플레이어가 언제나 행동할 수 있는 것도 아니다. 실제 차례와 전투 상태에 따라 행동할 수 있는 플레이어는 따로 결정된다.

처음에는 명령과 결과만 주고받으면 될 거라고 생각했다.

하지만 실제로는 게임 내부의 최신 전투 상태와 화면에 표시된 상태를 구분해서 관리해야 했다.


잘못된 행동 하나 때문에 게임이 멈췄다

멀티플레이를 구현한 뒤에는 정상적인 플레이뿐 아니라 잘못된 요청이 들어오는 상황도 테스트했다.

이미 끝난 턴의 명령을 다시 보내거나, 자신의 차례가 아닌데 행동을 요청하거나, 오래된 게임 상태를 기준으로 명령을 보내는 식이다.

이런 요청은 Host에서 거부해야 한다.

그런데 테스트 과정에서 이상한 문제가 발견됐다.

잘못된 행동은 정상적으로 거부됐는데, 그 뒤로 게임이 진행되지 않는 것이었다.

문제가 발생했던 상황은 이랬다.

Host와 Client가 이전 행동의 처리를 마치고 다음 행동을 받을 수 있는 상태에서, Client 쪽에서 자신의 차례가 아닌 행동 요청을 보내도록 했다.

Host의 전투 코어는 이 요청을 정상적으로 거부했다.

영웅의 체력이나 턴 상태도 바뀌지 않았다.

그런데 Host에서는 이후의 입력을 허용하지 않는 상태가 되어버렸다.

원인은 행동을 처리하는 순서에 있었다.

당시에는 새로운 행동 요청이 들어오면 먼저 다음 입력을 잠그고, 이후 전투 코어에 명령을 전달하는 구조였다.

정상적인 행동이라면 문제가 없었다.

전투 결과를 양쪽 화면에 전달하고, 재생이 끝난 뒤 ACK를 받으면 다시 다음 행동을 허용하면 됐기 때문이다.

하지만 코어가 잘못된 행동을 거부했을 때는 상황이 달라졌다.

전달할 전투 결과가 없으니 일반적인 결과 재생과 ACK 확인 과정도 진행되지 않았고, 이미 잠근 입력 상태만 남아버린 것이다.

특히 이번에 재현한 비정상 요청은 Client의 정상적인 요청 대기 상태를 거치지 않았기 때문에, 일반적인 거부 응답 이후의 동기화 복구에도 의존할 수 없었다.

문제가 발생한 흐름과 수정한 흐름을 비교하면 이렇다.

수정 전
요청 수신 → 입력 잠금 → 행동 판정 → 거부
                                    └→ 잠금 유지

수정 후
요청 수신 → 행동 판정
              ├→ 거부: 기존 입력 상태 유지
              └→ 승인: 입력 잠금 → 결과 전달

수정 자체는 생각보다 간단했다.

이제 Host는 먼저 전투 코어에서 명령을 검증하고, 실제로 승인된 행동일 때만 다음 입력을 잠근다.

거부된 요청은 전투 상태뿐 아니라 이미 정상적으로 열려 있던 입력 상태도 변경하지 않는다.

반대로 이전 결과를 재생하거나 동기화하는 중이라면, 잘못된 요청이 들어왔다고 해서 잠겨 있던 입력을 임의로 열지도 않는다.

이후 실제 두 프로세스를 연결해 같은 상황을 다시 재현하고, 정상적으로 진행되는지 확인했다.

물론 일반 플레이어가 평범하게 조작하다가 반드시 마주치는 오류는 아니었다. 테스트에서 의도적으로 비정상적인 원격 요청을 보내 발견한 문제였다.

그래도 이런 경우를 고려할 필요가 있었다.

잘못된 행동을 막는 것과, 그 행동을 막은 뒤에도 게임이 계속 진행되도록 만드는 것은 다른 문제였다.


실제 두 컴퓨터를 연결해보니


기본적인 구현과 테스트가 끝난 뒤에는 실제 네트워크 연결도 확인했다.

먼저 하나의 컴퓨터에서 게임 프로세스를 두 개 실행해 서로 대전하도록 만들었다.

카드를 뽑고, 영웅을 움직이고, 전투 결과를 주고받으며, 같은 연결에서 다시 대전하는 과정까지 자동화된 테스트로 확인했다.

일부 메시지를 지연시키거나 중복해서 전달하는 상황도 만들어봤다.

그렇지만 이것만으로 실제 멀티플레이가 완성됐다고 볼 수는 없었다.

같은 컴퓨터 안에서 두 프로그램이 통신하는 것과, 서로 다른 컴퓨터가 실제 네트워크를 통해 연결되는 것은 다른 문제이기 때문이다.

이후 같은 공유기에 연결된 두 Windows 컴퓨터로 LAN 연결을 시도했고, 올바른 네트워크 주소를 사용해 실제 연결에 성공했다.

물론 이 결과가 모든 네트워크 환경이나 전체 경기의 안정성까지 검증했다는 의미는 아니다.

그래도 한 컴퓨터에서만 진행되던 전투가 실제로 다른 컴퓨터의 플레이어와 연결되는 모습을 확인했다는 점은 의미가 있었다.


이제 연결은 된다. 그런데…

이렇게 해서 SAME DECK의 첫 멀티플레이 기반을 만들었다.

Host가 전투를 판정하고, Client는 공개된 결과를 전달받으며, 양쪽 화면의 연출이 끝난 뒤 다음 행동으로 넘어가는 구조였다.

그 과정에서 잘못된 요청 하나가 게임 진행을 막는 문제처럼, 혼자 플레이할 때는 생각하지 못했던 상황도 발견했다.

하지만 여전히 불편한 점이 하나 남아 있었다.

친구와 게임을 하려면 Host의 IP 주소와 포트를 알아야 했다.

같은 공유기에 연결된 컴퓨터라면 직접 주소를 확인해 접속할 수 있겠지만, 각자 다른 집에서 플레이하려면 이야기가 더 복잡해진다.

애초에 만들고 싶었던 것은 친구와 편하게 한 판 즐길 수 있는 게임이었다.

그런데 게임을 시작하기도 전에 네트워크 주소부터 설명해야 한다면 조금 아쉬울 것 같았다.

그래서 다음에는 친구에게 방 코드 하나만 보내면 같이 플레이할 수 있는 방식을 만들어보기로 했다.

그리고 이 작업에서는 처음 예상했던 것보다 훨씬 많은 문제를 만나게 됐다.

  • #1인개발
  • #게임개발
15
m
mustardoo

mustardoo님의 다른 글

  • 방 코드를 만들었는데, 연결이 되지 않았다 — SAME DECK #48일 전
  • 같은 덱을 쓴다고 전략이 생기는가? — SAME DECK #212일 전
  • 하나의 덱을 공유하는 턴제 게임 — SAME DECK #119일 전

댓글 0

My avatar