You are on page 1of 2

Enum 타입

Enum 타입의 정의
어떤 값이 범위를 갖되 연속적인 범위가 아니라 띄엄띄엄 값이 존재하는 경우 enum 타입을
사용해서 많이 정의한다. 예를 들면 다음과 같은 경우이다.

enum ValueRange
{
One = 1,
Two,
Three
} ;

enum 타입은 정수와 호환되기 때문에 타입 캐스팅을 통해서 정수 타입 변수와 enum 타입 변수는
서로 값을 교환할 수 있다.
여기까지 enum 타입은 큰 문제를 갖지 않는다. 이제 enum 타입을 사용하면서 좀 더 신경써야 할
점들을 하나씩 알아보자.

enum 타입은 단순히 값의 범위를 정의하는 것에서 그치지 않고 switch 나 if 같은 분기 문에서


값을 비교하는데 사용한다.
위의 ValueRange 의 경우 다음과 같은 switch 문의 조합으로 사용하는 것이 일반적이다.

ValueRange r ;
switch ( r ) {
case One : break ;
case Two : break ;
case Three : break ;
}

default case 는 일부러 제외했다. 이제 발생할 수 있는 문제들을 하나씩 살펴보자.


우선 default case 의 위치는 어디에 위치해야 할까? ValueRange 값의 초기화 값이라던가
프로그램의 사양에 따라서 One, Two, Three 의 case 위에 놓일 수도 있고, default : throw
"invalid range" ; 와 같이 예외를 발생시킬 수도 있다.

초기화 값은 프로그램 사양에 의해서 변경될 수도 있고, 초기 값을 분기문으로 정의하는 것이


바람직하지는 않아보인다. 그래서 assert(One <= r && r <= Three) ; 와 같이
단정문(assertion)을 사용하는 것이 훨씬 유용해 보인다.
switch 문은 클래스 구조로 리팩토링할 수도 있지만, 값을 표현하기 위해 클래스를 정의해야 하는
부담 등을 고려해서 이 방식의 리팩토링은 일단 배제하자.

단정문을 사용하게 되면, ValueRange 에 변경해 주어야 할 것이 있다. 바로 ValueRange 의 시작


값과 끝 값의 정의이다. 시작 값과 끝 값을 정의하지 않는다면 ValueRange 의 항목이 변경될
때마다 얼마나 많은 코드가 변경될 지 알 수 없는 노릇이다.

enum ValueRange
{
BeginValueRange = 1, // 시작 값과 같은 값을 할당했다.
One = 1,
Two,
Three,
EndValueRange
} ;

BeginValueRange 가 One 과 같은 값을 가져야 할 이유는 없다. 다만, Begin~, End~를 미리


넣지 않고 빼먹은 상황에서 기존에 One~Three 의 값을 사용하고 있는 코드와 이 코드가 참조하는
환경 설정 파일들의 변화를 최소하하기 위해서 BeginValueRange 는 One 과 같은 값을 같도록
했을 뿐이다.

이제 단정문은 assert(BeginValueRange <= r && r < EndValueRange) ; 와 같이 변경


가능성을 두려워하지 않고 사용할 수 있다.

만일 이 값들이 소스 코드 내부에서만 사용되는 값들이 아니라 사용자 환경 설정 파일에서도


사용되는 값이라면 범위를 검사해야 하는 부분은 한 군데 이상일 것이다. 그렇다면 단정문은
사용자 환경 설정 파일을 읽는 부분의 코드와 ValueRange 를 값으로 전달받고 사용하는 코드 중
어느 곳에 넣어야 할까?

일단은 모든 부분에 단정문을 넣을 것을 권하고 싶다. 단정문에 의한 검사로 인해 각 함수 모듈과


클래스를 충분히 튼튼하게 만들 수 있고, 충분히 테스트된 코드에서는 예외 상황이 발생할
가능성을 매우 낮은 수준까지 낮출 수 있으므로 릴리즈 버전에서는 옵션으로 쉽게 제거할 수 있다.
사실 릴리즈 버전에서 예외에 의한 오류 메시지가 발생하는 것이 좋은 일은 아니므로 단정문은
테스트 단계에서만 두어 예외적인 상황이 발생할 가능성을 최대한 낮춘 후에 어느 정도 확신이
생기면 가급적 제거하는 것이 좋다.

단, 사용자 혹은 외부 코드와 가장 마지막에 위치한 코드에서는 단정문에 의한 조건 검사보다는


명시적인 예외를 발생시키는 편이 피드백의 관점에서 훨씬 유리하다. 따라서, 사용자 환경 설정
파일을 읽는 코드의 경우는 단정문보다는 if ( !(BeginValueRange <= r && r <
EndValueRange ) ) throw "invalid value range" ; 와 같이 확실히 피드백될 수 있는
코드를 작성하는 것이 좋다.

Begin~, End~ 값을 정의하고 단정문을 사용하는 것으로 enum 타입을 잘 사용할 수 있다.

다음은 만일 enum 타입의 값을 사용자에게 피드 백, 즉 enum 타입의 값을 사용자에게 보여줄


필요가 있을 때는 문자열로 값을 변환해야 한다. 사용자에게 받은 입력이 비록 정수 값으로
받았다고 할지라도 보여줄 때는 숫자보다는 enum 타입에서 정의하고 있는 의미로 보여주는 것이
좋다.

이러한 경우에는 enum 타입을 사용하기 보다는 enum 타입과 같은 역할을 할 수 있도록 클래스를
설계하는 것이 코드의 중복을 최소화하는 방법이다.

You might also like