Isar 데이터베이스는 Flutter/Dart 애플리케이션에서 강력하면서도 사용하기 쉬운 NoSQL 데이터베이스입니다. 이 문서에서는 Isar를 사용하여 데이터를 생성, 읽기, 수정 및 삭제하는 방법을 초급 수준의 Dart 사용자도 이해할 수 있도록 자세히 설명합니다.
Isar를 사용하기 전에 데이터베이스를 열어야 합니다. 이 작업은 데이터베이스를 읽기 및 쓰기 작업에 사용할 준비를 합니다. 데이터베이스는 영구 디스크 저장소에 저장되며, 경로를 지정할 수도 있습니다.
// Isar 인스턴스를 열기 위한 코드 예시
final isar = await Isar.open(
schemas: [MySchema], // 여기서 `MySchema`는 데이터베이스에 저장할 데이터 구조를 나타냅니다. 이 구조는 Dart 코드에서 정의됩니다. 예를 들어, 사용자 데이터를 저장하려면 User 클래스와 같은 스키마를 만들어야 합니다. // 스키마는 데이터베이스에 저장할 데이터 구조를 정의합니다.
directory: "/data", // 여기에서 `/data`는 데이터베이스 파일을 저장할 디렉토리를 지정합니다. 그러나 모든 앱에서 동작하지 않을 수 있으니, 앱의 파일 저장 경로가 올바른지 확인하는 것이 중요합니다. 예를 들어, Flutter에서는 `path_provider` 패키지를 사용해 권장 경로를 설정할 수 있습니다.
);
// 예를 들어, 아래와 같은 스키마를 정의할 수 있습니다:
import 'package:isar/isar.dart';
()
class User {
// 자동 증가 ID 필드
Id id = Isar.autoIncrement;
// 사용자의 이름 (필수 필드)
late String name;
// 사용자의 나이 (필수 필드)
late int age;
// 선택적 이메일 필드 (null 허용)
String? email;
}
// 위 코드에서:
// - `@Collection()` 어노테이션은 Isar에서 이 클래스가 데이터베이스 테이블과 같음을 의미합니다.
// - `Id` 필드는 객체를 고유하게 식별하며 자동으로 증가합니다.
// - `late` 키워드는 필수 입력을 의미합니다.
// - `String?` 타입은 null 값을 허용하는 선택 필드를 나타냅니다.
| 설정 | 설명 |
|---|---|
schemas | 데이터베이스에서 사용할 스키마 목록을 정의합니다. |
directory | 데이터 파일을 저장할 디렉토리를 지정합니다. (기본값: 앱 디렉토리) |
inspector | true로 설정하면 Isar Inspector를 활성화할 수 있습니다. |
schemas에 사용할 스키마 이름 찾기데이터 구조를 나타내는 클래스를 이미 작성한 상태라면, Isar가 자동으로 생성한 스키마 파일에서 MySchema에 해당하는 이름을 찾을 수 있습니다. 이를 찾는 방법은 다음과 같습니다:
Isar Code Generator 사용: Isar는 build_runner를 사용하여 .g.dart 파일에 스키마 정보를 생성합니다.
빌드 실행: 프로젝트 루트에서 아래 명령어를 실행하세요.
flutter pub run build_runner build
생성된 파일 확인: 작성한 데이터 구조 클래스(예: User)와 관련된 .g.dart 파일이 생성됩니다. 이 파일은 Dart 파일과 같은 경로에 생성됩니다.
스키마 이름 찾기: 생성된 .g.dart 파일을 열어보면 다음과 같은 내용이 포함되어 있습니다:
const UserSchema = CollectionSchema(
name: 'User',
id: 1234567890, // 스키마 고유 ID
properties: {...},
...
);
스키마 이름 자동 추천: IDE에서 schemas:에 대괄호를 열고 자동 완성 기능(예: IntelliJ나 VSCode)을 사용하면 UserSchema 같은 스키마 이름이 추천됩니다.
참고 사항:
build_runner는 데이터를 정의할 때마다 실행해야 합니다.Schema를 붙인 형태로 자동 생성됩니다.데이터베이스 파일 경로로 단순히 "/data"를 사용하는 것은 모든 환경에서 동작하지 않을 수 있습니다. Flutter 앱에서는 path_provider 패키지를 사용해 안전한 경로를 지정하는 것이 좋습니다. 아래는 안전한 경로를 설정하는 예시입니다:
import 'package:path_provider/path_provider.dart';
// 안전한 디렉토리 경로 가져오기
final directory = (await getApplicationDocumentsDirectory()).path;
// Isar 데이터베이스 열기
final isar = await Isar.open(
schemas: [UserSchema],
directory: directory, // 안전한 경로를 지정
);
이 방법은 운영 체제에 맞는 적절한 경로를 반환하며, 저장소 관련 문제를 방지할 수 있습니다.
getApplicationDocumentsDirectory()는 Flutter의 path_provider 패키지를 통해 앱에서 데이터를 저장할 수 있는 안전한 디렉토리 경로를 제공합니다. 이 디렉토리는 아래와 같은 특징과 역할을 합니다:
플랫폼 의존적 경로:
/data/data/<앱 패키지 이름>/filesDocuments 디렉토리안전한 데이터 저장소:
이를 통해 운영체제와 환경에 맞는 적합한 경로를 자동으로 제공받아, 앱의 안정성과 데이터 관리가 크게 향상됩니다.
Isar는 데이터를 읽기 위한 다양한 메서드를 제공합니다. 다음은 주요 사용 방법입니다.
컬렉션은 데이터베이스 내의 데이터 집합을 나타냅니다.
// 컬렉션 가져오기
final userCollection = isar.users; // 컬렉션 이름(users)을 사용
객체를 ID를 기준으로 검색하려면 get() 메서드를 사용합니다.
// ID로 객체를 가져오는 예시
final user = await isar.users.get(123); // ID가 123인 객체 가져오기
if (user != null) {
print(user.name); // 사용자 이름 출력
}
특정 조건에 맞는 데이터를 가져오려면 쿼리를 사용할 수 있습니다.
// 조건에 맞는 데이터를 쿼리하는 예시
final users = await isar.users.filter()
.ageGreaterThan(18) // 나이가 18세 이상인 사용자 필터링
.findAll();
for (final user in users) {
print(user.name); // 각 사용자의 이름 출력
}
데이터베이스의 데이터를 수정하려면 put() 메서드를 사용합니다.
// 객체 수정 예시
final user = await isar.users.get(123);
if (user != null) {
user.name = "새 이름"; // 객체의 이름 수정
await isar.writeTxn(() async {
await isar.users.put(user); // 수정된 객체 저장
});
}
모든 쓰기 작업은 writeTxn() 내부에서 이루어져야 합니다.
새 데이터를 추가하려면 put() 메서드를 사용합니다.
// 새 객체 추가 예시
final newUser = User()
..id = 124
..name = "홍길동"
..age = 30;
await isar.writeTxn(() async {
await isar.users.put(newUser); // 새 객체 저장
});
데이터를 삭제하려면 delete() 메서드를 사용합니다.
// ID로 객체 삭제 예시
await isar.writeTxn(() async {
final success = await isar.users.delete(123); // ID가 123인 객체 삭제
if (success) {
print("삭제 성공!");
}
});
// 조건에 맞는 여러 객체 삭제 예시
await isar.writeTxn(() async {
final count = await isar.users.filter()
.ageLessThan(18) // 나이가 18세 미만인 사용자 필터링
.deleteAll();
print("$count개의 객체 삭제 완료");
});
이제 Isar 데이터베이스의 CRUD 작업을 쉽게 수행할 수 있습니다. 이를 바탕으로 더 복잡한 애플리케이션을 개발할 수 있습니다!
import 'package:isar/isar.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
//dart:io가 path_provider를 통해 얻어진 경로와 함께
//데이터베이스 파일을 안전한 디렉토리에 저장하는 데 도움을 줍니다.
//추가적으로 File, Directory, Process와 같은 클래스도 사용할 수 있습니다.
()
class User {
Id id = Isar.autoIncrement; // 자동 증가 ID
late String name; // 사용자의 이름
late int age; // 사용자의 나이
String? email; // 선택적 이메일
}
Future<void> main() async {
// 1. 안전한 디렉토리 경로 설정
final directory = (await getApplicationDocumentsDirectory()).path;
// 2. Isar 데이터베이스 열기
final isar = await Isar.open(
schemas: [UserSchema], // User 클래스의 스키마
directory: directory, // 안전한 경로
);
// 3. 새 데이터 삽입 (Create)
final newUser = User()
..name = "홍길동"
..age = 25
..email = "hong@example.com";
await isar.writeTxn(() async {
await isar.users.put(newUser); // 새 사용자 데이터 저장
});
print("새로운 사용자 추가 완료!");
// 4. ID로 데이터 가져오기 (Read)
final userById = await isar.users.get(newUser.id); // ID로 데이터 검색
if (userById != null) {
print("ID로 가져온 사용자: ${userById.name}, 나이: ${userById.age}");
}
// 5. 조건 쿼리로 데이터 가져오기 (Read)
final usersOver18 = await isar.users.filter()
.ageGreaterThan(18) // 나이가 18세 이상인 사용자
.findAll();
print("18세 이상 사용자 목록:");
for (final user in usersOver18) {
print("사용자 이름: ${user.name}, 나이: ${user.age}");
}
// 6. 데이터 수정 (Update)
if (userById != null) {
userById.name = "홍길동 수정";
await isar.writeTxn(() async {
await isar.users.put(userById); // 수정된 데이터 저장
});
print("사용자 이름 수정 완료!");
}
// 7. 데이터 삭제 (Delete)
if (userById != null) {
await isar.writeTxn(() async {
final success = await isar.users.delete(userById.id);
if (success) {
print("사용자 ID ${userById.id} 삭제 성공!");
}
});
}
// 조건에 맞는 여러 데이터 삭제
await isar.writeTxn(() async {
final deletedCount = await isar.users.filter()
.ageLessThan(18) // 나이가 18세 미만인 사용자 삭제
.deleteAll();
print("$deletedCount명의 사용자 삭제 완료!");
});
}