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을 실행하기 위해 비동기 콜백 함수를 간단히 사용하는 것도 지원합니다.

Drizzle는 항상 {rows: string[][]} 또는 {rows: string[]} 형태의 반환 값을 기다립니다.


PostgreSQL
MySQL
SQLite
// 드라이버 구현 예제
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}에서 실행 중입니다.`);
});