Drizzle와 Turso 시작하기

This guide assumes familiarity with:
  • dotenv - 환경 변수를 관리하기 위한 패키지 - 여기서 읽기
  • tsx - TypeScript 파일을 실행하기 위한 패키지 - 여기서 읽기
  • turso - 프로덕션용 SQLite - 여기서 읽기
  • libsql - 낮은 쿼리 지연 시간에 최적화된 SQLite 포크, 글로벌 애플리케이션에 적합 - 여기서 읽기

기본 파일 구조

이 프로젝트의 기본 파일 구조입니다. src/db 디렉토리 안에는 schema.ts 파일에 테이블 정의가 있습니다. drizzle 폴더에는 SQL 마이그레이션 파일과 스냅샷이 있습니다.

📦 <project root>
 ├ 📂 drizzle
 ├ 📂 src
 │   ├ 📂 db
 │   │  └ 📜 schema.ts
 │   └ 📜 index.ts
 ├ 📜 .env
 ├ 📜 drizzle.config.ts
 ├ 📜 package.json
 └ 📜 tsconfig.json

1단계 - 필요한 패키지 설치하기

npm
yarn
pnpm
bun
npm i drizzle-orm @libsql/client dotenv
npm i -D drizzle-kit tsx

2단계 - 연결 변수 설정하기

프로젝트 루트에 .env 파일을 생성하고 Turso 데이터베이스 URL과 인증 토큰을 추가하세요:

TURSO_DATABASE_URL=
TURSO_AUTH_TOKEN=
중요

TURSO_DATABASE_URLTURSO_AUTH_TOKEN 값을 모르는 경우, LibSQL Driver SDK 튜토리얼을 참고하세요.
여기에서 확인한 후, 생성된 모든 값을 .env 파일에 추가하세요.

3단계 - Drizzle ORM을 데이터베이스에 연결하기

Drizzle는 모든 @libsql/client 드라이버 변형을 기본적으로 지원합니다.

@libsql/client기본적으로 node 모듈로 임포트되며, 번들러에서 target이나 platform이 설정되면 자동으로 web 모듈로 변경됩니다. 예를 들어, esbuild --platform=browser와 같은 설정이 적용됩니다.
@libsql/client/nodenode 호환 모듈로, :memory:, file, wss, http, turso 연결 프로토콜을 지원합니다.
@libsql/client/webnext, nuxt, astro와 같은 풀스택 웹 프레임워크를 위한 모듈입니다.
@libsql/client/httphttphttps 연결 프로토콜을 위한 모듈입니다.
@libsql/client/wswswss 연결 프로토콜을 위한 모듈입니다.
@libsql/client/sqlite3:memory:file 연결 프로토콜을 위한 모듈입니다.
@libsql/client-wasmWASM을 위한 별도의 실험적 패키지입니다.

기본
Node
HTTP
웹 소켓
WASM
import { drizzle } from 'drizzle-orm/libsql';

const db = drizzle({ connection: {
  url: process.env.DATABASE_URL, 
  authToken: process.env.DATABASE_AUTH_TOKEN 
}});

src 디렉토리에 index.ts 파일을 생성하고 연결을 초기화합니다:

import 'dotenv/config';
import { drizzle } from 'drizzle-orm/libsql';

// libsql 연결 옵션에서 어떤 속성이라도 지정할 수 있습니다.
const db = drizzle({ 
  connection: { 
    url: process.env.TURSO_DATABASE_URL!, 
    authToken: process.env.TURSO_AUTH_TOKEN!
  }
});

기존 드라이버를 제공해야 하는 경우:

import 'dotenv/config';
import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';

const client = createClient({ 
  url: process.env.TURSO_DATABASE_URL!, 
  authToken: process.env.TURSO_AUTH_TOKEN!
});
const db = drizzle({ client });

4단계 - 테이블 생성

src/db 디렉토리에 schema.ts 파일을 생성하고 테이블을 선언해 보겠습니다. 아래 코드는 users_table이라는 테이블을 정의하며, 각 컬럼의 타입과 제약 조건을 설정합니다.

import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";

export const usersTable = sqliteTable("users_table", {
  id: int().primaryKey({ autoIncrement: true }), // 자동 증가하는 기본 키
  name: text().notNull(),                        // 이름 (필수 값)
  age: int().notNull(),                          // 나이 (필수 값)
  email: text().notNull().unique(),              // 이메일 (필수 값, 고유 값)
});

이 코드는 drizzle-orm 라이브러리를 사용하여 SQLite 데이터베이스의 테이블 스키마를 정의합니다. 각 컬럼은 타입과 제약 조건을 가지며, id는 자동 증가하는 기본 키로 설정됩니다.

5단계 - Drizzle 설정 파일 설정하기

Drizzle 설정 파일 - Drizzle Kit에서 사용하는 설정 파일로, 데이터베이스 연결 정보, 마이그레이션 폴더, 스키마 파일 등에 대한 모든 정보를 포함합니다.

프로젝트 루트에 drizzle.config.ts 파일을 생성하고 다음 내용을 추가하세요:

drizzle.config.ts
import 'dotenv/config';
import { defineConfig } from 'drizzle-kit';

export default defineConfig({
  out: './drizzle',
  schema: './src/db/schema.ts',
  dialect: 'turso',
  dbCredentials: {
    url: process.env.TURSO_DATABASE_URL,
    authToken: process.env.TURSO_AUTH_TOKEN,
  },
});

6단계 - 데이터베이스에 변경 사항 적용하기

drizzle-kit push 커맨드를 사용하면 데이터베이스에 직접 변경 사항을 적용할 수 있습니다. 이 방법은 로컬 개발 환경에서 새로운 스키마 디자인이나 수정 사항을 빠르게 테스트할 때 유용합니다. 마이그레이션 파일을 관리할 필요 없이 빠르게 반복 작업을 진행할 수 있습니다:

npx drizzle-kit push

push 커맨드에 대해 더 알아보려면 문서를 참고하세요.

또는 drizzle-kit generate 커맨드로 마이그레이션을 생성한 후, drizzle-kit migrate 커맨드로 적용할 수도 있습니다:

마이그레이션 생성:

npx drizzle-kit generate

마이그레이션 적용:

npx drizzle-kit migrate

마이그레이션 프로세스에 대해 더 알아보려면 문서를 참고하세요.

7단계 - 데이터베이스 시드 및 쿼리

src/index.ts 파일을 사용자 생성, 조회, 수정, 삭제 쿼리로 업데이트해 보겠습니다.

src/index.ts
import 'dotenv/config';
import { eq } from 'drizzle-orm';
import { drizzle } from 'drizzle-orm/libsql';
import { usersTable } from './db/schema';

async function main() {
  // 데이터베이스 연결 설정
  const db = drizzle({ 
    connection: { 
        url: process.env.TURSO_DATABASE_URL!, 
        authToken: process.env.TURSO_AUTH_TOKEN!
    }
  });

  // 새로운 사용자 데이터 생성
  const user: typeof usersTable.$inferInsert = {
    name: 'John',
    age: 30,
    email: 'john@example.com',
  };

  // 사용자 생성
  await db.insert(usersTable).values(user);
  console.log('새로운 사용자가 생성되었습니다!');

  // 모든 사용자 조회
  const users = await db.select().from(usersTable);
  console.log('데이터베이스에서 모든 사용자를 가져옵니다: ', users);
  /*
  const users: {
    id: number;
    name: string;
    age: number;
    email: string;
  }[]
  */

  // 사용자 정보 업데이트
  await db
    .update(usersTable)
    .set({
      age: 31,
    })
    .where(eq(usersTable.email, user.email));
  console.log('사용자 정보가 업데이트되었습니다!');

  // 사용자 삭제
  await db.delete(usersTable).where(eq(usersTable.email, user.email));
  console.log('사용자가 삭제되었습니다!');
}

main();

8단계 - index.ts 파일 실행하기

TypeScript 파일을 실행하는 방법은 여러 가지가 있지만, 여기서는 tsx를 사용하는 방법을 살펴보겠습니다.

이미 tsx를 설치했으므로, 이제 쿼리를 실행할 수 있습니다.

index.ts 스크립트 실행하기

<Npx>
  tsx src/index.ts
</Npx>

TypeScript 파일을 실행할 때 bun을 사용하는 것을 추천합니다. bun을 사용하면 프로젝트가 CommonJS(CJS), ECMAScript Modules(ESM) 또는 다른 모듈 형식으로 구성되어 있더라도 추가 설정 없이 스크립트를 실행할 수 있습니다. bun으로 스크립트를 실행하려면 다음 명령어를 사용하세요:

bun src/index.ts

만약 bun이 설치되어 있지 않다면, Bun 설치 문서를 참고하세요.