Flutter Isar

Posted on Feb 5, 2024
tl;dr: Isar는 유닛 테스트를 하기 어렵다.

Isar?

Isar: SQLite를 백엔드로 쓰는 로컬 DB. 클래스를 저장가능한 형태로 자동변환해줘서 편리함.

Isar Quickstart

  1. Add dependencies
(인터페이스를 위한 패키지)
flutter pub add isar isar_flutter_libs path_provider

(코드를 자동생성하는 패키지)
flutter pub add -d isar_generator build_runner

isar_generator, build_runner는 그냥 코드 생성기이기 때문에 dev dependency라는 점. 만약 모델을 별도 패키지에서 관리한다면 그 패키지에서만 이 두 패키지를 추가해서 사용하면 됨.

  1. Annotate classes
import 'package:isar/isar.dart';

part 'user.g.dart'; // *

@collection // *
class User {
  Id id = Isar.autoIncrement; // *; you can also use id = null to auto increment

  String? name;

  int? age;
}

* 표시한 줄은 반드시 필요함.

import 'package:equatable/equatable.dart';
import 'package:isar/isar.dart';

part 'user.g.dart';

@Collection(inheritance: false) // `equatable` 패키지를 쓰고싶으면 상속을 무시하는 annotation을 써야한다.
class User extends Equatable {
  const User({
    required this.id,
    this.isarId = Isar.autoIncrement,
    this.email,
    this.name,
    this.photo,
  });

  final Id isarId; // Isar는 필드 이름에 상관없이 `Id` 타입만 본다.
  final String id;
  final String? name;
  final int? age;

  @ignore // 저장하지 않는 필드는 @ignore를 쓴다.
  static const empty = User(id: '');

  @ignore
  bool get isEmpty => this == User.empty;

  @ignore
  bool get isNotEmpty => this != User.empty;

  @override
  @ignore
  List<Object?> get props => [email, id, name, photo];
}

equatable도 함께 쓸 수 있다.

  1. Run code generator
$ dart run build_runner build

user.g.dart 파일이 만들어진다.

  1. Open Isar instance
final dir = await getApplicationDocumentsDirectory(); // path_provider 패키지 함수
final isar = await Isar.open(
  [UserSchema],
  directory: dir.path,
);

user.g.dart에 정의된 UserSchema를 전달한다.

  1. Write and read
final newUser = User()..name = 'Jane Doe'..age = 36;

await isar.writeTxn(() async {
  await isar.users.put(newUser); // insert & update
});

final existingUser = await isar.users.get(newUser.id); // get

await isar.writeTxn(() async {
  await isar.users.delete(existingUser.id!); // delete
});

그러나…

나는 Business Logic이나 API를 별도 패키지에서 관리하고싶었는데, 여기서 반드시 Isar에 의존해야했다. 그러나 Isar는 unit test가 안된다는 단점이 있었다. 그래서 포기했다. 구글에 검색하니 이곳에서 방법을 찾을 수 있었는데 간단한 것 같지 않았다.

SQFlite를 쓰자니 이건 웹에서 지원이 안된다.