Drizzle HTTP 프록시
This guide assumes familiarity with:
HTTP 프록시의 작동 방식과 필요성
Drizzle 프록시는 데이터베이스와 직접 통신하는 드라이버를 직접 구현해야 할 때 사용됩니다. 기존 드라이버를 사용하면서 쿼리 단계에서 커스텀 로직을 추가하는 등 여러 경우에 활용할 수 있습니다. 가장 일반적인 사용 사례는 HTTP 드라이버와 함께 사용하는 경우입니다. 이 드라이버는 쿼리를 데이터베이스가 있는 서버로 보내고, 데이터베이스에서 쿼리를 실행한 후 Drizzle ORM이 결과로 매핑할 수 있는 원시 데이터를 반환합니다.
┌───────────────────────────┐ ┌─────────────────────────────┐
│ Drizzle ORM │ │ HTTP Server with Database │
└─┬─────────────────────────┘ └─────────────────────────┬───┘
│ ^ │
│-- 1. 쿼리 생성 2. 생성된 쿼리 전송 --│ │
│ │ │
│ ┌───────────────────────────┐ │ │
└─────────────>│ │─────┘ │
│ HTTP 프록시 드라이버 │ │
┌──────────────│ │<─────────────┬───────────┘
│ └───────────────────────────┘ │
│ 3. 쿼리 실행 + 원시 결과 반환
│-- 4. 데이터 매핑 후 반환
│
v
Drizzle ORM은 SQL을 실행하기 위해 비동기 콜백 함수를 간단히 사용하는 것도 지원합니다.
sql
은 플레이스홀더가 있는 쿼리 문자열입니다.
params
는 매개변수 배열입니다.
method
는 SQL 문에 따라 run
, all
, values
, get
중 하나로 설정됩니다.
Drizzle는 항상 {rows: string[][]}
또는 {rows: string[]}
형태의 반환 값을 기다립니다.
method
가 get
인 경우, {rows: string[]}
형태로 값을 반환해야 합니다.
그 외의 경우에는 {rows: string[][]}
형태로 반환해야 합니다.
// 드라이버 구현 예제
import { drizzle } from 'drizzle-orm/pg-proxy' ;
const db = drizzle ( async (sql , params , method) => {
try {
const rows = await axios .post ( 'http://localhost:3000/query' , { sql , params , method });
return { rows : rows .data };
} catch (e : any ) {
console .error ( 'pg 프록시 서버 오류: ' , e . response .data)
return { rows : [] };
}
});
// 서버 구현 예제
import { Client } from 'pg' ;
import express from 'express' ;
const app = express ();
app .use ( express .json ());
const port = 3000 ;
const client = new Client ( 'postgres://postgres:postgres@localhost:5432/postgres' );
app .post ( '/query' , async (req , res) => {
const { sql , params , method } = req .body;
// 다중 쿼리 방지
const sqlBody = sql .replace ( /;/ g , '' );
try {
const result = await client .query ({
text : sqlBody ,
values : params ,
rowMode : method === 'all' ? 'array' : undefined ,
});
res .send ( result .rows);
} catch (e : any ) {
res .status ( 500 ) .json ({ error : e });
}
res .status ( 500 ) .json ({ error : '알 수 없는 메서드 값' });
});
app .listen (port , () => {
console .log ( `예제 앱이 포트 ${ port } 에서 실행 중입니다.` );
});
// 드라이버 구현 예제
import { drizzle } from 'drizzle-orm/mysql-proxy' ;
const db = drizzle ( async (sql , params , method) => {
try {
const rows = await axios .post ( 'http://localhost:3000/query' , { sql , params , method });
return { rows : rows .data };
} catch (e : any ) {
console .error ( 'mysql 프록시 서버 오류: ' , e . response .data)
return { rows : [] };
}
});
// 서버 구현 예제
import * as mysql from 'mysql2/promise' ;
import express from 'express' ;
const app = express ();
app .use ( express .json ());
const port = 3000 ;
const main = async () => {
const connection = await mysql .createConnection ( 'mysql://root:mysql@127.0.0.1:5432/drizzle' );
app .post ( '/query' , async (req , res) => {
const { sql , params , method } = req .body;
// 다중 쿼리 방지
const sqlBody = sql .replace ( /;/ g , '' );
try {
const result = await connection .query ({
sql : sqlBody ,
values : params ,
rowsAsArray : method === 'all' ,
typeCast : function (field : any , next : any ) {
if ( field .type === 'TIMESTAMP' || field .type === 'DATETIME' || field .type === 'DATE' ) {
return field .string ();
}
return next ();
} ,
});
} catch (e : any ) {
res .status ( 500 ) .json ({ error : e });
}
if (method === 'all' ) {
res .send (result[ 0 ]);
} else if (method === 'execute' ) {
res .send (result);
}
res .status ( 500 ) .json ({ error : '알 수 없는 메서드 값' });
});
app .listen (port , () => {
console .log ( `예제 앱이 포트 ${ port } 에서 실행 중입니다.` );
});
}
main ();
import { drizzle } from 'drizzle-orm/sqlite-proxy' ;
const db = drizzle ( async (sql , params , method) => {
try {
const rows = await axios .post ( 'http://localhost:3000/query' , { sql , params , method });
return { rows : rows .data };
} catch (e : any ) {
console .error ( 'sqlite 프록시 서버 오류: ' , e . response .data)
return { rows : [] };
}
});
배치 지원
Sqlite 프록시는 다른 드라이버와 마찬가지로 배치 요청을 지원합니다. 전체 문서 를 확인하세요.
배치 쿼리를 위한 특정 콜백을 지정하고 프록시 서버에 요청을 처리해야 합니다:
import { drizzle } from 'drizzle-orm/sqlite-proxy' ;
type ResponseType = { rows : any [][] | any [] }[];
const db = drizzle ( async (sql , params , method) => {
// 단일 쿼리 로직. 위 코드와 동일
} , async (queries : { sql : string , params : any [] , method : 'all' | 'run' | 'get' | 'values' }[]) => {
try {
const result : ResponseType = await axios .post ( 'http://localhost:3000/batch' , { queries });
return result;
} catch (e : any ) {
console .error ( 'sqlite 프록시 서버 오류:' , e);
throw e;
}
});
그런 다음 db.batch([])
메서드를 사용할 수 있으며, 이 메서드는 모든 쿼리를 프록시로 전달합니다.
배치 응답은 프록시 서버로 전송된 순서대로 원시 값(배열 내 배열)의 배열이어야 합니다.
모든 SQL 쿼리를 직접 작성할 계획이 아니라면, 테이블 선언이 도움이 됩니다:
import { sql } from "drizzle-orm" ;
import { text , integer , sqliteTable } from "drizzle-orm/sqlite-core" ;
const users = sqliteTable ( 'users' , {
id : text ( 'id' ) ,
textModifiers : text ( 'text_modifiers' ) .notNull () .default ( sql `CURRENT_TIMESTAMP` ) ,
intModifiers : integer ( 'int_modifiers' , { mode : 'boolean' }) .notNull () .default ( false ) ,
});
컬럼 타입에 대한 자세한 내용은 **Drizzle의 SQLite 컬럼 타입 **을 참조하세요.