35. 멀티 디바이스 세션 목록의 교체·제거 경합 (C#)

난이도 중 해설 보기 →

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

결함 코드 · C#
// 시나리오: 멀티 디바이스 동시 접속 세션 관리 (C#)
//
// 이 게임은 한 계정으로 여러 기기(PC·모바일)에서 동시에 접속할 수 있고,
// 같은 종류(플랫폼)에서는 1개만 허용한다. 즉 계정당 세션 목록을 유지하며,
// 같은 플랫폼의 새 로그인이 오면 그 플랫폼의 기존 세션만 킥한다.
//
// 요구사항:
//  - 계정별 활성 세션 목록에 (플랫폼당 최대 1개) 세션을 등록한다.
//  - 같은 플랫폼 재로그인 시 그 플랫폼의 기존 세션만 종료하고 새 세션으로 교체한다.
//  - 로그아웃/연결 종료 시, "지금 그 연결에 해당하는" 세션만 목록에서 제거한다.
//  - 로그인/로그아웃/재접속이 여러 스레드에서 동시에 일어날 수 있다.
//
// 아래 매니저를 검토하라. 표시된 지점 (A)(B)(C).

using System;
using System.Collections.Generic;

public sealed class Session
{
    public long AccountId;
    public string Platform = "";   // "pc" | "mobile"
    public Guid ConnId = Guid.NewGuid();
    public void Kick() { /* 소켓 종료 통지 */ }
}

public sealed class MultiSessionManager
{
    // accountId -> (platform -> session)
    private readonly Dictionary<long, Dictionary<string, Session>> _byAccount = new();

    public void OnLogin(Session s)
    {
        if (!_byAccount.TryGetValue(s.AccountId, out var perPlatform))
        {
            perPlatform = new Dictionary<string, Session>();
            _byAccount[s.AccountId] = perPlatform;
        }

        // (A) 같은 플랫폼 기존 세션 킥 후 교체
        if (perPlatform.TryGetValue(s.Platform, out var old))
            old.Kick();

        perPlatform[s.Platform] = s;   // (B) 새 세션 등록
    }

    public void OnDisconnect(Session s)
    {
        if (_byAccount.TryGetValue(s.AccountId, out var perPlatform))
        {
            // (C) 이 플랫폼 슬롯 제거
            perPlatform.Remove(s.Platform);
            if (perPlatform.Count == 0)
                _byAccount.Remove(s.AccountId);
        }
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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