서버 없이 1:1 대전 붙이기 — QR에 localhost가 박혀서 아무도 못 들어온 이야기


아이랑 같이 할 카드 배틀 게임을 만들었습니다. 동물 카드 15장에 물▶불▶풀 상성이 있고, 합이 10이 되면 콤보가 터지는 규칙이에요. 놀면서 덧셈과 상성 관계를 자연스럽게 익히게 하려고 그렇게 짰습니다.

혼자 AI랑 하는 것까진 금방 됐는데, “아빠랑 하고 싶어”라는 말에 1:1 대전을 붙이게 됐습니다. 여기서부터가 본론이에요.

1. 서버를 만들고 싶지 않았습니다

개인 프로젝트에 실시간 대전을 붙이려면 보통 서버가 필요합니다. 그런데 아이랑 집에서 하는 게임 하나 때문에 서버를 띄우고, 비용 내고, 계속 관리하는 건 과하다고 생각했어요.

그래서 P2P로 갔습니다. PeerJS를 써서 두 기기를 직접 연결하고, 방을 만든 기기가 심판 역할을 맡습니다. 게임 규칙 판정, 턴 관리, 승패 결정을 전부 방장 기기가 하고 상대 기기는 입력을 보내고 결과를 받습니다.

중앙 서버는 없지만 판단하는 주체는 하나라서 두 기기의 상태가 어긋날 일이 없어요. 초대는 QR 코드로 하고요. 방장 화면의 QR을 찍으면 바로 접속됩니다.

2. 그런데 아무도 못 들어왔습니다

만들고 테스트하는데 QR을 찍어도 접속이 안 됐어요. 원인은 좀 민망했습니다.

개발 중이라 QR에 들어간 주소가 localhost 였습니다. 제 노트북에서는 잘 되죠. 그런데 그 QR을 아이 태블릿으로 찍으면 태블릿의 localhost, 즉 태블릿 자기 자신을 가리킵니다. 당연히 아무것도 없죠.

QR 코드는 다른 기기에서 열리는 게 목적인데, 제가 넣은 주소는 자기 자신에게만 유효한 주소였던 겁니다.

고친 방식은 QR을 만들 때 localhostLAN IP로 자동 변환하도록 한 거였어요. 이후로는 같은 와이파이에 있으면 바로 붙습니다.

3. 그리고 선턴이 너무 유리했습니다

기술 문제를 다 풀고 실제로 아이랑 붙어보니 다른 게 보였습니다. 먼저 시작하는 쪽이 확실히 유리했어요. 한 템포 먼저 카드를 깔면 그대로 주도권이 넘어갑니다.

이런 건 코드를 아무리 들여다봐도 안 보이고, 직접 여러 판 해봐야 나오는 문제더라고요.

해결은 후턴에게 보정 아이템(요정 열매)을 주는 걸로 했습니다. 규칙을 복잡하게 바꾸는 대신 아이템 하나 얹는 쪽이 아이한테 설명하기도 쉬웠어요.

💡 P2P 붙이며 배운 것 & 주의할 점

  • 팁: P2P는 연결이 끊어지는 게 정상이라고 생각하고 만드세요. 와이파이가 잠깐 흔들리거나 화면이 꺼지면 바로 끊깁니다. 저는 처음에 이걸 예외 상황으로 취급했다가 나중에 재접속 지원을 따로 붙여야 했어요. 처음부터 넣는 게 낫습니다.
  • 주의할 점: “내 기기에서 되는 주소”와 “남의 기기에서 되는 주소”는 다릅니다. QR·딥링크·공유 링크처럼 다른 기기로 건너가는 것을 만들 땐, 반드시 다른 기기에서 실제로 열어보세요. 제 노트북에서만 테스트했으면 영영 몰랐을 문제였습니다.

정리

서버 없이 실시간 대전을 붙이는 건 생각보다 할 만했습니다. 방장을 심판으로 두는 구조가 단순하고 확실했어요.

정작 시간을 잡아먹은 건 네트워크가 아니라 **“다른 기기 관점에서 생각하기”**였습니다. localhost 문제도, 선턴 유불리도 결국 내 화면만 보고 있어서 놓친 것들이었거든요.


태그: #P2P, #PeerJS, #WebRTC, #멀티플레이, #카드게임, #게임개발, #TypeScript, #클로드코드, #개인개발, #아이와함께