View
[Flutter] 같은 열거 값 이름을 가진 서로 다른 두 Enum 간의 변환에는 findWhere을 사용하자!
sm_amoled 2024. 9. 28. 16:23이번에 Enum 간의 타입 변환을 하는 새로운 방식을 찾아서, 기록으로 남겨두려고 한다. 생각도 못했던 방식… 오호…
ㅤ
대충 상황은 이런 느낌이였다.
레이어 분리를 위해 동일한 상태 값에 대해서 도메인 레이어에서는 Entity를 위한 enum 타입을 사용해주고 있었고, 데이터 레이어에서는 Model을 위한 enum 타입을 사용해주고 있었다.
enum MyDataTypeForEntity { A, B, C, D, none }
enum MyDataTypeForModel { A, B, C, D, none }
ㅤ
Entity와 Model에서는 이 두 타입을 각각 사용해 정의해주고 있었고, 나머지는 대부분 원시값으로 속성을 사용해주고 있었다.
class MyEntity {
final String name;
final MyDataTypeForEntity dataType;
MyEntity(this.name, this.dataType);
}
class MyModel {
final String name;
final MyDataTypeForModel dataType;
MyModel(this.name, this.dataType);
}
ㅤ
그런데, 계층을 넘어오면서 Entity와 Model 간에 상호변환이 필요한 시점이 있었는데 여기에서 두 타입간의 변환에서 막혀버렸다.
MyEntity fromModelToEntity(MyModel model) {
final name = model.name;
final type = model.dataType;
return MyEntity(name, type);
<< 에러 발생
<< Entity 가 가진 type은 MyDataTypeForEntity
<< Model이 가진 type은 MyDataTypeForModel
<< 두 타입이 변환이 불가능한 별도의 enum 이라 implicit 형변환이 불가능함
}
ㅤ
처음에는 ValueMapper를 따로 만들어서 Model에 내부 메서드나 getter로 넣어버릴까? 라고 생각을 했는데, Model 내부에 Entity 변환을 위한 메서드가 들어가는게 그렇게 썩 좋은 코드로 생각이 되지는 않았다.
enum MyDataTypeForModel {
A, B, C, D, none;
MyDataTypeForEntity toEntityEnum() {
// 이런 Enum 내부 메서드를 넣어볼까?
}
}
ㅤ
그래서 모델보다는 변환 메서드인 fromModelToEntity에 타입을 변환하는 로직도 들어가는게 좋겠다는 생각이 들었다. 그러고나서 그 다음에 고민했던 부분은 타입을 변환하는 방식을 어떻게 가져갈 지 였다.
ㅤ
단순히 Switch 문으로 처리해버리기에는 타입이 늘어날 때 마다 여기를 수정해줘야 한다는 단점이 있어, 유지보수를 하기 번거롭지 않을까 라는 생각이 들었다.
MyEntity fromModelToEntity(MyModel model) {
final name = model.name;
final type = switch (model.dataType) {
MyDataTypeForModel.A => MyDataTypeForEntity.A,
MyDataTypeForModel.B => MyDataTypeForEntity.B,
MyDataTypeForModel.C => MyDataTypeForEntity.C,
MyDataTypeForModel.D => MyDataTypeForEntity.D,
MyDataTypeForModel.none => MyDataTypeForEntity.none,
// E가 추가되면 여기에 작성해줘야함
// 문법 상 default => 00 에 대해 작성해주지 못해서,
// Model을 수정하면 여기에서 에러를 뱉기에 코드 수정이 강제된다.
};
return MyEntity(name, type);
}
ㅤ
그치만 다른 방법은 생각이 안나는걸? 고민을 조금 하다가 switch를 사용하는 방법을 들고 옆자리 사수분에게 어떻게 생각하는지를 여쭤봤다. 그리고 나온 답변은 firstWhere를 사용해본 예시가 프로젝트에 있을거니깐, 코드 한 번 찾아보라고 하셨다. 사실 처음 들었을 때는 퍼스트웨어라는 패키지가 따로 있는 줄 알고 ‘띠용?’ 이라 생각하고 있었다. ㅋㅋㅋ
ㅤ
어차피 이름이 동일한 값끼리 매핑을 할 것이니깐, 그 이름이 일치하는 열거 값으로 변환을 해주면 되기에 firstWhere를 사용하면 좀 더 유도리 있는 코드로 작성할 수 있다.
MyEntity fromModelToEntity(MyModel model) {
final name = model.name;
final type = MyDataTypeForEntity.values.firstWhere(
(type) => type.name == model.dataType.name,
orElse: () => MyDataTypeForEntity.none,
);
return MyEntity(name, type);
}
ㅤ
요렇게 MyDataTypeForEntity의 값들 중에서 model이 가지고 있는 dataType의 name과 동일한 name을 가진 타입으로 반환하는 놀라운 방법을 사용해주고 있었다. 더더욱 놀라운 것은 MyDataTypeForEntity 이랑 MyDataTypeForModel 에서 열거 값을 하나씩 확장해서 E 가 추가된다고 하더라도 변환 코드 상에서는 수정이 필요없다. 😮😮 더더더더욱 놀라운 점은 두 enum 중에서 한쪽에만 값이 추가되더라도 알아서 orElse 쪽에서 default 처럼 작동해서 none 같은 값으로 보내버릴 수 있다는 점이다. 😮😮😮😮
ㅤ
만약에 의존성 분리 등의 이슈로 두 쌍둥이 Enum이 있고 열거 값이 거의 동일하면서, 서로 간에 형변환이 필요한 시점이라면 firstWhere를 통한 열거 값 기반의 타입 캐스팅 방식을 적용해볼 수 있을 것 같다!
ㅤ
샤라웃
회사코드
'Develop > Flutter 개발' 카테고리의 다른 글
[Flutter] 3.24 버전부터 Swift Package Manager를 지원! (3) | 2024.09.28 |
---|---|
[Flutter] Dart의 void 타입은 null이 아니다 / this function has a return type of void and cannot be used (0) | 2024.09.20 |
[Flutter] 플러터의 화면 렌더링 과정 (2) | 2024.07.24 |
[Flutter] Dart는 Native Machine Code로 컴파일 되지만, Dart VM은 여전히 사용된다? (0) | 2024.07.12 |
[Flutter] 플러터 코드로만 Sign in with Apple 유저의 회원탈퇴 (Revoke) 기능 구현하기 (3) | 2024.06.26 |