본문 바로가기
WIKI 기술 지식 베이스

Go 레퍼런스

원문 보기 위키 갱신

Turso는 Go용 패키지 네 가지를 제공해요. 어떤 패키지를 골라야 할지 아래 표로 한눈에 비교해 보세요.

출처: 문서

본문

Turso가 제공하는 Go 패키지는 다음과 같아요:

tursogo tursogo-serverless libsql-client-go go-libsql
Use case 로컬/임베디드 데이터베이스, sync 원격 Turso 데이터베이스 (over-the-wire) 원격 libSQL 데이터베이스 (over-the-wire) 기존 libSQL 코드베이스
Engine Turso (rewrite) Turso (rewrite) libSQL wire protocol libSQL (SQLite fork)
Concurrent writes Yes (MVCC) Yes (MVCC) N/A (remote) Not supported
Sync push/pull (local-first) — — Embedded Replicas (쓰기는 클라우드 primary로)
CGO Not required Not required Not required Required
API database/sql database/sql database/sql database/sql

새 프로젝트를 시작하나요? 로컬/임베디드 용도나 동기화에는 tursogo를 사용해요. 원격 접근이 필요하다면 데이터베이스 엔진에 맞춰 드라이버를 고르면 돼요. Turso 데이터베이스에는 tursogo-serverless, libSQL 데이터베이스에는 libsql-client-go. 어떤 패키지도 CGO가 필요하지 않아요.

tursogo

로컬 및 임베디드 용도를 위한 패키지예요. 동시 쓰기(MVCC)와 비동기 I/O를 지원하는 Turso Database 엔진을 기반으로 해요.

설치

go get turso.tech/database/tursogo

연결

import (
	"database/sql"
	_ "turso.tech/database/tursogo"
)

db, err := sql.Open("turso", "app.db")

인메모리 데이터베이스도 지원해요.

db, err := sql.Open("turso", ":memory:")

쿼리

_, err = db.Exec(`CREATE TABLE IF NOT EXISTS users (
	id INTEGER PRIMARY KEY AUTOINCREMENT,
	name TEXT NOT NULL
)`)

_, err = db.Exec("INSERT INTO users (name) VALUES (?)", "Alice")

rows, err := db.Query("SELECT * FROM users")
defer rows.Close()

for rows.Next() {
	var id int
	var name string
	rows.Scan(&id, &name)
	fmt.Printf("User: %d %s\n", id, name)
}

암호화

DSN 옵션을 사용해 로컬 데이터베이스를 저장 시점에 암호화할 수 있어요.

import (
	"database/sql"
	"fmt"
	_ "turso.tech/database/tursogo"
)

hexkey := "b1bbfda4f589dc9daaf004fe21111e00dc00c98237102f5c7002a5669fc76327"
dsn := fmt.Sprintf("encrypted.db?experimental=encryption&encryption_cipher=aegis256&encryption_hexkey=%s", hexkey)

db, err := sql.Open("turso", dsn)

지원하는 암호: aegis256, aegis256x2, aegis128l, aegis128x2, aegis128x4, aes256gcm, aes128gcm.

암호화된 데이터베이스는 표준 SQLite 데이터베이스로는 읽을 수 없어요. 반드시 Turso Database 엔진으로 열어야 해요.

참고: Turso Cloud 데이터베이스도 bring-your-own-key 방식으로 암호화할 수 있어요 — 자세히 알아보기.

동기화 (Push와 Pull)

클라우드 동기화가 있는 로컬 데이터베이스용 기능이에요. 모든 읽기와 쓰기는 로컬에서 일어나고, Push()로 변경 사항을 클라우드에 보내고 Pull()로 원격 변경 사항을 가져와요.

import (
	"context"
	"os"
	turso "turso.tech/database/tursogo"
)

ctx := context.Background()

syncDb, err := turso.NewTursoSyncDb(ctx, turso.TursoSyncDbConfig{
	Path:      "app.db",
	RemoteUrl: os.Getenv("TURSO_DATABASE_URL"),
	AuthToken: os.Getenv("TURSO_AUTH_TOKEN"),
})

db, err := syncDb.Connect(ctx)

처음 실행하면 로컬 데이터베이스가 원격에서 자동으로 부트스트랩돼요. 자세한 내용은 Turso Sync를 참고해 주세요.

Push와 Pull
// Push local writes to Turso Cloud
err := syncDb.Push(ctx)

// Pull remote changes to local database
changed, err := syncDb.Pull(ctx)
Checkpoint

동기화 상태를 유지하면서 로컬 WAL을 압축해 디스크 사용량을 제어할 수 있어요.

err := syncDb.Checkpoint(ctx)
Stats
stats, err := syncDb.Stats(ctx)
fmt.Printf("CDC operations: %d\n", stats.CdcOperations)
fmt.Printf("Main WAL size: %d\n", stats.MainWalSize)
fmt.Printf("Network sent: %d bytes\n", stats.NetworkSentBytes)
fmt.Printf("Network received: %d bytes\n", stats.NetworkReceivedBytes)
fmt.Printf("Last pull: %d\n", stats.LastPullUnixTime)
fmt.Printf("Last push: %d\n", stats.LastPushUnixTime)
fmt.Printf("Revision: %s\n", stats.Revision)

libsql-client-go (원격)

네트워크를 통해 원격 Turso Cloud 데이터베이스에 접속하는 모든 애플리케이션을 위한 추천 패키지예요. 웹 서버, Docker 컨테이너, 서버리스 함수가 여기에 해당해요. 순수 Go라서 네이티브 의존성이 없어요.

설치

go get github.com/tursodatabase/libsql-client-go/libsql

연결

import (
	"database/sql"
	"os"
	_ "github.com/tursodatabase/libsql-client-go/libsql"
)

url := os.Getenv("TURSO_DATABASE_URL") + "?authToken=" + os.Getenv("TURSO_AUTH_TOKEN")
db, err := sql.Open("libsql", url)

쿼리

표준 database/sql 인터페이스를 사용해요 — tursogo와 동일해요.

rows, err := db.Query("SELECT * FROM users WHERE id = ?", 1)

go-libsql (libSQL)

go-libsql 패키지는 오늘날 Turso Cloud를 떠받치고 있는 SQLite의 오픈소스 포크인 libSQL을 기반으로 만들어졌어요. 프로덕션에서 검증이 충분히 끝난 안정적인 선택지이고, 기존 go-libsql 기반 코드베이스를 다룰 때 적합해요.

참고: go-libsql의 임베디드 레플리카에서는 읽기가 로컬에서 처리되고 쓰기는 클라우드 primary로 전송된 뒤 레플리카에 반영돼요. 임베디드 레플리카는 완전히 지원돼요. 동기화가 필요한 새 프로젝트라면 NewTursoSyncDb를 갖춘 tursogo를 추천해요 — 퀵스타트를 참고하세요.

임베디드 레플리카

참고: 오프라인 쓰기, 양방향 동기화, 다중 라이터 수렴이 필요한 워크로드라면 NewTursoSyncDb를 갖춘 tursogo를 추천해요. 읽기와 쓰기가 모두 로컬에서 일어나고, Push() / Pull()로 명시적으로 동기화할 수 있어요.

원격 데이터베이스에서 로컬 SQLite 파일로 동기화하고, 쓰기는 원격 primary 데이터베이스에 위임하는 임베디드 레플리카를 사용할 수 있어요.

package main

import (
  "database/sql"
  "fmt"
  "os"
  "path/filepath"

  "github.com/tursodatabase/go-libsql"
)

func main() {
    dbName := "local.db"
    primaryUrl := "libsql://[DATABASE].turso.io"
    authToken := "..."

    dir, err := os.MkdirTemp("", "libsql-*")
    if err != nil {
        fmt.Println("Error creating temporary directory:", err)
        os.Exit(1)
    }
    defer os.RemoveAll(dir)

    dbPath := filepath.Join(dir, dbName)

    connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
      libsql.WithAuthToken(authToken)
    )
    if err != nil {
        fmt.Println("Error creating connector:", err)
        os.Exit(1)
    }
    defer connector.Close()

    db := sql.OpenDB(connector)
    defer db.Close()
}
수동 동기화 (Manual Sync)
if err := connector.Sync(); err != nil {
    fmt.Println("Error syncing database:", err)
}
주기 동기화 (Periodic Sync)
syncInterval := time.Minute

connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
    libsql.WithAuthToken(authToken),
    libsql.WithSyncInterval(syncInterval),
)
Read Your Writes

기본값에서는 동기화 후 서버가 변경 사항을 완전히 따라잡아야 반환돼서, 항상 자신이 쓴 내용을 읽게 된다는 보장을 받아요. 더 안전하지만 서버가 대기 중인 변경 사항을 모두 처리해야 하기 때문에 훨씬 느려요. 결과적 일관성(eventual consistency) 읽기를 견딜 수 있다면 이 옵션을 끄면 동기화가 훨씬 빨라져요.

connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
    libsql.WithAuthToken(authToken),
    libsql.WithReadYourWrites(false),
)

암호화

경고: 새 프로젝트라면 로컬 암호화에는 tursogo를 추천해요. Turso Database 엔진 기반이라 성능이 더 좋고 동시 쓰기도 지원하거든요.

SQLite 파일에 암호화를 켜려면 생성자에 암호화 키 값을 인자로 전달해 주세요.

encryptionKey := "SuperSecretKey"

connector, err := libsql.NewEmbeddedReplicaConnector(dbPath, primaryUrl,
    libsql.WithAuthToken(authToken),
    libsql.WithEncryption(encryptionKey),
)

참고: 암호화된 데이터베이스는 원시 데이터처럼 보이고 표준 SQLite 데이터베이스로는 읽을 수 없어요. 모든 작업에 libSQL 클라이언트를 사용해야 해요 — 자세히 알아보기.

더 알아보기 (Learn more)