Workers Binding API
이 문서는 Cloudflare Worker에서 D1 데이터베이스에 SQL 쿼리를 실행하는 방법을 설명해요. 준비된 문장(prepared statements), 배치(batching), 타입 안전한 결과를 지원하는 D1 Binding API를 사용해 Worker 안에서 직접 쿼리를 날릴 수 있어요.
출처: 문서
본문
Worker Binding API를 사용하면 Worker에서 D1 데이터베이스에 SQL 쿼리를 실행할 수 있어요. 이를 위해 다음 단계를 수행하세요:
- D1 데이터베이스 바인딩하기.
- 문장 준비하기.
- 준비된 문장 실행하기.
- (필요하다면) 반환 객체 분석하기.
API 문서에 대한 자세한 내용은 해당 섹션을 참고하세요.
TypeScript 지원 (TypeScript support)
D1 Worker Bindings API는 wrangler types 패키지를 실행해 생성된 런타임 타입을 통해 완전히 타입이 지정되며, TypeScript API의 일부로 제네릭 타입(Generic types) ↗︎도 지원해요. 제네릭 타입을 사용하면 선택적인 type parameter를 제공해서 함수가 처리하는 데이터의 타입을 이해하도록 만들 수 있어요.
쿼리 문장 메서드 D1PreparedStatement::run, D1PreparedStatement::raw, D1PreparedStatement::first를 사용할 때, 각 데이터베이스 행을 나타내는 타입을 제공할 수 있어요. 그러면 D1 API가 올바른 타입으로 결과 객체를 반환해요.
예를 들어 D1PreparedStatement::run에 OrderRow 타입을 타입 매개변수로 제공하면, 기본 Record<string, unknown> 타입 대신 타입이 지정된 Array<OrderRow> 객체를 반환해요:
// Row definition
type OrderRow = {
Id: string;
CustomerName: string;
OrderDate: number;
};
// Elsewhere in your application
// env.MY_DB is the D1 database binding from your Wrangler configuration file
const result = await env.MY_DB.prepare(
"SELECT Id, CustomerName, OrderDate FROM [Order] ORDER BY ShippedDate DESC LIMIT 100",
).run<OrderRow>();
타입 변환 (Type conversion)
D1은 Workers Binding API를 통해 매개변수로 전달되는 지원되는 JavaScript(타입스크립트 포함) 타입을 해당하는 D1 타입으로 자동 변환해요 1. 이 변환은 영구적이고 단방향(one-way)이에요. 즉 코드에서 작성된 값을 다시 읽을 때, 원래 삽입한 값이 아니라 변환된 값으로 읽게 된다는 뜻이에요.
참고 (Note)
데이터베이스에 실제로 저장된 값과 스키마가 정의한 값 사이의 타입 불일치 문제를 피하려면 SQL 스키마에서 STRICT 테이블 ↗︎ 사용을 권장해요.
쓰기(write) 중 타입 변환은 다음과 같아요:
| JavaScript (write) | D1 | JavaScript (read) |
|---|---|---|
| null | NULL |
null |
| Number | REAL |
Number |
| Number 2 | INTEGER |
Number |
| String | TEXT |
String |
| Boolean 3 | INTEGER |
Number (0,1) |
| ArrayBuffer | BLOB |
Array 4 |
| ArrayBuffer View | BLOB |
Array 4 |
| undefined | Not supported. 5 | - |
1 D1 타입은 기본이 되는 SQLite 타입 ↗︎에 대응해요.
2 D1은 내부적으로 64비트 부호 있는 INTEGER 값을 지원하지만, API에서는 BigInt ↗︎가 아직 지원되지 않아요. JavaScript 정수는 Number.MAX_SAFE_INTEGER ↗︎까지 안전해요.
3 불리언은 INTEGER 타입으로 캐스팅되는데, 1은 TRUE, 0은 FALSE예요.
4 ArrayBuffer와 ArrayBuffer 뷰 ↗︎는 Array.from ↗︎을 사용해 변환돼요.
5 undefined 값을 가진 쿼리는 D1_TYPE_ERROR를 반환해요.
API 플레이그라운드 (API playground)
D1 Worker Binding API 플레이그라운드는 D1의 각 문서화된 Worker Binding API를 테스트할 수 있는 index.js 파일이에요. 이 파일은 Get started 코드의 최종 상태에서 만들어져요.
이 파일을 API 문서와 함께 사용하면 각 API가 어떻게 동작하는지 더 잘 이해할 수 있어요.
API 플레이그라운드를 설정하는 단계를 따라 하세요.
1. Get started 튜토리얼 완료하기
Get started 튜토리얼을 완료하세요. JavaScript(TypeScript가 아닌)를 사용해야 해요.
2. index.js 내용 수정하기
각 API의 효과를 보려면 index.js 파일의 내용을 아래 코드로 바꾸세요.
index.js
// D1 API Playground - Test each D1 Worker Binding API method
// Change the URL pathname to test different methods (e.g., /RUN, /RAW, /FIRST)
export default {
async fetch(request, env) {
const { pathname } = new URL(request.url);
// Sample data for testing
const companyName1 = `Bs Beverages`;
const companyName2 = `Around the Horn`;
// Prepare reusable statements
const stmt = env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`);
const stmtMulti = env.DB.prepare(`SELECT * FROM Customers; SELECT * FROM Customers WHERE CompanyName = ?`);
const session = env.DB.withSession("first-primary")
const sessionStmt = session.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`);
// Test D1PreparedStatement::run - returns full D1Result object
if (pathname === `/RUN`){
const returnValue = await stmt.bind(companyName1).run();
return Response.json(returnValue);
// Test D1PreparedStatement::raw - returns array of arrays
} else if (pathname === `/RAW`){
const returnValue = await stmt.bind(companyName1).raw();
return Response.json(returnValue);
// Test D1PreparedStatement::first - returns first row only
} else if (pathname === `/FIRST`){
const returnValue = await stmt.bind(companyName1).first();
return Response.json(returnValue);
// Test D1Database::batch - execute multiple statements
} else if (pathname === `/BATCH`) {
const batchResult = await env.DB.batch([
stmt.bind(companyName1),
stmt.bind(companyName2)
]);
return Response.json(batchResult);
// Test D1Database::exec - execute raw SQL without parameters
} else if (pathname === `/EXEC`){
const returnValue = await env.DB.exec(`SELECT * FROM Customers WHERE CompanyName = "Bs Beverages"`);
return Response.json(returnValue);
// Test D1 Sessions API with read replication
} else if (pathname === `/WITHSESSION`){
const returnValue = await sessionStmt.bind(companyName1).run();
console.log("You're now using D1 Sessions!")
return Response.json(returnValue);
}
// Default response with instructions
return new Response(
`Welcome to the D1 API Playground!
\nChange the URL to test the various methods inside your index.js file.`,
);
},
};
3. Worker 배포하기
-
1단계를 따라 만든 튜토리얼 디렉터리로 이동하세요.
-
npx wrangler deploy를 실행하세요.npx wrangler deploy⛅️ wrangler 3.112.0 -------------------- Total Upload: 1.90 KiB / gzip: 0.59 KiB Your worker has access to the following bindings: - D1 Databases: - DB: DATABASE_NAME (<DATABASE_ID>) Uploaded WORKER_NAME (7.01 sec) Deployed WORKER_NAME triggers (1.25 sec) https://jun-d1-rr.d1-sandbox.workers.dev Current Version ID: VERSION_ID -
브라우저에서 지정된 주소를 여세요.
4. API 테스트하기
URL을 바꿔 다양한 D1 Worker Binding API를 테스트해 보세요.