[Flutter]직렬화와 불변객체 + Freezed 도입

임효진·2024년 7월 10일
0

Flutter

목록 보기
21/22

Freezed 도입 이전에 직렬화와 불변 객체 생성에 대한 이해 개념이 필요하다.
본 글은 코딩 공부를 시작하는 조카를 위해 최대한 쉽게 설명해보겠다.

불변 객체란 무엇일까?

불변 객체는 한 번 만들어지면 그 값을 바꿀 수 없는 객체다.
예를 들어, 생성한 게임 캐릭터가 있다고 생각해보면 이 캐릭터의 이름이나 능력치를 한 번 정하면 바꿀 수 없는 것과 같다.

왜 필요할까?

안정성: 불변 객체는 값을 바꿀 수 없어서 실수로 값을 바꾸는 일이 없다.
게임 중에 갑자기 캐릭터의 능력치가 바뀌면 곤란하기 때문이다.
예측 가능성: 언제나 같은 값을 유지하니까 코드가 어떻게 동작할지 예측하기 쉽다.
안전한 공유: 여러 사람이 동시에 객체를 사용할 때도 안전하다.
예를 들어, 친구와 함께 게임을 하는데 친구가 캐릭터의 능력치를 바꾸면 혼란스러울 것이다.
불변 객체는 이런 일을 방지해준다.
간단한 디버깅: 값이 변하지 않아서 디버깅(오류를 찾는 작업)이 더 쉬워진다.

직렬화(serialization)란 무엇일까?

의미:

직렬화는 객체를 JSON 같은 형식으로 바꾸는 작업이다.
이렇게 하면 데이터를 네트워크로 주고받거나 파일에 저장할 수 있다.

왜 필요할까?

데이터 전송: 서버와 통신할 때 데이터를 JSON 형식으로 주고 받는다.
예를 들어, 게임 캐릭터 정보를 서버에 보내려면 JSON 형식으로 바꿔서 보내야 한다.
영구 저장: 데이터를 파일에 저장할 때도 JSON 형식으로 저장하면 나중에 쉽게 읽을 수 있다.
디버깅과 로깅: JSON 형식의 데이터를 쉽게 읽고 분석할 수 있어서 디버깅과 로깅에 유용하다.

freezed 라이브러리를 사용하는 이유

freezed는 불변 객체를 쉽게 만들고, JSON 직렬화도 간편하게 해주는 라이브러리다.
다음과 같은 장점이 있다:

자동으로 불변 객체 생성: freezed는 불변 객체를 자동으로 만들어줘서 쉽게 사용할 수 있다.
직렬화 및 역직렬화 자동화: JSON 형식으로 데이터를 쉽게 변환하고 다시 객체로 만들 수 있다.
보일러플레이트 코드 제거: 반복적인 코드를 자동으로 생성해줘서 코드가 간결해진다.

다른 라이브러리와 비교, 왜 freezed를 추천하는지?

1. freezed vs built_value

built_value는 Dart에서 불변 객체와 빌더 패턴을 제공하는 라이브러리다.
그러나 freezed와 비교했을 때 몇 가지 차이점이 있다.

주요 차이점:

코드 간결성:
freezed는 코드 제너레이션을 통해 더 간단한 문법을 제공한다.
built_value는 빌더 패턴을 사용하여 좀 더 복잡한 설정이 필요하다고 느꼈다.

// `freezed` 예제

class User with _$User {
  factory User({
    required String name,
    required int age,
  }) = _User;
}

// `built_value` 예제
abstract class User implements Built<User, UserBuilder> {
  String get name;
  int get age;

  User._();
  factory User([void Function(UserBuilder) updates]) = _$User;
}

패턴 매칭:
freezed는 패턴 매칭을 통해 다양한 상태를 쉽게 처리할 수 있다.
built_value는 패턴 매칭을 제공하지 않는다.

// `freezed` 패턴 매칭 예제

class Result with _$Result {
  const factory Result.success(String data) = Success;
  const factory Result.error(String message) = Error;
}

void main() {
  final result = Result.success('Data loaded');

  result.when(
    success: (data) => print('Success: $data'),
    error: (message) => print('Error: $message'),
  );
}

2. freezed vs json_serializable

json_serializable은 JSON 직렬화 및 역직렬화에 특화된 라이브러리다.
freezed와 함께 사용될 수 있지만, freezed만으로도 JSON 관련 기능을 처리할 수 있디.

주요 차이점:

기능의 포괄성:
freezed는 JSON 직렬화 외에도 불변 객체, 패턴 매칭 등 다양한 기능을 제공한다.
json_serializable은 JSON 직렬화에 특화되어 있으며, 데이터 클래스를 직접 생성하지는 않는다.

// `freezed` 예제

class User with _$User {
  factory User({
    required String name,
    required int age,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

3. freezed vs equatable

equatable은 객체의 동등성 비교를 쉽게 할 수 있도록 도와주는 라이브러리다.
freezed는 이를 내장하고 있어 별도로 사용하지 않아도 된다.

주요 차이점:

동등성 비교:
freezed는 equatable을 내장하여 객체의 동등성 비교를 자동으로 처리한다.
equatable은 동등성 비교만을 위한 라이브러리로, 다른 기능은 제공하지 않는다.

// `freezed` 예제

class User with _$User {
  factory User({
    required String name,
    required int age,
  }) = _User;
}

// `equatable` 예제
class User extends Equatable {
  final String name;
  final int age;

  User({required this.name, required this.age});

  
  List<Object> get props => [name, age];
}

결론

freezed는 다양한 기능을 하나의 라이브러리로 제공하여, 별도의 라이브러리를 사용하지 않고도 불변 객체 생성, JSON 직렬화, 패턴 매칭, 동등성 비교 등을 쉽게 할 수 있게 해준다.
built_value, json_serializable, equatable 등 다른 라이브러리와 비교했을 때, 더 많은 기능을 제공하며 코드의 간결성과
생산성을 높여준다.

Freezed 설치 방법과 사용 예제

1. 설치 방법

Step 1: pubspec.yaml 파일에 의존성 추가

dependencies:
  flutter:
    sdk: flutter
  freezed_annotation: ^2.0.0

dev_dependencies:
  build_runner: ^2.0.0
  freezed: ^2.0.0
  json_serializable: ^6.0.0 # JSON serialization을 사용하는 경우

Step 2: 의존성 설치

flutter pub get

2. 사용 예제

freezed를 사용하여 간단한 예제를 만들어 보겠다.
예제에서는 사용자(User) 모델을 생성하고, 이를 JSON으로 직렬화하는 방법을 포함한다.

Step 1: 모델 클래스 생성

user.dart 파일을 생성한다.
필요한 패키지를 임포트한다.

import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';


class User with _$User {
  const factory User({
    required String name,
    required int age,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

Step 2: 코드 생성

flutter pub run build_runner build

이 명령어는 user.freezed.dart와 user.g.dart 파일을 생성한다.
이 파일들은 freezed가 필요한 모든 boilerplate 코드를 생성한다.

Step 3: 사용 예제

void main() {
  // User 인스턴스 생성
  final user = User(name: 'John Doe', age: 30);

  // User 인스턴스를 JSON으로 변환
  final userJson = user.toJson();
  print(userJson); // { "name": "John Doe", "age": 30 }

  // JSON을 User 인스턴스로 변환
  final newUser = User.fromJson(userJson);
  print(newUser); // User(name: John Doe, age: 30)
}
profile
핫바리임

0개의 댓글