콘텐츠로 이동

tRPC API에서 관계형 데이터베이스로

connection 생성기는 tRPC API관계형 데이터베이스 프로젝트에 연결하여, 프로시저 컨텍스트에서 Prisma 클라이언트를 사용할 수 있게 하는 타입 안전 tRPC 미들웨어 플러그인을 생성합니다.

이 생성기를 사용하기 전에 다음이 필요합니다:

  1. tRPC API 프로젝트 (ts#api로 생성)
  2. ts#rdb 프로젝트
Terminal window
pnpm nx g @aws/nx-plugin:connection
어떤 파일이 변경될지 확인하기 위해 드라이 런을 수행할 수도 있습니다
Terminal window
pnpm nx g @aws/nx-plugin:connection --dry-run

tRPC API 프로젝트를 소스로, 관계형 데이터베이스 프로젝트를 타겟으로 선택하세요.

매개변수타입기본값설명
sourceProject 필수string-소스 프로젝트
targetProject 필수string-연결할 대상 프로젝트
sourceComponent string-연결을 시작할 소스 컴포넌트 (컴포넌트 이름, 소스 프로젝트 루트 기준 상대 경로, 또는 generator id). 프로젝트를 소스로 명시적으로 선택하려면 '.'을 사용하세요.
targetComponent string-연결할 대상 컴포넌트 (컴포넌트 이름, 대상 프로젝트 루트 기준 상대 경로, 또는 generator id). 프로젝트를 대상으로 명시적으로 선택하려면 '.'을 사용하세요.
preferInstallDependencies booleantrue생성기 실행 후 의존성 설치를 선호할지 여부입니다. 여러 생성기를 일괄 처리할 때 설치를 연기하려면 false로 설정하세요 (후속 생성기가 Nx 프로젝트 그래프를 계산할 수 있도록 필요한 경우 설치는 여전히 실행됩니다); 마지막에 한 번만 설치합니다.

생성기는 tRPC API 프로젝트에 미들웨어 파일을 생성합니다:

  • 디렉터리packages/api/src
    • 디렉터리middleware
      • <db-name>.ts 프로시저 컨텍스트에서 Prisma 클라이언트를 노출하는 tRPC 플러그인

또한 tRPC API의 dev 타겟을 업데이트하여 로컬에서 실행할 때 데이터베이스가 자동으로 시작되도록 합니다.

생성된 플러그인을 tRPC 라우터에 추가하여 이를 사용하는 모든 프로시저가 데이터베이스에 액세스할 수 있도록 합니다:

packages/api/src/router.ts
import { t } from './init.js';
import { createMyDbPlugin } from './middleware/my-db.js';
export const authenticatedProcedure = t.procedure
.concat(createMyDbPlugin());

프로시저에서 데이터베이스 액세스

섹션 제목: “프로시저에서 데이터베이스 액세스”

플러그인은 IMyDbContext를 프로시저 컨텍스트에 병합하여 myDb를 선택적 속성으로 사용할 수 있게 합니다:

packages/api/src/procedures/users.ts
import { z } from 'zod';
import { authenticatedProcedure } from '../router.js';
export const listUsers = authenticatedProcedure
.output(z.array(z.object({ id: z.string(), name: z.string() })))
.query(async ({ ctx }) => {
// ctx.myDb is the Prisma client — typed as Awaited<ReturnType<typeof getPrisma>>
return await ctx.myDb!.user.findMany();
});

타겟 데이터베이스가 MySQL 엔진을 사용하는 경우, 생성된 미들웨어는 opts.next()try/finally 블록으로 감싸서 $disconnect()를 호출합니다:

packages/api/src/middleware/my-db.ts
return t.procedure.use(async (opts) => {
const myDb = await getPrisma();
try {
return await opts.next({ ctx: { ...opts.ctx, myDb } });
} finally {
await myDb.$disconnect();
}
});

이는 MySQL 어댑터가 쿼리 후 Node.js 이벤트 루프를 열어두는 문제를 해결합니다. 이 문제는 Lambda가 스트리밍 응답을 플러시하는 것을 방해할 수 있습니다. finally에서 연결을 해제하면 이벤트 루프가 해제되어 응답이 완료될 수 있습니다. 자세한 내용은 MySQL: API Gateway 스트리밍 모드를 참조하세요.

PostgreSQL은 이 작업이 필요하지 않습니다. 해당 어댑터는 allowExitOnIdle: true로 구성된 연결 풀을 사용합니다.

다른 타겟으로 생성기를 다시 실행하여 추가 데이터베이스를 연결할 수 있습니다. 각 데이터베이스는 자체 플러그인과 컨텍스트 인터페이스를 갖습니다:

packages/api/src/router.ts
export const dbProcedure = t.procedure
.concat(createMyDbPlugin())
.concat(createOtherDbPlugin());

런타임에 API가 데이터베이스에 연결할 수 있도록 하려면, API Lambda 함수가 데이터베이스와 동일한 VPC에 배포되어야 하며 네트워크 및 IAM 액세스 권한이 부여되어야 합니다.

애플리케이션 스택에서 API를 데이터베이스와 동일한 VPC에 배포한 다음, allowDefaultPortFromgrantConnect를 호출하여 네트워크 경로를 열고 각 Lambda 핸들러에 IAM rds-db:connect 권한을 부여합니다:

packages/infra/src/stacks/application-stack.ts
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { vpc, ... });
const api = new MyApi(this, 'Api', {
integrations: MyApi.defaultIntegrations(this)
.withDefaultOptions({
vpc,
vpcSubnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS },
})
.build(),
});
Object.entries(api.integrations).forEach(([operation, integration]) => {
db.allowDefaultPortFrom(integration.handler, `Allow ${operation} to connect to the database`);
db.grantConnect(integration.handler);
});

API Lambda 함수를 프라이빗 격리 서브넷이 아닌 이그레스가 있는 프라이빗 서브넷에 배포하세요. 런타임에 getPrisma()는 AWS AppConfig에서 데이터베이스 연결 세부 정보를 가져오는데, 이는 아웃바운드 인터넷 액세스가 필요한 퍼블릭 AWS 서비스 엔드포인트입니다.

RDS Proxy 없이 연결할 때 SSL 요구 사항

섹션 제목: “RDS Proxy 없이 연결할 때 SSL 요구 사항”

Node.js 20 이상의 Lambda 런타임에서 Aurora 클러스터에 직접 연결하려면 NODE_EXTRA_CA_CERTS를 설정하여 Amazon RDS CA 번들을 로드하세요:

packages/infra/src/stacks/application-stack.ts
const api = new Api(this, 'Api', {
integrations: Api.defaultIntegrations(this)
.withDefaultOptions({
environment: {
NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
},
})
.build(),
});

자세한 내용은 AWS Lambda Amazon RDS 연결을 위한 SSL/TLS 요구사항 및 Amazon RDS Proxy TLS 문서를 참조하세요. RDS Proxy를 사용하는 경우 Lambda 함수에서 RDS CA 번들을 구성할 필요가 없습니다.

생성기는 tRPC API의 dev 타겟이 데이터베이스의 dev 타겟에 의존하도록 구성하므로 다음을 실행하면:

Terminal window
pnpm nx dev <api-project-name>

API와 함께 로컬 데이터베이스가 자동으로 시작됩니다.