교환 시스템의 생명 서버 주도형 트랜잭션

1. 교환 시스템의 생명: 서버 주도형 트랜잭션

단순한 클라이언트-서버 통신을 넘어, 아이템 교환은 ‘서버 주도형 트랜잭션’으로 설계해야 합니다. 이는 클라이언트의 모든 요청이 ‘거래 제안(Offer)’일 뿐이며, 최종적인 아이템 이동은 오직 서버의 엄격한 통제 하에 이루어진다는 의미입니다. 만약 클라이언트가 아이템을 보유하고 있다고 주장해도, 서버의 데이터베이스를 통해 확인하기 전에는 어떤 행동도 허용하지 않습니다.

이러한 접근 방식은 해킹, 아이템 복사(duplication), 또는 분실(loss)과 같은 치명적인 문제를 원천적으로 방지합니다.

2. 교환 요청 객체와 상태 관리

아이템 교환은 한 순간의 이벤트가 아니라, ‘요청 → 대기 → 수락 → 완료’라는 일련의 상태를 거치는 라이프사이클을 가집니다. 따라서 교환 자체를 하나의 객체(Object)로 정의하고, 그 상태를 서버에서 관리해야 합니다.

  • TradeRequest 객체:
    • tradeId: 고유 식별자 (GUID)
    • senderId, receiverId: 교환 당사자 ID
    • senderItems, receiverItems: 각 플레이어가 제시한 아이템 목록 (아이템 ID와 수량)
    • status: ‘Pending’, ‘AcceptedBySender’, ‘AcceptedByReceiver’, ‘Completed’, ‘Canceled’

플레이어가 교환을 제안하면, 서버는 이 TradeRequest 객체를 생성하고 ‘Pending’ 상태로 저장합니다. 이후 모든 클라이언트의 상호작용은 이 객체의 상태를 변경하는 방식으로 이루어집니다.

3. ‘원자성(Atomicity)’을 보장하는 데이터베이스 트랜잭션

교환 시스템에서 가장 중요한 단계는 데이터베이스 업데이트입니다. 아이템의 이동은 ‘성공 또는 실패’라는 이분법적 결과만 가져야 합니다. 한 플레이어의 아이템은 사라졌는데 다른 플레이어의 인벤토리는 업데이트되지 않는 상황은 절대 발생해서는 안 됩니다.

이를 위해 데이터베이스의 ‘트랜잭션’ 기능을 활용합니다.

  1. 시작(Begin): 서버는 데이터베이스 트랜잭션을 시작합니다.
  2. 검증(Verify): 양측 플레이어의 인벤토리에 제안한 아이템이 모두 있는지 확인합니다.
  3. 이동(Transfer):
    • sender의 아이템을 인벤토리에서 제거합니다.
    • receiver의 인벤토리에 새로운 아이템을 추가합니다.
  4. 확정(Commit): 모든 과정이 오류 없이 완료되면 트랜잭션을 최종 확정합니다.
  5. 롤백(Rollback): 만약 한 단계라도 실패하면, 모든 변경 사항을 취소하고 원래 상태로 되돌립니다.

이러한 과정을 통해 서버는 아이템 교환의 무결성을 철저하게 지켜냅니다.

4. 지연 및 비동기적 응답 처리

실제 네트워크 환경에서는 패킷 유실, 지연, 클라이언트 접속 종료 등 다양한 문제가 발생합니다. 교환 시스템은 이러한 상황을 예측하고 처리해야 합니다.

  • 비동기적 처리: 교환 요청이 서버에 도달하면, 서버는 즉시 응답하는 대신 백그라운드에서 트랜잭션을 처리합니다. 클라이언트는 ‘요청을 보냈음’을 확인하는 응답만 받습니다.
  • 재접속 시 상태 확인: 교환 도중 클라이언트가 접속을 종료하면, 재접속 시 서버에 tradeId를 보내 현재 교환의 상태를 확인합니다. 서버는 ‘Completed’ 상태라면 완료 메시지를, ‘Pending’ 상태라면 알림을 다시 보내 교환을 이어나가게 합니다.

이처럼 심화된 아이템 교환 시스템은 단순한 네트워크 통신 코드를 넘어, 게임의 경제 시스템을 지탱하는 강력한 아키텍처를 기반으로 합니다.

댓글 남기기