Flutter 개발을 하다 보면 불변 객체와 다양한 유틸리티를 제공하는 모델을 쉽게 생성하고 싶을 때가 많습니다. 이때 유용하게 사용할 수 있는 것이 바로 Freezed 패키지입니다. 이 포스트에서는 freezed
패키지의 주요 기능과 사용 방법, 장점과 단점에 대해 알아보겠습니다.
Freezed란 무엇인가?
freezed
는 Flutter에서 불변 객체를 생성하는 데 도움을 주는 패키지입니다. 특히, 데이터 클래스를 작성할 때 반복적으로 작성해야 하는 코드를 간편하게 줄여주고, 타입 안전성, JSON 직렬화, 복사 및 변경 메서드 등을 자동으로 생성해 줍니다.
주요 기능
- 불변 객체 생성: 객체의 상태를 변경할 수 없도록 만들어 안전한 데이터 구조를 보장합니다.
- copyWith 메서드: 객체의 특정 필드를 변경하여 새로운 인스턴스를 쉽게 만들 수 있습니다.
- JSON 직렬화:
json_serializable
과 함께 사용하여 JSON 데이터를 쉽게 변환할 수 있습니다. - Union 타입 지원: 여러 상태를 가지는 클래스, 예를 들어 다양한 상태를 표현하는 sealed class를 작성할 때 유용합니다.
설치하기
freezed
패키지를 사용하기 위해서는 freezed
와 build_runner
패키지를 의존성에 추가해야 합니다.
dependencies:
freezed_annotation: ^2.0.0
json_annotation: ^4.4.0
dev_dependencies:
build_runner: ^2.0.0
freezed: ^2.0.0
json_serializable: ^6.0.0
설치 후, pub get
을 실행하여 패키지를 다운로드합니다.
기본 사용법
freezed
패키지를 사용하여 간단한 모델 클래스를 만들어 보겠습니다. 예를 들어, 사용자 정보를 담고 있는 User
클래스를 작성해 봅니다.
1. 클래스 정의하기
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
const factory User({
required String name,
required int age,
String? email,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
위 코드에서 @freezed
어노테이션을 사용하면 freezed
가 자동으로 필요한 메서드와 불변 객체 클래스를 생성해 줍니다. User
클래스에 copyWith
메서드와 toString
, ==
, hashCode
등의 메서드가 추가됩니다.
2. 코드 생성하기
모델 파일을 정의한 후, build_runner
를 사용하여 코드를 생성합니다.
flutter pub run build_runner build
이 명령어를 실행하면 user.freezed.dart
파일과 user.g.dart
파일이 생성되며, 여기에 freezed
와 JSON 직렬화에 필요한 코드가 포함됩니다.
Freezed의 기능 알아보기
1. copyWith 메서드
copyWith
메서드를 사용하면 불변 객체의 특정 필드를 변경하여 새로운 인스턴스를 만들 수 있습니다.
void main() {
final user = User(name: 'Alice', age: 25);
final updatedUser = user.copyWith(age: 26);
print(user); // User(name: Alice, age: 25)
print(updatedUser); // User(name: Alice, age: 26)
}
2. JSON 직렬화
fromJson
및 toJson
메서드를 사용하여 JSON 데이터를 쉽게 변환할 수 있습니다.
void main() {
final json = {'name': 'Alice', 'age': 25};
final user = User.fromJson(json);
print(user); // User(name: Alice, age: 25)
print(user.toJson()); // {'name': 'Alice', 'age': 25}
}
3. Union 타입 (Sealed Class)
freezed
는 Union 타입을 지원하므로, 상태를 구분하는 데 유용합니다. 예를 들어, 네트워크 요청의 결과 상태를 표현할 수 있습니다.
@freezed
class NetworkResult<T> with _$NetworkResult<T> {
const factory NetworkResult.success(T data) = Success<T>;
const factory NetworkResult.error(String message) = Error<T>;
}
void main() {
final successResult = NetworkResult.success('Data loaded');
final errorResult = NetworkResult.error('Failed to load data');
print(successResult); // Success(data: Data loaded)
print(errorResult); // Error(message: Failed to load data)
}
장점
- 간결한 코드: boilerplate 코드를 줄여주어 가독성과 유지보수성을 높여줍니다.
- 강력한 타입 안전성: 불변 객체를 통해 데이터의 안정성과 신뢰성을 보장합니다.
- 자동화된 JSON 직렬화:
json_serializable
과 함께 JSON 직렬화/역직렬화를 간편하게 처리할 수 있습니다.
단점
- 빌드 시간 증가:
build_runner
를 통해 코드를 생성하므로, 큰 프로젝트에서 빌드 시간이 다소 길어질 수 있습니다. - 러닝 커브: Union 타입과 같은 고급 기능을 사용할 때, 초기 학습이 필요할 수 있습니다.
- 제네릭 타입 제한: 복잡한 제네릭 타입 사용 시 일부 기능이 제한적일 수 있습니다.
마치며
freezed
패키지는 불변 객체를 손쉽게 관리할 수 있도록 도와주는 강력한 도구입니다. copyWith
와 JSON 직렬화, Union 타입을 활용하여 데이터 모델을 보다 간결하고 안정적으로 관리할 수 있습니다. 더 많은 기능과 예제는 freezed 공식 문서를 참고하세요.
freezed
패키지를 활용해 더욱 안전하고 강력한 Flutter 코드를 작성해 보세요!