@gj-kit/toss-payments-postgresql 레시피
각 코드 블록은 패키지 README에서 이미 타입 검사하는 public-contract 예제를 재사용합니다.
1. 보호된 PostgreSQL store 조립하기
섹션 제목: “1. 보호된 PostgreSQL store 조립하기”payment store를 노출하기 전에 호스트 pool을 adapter에 연결하고 앱 소유 protector를 전달합니다.
완료 상태: 명시적인 migration 단계 하나를 갖는 PostgreSQL 기반 Toss store를 만듭니다.
앱 소유 경계:
fromPgPool로 pool을 adapter에 연결하고 실제 암호화 sensitiveValueProtector를 사용하며, migration은 배포 중에 실행합니다.
import { createTossPaymentsPostgres, fromPgPool, type PgPoolLike, type SensitiveValueProtector } from '@gj-kit/toss-payments-postgresql';
declare const pool: PgPoolLike;declare const sensitiveValueProtector: SensitiveValueProtector; // App KMS/encryption boundary.
export const stores = createTossPaymentsPostgres({ sql: fromPgPool(pool), sensitiveValueProtector,});
// Run await stores.migrate() once in deployment, never per request.2. opaque lock key 뒤에서 billing data 변경하기
섹션 제목: “2. opaque lock key 뒤에서 billing data 변경하기”raw customer identifier를 storage에 넘기지 말고 branded opaque key와 제공된 lock 순서를 사용합니다.
protector는 빠뜨릴 수 있는 옵션이 아니고, raw 식별자는 lock key 자리에 들어가지 못합니다. 둘 다 DB에 닿기 전에 tsc가 TS2345로 거부합니다. 두 lock을 함께 잡는 API도 withOpaqueMutationLock 하나뿐이라, opaque → customer 순서는 호출자가 정할 여지가 없습니다.
import type { Pool } from 'pg';import type { BillingKeyRecord } from '@gj-kit/toss-payments/server';import { createAes256GcmSensitiveValueProtector, createOpaqueAdvisoryLockKey, createTossPaymentsPostgres, fromPgPool } from '@gj-kit/toss-payments-postgresql';
declare const pool: Pool; // app owns the pg Pooldeclare const keyHex: string; // app owns key custody and rotationdeclare const blindIndex: string; // app owns the blind index of the customer iddeclare const record: BillingKeyRecord; // app owns the freshly issued billing key
export const pg = createTossPaymentsPostgres({ sql: fromPgPool(pool), sensitiveValueProtector: createAes256GcmSensitiveValueProtector({ key: keyHex, keyId: '2026-08' }),});// Without sensitiveValueProtector: TS2345 '{ sql: SqlClient; }' is not assignable to 'TossPaymentsPostgresOptions'.
export const previous = await pg.billingKeys.withOpaqueMutationLock( createOpaqueAdvisoryLockKey(blindIndex), // raw blindIndex: TS2345 'string' is not assignable to 'OpaqueAdvisoryLockKey' record.customerKey, (mutation) => mutation.replaceAndGetPrevious(record),);전체 API reference에서 모든 export와 import path를 확인하세요.