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

Usage

원문 보기 위키 갱신

Turso에서 TypeScript, Python, Go로 동기화를 활성화하고 사용하는 방법을 다루는 가이드예요. 데이터베이스 준비부터 push/pull, 체크포인트, 통계 조회까지 차례로 따라 해 보세요.

출처: 문서

본문

이 가이드는 Turso 데이터베이스를 준비하고 애플리케이션에서 동기화 기능을 사용하는 방법을 보여 줘요.

이 사용법은 로컬 Turso 데이터베이스를 동기화하기 위해 Turso Cloud를 사용하며, 계정이 있다고 가정해요. * [Quickstart](/quickstart)를 따라 CLI를 설치하고 데이터베이스를 만들어요.
* 데이터베이스 URL(`turso://...`)을 확인해요.

```
turso db show <db>
```

* 앱용 토큰을 만들어요.

```
turso db tokens create <db>
```
동기화를 켜려면 세 가지 필수 요소가 필요해요.
* Local path: 로컬에 저장되는 동기화된 tursodb 파일의 위치
* Remote URL: Turso Cloud URL (`turso://...`)
* Auth token: 요청을 인증하는 Turso Cloud 토큰

<CodeGroup>
  ```ts TypeScript
  import { connect } from '@tursodatabase/sync';

  const db = await connect({
    path: './app.db',                               // local path
    url: 'turso://...',                            // remote URL (turso db show <db-name> --url로 생성)
    authToken: process.env.TURSO_AUTH_TOKEN,        // authentication token (turso db tokens create <db-name>로 생성)
    // longPollTimeoutMs: 10_000,                   // optional: server waits before replying to pull
    // bootstrapIfEmpty: false,                     // set to false to avoid bootstrapping on first run
  });
  ```

  ```py Python
  import os
  import turso.sync

  conn = turso.sync.connect(
      path="./app.db",                                  # local path
      remote_url="turso://...",                        # remote URL (turso db show <db-name> --url로 생성)
      auth_token=os.environ["TURSO_AUTH_TOKEN"],        # authentication token (turso db tokens create <db-name>로 생성)
      # long_poll_timeout_ms=10_000,                    # optional: server waits before replying to pull
      # bootstrap_if_empty=False,                       # set to false to avoid bootstrapping on first run
  )
  ```

  ```go Go
  package main

  import (
  \tturso "turso.tech/database/tursogo"
  )

  db, err := turso.NewTursoSyncDb(ctx, turso.TursoSyncDbConfig{
    Path:              "./app.db",                    // local path
    RemoteUrl:         "turso://...",                // remote URL (turso db show <db-name> --url로 생성)
    AuthToken:         os.Getenv("TURSO_AUTH_TOKEN"), // authentication token (turso db tokens create <db-name>로 생성)
    // LongPollTimeoutMs: 10_000,                     // optional: server waits before replying to pull
    // BootstrapIfEmpty: new(bool),                   // *bool; point at false to avoid bootstrapping on first run
  })
  ```
</CodeGroup>

<Note>
  첫 실행에서 로컬 데이터베이스는 원격으로부터 자동으로 부트스트랩돼요. 그래서 초기 connect 시점에 원격에 접근할 수 있어야 해요.

  `bootstrap_if_empty`를 `false`로 설정하면 로컬 데이터베이스는 비어 있는 상태로 시작해요.
  이후 언제든 `pull()`을 명시적으로 호출해서 부트스트랩하거나 갱신할 수 있어요.
</Note>
push는 로컬 변경을 Turso Cloud 서버로 보내요. 내부적으로는 논리적 문장(logical statement)이 전송되고, 충돌이 나면 "last push wins" 전략을 따라요.
<CodeGroup>
  ```ts TypeScript
  await db.exec("CREATE TABLE IF NOT EXISTS notes(id TEXT PRIMARY KEY, body TEXT)");
  await db.exec("INSERT INTO notes VALUES ('n1', 'hello')");

  await db.push();
  ```

  ```py Python
  conn.execute("CREATE TABLE IF NOT EXISTS notes(id TEXT PRIMARY KEY, body TEXT)")
  conn.commit()
  conn.execute("INSERT INTO notes VALUES ('n1', 'hello')")
  conn.commit()

  conn.push()
  ```

  ```go Go
  // create *sql.DB instance
  conn, err := db.Connect(ctx)
  if err != nil {
    return err
  }

  _, err = conn.ExecContext(ctx, "CREATE TABLE IF NOT EXISTS notes(id TEXT PRIMARY KEY, body TEXT)")
  if err != nil {
    return err
  }
  _, err = conn.ExecContext(ctx, "INSERT INTO notes VALUES ('n1', 'hello')")
  if err != nil {
    return err
  }

  if err := db.Push(ctx); err != nil {
  \treturn err
  }
  ```
</CodeGroup>
pull은 원격 변경을 가져와 로컬에 적용해요. 무언가 바뀌었는지 알려 주는 불리언 값을 돌려줘요.
* 서버가 변경을 기다렸다가 빈 응답을 피하게 하려면 `long_poll_timeout_ms`/`LongPollTimeoutMs`를 설정하세요.
* 이전에 push했다면, 서버 쪽 충돌 해결 프레임 때문에 이후의 pull이 변경이 있었다고 알려줄 수 있어요.

<CodeGroup>
  ```ts TypeScript
  // 로컬에서 무언가 바뀌었으면 true를 돌려줘요
  const changed = await db.pull();
  console.info('pulled changes:', changed);
  ```

  ```py Python
  changed = conn.pull()
  print("pulled changes:", changed)
  ```

  ```go Go
  changed, err := db.Pull(ctx)
  if err != nil {
  \treturn err
  }
  log.Println("pulled changes:", changed)
  ```
</CodeGroup>
checkpoint는 동기화 상태를 유지하면서 로컬 WAL을 압축해 디스크 사용량을 한도 안으로 묶어 줘요.
<CodeGroup>
  ```ts TypeScript
  await db.checkpoint();
  ```

  ```py Python
  conn.checkpoint()
  ```

  ```go Go
  if err := db.Checkpoint(ctx); err != nil {
  \treturn err
  }
  ```
</CodeGroup>
stats는 동기화 동작과 사용량(WAL 크기, 마지막 push/pull 시각, 네트워크 사용량, revision 등)을 관찰하게 해 줘요.
<CodeGroup>
  ```ts TypeScript
  const s = await db.stats();
  console.info({
    cdcOperations: s.cdcOperations,
    mainWalSize: s.mainWalSize,
    revertWalSize: s.revertWalSize,
    networkReceivedBytes: s.networkReceivedBytes,
    networkSentBytes: s.networkSentBytes,
    lastPullUnixTime: s.lastPullUnixTime,
    lastPushUnixTime: s.lastPushUnixTime,
    revision: s.revision,
  });
  ```

  ```py Python
  s = conn.stats()
  print({
      "cdc_operations": s.cdc_operations,
      "main_wal_size": s.main_wal_size,
      "revert_wal_size": s.revert_wal_size,
      "network_received_bytes": s.network_received_bytes,
      "network_sent_bytes": s.network_sent_bytes,
      "last_pull_unix_time": s.last_pull_unix_time,
      "last_push_unix_time": s.last_push_unix_time,
      "revision": s.revision,
  })
  ```

  ```go Go
  s, err := db.Stats(ctx)
  if err != nil {
  \treturn err
  }
  log.Printf("stats: cdc=%v, main=%d revert=%d rx=%d tx=%d pull=%d push=%d revision=%s",
    s.CdcOperations,
    s.MainWalSize,
    s.RevertWalSize,
    s.NetworkReceivedBytes,
    s.NetworkSentBytes,
    s.LastPullUnixTime,
    s.LastPushUnixTime,
    s.Revision,
  )
  ```
</CodeGroup>

Offline-first writes

인터넷 연결 없이도 쓰기를 받아야 하는 앱이라면, 로컬에 쓰고 연결이 살아나면 push()를 호출하세요. 모든 변경은 동기화될 수 있을 때까지 로컬 데이터베이스 파일에 안전하게 저장돼요.

```ts TypeScript import { connect } from '@tursodatabase/sync';

// bootstrapIfEmpty: false는 첫 실행에서 원격에 접근하지 않고도 // 앱이 오프라인으로 시작할 수 있게 해 줘요 const db = await connect({ path: './local.db', url: process.env.TURSO_URL!, authToken: process.env.TURSO_AUTH_TOKEN!, bootstrapIfEmpty: false, });

async function syncWhenOnline(db) { try { await db.push(); } catch (e) { // 연결 없음 — 변경은 로컬 파일에 안전하게 보관되고 // 다음 push() 호출 때 동기화돼요 } }

// 앱 시작 시 온라인이라면 최신 상태를 pull해요 try { await db.pull(); } catch (e) { // 오프라인 — 로컬 데이터는 여전히 읽고 쓸 수 있어요 }

// 타이머나 연결 이벤트에서 await syncWhenOnline(db);


```py Python
import os
import turso.sync

# bootstrap_if_empty=False는 첫 실행에서 원격에 접근하지 않고도
# 앱이 오프라인으로 시작할 수 있게 해 줘요
conn = turso.sync.connect(
    path="./local.db",
    remote_url=os.environ["TURSO_URL"],
    auth_token=os.environ["TURSO_AUTH_TOKEN"],
    bootstrap_if_empty=False,
)

def sync_when_online(conn):
    try:
        conn.push()
    except Exception:
        # 연결 없음 — 변경은 로컬 파일에 안전하게 보관되고
        # 다음 push() 호출 때 동기화돼요
        pass

# 앱 시작 시 온라인이라면 최신 상태를 pull해요
try:
    conn.pull()
except Exception:
    # 오프라인 — 로컬 데이터는 여전히 읽고 쓸 수 있어요
    pass

# 타이머나 연결 이벤트에서
sync_when_online(conn)
// BootstrapIfEmpty를 false로 가리키면 첫 실행에서 원격에 접근하지 않고도
// 앱이 오프라인으로 시작할 수 있어요
noBootstrap := false
db, err := turso.NewTursoSyncDb(ctx, turso.TursoSyncDbConfig{
\tPath:             "./local.db",
\tRemoteUrl:        os.Getenv("TURSO_URL"),
\tAuthToken:        os.Getenv("TURSO_AUTH_TOKEN"),
\tBootstrapIfEmpty: &noBootstrap,
})

func syncWhenOnline(ctx context.Context, db *turso.TursoSyncDb) {
\tif err := db.Push(ctx); err != nil {
\t\t// 연결 없음 — 변경은 로컬 파일에 안전하게 보관되고
\t\t// 다음 Push() 호출 때 동기화돼요
\t\tlog.Println("push deferred:", err)
\t}
}

// 앱 시작 시 온라인이라면 최신 상태를 pull해요
if _, err := db.Pull(ctx); err != nil {
\t// 오프라인 — 로컬 데이터는 여전히 읽고 쓸 수 있어요
\tlog.Println("pull deferred:", err)
}

// 타이머나 연결 이벤트에서
syncWhenOnline(ctx, db)

이것은 @libsql/client Embedded Replicas의 offline: true 플래그에 해당하는 현대적인 방식이에요. Turso Sync에서는 모든 읽기와 쓰기가 기본적으로 로컬에서 일어나고, 명시적인 push()와 pull() 호출로 동기화 시점을 직접 제어해요.

더 알아보기 (Learn more)