Drizzle <> Expo SQLite
**๊ณต์ ์น์ฌ์ดํธ**์ ๋ฐ๋ฅด๋ฉด, Expo๋ React Native์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐ, ๋น๋ ๋ฐ ๋ฐฐํฌํ๊ธฐ ์ํ ๋๊ตฌ ์ํ๊ณ์ ๋๋ค. Hermes JavaScript ๋ฐํ์๊ณผ Metro ๋ฒ๋ค๋ฌ๋ก ๊ตฌ๋๋๋ฉฐ, Drizzle Expo ๋๋ผ์ด๋ฒ๋ ๋ ๊ฐ์ง๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ๋๋ก ๊ตฌ์ถ๋์์ต๋๋ค.
Drizzle ORM์ Expo SQLite๋ฅผ ์ํ ์ต๊ณ ์ ํดํท์ ์ ๊ณตํฉ๋๋ค:
- Expo SQLite์ฉ ๋ค์ดํฐ๋ธ ORM ๋๋ผ์ด๋ฒ โ
- ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ง์ด๊ทธ๋ ์ด์ ์์ฑ ๋ฐ ๋ฒ๋ค๋ง์ ์ง์ํ๋ Drizzle Kit โ
- ๊ธฐ๊ธฐ ๋ด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ์ํ ์ ์๋ Drizzle Studio ๊ฐ๋ฐ ๋๊ตฌ ํ๋ฌ๊ทธ์ธ โ
- Live Queries โ
npm i drizzle-orm expo-sqlite@next
npm i -D drizzle-kit
import { drizzle } from "drizzle-orm/expo-sqlite";
import { openDatabaseSync } from "expo-sqlite";
const expo = openDatabaseSync("db.db");
const db = drizzle(expo);
await db.select().from(users);Live Queries
useLiveQuery ํ
์ ์ฌ์ฉํ๋ฉด ๋ชจ๋ Drizzle ์ฟผ๋ฆฌ๋ฅผ ๋ฐ์ํ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค:
import { useLiveQuery, drizzle } from 'drizzle-orm/expo-sqlite';
import { openDatabaseSync } from 'expo-sqlite';
import { Text } from 'react-native';
import * as schema from './schema';
const expo = openDatabaseSync('db.db', { enableChangeListener: true }); // <-- ๋ณ๊ฒฝ ๋ฆฌ์ค๋ ํ์ฑํ
const db = drizzle(expo);
const App = () => {
// ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์๋์ผ๋ก ๋ค์ ๋ ๋๋ง๋ฉ๋๋ค
const { data } = useLiveQuery(db.select().from(schema.users));
return <Text>{JSON.stringify(data)}</Text>;
};
export default App;Drizzle Kit๋ฅผ ์ฌ์ฉํ Expo SQLite ๋ง์ด๊ทธ๋ ์ด์
Drizzle Kit๋ฅผ SQL ๋ง์ด๊ทธ๋ ์ด์ ์์ฑ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์งํํ๊ธฐ ์ ์ Drizzle ๋ง์ด๊ทธ๋ ์ด์ ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ํ์ธํ์ธ์. Expo / React Native๋ SQL ๋ง์ด๊ทธ๋ ์ด์ ์ ์ฑ์ ๋ฒ๋ค๋ก ํฌํจํด์ผ ํ๋ฉฐ, ์ ํฌ๊ฐ ์ด๋ฅผ ์ง์ํฉ๋๋ค.
babel ํ๋ฌ๊ทธ์ธ ์ค์น
SQL ๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ ๋ฌธ์์ด๋ก ์ง์ ๋ฒ๋ค์ ํฌํจํ๋ ค๋ฉด ํ์ํฉ๋๋ค.
npm install babel-plugin-inline-import์ค์ ํ์ผ ์ ๋ฐ์ดํธ
babel.config.js, metro.config.js ๋ฐ drizzle.config.ts ํ์ผ์ ์
๋ฐ์ดํธํด์ผ ํฉ๋๋ค
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [["inline-import", { "extensions": [".sql"] }]] // <-- ์ด ๋ถ๋ถ์ ์ถ๊ฐํ์ธ์
};
};const { getDefaultConfig } = require('expo/metro-config');
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
config.resolver.sourceExts.push('sql'); // <--- ์ด ๋ถ๋ถ์ ์ถ๊ฐํ์ธ์
module.exports = config;Drizzle Kit ์ค์ ์ dialect: 'sqlite' ๋ฐ driver: 'expo'๊ฐ ์๋์ง ํ์ธํ์ธ์
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './db/schema.ts',
out: './drizzle',
dialect: 'sqlite',
driver: 'expo', // <--- ๋งค์ฐ ์ค์ํฉ๋๋ค
});๋ง์ด๊ทธ๋ ์ด์ ์์ฑ
SQL ์คํค๋ง ํ์ผ๊ณผ drizzle.config.ts ํ์ผ์ ์์ฑํ ํ ๋ง์ด๊ทธ๋ ์ด์ ์ ์์ฑํ ์ ์์ต๋๋ค
npx drizzle-kit generate์ฑ์ ๋ง์ด๊ทธ๋ ์ด์ ์ถ๊ฐ
์ด์ ./drizzle ํด๋์์ migrations.js ํ์ผ์ Expo/React Native ์ฑ์ผ๋ก ๊ฐ์ ธ์์ผ ํฉ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์
์์ ์ ์ปค์คํ
useMigrations ๋ง์ด๊ทธ๋ ์ด์
ํ
์ ์ฌ์ฉํ๊ฑฐ๋ ์ํ๋ ๋๋ก useEffect ํ
์์ ์๋์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์
์ ์คํํ ์ ์์ต๋๋ค.
import { drizzle } from "drizzle-orm/expo-sqlite";
import { openDatabaseSync } from "expo-sqlite";
import { useMigrations } from 'drizzle-orm/expo-sqlite/migrator';
import migrations from './drizzle/migrations';
const expoDb = openDatabaseSync("db.db");
const db = drizzle(expoDb);
export default function App() {
const { success, error } = useMigrations(db, migrations);
if (error) {
return (
<View>
<Text>Migration error: {error.message}</Text>
</View>
);
}
if (!success) {
return (
<View>
<Text>Migration is in progress...</Text>
</View>
);
}
return ...your application component;
}