Flutter 로컬 데이터베이스

SQLite, Drift, Hive로 데이터 관리

Flutter중급
6시간
2개 항목
학습 진행률0 / 2 (0%)

학습 항목

1. Flutter
Flutter|SQLite|데이터베이스|완벽|가이드
퀴즈튜토리얼
2. Flutter
Drift|Moor|로컬|데이터베이스|구축하기
퀴즈튜토리얼
1 / 2

이미지 로딩 중...

Flutter SQLite 데이터베이스 완벽 가이드 - 슬라이드 1/13

Flutter SQLite 데이터베이스 완벽 가이드

Flutter 앱에서 SQLite를 사용하여 로컬 데이터베이스를 구축하는 방법을 배웁니다. 기본적인 CRUD 작업부터 실무에서 바로 사용할 수 있는 패턴까지 단계별로 학습합니다.


카테고리:Flutter
언어:Dart
메인 태그:#Flutter
서브 태그:
#SQLite#sqflite#Database#LocalStorage

들어가며

이 글에서는 Flutter SQLite 데이터베이스 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. SQLite_패키지_설치
  2. 데이터베이스_헬퍼_클래스_생성
  3. 데이터베이스_초기화
  4. 테이블_생성_쿼리
  5. 모델_클래스_정의
  6. 데이터_삽입_CREATE
  7. 데이터_조회_READ
  8. 특정_데이터_조회
  9. 데이터_수정_UPDATE
  10. 데이터_삭제_DELETE
  11. 트랜잭션_사용하기
  12. 데이터베이스_닫기

1. SQLite_패키지_설치

개요

Flutter에서 SQLite를 사용하기 위해 sqflite와 path 패키지를 설치합니다. pubspec.yaml 파일에 의존성을 추가하는 것이 첫 단계입니다.

코드 예제

dependencies:
  flutter:
    sdk: flutter
  sqflite: ^2.3.0
  path: ^1.8.3

설명

sqflite는 Flutter용 SQLite 플러그인이며, path는 데이터베이스 파일 경로를 관리하는 데 사용됩니다. 패키지 추가 후 flutter pub get 명령어로 설치합니다.


2. 데이터베이스_헬퍼_클래스_생성

개요

데이터베이스 연결을 관리하는 싱글톤 패턴의 헬퍼 클래스를 만듭니다. 앱 전체에서 하나의 데이터베이스 인스턴스만 사용합니다.

코드 예제

class DatabaseHelper {
  static final DatabaseHelper instance = DatabaseHelper._init();
  static Database? _database;

  DatabaseHelper._init();

  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDB('notes.db');
    return _database!;
  }
}

설명

싱글톤 패턴으로 구현하여 메모리 효율을 높이고, getter를 통해 데이터베이스가 없으면 초기화하고 있으면 기존 인스턴스를 반환합니다.


3. 데이터베이스_초기화

개요

데이터베이스 파일을 생성하고 테이블을 정의합니다. getDatabasesPath()로 앱의 데이터베이스 디렉토리 경로를 가져옵니다.

코드 예제

Future<Database> _initDB(String filePath) async {
  final dbPath = await getDatabasesPath();
  final path = join(dbPath, filePath);

  return await openDatabase(
    path,
    version: 1,
    onCreate: _createDB,
  );
}

설명

openDatabase()는 데이터베이스를 열거나 생성하며, version을 통해 스키마 버전을 관리하고, onCreate 콜백으로 테이블을 생성합니다.


4. 테이블_생성_쿼리

개요

SQL CREATE TABLE 문으로 데이터를 저장할 테이블 구조를 정의합니다. 각 컬럼의 타입과 제약조건을 지정합니다.

코드 예제

Future _createDB(Database db, int version) async {
  await db.execute('''
    CREATE TABLE notes (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      title TEXT NOT NULL,
      content TEXT NOT NULL,
      createdAt TEXT NOT NULL
    )
  ''');
}

설명

id는 자동 증가하는 기본 키이며, NOT NULL 제약으로 필수 필드를 지정합니다. 날짜는 TEXT 타입으로 ISO 8601 형식의 문자열로 저장합니다.


5. 모델_클래스_정의

개요

데이터베이스 테이블과 매핑되는 Dart 클래스를 만듭니다. JSON 변환 메서드로 데이터를 쉽게 다룰 수 있습니다.

코드 예제

class Note {
  final int? id;
  final String title;
  final String content;
  final DateTime createdAt;

  Note({this.id, required this.title,
        required this.content, required this.createdAt});

  Map<String, dynamic> toMap() => {
    'id': id, 'title': title,
    'content': content, 'createdAt': createdAt.toIso8601String()
  };
}

설명

toMap() 메서드는 객체를 Map으로 변환하여 데이터베이스에 저장할 수 있게 하고, DateTime은 ISO 8601 문자열로 변환합니다.


6. 데이터_삽입_CREATE

개요

insert() 메서드로 새로운 데이터를 테이블에 추가합니다. conflictAlgorithm으로 중복 처리 방식을 지정할 수 있습니다.

코드 예제

Future<int> createNote(Note note) async {
  final db = await database;

  return await db.insert(
    'notes',
    note.toMap(),
    conflictAlgorithm: ConflictAlgorithm.replace,
  );
}

설명

insert()는 삽입된 행의 id를 반환합니다. ConflictAlgorithm.replace는 기본 키가 중복되면 기존 데이터를 덮어씁니다.


7. 데이터_조회_READ

개요

query() 메서드로 테이블의 데이터를 조회합니다. where 절로 조건을 지정하거나 전체 데이터를 가져올 수 있습니다.

코드 예제

Future<List<Note>> readAllNotes() async {
  final db = await database;
  final result = await db.query('notes',
                    orderBy: 'createdAt DESC');

  return result.map((json) => Note(
    id: json['id'] as int,
    title: json['title'] as String,
    content: json['content'] as String,
    createdAt: DateTime.parse(json['createdAt'] as String)
  )).toList();
}

설명

query()는 Map 리스트를 반환하며, orderBy로 정렬 순서를 지정합니다. map()으로 각 Map을 Note 객체로 변환합니다.


8. 특정_데이터_조회

개요

where와 whereArgs를 사용하여 조건에 맞는 특정 데이터만 조회합니다. SQL 인젝션 방지를 위해 ?를 사용합니다.

코드 예제

Future<Note?> readNote(int id) async {
  final db = await database;
  final maps = await db.query(
    'notes',
    where: 'id = ?',
    whereArgs: [id],
  );

  if (maps.isNotEmpty) {
    return Note(id: maps.first['id'] as int, ...);
  }
  return null;
}

설명

where 절의 ?는 플레이스홀더로, whereArgs의 값이 순서대로 대입됩니다. 이 방식으로 SQL 인젝션 공격을 방지합니다.


9. 데이터_수정_UPDATE

개요

update() 메서드로 기존 데이터를 수정합니다. where 조건으로 수정할 행을 지정하고, Map으로 새 값을 전달합니다.

코드 예제

Future<int> updateNote(Note note) async {
  final db = await database;

  return await db.update(
    'notes',
    note.toMap(),
    where: 'id = ?',
    whereArgs: [note.id],
  );
}

설명

update()는 수정된 행의 개수를 반환합니다. where 조건이 없으면 모든 행이 수정되므로 주의해야 합니다.


10. 데이터_삭제_DELETE

개요

delete() 메서드로 데이터를 삭제합니다. where 조건으로 삭제할 행을 지정하며, 조건 없이 호출하면 모든 데이터가 삭제됩니다.

코드 예제

Future<int> deleteNote(int id) async {
  final db = await database;

  return await db.delete(
    'notes',
    where: 'id = ?',
    whereArgs: [id],
  );
}

설명

delete()는 삭제된 행의 개수를 반환합니다. 여러 조건을 조합할 때는 where 절에 AND나 OR를 사용할 수 있습니다.


11. 트랜잭션_사용하기

개요

여러 데이터베이스 작업을 하나의 트랜잭션으로 묶어 원자성을 보장합니다. 하나라도 실패하면 모든 작업이 롤백됩니다.

코드 예제

Future<void> batchInsert(List<Note> notes) async {
  final db = await database;

  await db.transaction((txn) async {
    for (var note in notes) {
      await txn.insert('notes', note.toMap());
    }
  });
}

설명

transaction() 블록 내의 모든 작업은 하나의 단위로 처리되어, 중간에 에러가 발생하면 자동으로 롤백되어 데이터 무결성을 유지합니다.


12. 데이터베이스_닫기

개요

앱 종료 시 데이터베이스 연결을 안전하게 닫습니다. 메모리 누수를 방지하고 리소스를 정리합니다.

코드 예제

Future<void> close() async {
  final db = await database;
  await db.close();
  _database = null;
}

설명

close()는 데이터베이스 연결을 종료하며, _database를 null로 설정하여 다음 접근 시 새로운 연결이 생성되도록 합니다.


마치며

이번 글에서는 Flutter SQLite 데이터베이스 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#Flutter #SQLite #sqflite #Database #LocalStorage

#Flutter#SQLite#sqflite#Database#LocalStorage