11. 크로스-샤드 구매 사가: 부분 실패 보상·멱등·내구 로그 부재 (C#)

난이도 최상 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// [시나리오] 크로스-샤드 구매 사가 (서버-서버)
// 프리미엄 상점 구매는 서로 다른 서비스에 걸쳐 있다:
//   - 지갑 서비스(샤드 A): 플레이어의 유료 재화를 차감한다.
//   - 인벤토리 서비스(샤드 B): 구매한 아이템을 지급한다.
// 하나의 로컬 트랜잭션으로 두 서비스를 함께 커밋할 수 없으므로, 각 단계는
// 독립적인 원격 호출이다(각각 성공/실패/타임아웃할 수 있다).
//
// [요구사항]
//   - 돈을 냈으면 아이템을 받아야 하고, 아이템을 못 주면 돈을 돌려줘야 한다(원자성 효과).
//   - 재시도나 프로세스 재기동이 있어도 이중 차감·이중 지급이 없어야 한다.
//
// [과제] PurchaseSaga.BuyItem 을 검토하고, 지급 단계가 실패/타임아웃하거나
//        중간에 프로세스가 죽는 경우 무엇이 남는지, 그리고 재시도하면 어떻게
//        되는지 원인과 수정안을 제시하라. 표시된 (A)(B) 지점에 주목하라.

using System;

interface IWalletService     { void Debit(int playerId, long amount); void Refund(int playerId, long amount); }
interface IInventoryService  { void Grant(int playerId, string itemId); }

class PurchaseSaga
{
    private readonly IWalletService _wallet;         // 샤드 A
    private readonly IInventoryService _inventory;   // 샤드 B

    public PurchaseSaga(IWalletService w, IInventoryService i) { _wallet = w; _inventory = i; }

    public void BuyItem(int playerId, string itemId, long price)
    {
        // (A)
        _wallet.Debit(playerId, price);

        // (B)
        _inventory.Grant(playerId, itemId);
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.