55. 캐릭터 이름 변경의 유일성 검사-예약 비원자(중복 이름 발생) · C#

난이도 하 해설 보기 →

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

결함 코드 · C#
// 시나리오: MMORPG 캐릭터 "이름 변경권" 처리
//
// 플레이어가 이름 변경권을 사용하면 원하는 새 이름으로 캐릭터명을 바꾼다.
// 서버 요구사항:
//   - 캐릭터 이름은 월드 전체에서 유일해야 한다(대소문자 무시 정규화 후).
//   - 이미 누군가 쓰는 이름으로는 변경할 수 없고, 이 경우 변경권을 소모하지 않는다.
//   - 변경에 성공하면 이전 이름은 다시 다른 사람이 쓸 수 있게 풀린다.
//   - 이름 변경 요청은 여러 플레이어로부터 스레드 풀에서 동시에 처리된다.
//
// 아래 NameChangeService 는 사용 중인 이름 집합(_taken)과 캐릭터별 현재 이름을 관리한다.
// 같은 미사용 이름 "Aria" 로 두 플레이어가 거의 동시에 변경을 요청하는 상황을 검토하라.
//
// 과제:
//  1) (A)(B) 지점을 중심으로, 동시 요청이 겹칠 때 요구사항이 어떻게 깨지는지 설명하라.
//  2) 재현되는 구체적 인터리빙(시간 순서)을 제시하라.
//  3) 요구사항을 지키도록 수정안을 제시하라.

using System;
using System.Collections.Generic;

public class Character
{
    public long Id;
    public string Name = "";
    public int NameChangeTickets;
}

public class NameChangeService
{
    // 현재 사용 중인 이름(정규화된 형태)
    private readonly HashSet<string> _taken = new HashSet<string>();
    private readonly Dictionary<long, Character> _chars = new Dictionary<long, Character>();

    private static string Normalize(string s) => s.Trim().ToLowerInvariant();

    public bool TryRename(long charId, string newName)
    {
        Character c = _chars[charId];
        if (c.NameChangeTickets <= 0) return false;

        string key = Normalize(newName);

        // (A) 이 이름을 지금 아무도 안 쓰는지 확인
        if (_taken.Contains(key))
            return false;   // 이미 사용 중 → 실패, 변경권 보존

        // ... 검증/로깅/DB 반영 준비 등 (짧은 처리 시간) ...

        // (B) 예약하고 캐릭터에 반영
        _taken.Remove(Normalize(c.Name));  // 이전 이름 반납
        _taken.Add(key);
        c.Name = newName;
        c.NameChangeTickets -= 1;
        return true;
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

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