[flutter] RxDart와 SQLite 데이터베이스 연동하기

Flutter 앱을 개발할 때 데이터 관리는 매우 중요한 요소입니다. RxDart는 리액티브 프로그래밍을 지원하는 라이브러리로, 앱의 데이터 플로우를 간단하게 관리할 수 있게 도와줍니다. SQLite는 널리 사용되는 경량 데이터베이스로, 영속적인 데이터 관리에 좋은 선택입니다. 이번 포스트에서는 RxDart와 SQLite 데이터베이스를 연동하는 방법을 알아보겠습니다.

RxDart와 SQLite 패키지 추가하기

먼저, 프로젝트에 RxDart와 SQLite 패키지를 추가해야 합니다. pubspec.yaml 파일에 다음의 의존성을 추가합니다.

dependencies:
  rxdart: ^0.26.0
  sqflite: ^2.0.0+3

의존성을 추가한 후, 패키지를 설치하기 위해 flutter pub get 명령어를 실행합니다.

데이터베이스 생성하기

SQLite 데이터베이스를 사용하기 위해 먼저 데이터베이스를 생성해야 합니다. database_helper.dart라는 파일을 생성하고 다음 코드를 추가합니다.

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class DatabaseHelper {
  static Database? _database;

  Future<Database?> get database async {
    if (_database != null) {
      return _database;
    }

    _database = await initializeDatabase();
    return _database;
  }

  Future<Database> initializeDatabase() async {
    String path = await getDatabasesPath();
    String dbName = 'my_database.db';
    int dbVersion = 1;

    return await openDatabase(
      join(path, dbName),
      version: dbVersion,
      onCreate: _createDatabase,
    );
  }

  void _createDatabase(Database db, int version) async {
    // 테이블 생성 등 초기화 작업을 수행합니다.
  }
}

위 코드는 데이터베이스를 생성하고 초기화하는 기능을 제공합니다. initializeDatabase 메소드는 데이터베이스 경로, 이름 및 버전을 지정하고 데이터베이스를 엽니다. _createDatabase 메소드는 데이터베이스가 생성될 때 호출되며, 테이블 생성 등 초기화 작업을 수행할 수 있습니다.

데이터 조회 및 수정하기

이제 데이터베이스에 데이터를 조회하고 수정하는 방법에 대해 알아보겠습니다. database_helper.dart에 다음 코드를 추가합니다.

class DatabaseHelper {
  // ...

  Future<List<Map<String, dynamic>>> getUsers() async {
    Database? db = await database;
    return db!.query('users');
  }

  Future<int> updateUser(Map<String, dynamic> user) async {
    Database? db = await database;
    int id = user['id'];
    return db!.update('users', user, where: 'id = ?', whereArgs: [id]);
  }
}

getUsers 메소드는 모든 사용자를 조회하여 Map<String, dynamic>의 리스트로 반환합니다. updateUser 메소드는 사용자 정보를 업데이트하고 업데이트된 행의 개수를 반환합니다.

RxDart와 데이터베이스 연동하기

마지막으로, RxDart를 사용하여 데이터베이스와 연동하는 방법에 대해 알아보겠습니다. users_bloc.dart라는 파일을 생성하고 다음 코드를 추가합니다.

import 'package:rxdart/rxdart.dart';
import 'database_helper.dart';

class UsersBloc {
  final _usersFetcher = PublishSubject<List<Map<String, dynamic>>>();

  Stream<List<Map<String, dynamic>>> get users => _usersFetcher.stream;

  final _databaseHelper = DatabaseHelper();

  void getUsers() async {
    List<Map<String, dynamic>> users = await _databaseHelper.getUsers();
    _usersFetcher.sink.add(users);
  }

  void updateUser(Map<String, dynamic> user) async {
    await _databaseHelper.updateUser(user);
    getUsers();
  }

  void dispose() {
    _usersFetcher.close();
  }
}

final usersBloc = UsersBloc();

위 코드는 RxDart의 PublishSubject를 활용하여 사용자 정보를 스트림으로 제공합니다. getUsers 메소드는 데이터베이스에서 사용자 정보를 가져와 _usersFetcher에 데이터를 추가합니다. updateUser 메소드는 사용자 정보를 업데이트하고, 데이터베이스에서 사용자 정보를 다시 가져와 스트림을 업데이트합니다. dispose 메소드는 메모리 누수를 방지하기 위해 PublishSubject를 클로즈합니다.

사용하기

이제 RxDart와 SQLite 데이터베이스를 사용하는 방법을 알아봤으니, 이를 사용하여 Flutter 앱에서 데이터를 관리하고 처리할 수 있습니다. main.dart 파일에서 다음과 같이 사용할 수 있습니다.

import 'dart:async';
import 'package:flutter/material.dart';
import 'users_bloc.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'RxDart와 SQLite',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _usersBloc = usersBloc;

  @override
  void initState() {
    _usersBloc.getUsers();
    super.initState();
  }

  @override
  void dispose() {
    _usersBloc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('RxDart와 SQLite'),
      ),
      body: StreamBuilder<List<Map<String, dynamic>>>(
        stream: _usersBloc.users,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            List<Map<String, dynamic>> users = snapshot.data!;
            // 사용자 정보를 표시하는 위젯을 반환합니다.
          } else if (snapshot.hasError) {
            // 에러 상황을 처리하는 위젯을 반환합니다.
          } else {
            // 데이터 로딩 중인 상황을 처리하는 위젯을 반환합니다.
          }
        },
      ),
    );
  }
}

위 코드는 Flutter 앱의 메인 파일인 main.dart를 보여줍니다. 사용자 정보를 받아와 화면에 표시하고 데이터를 업데이트하는 기능을 구현하였습니다.

마무리

이번 포스트에서는 RxDart와 SQLite 데이터베이스를 연동하는 방법에 대해 알아보았습니다. RxDart를 사용하면 데이터 플로우를 간편하게 관리할 수 있고, SQLite를 활용하여 영속적인 데이터 관리를 할 수 있습니다. 이러한 기술을 활용하면 더 효과적인 데이터 관리가 가능해질 것입니다.

참고 자료