Dart 3.3부터 도입된 Extension Types(확장 타입)은 기존 타입에 새로운 타입 레이어를 씌워, 더 안전하고 명확하게 코드를 작성할 수 있게 해주는 기능이다. 이번 포스팅에서는 Dart Extension Types의 개념, 장점, 사용법, 그리고 실전 예시를 정리해보도록 한다.

1. Extension Types란?
- 정의: Extension Type은 기존 타입(int, String, List 등)에 컴파일 타임에서만 존재하는 새로운 타입을 덧씌우는 기능이다.
- 특징: 런타임에는 실제로 래핑(wrapping)된 타입(Representation Type)으로 동작하며, 별도의 메모리 비용 없이 타입 안정성과 코드 가독성을 높여준다.
- 비교: 기존의 Wrapper Class(예: class MyId { final int id; ... })는 객체를 생성하고 메모리를 차지하지만, Extension Type은 이런 오버헤드가 없다.
<공식 홈페이지 매뉴얼>
2. Extension Types의 장점
- 성능 최적화: 런타임 오버헤드가 없어 대량의 데이터나 빈번한 객체 생성 상황에서 유리하다.
- 타입 안전성: 기존 타입과 확장 타입을 명확히 구분해, 잘못된 타입 사용을 컴파일 타임에 잡아낼 수 있다.
- 코드 가독성: 의미 있는 이름을 부여해 코드의 목적과 데이터를 더 명확하게 표현할 수 있다.
- 플랫폼/언어 간 연동: JS, C++ 등 네이티브 코드와의 상호 운용성(interop)이 좋아진다.
3. 기본 사용 방법
1) 선언과 생성
extension type MyId(int id) {}
void main() {
final id = MyId(1);
print(id); // 1
print(id.runtimeType); // int
}
MyId는 int를 감싸는 확장 타입이며, 런타임에는 int로 동작한다.
2) 타입 변환
MyId myId = MyId(10);
int number = myId; // ❌ 컴파일 에러
int number2 = myId as int; // ✅
myId = number2 as MyId; // ✅
확장 타입과 원본 타입은 직접 대입 불가. as를 통해 변환해야 한다.
3) 연산자 및 메서드 추가
extension type MyId(int id) {
bool isBiggerThan(MyId other) => id > other.id;
}
void main() {
MyId a = MyId(100);
MyId b = MyId(200);
print(a.isBiggerThan(b)); // false
}
기존 int의 연산자(+, -, > 등)는 사용할 수 없고, 직접 정의해야 한다.
4. 확장 타입의 제약과 활용
1) 타입 제한
- 확장 타입과 원본 타입은 별개로 취급되어, 실수로 타입이 섞이는 것을 방지한다.
- 예를 들어, 사용자 ID, 주문 번호 등 의미가 다른 int 값을 명확히 구분할 수 있다.
2) 제네릭 사용
extension type MyList<T>(List<T> elements) {
void add(T value) => elements.add(value);
}
void main() {
MyList<int> list = MyList([1, 2]);
list.add(3);
print(list); // [1, 2, 3]
}
3) 생성자 다양화
extension type Password._(String value) {
Password(this.value) {
if (value.length < 8) throw Exception('비밀번호는 8자 이상이어야 합니다.');
}
Password.random() : value = _generateRandomPassword();
static String _generateRandomPassword() => '랜덤비밀번호';
bool get isValid => value.length >= 8;
}
기본 생성자 외에, 네임드 생성자, private 생성자 등도 정의할 수 있다.
5. implements를 활용한 안전한 별칭(Safe Aliases)
확장 타입에 implements를 사용하면 원본 타입의 모든 기능을 사용할 수 있다.
extension type Height(double _) implements double {}
extension type Weight(double _) implements double {}
double calculateBmi(Height height, Weight weight) => weight / (height * height);
void main() {
var height = Height(1.75);
var weight = Weight(65);
print(calculateBmi(height, weight)); // 21.22...
}
Height, Weight 모두 double을 구현하지만, 서로 다른 타입이므로 잘못된 인자 전달을 컴파일 타임에 막을 수 있다.
6. 활용 예시
1) 네이티브/JS 연동
- JS, C++ 등 외부 라이브러리와 연동할 때, 별도의 래퍼 클래스를 만들지 않고도 안전하게 타입을 감쌀 수 있다.
2) JSON 데이터 구조화
typedef UserInfo = ({String email, String password});
extension type User(UserInfo info) {
void printInfo() => print("Email: ${info.email}, Password: ${info.password}");
}
void main() {
final user = User((email: 'test@gmail.com', password: '1234'));
user.printInfo();
}
3) 테스트용 Mock 클래스
abstract final class Repository {
String getToken();
}
final class MyRepository implements Repository {
@override String getToken() => 'token';
}
extension type MockRepository(Repository repository) implements Repository {
String getToken() => 'Testing';
}
7. 앞선 포스팅에서 작성했던 Extension Method와의 차이점
| 구분 | Extension Method | Extension Type |
| 목적 | 기존 타입에 메서드 추가 | 기존 타입에 새로운 타입 레이어 부여 |
| 런타임 영향 | 없음 | 없음(컴파일 타임에만 존재) |
| 타입 안정성 | 기존 타입 그대로 사용 | 타입 구분 및 안전성 강화 |
| 사용 예시 | String 확장 메서드 | 의미 있는 타입 분리(예: UserId, OrderId 등) |
8. 주의사항 및 한계
- 확장 타입은 컴파일 타임에만 존재하며, 런타임에는 원본 타입으로 동작한다.
- 기존 타입의 모든 기능을 사용하려면 implements를 사용해야 한다.
- 기존 타입과 확장 타입을 직접 대입할 수 없고, as를 통해 변환해야 한다.
- Extension Type은 복잡한 타입 구조를 안전하게 관리하고, 네이티브 연동, 대규모 데이터 처리 등에서 성능과 유지보수성을 크게 향상시킬 수 있다.
9. 정리
- Extension Type은 기존 타입에 의미 있는 이름과 타입 안전성을 더하는 Dart 3.3의 새로운 기능이다.
- Wrapper Class의 런타임 오버헤드 없이, 타입 구분과 코드 가독성을 높일 수 있다.
- 네이티브 연동, 대규모 데이터 처리, 의미 있는 타입 분리 등 다양한 상황에서 활용할 수 있다.
- 실제 프로젝트에서 UserId, ProductId, Money 등 의미가 분명한 값에 Extension Type을 활용하면, 실수로 잘못된 값을 사용하는 버그를 컴파일 타임에 미리 막을 수 있다.
아래 아티클을 읽고 그대로 번역한 것이 아닌 새롭게 정리한 내용입니다.
https://medium.com/flutter-community/what-can-i-do-with-extension-types-in-dart-5dfa73e4b009
'Personal Posting > Flutter' 카테고리의 다른 글
| Extension Method in Dart (0) | 2025.05.22 |
|---|---|
| Flutter에서의 Permission Handler 사용 (1) | 2025.05.21 |
| Flutter Data ENCRYPT & DECRYPT (플러터 데이터 암호화/복호화) (0) | 2025.05.21 |
| Dart의 Event Loop 정리 (0) | 2025.04.03 |
| Flutter TextFormFields 사용 시 체크사항 (0) | 2025.04.03 |