- pgmock는 단위 테스트와 E2E 테스트를 위한 인메모리 PostgreSQL 모의 서버이며, 외부 의존성 없이 Node.js와 브라우저에서 WebAssembly로 실행됨
node-postgres 사용자는 포트를 열지 않는 설정 객체를 받아 연결할 수 있고, 이 방식은 브라우저에서도 동작함
- 브라우저에서는 웹앱이 TCP 포트를 열 수 없지만
PostgresMock.createSocket과 node-postgres 설정을 사용할 수 있으며, 번들러가 정적 import를 분석하면 선택적 Node.js 모듈 경고가 날 수 있음
- 구현은 현재 x86 에뮬레이터 안에서 PostgreSQL 서버를 실행하는 방식을 쓰며, 테스트와 프로덕션 간 동작 차이 방지를 성능보다 우선함
- 장기적으로는 네이티브 PostgreSQL WASM 포크가 성숙하면 두 방식을 모두 제공하고, 이후 네이티브 WASM을 기본값으로 전환할 계획이 있음
pgmock가 제공하는 것
- pgmock는 단위 테스트와 E2E 테스트용 인메모리 PostgreSQL 모의 서버임
- 외부 의존성이 필요 없고, Node.js와 브라우저 양쪽에서 WebAssembly 안에서 실행됨
- 설치는 npm으로 가능함
npm install pgmock
기본 사용 흐름
- 인메모리 서버는
PostgresMock.create()로 만들고, listen(5432)로 연결 문자열을 받을 수 있음
import { PostgresMock } from "pgmock";
const mock = await PostgresMock.create();
const connectionString = await mock.listen(5432);
node-postgres를 쓰는 경우 mock.getNodePostgresConfig()가 포트 리스닝 없이 연결할 수 있는 설정 객체를 제공함
- 작업이 끝나면 리소스를 해제하기 위해
mock.destroy()를 호출하는 방식이 권장됨
mock.destroy();
브라우저 지원과 pglite와의 차이
pgmock는 브라우저 환경을 완전히 지원함
- 웹앱은 TCP 포트를 열 수 없지만,
PostgresMock.createSocket과 node-postgres 설정을 사용할 수 있음
- 번들러가 import를 정적으로 분석하면 선택적 Node.js 모듈이 없다는 경고가 날 수 있으며, Webpack 설정 예시는
examples/web-demo/next.config.mjs에 있음
- 브라우저에서 데이터베이스만 실행하려는 경우 pglite를 고려할 수 있음
- pglite는 더 빠르고 가볍지만 기능 집합이 제한적임
pgmock는 테스트 환경에서 원하는 프로덕션 PostgreSQL과의 기능 동등성을 목표로 설계됨
WebAssembly에서 PostgreSQL을 실행하는 방식
- WebAssembly에서 PostgreSQL을 실행하는 방식은 두 가지가 있음
- 네이티브 WASM 포크 방식은 더 빠르고 메모리를 훨씬 적게 쓰지만, 단일 사용자 모드만 지원하고 연결과 확장을 지원하지 않음
pgmock는 현재 x86 에뮬레이터 방식을 사용함
- 테스트와 프로덕션 간 불일치를 막는 것이 목적임
- 테스트에서는 성능이 보통 큰 문제가 아니기 때문임
- 중기적으로 네이티브 PostgreSQL WASM 포크가 성숙하면 두 옵션을 모두 제공할 계획임
- 이후에는 네이티브 WASM을 기본값으로 전환할 계획이며,
PostgresMock.subtle 내부 API 외에는 큰 breaking change가 많지 않을 것으로 예상함
기존 브라우저 PostgreSQL 프로젝트와의 차이
pgmock는 JavaScript 런타임 안에서 전체 기능 호환성을 제공하며, 통신을 위해 네트워크 프록시에 의존하지 않음
- JavaScript로 네트워크 스택을 시뮬레이션해 실제 네트워크처럼 동작하게 만들고, raw socket 접근을 허용하지 않는 플랫폼에서도 TCP 연결을 시뮬레이션할 수 있음
확장 가능성과 관련 프로젝트
- 다른 Docker 이미지나 데이터베이스도 이론적으로 실행 가능하지만 테스트되지는 않았음
- 관련 구현과 기반 프로젝트로 다음이 언급됨