Flutter - 데이터베이스 만들기

유의선·2024년 4월 2일
0

플러터에서 SQLite를 이용해 데이터베이스를 만들어보았다.

플러터에선 sqflite라는 패키지를 제공해 SQLite를 사용할 수 있게 해준다.


pubspec.yaml에 SQLite 사용을 위한 sqflite와 내부 저장소 사용을 위한 path 패키지를 추가했다.

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  sqflite: ^2.0.0+3
  path: ^1.8.0

데이터베이스 구조를 만들었다.
lib 폴더에 todo.dart 파일을 만들고 코드를 다음과 같이 작성하였다.

class Todo {
  String? title;
  String? content;
  int? active;
  int? id;

  Todo({this.title, this.content, this.active, this.id});

  Map<String, dynamic> toMap(){
    return {
      'id' : id,
      'title' : title,
      'content' : content,
      'active' : active,
    };
  }
}

데이터베이스에 넣을 데이터를 title, content, active, id 로 구성하였다. 각각 제목, 내용, 완료여부, 순번을 나타낸다.

플러터의 sqflite 패키지는 데이터를 Map 형태로 다루기때문에 데이터를 Map 형태로 반환해주는 toMap() 함수를 정의하였다.


main.dart 파일을 다음처럼 수정하였다.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: DatabaseApp()
    );
  }
}

class DatabaseApp extends StatefulWidget {
  
  State<StatefulWidget> createState() {
    return _DatabaseApp();
  }
}

class _DatabaseApp extends State<DatabaseApp>{
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Database Example'),),
      body: Container(),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          final todo = await Navigator.of(context).pushNamed('/add');
        },
        child: Icon(Icons.add),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

StatefulWidget을 상속받는 DatabaseApp 클래스를 작성해 home으로 지정하였다.

DatabaseApp 클래스에 데이터베이스에서 가져온 할 일 목록을 보여주는 UI를 구현하고,
앱이 시작될 때 MyApp 클래스에서 데이터베이스를 만들어 DatabaseApp 클래스에 전달하도록 만들어보았다.


main.dart 파일의 MyApp 클래스에 데이터베이스를 생성하는 initDatabase() 함수를 만들었다.
데이터베이스 함수를 사용하는데 필요한 패키지들도 import 하였다.

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: DatabaseApp()
    );
  }

  Future<Database> initDatabase() async{
    return openDatabase(
      join(await getDatabasesPath(), 'todo_database.db'),
      onCreate: (db, version) {
        return db.execute(
          "CREATE TABLE todos(id INTEGER PRIMARY KEY AUTOINCREMENT, "
              "title TEXT, content TEXT, active INTEGER)"
        );
      },
      version: 1
    );
  }
}

initDatabase() 함수는 데이터베이스를 열어서 반환해준다.
데이터베이스는 getDatabasePath() 함수가 반환하는 경로에 todo_database.db라는 파일로 저장되어 있으므로 이 파일을 불러와 반환해준다.

todo_database.db 파일에 테이블이 없다면 onCreate를 이용해 새로운 테이블을 만든다.


build() 함수에서 initDatabase() 함수를 호출하도록 코드를 추가했다

  
  Widget build(BuildContext context) {
    Future<Database> database = initDatabase();

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      initialRoute: '/',
      routes: {
        '/' : (context) => DatabaseApp(database),
        '/add' : (context) => AddTodoApp(database)
      },
    );
  }

routes를 이용해 경로를 지정하였고,
각 클래스를 호출하면서 database 객체를 전달하도록 만들었다.


build() 함수에서 DatabaseApp 클래스를 호출할 때 database 객체를 전달했으므로 DatabaseApp 클래스를 다음처럼 수정했다.

class DatabaseApp extends StatefulWidget {
  final Future<Database> db;
  DatabaseApp(this.db);
  
  ...

routes에서 /add로 경로를 지정한 AppTodoApp 클래스를 작성하였다.

addTodo.dart 파일을 만들고 그 안에 StatefulWidget을 상속받는 AddTodoApp 클래스를 작성하였다.

이 클래스에서는 데이터를 입력해 테이블에 추가하는 화면을 만들 예정이다.

import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'todo.dart';

class AddTodoApp extends StatefulWidget {
  final Future<Database> db;
  AddTodoApp(this.db);

  
  State<StatefulWidget> createState() {
    return _AddTodoApp();
  }
}

class _AddTodoApp extends State<StatefulWidget>{

  
  void initState() {

  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Todo 추가'),),
      body: Container(
        child: Center(
          child: Column(
            children: <Widget>[],
          ),
        ),
      ),
    );
  }

}

이것으로 데이터베이스를 사용할 준비를 마쳤다.
다음부터 데이터베이스를 이용해 생성, 읽기, 갱신, 삭제 기능을 추가해보겠다.


요약

  • SQLite 사용을 위해 sqflite 패키지를 사용한다.
  sqflite: ^2.0.0+3
  • 데이터베이스 구조 정의를 위한 클래스를 만든다.
    sqflite 패키지는 데이터를 Map 형태로 다룬다.

  • openDatabase() 함수로 지정된 위치의 데이터베이스를 연다.
    getDatabasesPath() 함수로 데이터베이스가 저장되는 기본 위치 경로를 얻는다
    테이블이 없다면 onCreate()로 새 테이블을 만든다.

    return openDatabase(
      join(await getDatabasesPath(), 'todo_database.db'),
      onCreate: (db, version) {
        return db.execute(
          "CREATE TABLE todos(id INTEGER PRIMARY KEY AUTOINCREMENT, "
              "title TEXT, content TEXT, active INTEGER)"
        );
      },
      version: 1
    );

0개의 댓글