[TIL] Unity - Enum 기반 리팩토링 - day 100

뭉크의 개발·2023년 12월 7일
0

Unity - Camp

목록 보기
68/70
post-thumbnail

🐧 들어가기 앞서

드디어 100일!!!!!


오늘은 오디오 매니저와 씬을 로드하는 코드를 리팩토링했다.

⚠️ 리팩토링 전의 문제

오류 발생 가능성

문자열 기반의 코드는 타이핑 오류나, 문자열 불일치 등으로 인해 런타임 오류가 발생할 가능성이 높았다.

코드 변경 시 오류 위험

문자열을 직접 사용하면, 해당 문자열을 변경할 때 관련된 모든 코드를 찾아 수정해야 한다.

코드의 일관성 부족

문자열을 직접 사용하면, 동일한 문자열에 대해 일관성을 유지하기 어렵다.


🤔 리팩토링 이유

타입 안전성 증가

기존 코드는 문자열 기반으로 오류 가능성이 높고, 컴파일 시 오류를 잡아내기 어려웠다. Enum이나 상수를 사용하면 이러한 문제를 줄일 수 있었다.

코드의 가독성과 유지보수성 향상

Enum이나 상수를 사용하면 코드가 더 명확해지고, 추후에 수정이 필요할 때 쉽게 찾아 변경할 수 있다.

중복 코드 감소

같은 문자열을 여러 곳에서 사용하는 경우, 중복 코드가 발생할 수 있다. 이를 Enum이나 상수로 관리하면 중복을 줄일 수 있다.

어떤 방법이 있을까?

처음에는 nameof 방법을 생각했다. nameof 연산자는 변수, 타입, 멤버 등의 이름을 문자열로 반환한다.
컴파일 시간에 검증되며, 해당 식별자의 이름만을 문자열로 반환한다.
예를 들어, nameof(SFXClips.Tackle)는 단순히 "Tackle"라는 문자열을 반환하는 것이 아니라, 항상 "Tackle"이라는 문자열을 반환한다.
nameof는 주로 리팩토링에 유용하며, 식별자 이름이 변경되더라도 자동으로 업데이트된다.

  • AudioManager.cs (Orininal)
 public void PlaySFX(string category, string clipName)
    {
        AudioClip clip = ResourceManager.Instance.LoadPrefab<AudioClip>($"AudioClip/{category}/SFX/{clipName}", clipName);
        if (clip)
        {
            PlayAudioClip(clip);
        }
    }
  • AudioManager.cs (nameof Ver)
public void PlaySFX2(SFXCategory category, SFXClips clip)
{
    string categoryName = nameof(category);
    string clipName = nameof(clip);
    AudioClip audioClip = ResourceManager.Instance.LoadPrefab<AudioClip>($"AudioClip/{categoryName}/SFX/{clipName}", clipName);
    if (audioClip)
    {
        PlayAudioClip(audioClip);
    }
}

그러나

nameof를 사용하면, Enum의 실제 값을 문자열로 가져오는 대신 항상 변수나 타입의 이름만을 문자열로 반환한다.

즉, nameof(SFXClips.Tackle)는 Tackle이라는 문자열을 반환하지 않고, 매개변수나 변수 이름을 문자열로 반환한다.

오디오 시스템에서는 Enum 값에 해당하는 실제 오디오 클립 이름이 필요하다.

SFXClips.Tackle이라는 Enum 값이 실제로 어떤 오디오 클립과 연관되어 있는지를 알아야 하기 때문에 ToString 메서드가 필요하다.

따라서, Enum 값의 실제 이름을 얻기 위해서는 ToString 메서드를 사용해야 하며, nameof는 이 경우에 적합하지 않는다.

결론적으로, nameof는 코드의 리팩토링과 유지 관리를 용이하게 하는 데 유용하지만, Enum 값의 실제 문자열 표현을 얻기 위해서는 ToString 메서드를 사용해야 한다...


🐧 오늘 배운 것

ToString()

사실 ToString 말고도 Refelection을 이용해 Enum의 이름과 값을 매핑하는 방법, Dictionary에 Enum 값을 키로, 문자열을 값으로 할 수 있었다.

그럼에도 ToString을 선택한 이유는

1. 간결성

간단하고 직관적인 방법으로 Enum 값을 문자열로 변환할 수 있다.

2. 효율성

성능적으로 Reflection보다 효율적이며, 추가적인 데이터 구조 없이도 작동한다.

3. 유지보수 용이성

Enum의 값을 변경하거나 추가할 때, ToString 방법은 자동으로 이를 반영한다.

✅ 장점?

코드의 안정성

ToString을 사용하면 컴파일 시 타입 체크를 통해 오류를 줄일 수 있다.

코드의 명확성

Enum 사용은 코드의 의도를 명확하게 전달한다.

리팩토링 용이성

추후 코드 변경이 필요한 경우, Enum 값만 변경하면 되므로 유지보수가 쉬워진다.

일관성 유지

프로젝트 전반에 걸쳐 일관된 방식으로 오디오 클립과 씬 이름을 관리할 수 있다.


🐧 기억할 것 & 진행

Enum 정의

public enum SFXClips
{
    Check,
    Close,
    EndDay,
    Hand,
    Hover,
    Open,
    Pause,
    Reroll,
    ...
}

AudioManager.cs 수정

public void PlaySFX(SFXCategory category, SFXClips clip)
{
    string categoryName = category.ToString();
    string clipName = clip.ToString();
    AudioClip audioClip = ResourceManager.Instance.LoadPrefab<AudioClip>($"AudioClip/{categoryName}/SFX/{clipName}", clipName);
    if (audioClip)
    {
        PlayAudioClip(audioClip);
    }
}

🐧 게임에 구현한다면?

결론적으로, Enum에 포함되어 있지 않는다면, 컴파일 단계에서 오류를 발견할 수 있다.

또한 만약 오류가 생기더라도, 참조한 코드를 전부 찾아보지 않고, Enum과 경로, 그리고 해당 메서드만 확인하면 오류를 잡을 수 있다.


0개의 댓글