pg 패키지)는 Node.js에서 가장 널리 사용되는 Postgres 드라이버입니다. 이 가이드에서는 TLS 인증서를 완전하게 검증하는 pg.Pool을 사용해 ClickHouse Managed Postgres에 연결하고, 테이블 2개를 생성한 다음, 트랜잭션(transaction) 내에서 계좌 간 자금을 이체하고, 간단한 node:http 서버로 데이터를 제공합니다.
사전 요구 사항
- Node.js 20.6 이상(내장
--env-file플래그를 사용하기 위해 필요). 이 가이드는 Node.js 24.21.0 및pg8.23.1 환경에서 테스트되었습니다. - ClickHouse Cloud 계정
- 데이터베이스 생성에 사용할
psql
ClickHouse Managed Postgres 서비스 생성
ClickHouse Cloud 콘솔에서 New service를 클릭한 후 Postgres를 선택하십시오. 몇 분 후면 인스턴스가 준비됩니다. 단계별 안내는 빠른 시작 가이드를 참조하십시오.연결 정보 확인하기
서비스의 왼쪽 사이드바에서 Connect를 클릭합니다. Directly가 선택된 상태에서 url 탭의 연결 URL을 복사합니다. Use SSL은 끈 상태로 두십시오. 애플리케이션은 CA 인증서를 URL이 아닌 코드에서 전달합니다(연결 풀 구성하기 참조). 이 가이드에서는 포트5432를 통해 Postgres에 직접 연결합니다. 장시간 실행되는 Node.js 서버는 이미 pg.Pool로 자체 연결 풀을 유지하므로, Postgres 앞단에 풀러(pooler)를 추가로 둘 필요가 없습니다. 여러 프로세스나 서버리스 함수(serverless function)를 실행한다면 함께 제공되는 PgBouncer를 사용하십시오. 자세한 내용은 PgBouncer 사용하기를 참조하십시오.
다음으로, 인스턴스의 CA 인증서를 다운로드합니다. Use SSL을 켜고 Download CA certificate를 클릭하거나, Settings → CA Certificate → Download CA certificate로 이동하십시오. 인증서는 인스턴스마다 고유합니다.
프로젝트 설정
프로젝트를 생성한 후pg를 설치하십시오.
.mjs 확장자를 사용하는 ES 모듈이므로, package.json에서 CommonJS와 ES 모듈 중 어느 쪽을 사용하든 동작합니다.
데이터베이스 생성
다운로드한<service-name>-ca-certificate.pem 파일을 프로젝트 디렉터리로 옮긴 후 파일 이름을 ca-certificate.pem으로 변경하세요. 그런 다음 앱에서 사용할 데이터베이스를 생성하세요:
guide_nodejs로 변경)과 인증서 경로를 담은 .env 파일을 생성하세요:
.env
@, /, # 등의 문자가 포함되어 있다면 URL에서 해당 문자를 퍼센트 인코딩하십시오.
연결 풀 구성
db.mjs 파일을 생성하십시오. 이 파일은 앱 전체에서 공유하는 단일 풀을 내보냅니다.
db.mjs
ssl: { ca }를 전달하면 sslmode=verify-full과 동일한 효과를 얻을 수 있습니다. 즉, pg는 서버 인증서가 인스턴스의 CA로 서명되었는지, 그리고 호스트명과 일치하는지 확인합니다. rejectUnauthorized의 기본값은 true이며, 이 값을 false로 설정하지 마십시오.
스키마 생성하기
setup.mjs 파일을 생성하십시오. 이 스크립트는 테이블을 생성하고, 매개변수화된 쿼리로 계정 2개를 삽입한 후, 삽입한 계정을 다시 읽어옵니다.
setup.mjs
$1, $2, …)로 전달하십시오. pg는 매개변수를 쿼리 텍스트와 별도로 전송하므로 SQL 인젝션을 방지할 수 있습니다. ANY($1) 쿼리에서 볼 수 있듯이 JavaScript 배열은 Postgres 배열에 매핑됩니다.
다음과 같이 실행합니다:
pg는 정밀도가 손실되지 않도록 numeric(및 bigint) 값을 문자열로 반환합니다. 숫자 값이 필요하면 명시적으로 변환하십시오.
트랜잭션 내에서 쿼리 실행하기
트랜잭션은 단일 연결에서 실행되어야 하므로pool.connect로 클라이언트를 가져오고, 사용 후에는 반드시 해제하십시오. transfer.mjs 파일을 생성하십시오:
transfer.mjs
pool.query를 사용하지 마십시오. pool.query를 호출할 때마다 서로 다른 연결에서 실행될 수 있습니다.
HTTP로 데이터 제공하기
server.mjs 파일을 생성하십시오. 이 서버는 포트 3107에서 계정 및 이체 내역을 JSON으로 제공하고, 새로운 이체 요청을 받아 처리하며, SIGINT(Ctrl+C) 또는 SIGTERM 신호를 받으면 정상적으로 종료됩니다.
server.mjs
pool.end는 요청마다 호출하지 말고, 프로세스가 종료될 때 한 번만 호출하십시오. 이 메서드는 체크아웃된 클라이언트가 모두 반환될 때까지 기다린 다음 모든 연결을 닫습니다.
확인
서버를 시작합니다:alice의 잔액에서 금액을 차감한 상태였지만, ROLLBACK으로 이 변경이 취소되었습니다. 브라우저에서 http://localhost:3107/accounts를 열어 잔액을 확인하십시오. 응답은 다음과 같습니다:
pg_stat_ssl을 조회하는 쿼리를 실행하십시오:
DATABASE_CA_CERT가 다른 인증서를 가리키도록 설정하면 unable to verify the first certificate 오류와 함께 연결이 실패합니다. 이를 통해 서버 인증서가 실제로 검증된다는 것을 알 수 있습니다.
마지막으로 Ctrl+C를 눌러 서버를 중지하십시오. SIGINT received, shutting down에 이어 Pool closed가 출력됩니다.
콘솔에서도 데이터를 확인할 수 있습니다. SQL 콘솔을 열고 guide_nodejs 데이터베이스를 펼친 다음 accounts 테이블을 여십시오.
PgBouncer 사용
번들로 제공되는 PgBouncer를 통해 연결하려면 Connect 모달에서 via PgBouncer를 선택하고DATABASE_URL의 포트를 6432로 지정하십시오. 코드는 변경할 필요가 없으며, 기존 CA 인증서도 그대로 사용할 수 있습니다.
PgBouncer는 트랜잭션 풀링(transaction pooling) 모드로 실행되므로, 트랜잭션마다 서로 다른 Postgres 연결에서 실행될 수 있습니다. pg에서는 다음 사항에 유의하십시오.
- 매개변수화된 쿼리, 이름이 지정된 prepared statement(
pool.query({ name, text, values })),pool.connect를 사용하는 트랜잭션은 이 가이드에서 설명한 대로 동작합니다. - SQL 수준의
PREPARE,EXECUTE와SET으로 지정한 세션 설정은 트랜잭션 간에 유지되지 않습니다. 대신 트랜잭션 내에서SET LOCAL을 사용하십시오. pg_stat_ssl은 PgBouncer와 Postgres 사이의 연결 정보를 보여 주므로, 앞에서 설명한 TLS 확인 쿼리는ssl: false를 반환합니다. 그러나 애플리케이션과 PgBouncer 간의 연결은 여전히 검증되므로, 잘못된 CA 인증서를 사용하면 마찬가지로 연결에 실패합니다.