티스토리 뷰

많은 프로그램 언어들이 열거형을 지원한다.

Dart도 물론 enum 타입을 사용할 수 있는데 보통 그룹화해 사용할 수 있는 상수 값들을 하나의 묶음으로 만들기 위해서 사용한다.

프로그램 언어들 마다 enum을 다양하게 활용할 수 있는 기능을 제공하는데 dart에서는 enum에 추가적인 기능을 정의할 수 없고 오직  단순한 선언과 사용만을 지원한다. 
(dart 2.17부터는 enum도 일반 클래스 처럼 쉽게 기능을 정의하고 사용할 수 있게 되었다 - 본문 마지막 참고)

enum의 기본 사용법

예를 들어 아래와 같이 공지사항 게시판, 자유게시판으로 게시판이 타입이 구분된다고 가정해보자

enum을 사용하면 아래와 같이 선언해서 사용할것이다.

enum BoardType { notice, free, undefined }

아래 코드에서 문자열을 직접 비교하는 방법과 enum 타입을 비교하는 코드를 확인할 수 있다.

코드상에 문자열을 직접 사용하는 방법은 가능하면 피해야 하는 코딩 스타일이다.
특히 로직 중에 문자열을 직접 비교하는 방법은 사용하지 않는 것이 좋다.

가능하면 enum을 사용할 수 있도록 하자!!

// BAD
// board 모델에서 string타입의 type 변수를 사용할경우

if (board.type == "notice") {
   ...
} else if (board.Type == "free") {
  .....
} else {
....
}

// GOOD
// enum 형식으로 type 변수를 사용할경우 
if (board.type == BoardType.notice) {
...
} else  if (board.type == BoardType.free) {
...
} else {
...
}

Dart에서 string을 enum으로 바로 변환할 수 없다.

enum을 사용하는 것이 string을 사용하는 것보다 훨씬 더 좋은 방법임은 다들 알 것이다.

하지만 dart에서는 서버 API 등에서 받은 string형식의 값을 enum으로 변환하는 별도의 기능을 제공하지 않아 string값을 enum으로 변환하는데 불편함이 있다.

 

서버로부터 게시판 목록을 가져오는 API에서 아래와 같은 결과를 받았다고 가정해보자.

이 응답 값을 앱에서 사용하기 위해서는 적당한 모델 클래스로 변환해야 할 것이다.

// API response - JSON

"boaders"  : [
    {
      "id" : "notice01",
      "title" : "공지사항",
       "type" : "notice",
       .....
    }, 
    {
      "id" : "free01",
      "title" : "자유게시판",
       "type" : "free",
       .....
    }, 
]

이제 위 결과 값을 아래 Boader 클래스로 변환한다고 가정해보자. 
Board 클래스의 type 필드는 API에서는 문자열 "notice"임으로 parseToBoardType
함수와 같이 string형식의 값을 BoaderType으로 변화하는 과정이 필요하다.

// Boader Model
class Boader {
     final String id;
     final String title;
     final BoaderType type;
}

// value를 입력받아 BoarderType으로 변환함
BoaderType parseToBoardType(String value) {
   if (value == "notice") {
      return BoaderType.notice;
  } else if (value == "free") {
      return BoaderType.free
  }
  return BoaderType.undefinde;
}

 

swift나 kotlin의 경우 string값을 enum으로 변환해주는 기능을 언어적으로 제공한다.

// swift
enum BoaderType: String {
 case notice
 case free
 case undefinde
}

let boaderType = BoaderType(rawValue: "notice")
// kotlin
enum class BoardType(val code: String) {
    NOTICE("notice")
    FREE("free")
    UNDEFINED("")

    companion object {
        fun getByCode(code: Int) = Color.values().find { it.code == code }
     }
}

val boardType = BoardType.getByCode("notice")

하지만 dart에서는 위와 같이 언어적으로 enum으로 쉽게 변환할 수 있는 기능이 없어 직접 비교 구문을 사용해야 하는 불편함이 있다.
아래 코드는 비교 구분 없이 언어적으로 조금 더 깔끔하게 enum으로 변하고 값을 사용할 수 있도록 만든 코드이다.


Extension과 EnumData 클래스를 이용한 쉬운 enum변환 및 활용

 

Dart에서는 Extension을 이용해서 enum을 확장해서 사용할 수 있다.

EnumData라는 클래스를 만들어 enum에 필요한 property를 정의하였고,  extension의 code와 name getter을 통해 별도의 조건식 없이 값을 가져다 사용할 수 있도록 하였다. 

class EnumData {
  final String code;
  final String displayName;
  EnumData({required this.code, required this.displayName});
}

enum BoardType { notice, free, undefined }

extension BoaderTypeExt on BoaderType {
  static final _data = {
    BoaderType.notice: EnumData(code: 'notice', displayName: 'Notice'),
    BoaderType.free: EnumData(code: 'free', displayName: 'Free'),
    BoaderType.undefined: EnumData(code: '', displayName ''),
  };

  static BoaderType.getByCode(String code) {
    try {
      return _data.entries.firstWhere((el) => el.value.code == code).key;
    } catch (e) {
      return BoaderType.undefined;
    }
  }
  String get code => _data[this]!.code;
  String get displayName => _data[this]!.displayName;
}

 

Dart 2.15에서는 name과 byName을 사용할 수 있다.

flutter 2.8부터 사용할수 있는 dart2.15에서 enum 기능이 조금 추가되었다.

다른 언어에서 처럼 name과 byName() 함수를 사용할 수 있다. 

final boardType = BoardType.values.byName('notice') // BoardType.notice 
print(boardType.name)  // 'notice'


Dart 2.17에서 enum은 다르다!!!

flutter 3.0에서 사용되는 dart 2.17에서는 그동안 불편했던 enum에 많은 기능이 추가되었다. 

enum에서도 일반 class처럼 property나 method, static method를 추가할 수  있게 되었다. 

(이제는 enum의 기능 확장을 위해 별도의 extension을 정의할 필요가 없다. ) 

드디어 다른 언어들에서 처럼 좀 편하게 enum을 사용할 수 있을 것 같다. 


dart 2.17 이후부터는 아래와 같이 extension도움 없이 enum을 편하게 사용해보자!

enum BoardType {
  notice('notice', '공지사항'),
  free('free', '자유게시판'),
  undefined('undefined', '');
  
  const BoardType(this.code, this.displayName);    
  final String code;
  final String displayName;  
  
  factory BoardType.getByCode(String code){
    return BoardType.values.firstWhere((value) => value.code == code, 
                                        orElse: () => BoardType.undefined);
  }
}

 

 

 

마치며

로직 중간에 문자열을 직접 사용하는 코드를 만들어서는 안 됩니다.

특히 고정된 값 들만 있을 경우에는 꼭 enum으로 만들어서 사용하시기 바랍니다. 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함