SQLite
ํ์ผ ๊ธฐ๋ฐ์ ๋ด์ฅํ(Embedded) ๋ฐ์ดํฐ๋ฒ ์ด์ค
โข
SQLite ํน์ง
โข
SQLite๊ฐ ์ฌ์ฉ๋๋ ๊ณณ
โข
SQLite ๊ธฐ๋ณธ ๋ช
๋ น์ด
โข
SQLite์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋น๊ต
โข
SQLite์ ์ฅ๋จ์
โข
SQLite๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ
โข
SQLite ๋ฐ์ดํฐ ํ์
โข
์์ ์ฝ๋
1. SQLite์ ํน์ง
ํ์ผ ๊ธฐ๋ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค
โข
MySQL, PostgreSQL ๊ฐ์ ๋ค๋ฅธ RDBMS์ ๋ฌ๋ฆฌ ๋ณ๋์ ์๋ฒ ํ๋ก์ธ์ค๊ฐ ํ์ํ์ง ์์
โข
๋ชจ๋ ๋ฐ์ดํฐ๋ ํ๋์ .db ํ์ผ์ ์ ์ฅ๋จ
๊ฐ๋ณ๊ณ ๋น ๋ฆ
โข
๋จ์ผ ํ์ผ๋ก ๊ตฌ์ฑ๋์ด ๊ด๋ฆฌ๊ฐ ๊ฐํธ
โข
์์ ํฌ๊ธฐ์ ์ฝ๋(์ฝ 600KB)
โข
์ฝ๊ธฐ ์๋๊ฐ ๋น ๋ฅด๊ณ , ํธ๋์ญ์
์ ์ง์
ACID(์์์ฑ, ์ผ๊ด์ฑ, ๋
๋ฆฝ์ฑ, ์ง์์ฑ) ์ง์
โข
SQLite๋ ํธ๋์ญ์
์ ์ง์ํ์ฌ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํจ
ํฌ๋ก์ค ํ๋ซํผ ์ง์
โข
Windows, macOS, Linux, Android, iOS ๋ฑ ๋ค์ํ ์ด์์ฒด์ ์์ ์ฌ์ฉ ๊ฐ๋ฅ
์คํ ์์ค ๋ฐ ๋ฌด๋ฃ
โข
๋๊ตฌ๋ ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์์ (๊ณต๊ฐ ๋ผ์ด์ ์ค)
2. SQLite๊ฐ ์ฌ์ฉ๋๋ ๊ณณ
โข
๋ชจ๋ฐ์ผ ์ฑ (Android, iOS) โ ์: Flutter, React Native, Swift, Kotlin
โข
์น ๋ธ๋ผ์ฐ์ โ ์: Google Chrome, Firefox์ ๋ด๋ถ ๋ฐ์ดํฐ ์ ์ฅ
โข
๋ฐ์คํฌํฑ ํ๋ก๊ทธ๋จ โ ์: Windows์ ์ผ๋ถ ์ค์ ์ ์ฅ, macOS์ ํ์ผ ์ธ๋ฑ์ฑ
โข
IoT ๋ฐ ์๋ฒ ๋๋ ์์คํ
โ ์: ์๋์ฐจ ๋ด๋น๊ฒ์ด์
, ์ค๋งํธ TV ๋ฑ
3. SQLite ๊ธฐ๋ณธ ๋ช ๋ น์ด
SQLite๋ฅผ ์ฌ์ฉํ ๋ ์์ฃผ ์ฌ์ฉํ๋ SQL ๋ฌธ๋ฒ์
๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ
sqlite3 my_database.db;
SQL
๋ณต์ฌ
ํ
์ด๋ธ ์์ฑ
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER NOT NULL
);
SQL
๋ณต์ฌ
๋ฐ์ดํฐ ์ฝ์
INSERT INTO users (name, age) VALUES ('ํ๊ธธ๋', 25);
SQL
๋ณต์ฌ
๋ฐ์ดํฐ ์กฐํ
SELECT * FROM users;
SQL
๋ณต์ฌ
๋ฐ์ดํฐ ์์
UPDATE users SET age = 26 WHERE id = 1;
SQL
๋ณต์ฌ
๋ฐ์ดํฐ ์ญ์
DELETE FROM users WHERE id = 1;
SQL
๋ณต์ฌ
ํ
์ด๋ธ ์ญ์
DROP TABLE users;
SQL
๋ณต์ฌ
4. SQLite์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋น๊ต
ํน์ง | SQLite | MySQL | PostgreSQL |
์ค์น ๋ฐฉ์ | ๋ด์ฅํ (ํ์ผ ๊ธฐ๋ฐ) | ์๋ฒ ๊ธฐ๋ฐ | ์๋ฒ ๊ธฐ๋ฐ |
ํ์ผ ํฌ๊ธฐ | ๋งค์ฐ ์์ (600KB) | ๋น๊ต์ ํผ | ํผ |
ํธ๋์ญ์
| ์ง์ | ์ง์ | ๊ฐ๋ ฅํ ์ง์ |
์๋ | ๋น ๋ฆ (๊ฒฝ๋ํ) | ๋น ๋ฆ | ๋๋ ๋ฐ์ดํฐ์ ์ต์ ํ |
์ฌ์ฉ์ฒ | ๋ชจ๋ฐ์ผ, IoT, ์ํ ์ฑ | ์น, ์ค์ ๊ท๋ชจ ์๋น์ค | ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ฒ๋ฆฌ |
SQLite๋ ์๋ฒ๊ฐ ํ์ ์๋ ๊ฐ๋ฒผ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ด๋ฏ๋ก, ๋ชจ๋ฐ์ผ ์ฑ์ด๋ ์๊ท๋ชจ ํ๋ก์ ํธ์ ์ ํฉํฉ๋๋ค. ๋ฐ๋ฉด, MySQL์ด๋ PostgreSQL์ ๋๊ท๋ชจ ์น ์๋น์ค๋ ๋น
๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ๋ ๋ ์ ํฉํฉ๋๋ค.
5. SQLite๋ฅผ Flutter์์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
Flutter์์๋ sqflite ํจํค์ง๋ฅผ ์ฌ์ฉํ์ฌ SQLite๋ฅผ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์์ต๋๋ค.
ํจํค์ง ์ค์น (pubspec.yaml)
dependencies:
sqflite: ^2.3.2
path_provider: ^2.1.2
YAML
๋ณต์ฌ
SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
Future<Database> openDB() async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, 'my_database.db');
return await openDatabase(
path,
version: 1,
onCreate: (db, version) async {
await db.execute('''
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER NOT NULL
)
''');
},
);
}
Dart
๋ณต์ฌ
๋ฐ์ดํฐ ์ฝ์
Future<void> insertUser(String name, int age) async {
final db = await openDB();
await db.insert('users', {'name': name, 'age': age});
}
Dart
๋ณต์ฌ
๋ฐ์ดํฐ ์กฐํ
Future<List<Map<String, dynamic>>> getUsers() async {
final db = await openDB();
return await db.query('users');
}
Dart
๋ณต์ฌ
6. SQLite์ ์ฅ๋จ์
โข ์๋ฒ ์์ด๋ ๋์ (์ค์น ํ์ ์์)
โข ๋น ๋ฅด๊ณ ๊ฐ๋ฒผ์ (๋จ์ผ ํ์ผ ๊ด๋ฆฌ)
โข ๋ชจ๋ฐ์ผ ๋ฐ ์๋ฒ ๋๋ ์์คํ
์์ ์ต์ ํ๋จ
โข ์คํ์์ค์ด๋ฏ๋ก ๋ฌด๋ฃ๋ก ์ฌ์ฉ ๊ฐ๋ฅ | โข ๋์ ์ ์์ด ๋ง์ ํ๊ฒฝ(์น ์๋ฒ)์๋ ์ ํฉํ์ง ์์
โข ๋ฐ์ดํฐ ์ํธํ ๊ธฐ๋ฅ์ด ๊ธฐ๋ณธ ์ ๊ณต๋์ง ์์
โข ๋ณต์กํ ์ฟผ๋ฆฌ๋ ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ํ๊ณ๊ฐ ์์ |
7. SQLite๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ
SQLite ์ฌ์ฉ์ด ์ ํฉํ ๊ฒฝ์ฐ | ๋ค๋ฅธ DB๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ ๊ฒฝ์ฐ |
โข ๋ชจ๋ฐ์ผ ์ฑ ๊ฐ๋ฐ (Android, iOS)
โข ์๋ฒ ๋๋ ์์คํ
๋ฐ IoT ๊ธฐ๊ธฐ
โข ๋ฐ์คํฌํฑ ์ ํ๋ฆฌ์ผ์ด์
โข ์์ ๊ท๋ชจ์ ๋ก์ปฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค
โข ์คํ๋ผ์ธ ๋ฐ์ดํฐ ์ ์ฅ์ด ํ์ํ ๊ฒฝ์ฐ
โข ๋จ์ผ ์ฌ์ฉ์ ํ๊ฒฝ | โข ๋๊ท๋ชจ ์น ์ ํ๋ฆฌ์ผ์ด์
โข ๋์ ์ ์์๊ฐ ๋ง์ ์๋น์ค
โข ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์
โข ๋ณต์กํ ๊ด๊ณํ ๋ฐ์ดํฐ ๋ชจ๋ธ
โข ๊ณ ๊ธ ๋ณด์ ๊ธฐ๋ฅ์ด ํ์ํ ๊ฒฝ์ฐ
โข ๋ค์ค ์ฌ์ฉ์ ํ๊ฒฝ |
SQLite๋ ๋จ์ํ๊ณ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ๊ด๋ฆฌ๊ฐ ํ์ํ ๊ฒฝ์ฐ์ ์ต์ ์ ์ ํ์ด ๋ ์ ์์ต๋๋ค. ํนํ ๋ชจ๋ฐ์ผ ์ฑ์ด๋ ์๋ฒ ๋๋ ์์คํ
์์๋ SQLite์ ์ฅ์ ์ ์ต๋ํ ํ์ฉํ ์ ์์ต๋๋ค.
SQLite ๋ฐ์ดํฐ ํ์
๋ฐ์ดํฐ ํ์
| ์ค๋ช
| ์ค์ ์ ์ฅ ํํ |
INTEGER | ์ ์๊ฐ (1, 2, 3, โฆ) | 1, 2, 3, 4, 6, 8 ๋ฐ์ดํธ (๊ฐ์ ํฌ๊ธฐ์ ๋ฐ๋ผ ์๋ ๊ฒฐ์ ) |
REAL | ์ค์ (๋ถ๋์์์ ) | 8๋ฐ์ดํธ IEEE 754 ๋ถ๋์์์ |
TEXT | ๋ฌธ์์ด (UTF-8, UTF-16) | ์ ์ฅ๋ ๋ฌธ์์ด ๊ธธ์ด์ ๋ฐ๋ผ ๊ฐ๋ณ์ |
BLOB | ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ (์ด๋ฏธ์ง, ํ์ผ ๋ฑ) | ์
๋ ฅ๋ ๊ทธ๋๋ก ์ ์ฅ |
NULL | NULL ๊ฐ | NULL |
ํ์
๊ณ์ด | ์ค๋ช
| ์์ ๋ฐ์ดํฐ ํ์
|
INTEGER | ์ ์๊ฐ ์ ์ฅ | INT, INTEGER, TINYINT, SMALLINT, BIGINT, UNSIGNED BIG INT |
REAL | ์ค์ ์ ์ฅ (๋ถ๋์์์ ) | REAL, DOUBLE, DOUBLE PRECISION, FLOAT |
TEXT | ๋ฌธ์์ด ์ ์ฅ | TEXT, CHAR(n), VARCHAR(n), CLOB |
BLOB | ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ | BLOB (๊ทธ๋๋ก ์ ์ฅ) |
NUMERIC | ์ซ์(์ ์, ์ค์, ๋ ์ง ๋ฑ) ์ ์ฅ | NUMERIC, DECIMAL, BOOLEAN, DATE, DATETIME |
์์ ์ฝ๋
Flutter์์ SQLite๋ฅผ ์ฌ์ฉํ ๋๋ sqflite ํจํค์ง๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๊ฒ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
1. sqflite ํจํค์ง ์ค์น
๋จผ์ pubspec.yaml ํ์ผ์ sqflite์ path_provider ํจํค์ง๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
dependencies:
flutter:
sdk: flutter
sqflite: ^2.3.2
path_provider: ^2.1.2
YAML
๋ณต์ฌ
ํฐ๋ฏธ๋์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ์ฌ ํจํค์ง๋ฅผ ์ค์นํฉ๋๋ค.
flutter pub get
Plain Text
๋ณต์ฌ
2. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๊ธฐํ ๋ฐ ํ ์ด๋ธ ์์ฑ
Flutter์์ SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์์ฑํ๋ ค๋ฉด getDatabasesPath()๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ค์ ํ ํ, openDatabase()๋ฅผ ํธ์ถํฉ๋๋ค.
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
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('my_database.db');
return _database!;
}
Future<Database> _initDB(String fileName) async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, fileName);
return await openDatabase(
path,
version: 1,
onCreate: _createDB,
);
}
Future<void> _createDB(Database db, int version) async {
await db.execute('''
CREATE TABLE users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER NOT NULL
)
''');
}
}
Dart
๋ณต์ฌ
3. ๋ฐ์ดํฐ ์ฝ์
์ฌ์ฉ์๋ฅผ ์ถ๊ฐํ๋ ๋ฉ์๋๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
Future<int> insertUser(String name, int age) async {
final db = await DatabaseHelper.instance.database;
return await db.insert(
'users',
{'name': name, 'age': age},
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Dart
๋ณต์ฌ
4. ๋ฐ์ดํฐ ์กฐํ
ํ
์ด๋ธ์์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋์
๋๋ค.
Future<List<Map<String, dynamic>>> getUsers() async {
final db = await DatabaseHelper.instance.database;
return await db.query('users');
}
Dart
๋ณต์ฌ
5. ๋ฐ์ดํฐ ์์
ํน์ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ์
๋ฐ์ดํธํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
Future<int> updateUser(int id, String name, int age) async {
final db = await DatabaseHelper.instance.database;
return await db.update(
'users',
{'name': name, 'age': age},
where: 'id = ?',
whereArgs: [id],
);
}
Dart
๋ณต์ฌ
6. ๋ฐ์ดํฐ ์ญ์
ํน์ ์ฌ์ฉ์๋ฅผ ์ญ์ ํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
Future<int> deleteUser(int id) async {
final db = await DatabaseHelper.instance.database;
return await db.delete(
'users',
where: 'id = ?',
whereArgs: [id],
);
}
Dart
๋ณต์ฌ
7. ์ ์ฒด ์ฝ๋ ์์
SQLite๋ฅผ ํ์ฉํ ๊ฐ๋จํ ์ฌ์ฉ์ ๊ด๋ฆฌ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ์ ์ฒด ์ฝ๋์
๋๋ค.
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Map<String, dynamic>> users = [];
void initState() {
super.initState();
_loadUsers();
}
Future<void> _loadUsers() async {
final data = await DatabaseHelper.instance.getUsers();
setState(() {
users = data;
});
}
Future<void> _addUser() async {
await DatabaseHelper.instance.insertUser('ํ๊ธธ๋', 25);
_loadUsers();
}
Future<void> _deleteUser(int id) async {
await DatabaseHelper.instance.deleteUser(id);
_loadUsers();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('SQLite Example')),
body: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index]['name']),
subtitle: Text('Age: ${users[index]['age']}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => _deleteUser(users[index]['id']),
),
);
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _addUser,
),
);
}
}
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('my_database.db');
return _database!;
}
Future<Database> _initDB(String fileName) async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, fileName);
return await openDatabase(
path,
version: 1,
onCreate: _createDB,
);
}
Future<void> _createDB(Database db, int version) async {
await db.execute('''
CREATE TABLE users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER NOT NULL
)
''');
}
Future<int> insertUser(String name, int age) async {
final db = await database;
return await db.insert(
'users',
{'name': name, 'age': age},
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Future<List<Map<String, dynamic>>> getUsers() async {
final db = await database;
return await db.query('users');
}
Future<int> deleteUser(int id) async {
final db = await database;
return await db.delete(
'users',
where: 'id = ?',
whereArgs: [id],
);
}
}
Dart
๋ณต์ฌ
์ด์ ์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด SQLite๋ฅผ ์ด์ฉํด ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ, ์กฐํ, ์ญ์ ํ ์ ์์ต๋๋ค. ๋ ๋ณต์กํ ์ฑ์ ๋ง๋ค๋ ค๋ฉด FutureBuilder๋ฅผ ํ์ฉํ๊ฑฐ๋ Provider ๊ฐ์ ์ํ ๊ด๋ฆฌ ํจํค์ง๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.