Article
Freezed: Flutter 불변 모델의 보일러플레이트 제거
Freezed: 모델 클래스 작성의 혁명

Flutter/Dart 개발을 하다 보면 가장 지루한 일은 무엇일까요? 바로 모델 클래스 작성입니다.
API 응답을 받을 때마다:
class User {
final String name;
final int age;
final String email;
User({
required this.name,
required this.age,
required this.email,
});
bool operator ==(Object other) => /* 장황한 비교 로직 */;
int get hashCode => /* 더 장황한 해시 로직 */;
User copyWith({
String? name,
int? age,
String? email,
}) => User(
name: name ?? this.name,
age: age ?? this.age,
email: email ?? this.email,
);
String toString() => /* toString 구현 */;
factory User.fromJson(Map<String, dynamic> json) => /* fromJson */;
Map<String, dynamic> toJson() => /* toJson */;
}
이렇게 200줄을 작성합니다. Freezed는 이를 10줄로 줄입니다.
설치: 한 줄로 끝내기
# 기본 설치
flutter pub add freezed_annotation
flutter pub add --dev build_runner freezed
# API 데이터 모델링을 하려면 추가
flutter pub add json_annotation
flutter pub add --dev json_serializable
Freezed의 간단한 사용법
예제 1: 기본 모델 - User
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
class User with _$User {
factory User({
required String name,
required int age,
required String email,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) =>
_$UserFromJson(json);
}
끝입니다. 이 10줄의 코드로 다음이 자동으로 생성됩니다:
==연산자 (동등성 비교)hashCode(Set, Map에서 사용 가능)toString()(디버깅 출력)copyWith()(불변 수정)fromJson()/toJson()(API 직렬화)
예제 2: 선택적 필드 - Post
enum PostStatus { draft, published, archived }
class Post with _$Post {
factory Post({
required String title,
required String content,
String? author,
required PostStatus status,
(0) int likes,
([]) List<String> tags,
}) = _Post;
factory Post.fromJson(Map<String, dynamic> json) =>
_$PostFromJson(json);
}
주목할 점:
String?: nullable 필드@Default(0): 기본값 설정- Enum 타입 자동 지원
코드 생성 명령
# 일회성 빌드
flutter pub run build_runner build
# 파일 변경 시마다 자동 생성
flutter pub run build_runner watch
Freezed로 얻는 것들
| 기능 | 수작업 | Freezed | 절약 시간 |
|---|---|---|---|
| equals/hashCode | 20줄 | 자동 | 5분 |
| copyWith | 15줄 | 자동 | 3분 |
| fromJson/toJson | 10줄 | 자동 | 2분 |
| toString | 5줄 | 자동 | 1분 |
| 모델 클래스 1개 | 200줄 | 10줄 | 15분 |
프로젝트에 모델 클래스가 30개 있다면? 450분 절약입니다.
실전 팁
1. 패턴 매칭과 함께 사용
// Freezed는 union type을 지원합니다
class ApiResponse<T> with _$ApiResponse<T> {
const factory ApiResponse.loading() = _Loading<T>;
const factory ApiResponse.data(T data) = _Data<T>;
const factory ApiResponse.error(String message) = _Error<T>;
}
// 사용할 때
response.when(
loading: () => CircularProgressIndicator(),
data: (data) => DataWidget(data),
error: (message) => ErrorWidget(message),
);
2. 기본값 설정
class Settings with _$Settings {
const factory Settings({
(true) bool darkMode,
('en') String language,
([]) List<String> favorites,
}) = _Settings;
}
3. JSON 변환 커스터마이징
()
class ComplexModel with _$ComplexModel {
factory ComplexModel({
(name: 'user_id') required int userId,
(fromJson: dateTimeFromJson) DateTime? createdAt,
}) = _ComplexModel;
}
마치며
Freezed는 단순한 코드 생성 도구가 아닙니다. Flutter 개발에서 모델 계층을 완전히 변화시키는 도구입니다.
- 보일러플레이트 제거로 집중력 향상
- 자동 생성으로 버그 감소
- 필드 변경 시 컴파일 에러로 감지 (런타임 버그 방지)
- Union type 지원으로 타입 안전성 극대화
API 기반 앱을 개발한다면, Freezed는 선택이 아닌 필수입니다.
댓글