Dart 언어에서 Enum(열거형)은 특별한 클래스 타입으로, 고정된 상수 값들의 집합을 나타내는 데 사용됩니다. 이러한 Enum은 연관된 상수들을 이름으로 참조할 수 있어 코드의 가독성과 유지보수성을 크게 향상시킵니다. Dart의 Enum 기능은 다른 많은 프로그래밍 언어들과 비교했을 때 매우 강력하고 유연하게 설계되어 있어, 이를 잘 활용하면 더 간결하고 직관적인 코드를 작성할 수 있습니다.
이 글에서는 Dart의 Enum 기능을 활용하는 방법에 대해 설명하고, 다양한 예제를 통해 Dart에서 제공하는 일반적인 Enum과 확장된 Enum의 차이점과 활용법을 알아보겠습니다.
Dart에서 모든 Enum은 Enum 클래스를 상속받으며, 이는 Dart의 Enum이 강력하고 유연한 기능을 제공하는 이유 중 하나입니다. Enum은 하위 클래스화, 구현, 믹스인, 명시적 인스턴스화가 불가능하여 Enum 타입의 무결성과 불변성을 보장합니다.
기본적으로 Enum은 다음과 같이 간단하게 선언할 수 있습니다.
enum Status {
initial,
loading,
failure,
success;
}
위의 Status Enum은 앱 내에서 작업의 상태를 나타내는 데 사용될 수 있습니다. 예를 들어, API에서 데이터를 가져오거나 검색 작업을 수행할 때 각 상태를 의미 있게 표현할 수 있습니다. 이렇게 정의된 Enum을 사용하면 상태에 따라 서로 다른 위젯을 표시하는 등, 코드를 더 읽기 쉽게 만들 수 있습니다.
// build 함수 내부에서
return switch(status) {
Status.loading => LoadingWidget(),
Status.success => SuccessWidget(),
Status.failure => FailureWidget(),
_ => InitialWidget(),
};
Dart에서는 간단한 Enum에도 Getter를 정의할 수 있어, Enum 값에 따라 계산된 결과를 반환하거나 추가적인 논리를 구현할 수 있습니다.
enum Status {
initial,
loading,
failure,
success;
bool get isInitial => this == Status.initial;
bool get isLoading => this == Status.loading;
bool get isFailure => this == Status.failure;
bool get isSuccess => this == Status.success;
}
위의 코드에서는 Status Enum의 각 값에 대해 Boolean 속성을 정의하여, 해당 상태인지 쉽게 확인할 수 있도록 했습니다. 이러한 기능은 조건부 로직을 단순화하는 데 유용하게 사용될 수 있습니다.
if(status.isSuccess) {
// 예: 대시보드로 리디렉션
navigateTo(AppRoute.dashboard);
} else {
handleFailure();
}
Dart의 확장된 Enum(Enhanced Enum)은 일반적인 Enum보다 더 강력한 기능을 제공합니다. 확장된 Enum은 필드, 메서드, 생성자 등을 가질 수 있어, 더 복잡한 동작과 속성을 Enum 자체 내에 캡슐화할 수 있습니다.
enum AccountStatus {
locked(value: 'locked', description: 'You are locked'),
banned(value: 'banned', description: 'Banned from system'),
pending(value: 'pending', description: 'We are reviewing your status'),
active(value: 'active', description: 'You have no restrictions'),
unknown(value: 'unknown', description: 'Unknown status');
const AccountStatus({
required this.value,
required this.description,
});
final String value;
final String description;
bool get isLocked => this == AccountStatus.locked;
bool get isBanned => this == AccountStatus.banned;
bool get isPending => this == AccountStatus.pending;
bool get isActive => this == AccountStatus.active;
}
이 예시에서 AccountStatus Enum은 사용자 계정의 상태를 관리하는 데 사용될 수 있습니다. 각 상태는 value와 description 필드를 가지고 있으며, 해당 상태를 쉽게 확인할 수 있는 Getter를 포함하고 있습니다. 이러한 구조는 코드의 가독성을 높이고 유지보수를 쉽게 합니다.
때로는 서버에서 받은 데이터가 예상하지 못한 값일 수 있습니다. 이런 경우를 처리하기 위해 unknown 상태와 이를 반환하는 Factory 생성자를 추가할 수 있습니다.
enum AccountStatus {
// 이전 코드와 동일
...
unknown(value: 'unknown', description: "Unknown status");
factory AccountStatus.fromString(String status) {
return AccountStatus.values.firstWhere(
(el) => el.value == status,
orElse: () => AccountStatus.unknown,
);
}
}
이 구현을 통해 서버에서 받은 데이터를 안전하게 처리하고, 일치하는 상태가 없을 경우 unknown 상태를 반환하여 예상치 못한 오류를 방지할 수 있습니다.
Dart의 확장된 Enum을 활용하면 Enum 자체 내에 위젯을 빌드하는 로직을 포함시킬 수도 있습니다.
enum AccountStatus {
// 이전 코드와 동일
...
Widget accountStatusComponent() {
return switch(this) {
AccountStatus.unknown => Text('User is unknown'),
_ => Text('User is ${this.value}')
};
}
}
// 사용 예시
return status.accountStatusComponent();
이렇게 하면 상태에 따라 자동으로 적절한 위젯을 생성할 수 있어, 코드의 중복을 줄이고 유지보수성을 높일 수 있습니다.
Dart의 Enum은 다른 프로그래밍 언어와 비교했을 때 매우 강력한 기능을 제공합니다. 단순한 상수 집합에 불과한 기존의 Enum과 달리, Dart의 Enum은 필드, 생성자, 메서드를 포함할 수 있어 더 복잡한 동작과 상태를 캡슐화할 수 있습니다. 이러한 기능 덕분에 Dart의 Enum은 고정된 상수 집합을 표현하는 데 그치지 않고, 관련된 데이터와 기능을 함께 관리하는 데 유용하게 사용될 수 있습니다.
Dart의 공식 문서에서 더 많은 정보를 확인할 수 있으며, 이 글이 Dart Enum의 강력한 기능을 이해하는 데 도움이 되었기를 바랍니다.
Ethiel ADIASSA의 Enums on Steroids with Dart. Best Enum features ever!을 한국어로 번역해서 다시 작성했습니다.
https://medium.com/@ethiel97/enums-on-steroids-with-dart-best-enum-features-ever-ff7ba7996b87