Article

Freezed: Flutter 불변 모델의 보일러플레이트 제거

Freezed: 모델 클래스 작성의 혁명

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/hashCode20줄자동5분
copyWith15줄자동3분
fromJson/toJson10줄자동2분
toString5줄자동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는 선택이 아닌 필수입니다.

댓글