콘텐츠로 이동

Smithy API를 관계형 데이터베이스에 연결

connection 생성기는 Smithy API관계형 데이터베이스 프로젝트에 연결하여, 모든 작업 구현이 데이터베이스에 액세스할 수 있도록 서비스 컨텍스트에 Prisma 클라이언트를 주입합니다.

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

  1. ts#smithy-api 프로젝트 (TypeScript 백엔드)
  2. ts#rdb 프로젝트
  1. 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
  2. VSCode에서 Nx 콘솔 열기
  3. 클릭 Generate (UI) "Common Nx Commands" 섹션에서
  4. 검색 @aws/nx-plugin - connection
  5. 필수 매개변수 입력
    • 클릭 Generate

    Smithy API 백엔드 프로젝트를 소스로 선택하고 관계형 데이터베이스 프로젝트를 대상으로 선택합니다.

    매개변수 타입 기본값 설명
    sourceProject 필수 string - 소스 프로젝트
    targetProject 필수 string - 연결할 대상 프로젝트
    sourceComponent string - 연결을 시작할 소스 컴포넌트 (컴포넌트 이름, 소스 프로젝트 루트 기준 상대 경로, 또는 generator id). 프로젝트를 소스로 명시적으로 선택하려면 '.'을 사용하세요.
    targetComponent string - 연결할 대상 컴포넌트 (컴포넌트 이름, 대상 프로젝트 루트 기준 상대 경로, 또는 generator id). 프로젝트를 대상으로 명시적으로 선택하려면 '.'을 사용하세요.

    생성기는 Smithy API 백엔드의 기존 파일 세 개를 수정합니다:

    • 디렉터리packages/api/src
      • context.ts ServiceContextdb 속성 추가
      • handler.ts lambdaHandler 내부에서 Prisma 클라이언트 생성, serviceHandler.handle로 전달
      • local-server.ts 요청 핸들러 내부에서 Prisma 클라이언트 생성, serviceHandler.handle로 전달

    또한 API의 serve-local 타겟을 업데이트하여 데이터베이스를 자동으로 시작합니다.

    생성기는 context.tsServiceContext에 타입이 지정된 db 속성을 추가합니다:

    packages/api/src/context.ts
    import { getPrisma as getMyDb } from ':my-scope/my-db';
    export interface ServiceContext {
    tracer: Tracer;
    logger: Logger;
    metrics: Metrics;
    myDb: Awaited<ReturnType<typeof getMyDb>>;
    }

    Prisma 클라이언트는 lambdaHandler 내부에서 인스턴스화되고 서비스 컨텍스트를 통해 전달됩니다:

    packages/api/src/handler.ts
    import { getPrisma as getMyDb } from ':my-scope/my-db';
    export const lambdaHandler = async (event: APIGatewayProxyEvent) => {
    const httpRequest = convertEvent(event);
    const myDb = await getMyDb();
    const httpResponse = await serviceHandler.handle(httpRequest, {
    tracer,
    logger,
    metrics,
    myDb,
    });
    return convertVersion1Response(httpResponse);
    };

    작업 구현에서 컨텍스트로부터 db에 액세스합니다:

    packages/api/src/operations/list-users.ts
    import { ListUsersOperationInput, ListUsersOperationOutput } from '../generated/ssdk/index.js';
    import { ServiceContext } from '../context.js';
    export const listUsers = async (
    input: ListUsersOperationInput,
    ctx: ServiceContext,
    ): Promise<ListUsersOperationOutput> => {
    const users = await ctx.myDb.user.findMany();
    return { users };
    };

    런타임에 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 서비스 엔드포인트입니다.

    생성기는 local-server.ts의 요청 핸들러 내부에 동일한 Prisma 클라이언트 주입을 적용합니다:

    packages/api/src/local-server.ts
    import { getPrisma as getMyDb } from ':my-scope/my-db';
    const server = createServer(async function (req, res) {
    const httpRequest = convertRequest(req);
    const myDb = await getMyDb();
    const httpResponse = await serviceHandler.handle(httpRequest, {
    tracer,
    logger,
    metrics,
    myDb,
    });
    return writeResponse(httpResponse, res);
    });
    Terminal window
    pnpm nx serve-local <api-project-name>

    이렇게 하면 API와 로컬 데이터베이스가 모두 시작됩니다. SERVE_LOCAL=true 환경 변수가 자동으로 설정되므로 Prisma 클라이언트는 Aurora 대신 로컬 Docker 데이터베이스에 연결됩니다.