콘텐츠로 이동

Python 관계형 데이터베이스

이 생성기는 Amazon Aurora (PostgreSQL 또는 MySQL), 데이터 모델링을 위한 SQLModel, 스키마 마이그레이션을 위한 Alembic을 기반으로 하는 새로운 Python 관계형 데이터베이스 프로젝트를 생성합니다. AWS CDK 또는 Terraform을 사용하여 데이터베이스를 프로비저닝하고 관리하는 데 필요한 애플리케이션 코드와 인프라를 생성하며, 선언적 스키마 정의, 자동 마이그레이션 배포 및 데이터베이스 클라이언트를 제공합니다.

  1. 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
  2. VSCode에서 Nx 콘솔 열기
  3. 클릭 Generate (UI) "Common Nx Commands" 섹션에서
  4. 검색 @aws/nx-plugin - py#rdb
  5. 필수 매개변수 입력
    • 클릭 Generate
    매개변수타입기본값설명
    name 필수string-생성할 데이터베이스 프로젝트의 이름
    directory stringpackages애플리케이션을 저장할 디렉토리입니다.
    subDirectory string-프로젝트가 배치되는 하위 디렉토리입니다. 기본값은 프로젝트 이름입니다.
    infra aurora | noneaurora프로비저닝할 관계형 데이터베이스 서비스입니다.
    engine postgres | mysqlpostgres선택한 서비스와 함께 사용할 데이터베이스 엔진입니다.
    databaseUser stringdbadmin데이터베이스 관리자 사용자 이름입니다. 기본값은 'dbadmin'입니다.
    databaseName string-초기 데이터베이스 이름입니다. 기본값은 프로젝트 이름입니다.
    framework sqlmodelsqlmodel생성된 프로젝트에 사용할 ORM 프레임워크입니다.
    iac inherit | cdk | terraforminherit선호하는 IaC 공급자입니다. 기본적으로 초기 선택에서 상속됩니다.
    preferInstallDependencies booleantrue제너레이터 실행 후 의존성 설치를 선호할지 여부입니다. 여러 제너레이터를 일괄 처리할 때 설치를 연기하려면 false로 설정하세요(후속 제너레이터가 Nx 프로젝트 그래프를 계산할 수 있도록 필요한 경우 설치는 여전히 실행됩니다). 마지막에 한 번 설치하세요.

    생성기는 <directory>/<name> 디렉토리에 다음과 같은 프로젝트 구조를 생성합니다:

    • 디렉터리<name>
      • __init__.py 패키지 내보내기 (get_engine, session_context)
      • connection.py IAM 인증을 사용하는 데이터베이스 엔진 및 세션 팩토리
      • utils.py 런타임 구성 및 로컬 개발 헬퍼
      • migration_handler.py 배포 중 Alembic 마이그레이션을 실행하는 Lambda 핸들러
      • create_db_user_handler.py 배포 중 애플리케이션 데이터베이스 사용자를 생성하는 Lambda 핸들러
      • 디렉터리models
        • example.py 예제 SQLModel 테이블 정의
    • 디렉터리migrations
      • versions Alembic이 생성한 마이그레이션 스크립트
      • env.py Alembic 환경 (데이터베이스에 연결)
      • script.py.mako Alembic 마이그레이션 스크립트 템플릿
    • alembic.ini Alembic 구성
    • config.json 로컬 개발 연결 세부 정보 및 런타임 구성 키
    • Dockerfile.migration 마이그레이션 핸들러용 컨테이너 이미지
    • Dockerfile.create-db-user create-db-user 핸들러용 컨테이너 이미지
    • project.json 프로젝트 구성 및 빌드 타겟

    로컬 개발 스크립트는 모든 데이터베이스 프로젝트에서 공유되며 packages/common/scripts/에 생성됩니다:

    • 디렉터리packages/common/scripts/src/rdb
      • pull-image.ts 데이터베이스 컨테이너 이미지를 가져옵니다
      • start-container.ts 로컬 데이터베이스 컨테이너를 시작합니다
      • wait-for-postgres-db.ts 로컬 데이터베이스가 준비될 때까지 대기합니다 (PostgreSQL)
      • wait-for-mysql-db.ts 로컬 데이터베이스가 준비될 때까지 대기합니다 (MySQL)

    이 생성기는 선택한 iacProvider 기반으로 인프라를 코드 형태로 제공하므로, packages/common 디렉터리에 관련 CDK 구축 요소 또는 Terraform 모듈을 포함하는 프로젝트를 생성합니다.

    공통 인프라스트럭처 코드 프로젝트의 구조는 다음과 같습니다:

    • 디렉터리packages/common/constructs
      • 디렉터리src
        • 디렉터리app/ 특정 프로젝트/생성기에 종속적인 인프라를 위한 구축 요소
        • 디렉터리core/ app 내 구축 요소에서 재사용되는 일반적 구축 요소
        • index.ts app의 구축 요소를 익스포트하는 진입점
      • project.json 프로젝트 빌드 대상 및 구성
    • 디렉터리packages/common/constructs/src
      • 디렉터리app
        • 디렉터리dbs
          • <name>.ts 데이터베이스에 특화된 인프라
      • 디렉터리core
        • 디렉터리rdb
          • aurora.ts 범용 Aurora 데이터베이스 구성

    배포된 데이터베이스는 다음과 같은 아키텍처를 가지고 있습니다. 기본적으로 Amazon RDS Proxy가 Aurora 클러스터 앞에 위치하여 연결을 풀링하고 IAM 인증을 활성화합니다 — 대안은 RDS Proxy 비활성화를 참조하세요. PostgreSQL 또는 MySQL 엔진을 선택하더라도 아키텍처는 동일하며, Aurora 엔진 종류만 다릅니다.

    Application(Lambda, Agent, ...)RDS ProxyMigrations LambdaAurora(PostgreSQL or MySQL)Secrets Manager(DB credentials) SQL (IAM auth) Schema migrations Admin credentials

    생성된 프로젝트는 SQLModel을 사용하여 데이터베이스 스키마를 정의합니다. 워크플로는 모델 우선입니다: 데이터베이스 프로젝트의 <name>/models/ 디렉토리 아래에 SQLModel 테이블 클래스를 추가하거나 업데이트한 다음, 해당 모델 변경 사항에서 마이그레이션을 생성합니다.

    예제 모델:

    packages/my_db/my_db/models/example.py
    from sqlalchemy import Column, String
    from sqlmodel import Field, SQLModel
    class ExampleModel(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(sa_column=Column(String(255), nullable=False))
    description: str | None = Field(default=None, sa_column=Column(String(255), nullable=True))

    Alembic이 자동 생성 중에 모델을 발견할 수 있도록 <name>/models/__init__.py에서 모델을 가져옵니다.

    모델을 추가하거나 업데이트한 후 Alembic을 사용하여 마이그레이션 스크립트를 생성하고 적용합니다. 생성된 alembic 타겟은 실행 전에 자동으로 로컬 데이터베이스 컨테이너를 시작합니다:

    Terminal window
    pnpm nx run <project>:alembic revision --autogenerate -m "describe your change"

    이렇게 하면 migrations/versions/ 아래에 새 마이그레이션 스크립트가 생성됩니다. 적용하기 전에 생성된 스크립트를 검토하세요.

    로컬 데이터베이스에 마이그레이션을 적용합니다:

    Terminal window
    pnpm nx run <project>:migrate

    AWS 스택을 배포하면 생성된 인프라가 배포된 데이터베이스에 생성된 마이그레이션을 자동으로 적용합니다.

    다른 개발자가 생성한 마이그레이션 파일을 가져올 때 로컬 데이터베이스에 적용합니다:

    Terminal window
    pnpm nx run <project>:migrate

    생성된 alembic 타겟은 Alembic CLI를 노출하므로 로컬 데이터베이스에 대해 모든 Alembic 명령을 실행할 수 있습니다. 사용 가능한 명령은 Alembic 명령 참조를 참조하세요.

    Terminal window
    pnpm nx run <project>:alembic <alembic-command>

    dev를 중지하면 (예: Ctrl+C로) 로컬 데이터베이스 컨테이너가 자동으로 제거되지만, 명명된 볼륨은 보존되므로 재시작 시에도 데이터가 유지됩니다.

    데이터베이스 패키지에서 session_context를 가져와서 비동기 컨텍스트 매니저로 사용하여 AsyncSession을 얻습니다:

    from sqlmodel import select
    from my_scope.my_db import session_context
    from my_scope.my_db.models.example import ExampleModel
    async def example():
    async with session_context() as session:
    results = (await session.execute(select(ExampleModel))).all()

    데이터베이스 클라이언트는 자동으로:

    • RUNTIME_CONFIG_APP_ID 환경 변수를 사용하여 AWS AppConfig에서 데이터베이스 구성을 검색합니다
    • IAM 인증을 위해 boto3 RDS Signer를 통해 임시 인증 토큰을 생성합니다
    • ssl.create_default_context()를 사용하여 TLS 연결을 설정합니다

    관계형 데이터베이스 생성기는 선택한 iacProvider에 따라 CDK 또는 Terraform 인프라를 생성합니다.

    CDK 구성은 common/constructs에 생성됩니다. 사용 예시:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    export class ApplicationStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    ...
    const db = new MyDatabase(this, 'Db', {
    vpc,
    vpcSubnets: {
    subnetType: SubnetType.PRIVATE_ISOLATED,
    }
    });
    }
    }

    이것은 RDS Proxy가 있는 Aurora 클러스터, 관리자 자격 증명, 애플리케이션 데이터베이스 사용자, 런타임 구성 등록 및 마이그레이션 핸들러를 프로비저닝합니다.

    생성된 인프라는 두 개의 데이터베이스 사용자를 생성합니다:

    • 관리자 사용자 - 클러스터 프로비저닝 중에 생성되며 자격 증명은 AWS Secrets Manager에 저장됩니다
    • 애플리케이션 사용자 - Lambda 사용자 지정 리소스를 통해 생성되며 IAM 인증이 활성화되고 애플리케이션 데이터베이스에 대한 DML 권한(SELECT, INSERT, UPDATE, DELETE)을 가집니다

    애플리케이션 사용자는 임의의 이름과 IAM 인증으로 자동 생성됩니다. 생성된 데이터베이스 클라이언트는 이미 단기 RDS 토큰을 사용하여 이 사용자로 인증하도록 구성되어 있으므로 애플리케이션 코드는 데이터베이스 비밀번호를 처리할 필요가 없습니다.

    VPC에는 퍼블릭 서브넷, 이그레스가 있는 프라이빗 서브넷, 프라이빗 격리 서브넷이 포함되어야 합니다. 데이터베이스는 프라이빗 격리 서브넷에서 실행될 수 있으며, 애플리케이션 Lambda 함수는 AppConfig와 같은 AWS 서비스에 도달할 수 있도록 이그레스가 있는 프라이빗 서브넷에서 실행되어야 합니다.

    packages/infra/src/stacks/application-stack.ts
    const vpc = new Vpc(this, 'Vpc', {
    subnetConfiguration: [
    {
    name: 'public',
    subnetType: SubnetType.PUBLIC,
    },
    {
    name: 'private_with_egress',
    subnetType: SubnetType.PRIVATE_WITH_EGRESS,
    },
    {
    name: 'private_isolated',
    subnetType: SubnetType.PRIVATE_ISOLATED,
    },
    ],
    });

    connection 생성기를 사용하여 프로젝트를 이 데이터베이스에 연결하세요 — 데이터베이스에 도달하는 데 필요한 인프라 연결에 대해서는 관련 컴퓨팅 유형(예: FastAPI, MCP 서버, 에이전트)에 대한 연결 가이드를 참조하세요.

    생성된 인프라에는 기본적으로 RDS Proxy가 포함되어 있으며, 이는 애플리케이션과 Aurora 클러스터 사이에 위치합니다. RDS Proxy는 다음과 같은 여러 이점을 제공합니다:

    • 연결 풀링 - 애플리케이션 인스턴스 간에 공유할 수 있는 데이터베이스 연결 풀을 유지하여 새 연결 설정의 오버헤드를 줄입니다
    • 연결 복원력 - Aurora 인스턴스 교체 또는 유지 관리 중 장애 조치 및 재연결을 자동으로 처리합니다
    • IAM 인증 - IAM 기반 데이터베이스 인증을 지원하여 애플리케이션 코드에서 데이터베이스 자격 증명을 관리할 필요가 없습니다
    • 향상된 보안 - 모든 연결에 대해 TLS 암호화를 적용합니다

    다음과 같이 RDS 프록시를 비활성화할 수 있습니다:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableRdsProxy: false,
    });

    RDS Proxy가 비활성화되면 애플리케이션이 Aurora 클러스터 엔드포인트에 직접 연결됩니다.

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

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

    Amazon RDS CA 번들은 런타임의 시스템 신뢰 저장소에 있어야 합니다.

    ADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /etc/pki/ca-trust/source/anchors/global-bundle.pem
    RUN update-ca-trust

    zip으로 배포된 Lambda 함수(예: py#api FastAPI)의 경우, Amazon Linux 2023 Lambda 실행 환경의 내장 CA 신뢰 저장소에는 RDS에서 사용하는 Amazon Root CA가 포함되어 있습니다.

    RDS Proxy를 사용하는 경우 데이터베이스에 연결하는 런타임에서 RDS CA 번들을 구성할 필요가 없습니다.

    Aurora 클러스터의 writer 및 reader 인스턴스를 구성합니다.

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    writer: ClusterInstance.serverlessV2('writer'),
    readers: [ClusterInstance.serverlessV2('reader')],
    });

    워크로드에 맞게 Aurora Serverless v2 스케일링 제한을 제어합니다.

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    serverlessV2MinCapacity: 0.5,
    serverlessV2MaxCapacity: 8,
    });

    특정 Aurora 엔진 버전을 고정합니다.

    기본적으로 생성된 로컬 데이터베이스 컨테이너 이미지는 기본 Aurora 엔진 버전과 일치합니다. Aurora 엔진 버전을 변경하는 경우, 최대 호환성을 위해 일치하는 로컬 컨테이너 이미지 버전을 사용하는 것이 권장됩니다. 해당하는 커뮤니티 데이터베이스 버전을 확인하려면 Aurora PostgreSQL 버전Aurora MySQL 버전에 대한 AWS 릴리스 노트를 참조하세요.

    로컬 데이터베이스 이미지는 데이터베이스 프로젝트 루트에 생성된 config.json 파일의 localDev.image 필드에서 구성됩니다. 엔진 버전을 변경할 때 해당 값을 업데이트하세요.

    engine = postgres
    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    engineVersion: AuroraPostgresEngineVersion.VER_17_7,
    });
    engine = mysql
    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,
    });

    삭제 방지는 기본적으로 활성화되어 있으며(CDK에서 deletionProtection: true, Terraform에서 deletion_protection = true) Aurora 클러스터를 실수로 인한 삭제로부터 보호합니다.

    단기 개발 환경이나 프리뷰 스택과 같이 데이터베이스 삭제가 예상되는 환경에서는 삭제 방지를 비활성화할 수 있습니다.

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    deletionProtection: false,
    });

    CDK 구성은 기본적으로 Aurora 클러스터를 유지합니다 (removalPolicy: RemovalPolicy.RETAIN). CDK 스택 삭제 시 클러스터를 스냅샷하거나 삭제하려면 이 설정을 변경하세요.

    RemovalPolicy.DESTROY를 사용할 때는 클러스터를 삭제하기 전에 삭제 보호도 비활성화해야 합니다.

    packages/infra/src/stacks/application-stack.ts
    import { RemovalPolicy } from 'aws-cdk-lib';
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    removalPolicy: RemovalPolicy.SNAPSHOT,
    });

    스택과 함께 데이터베이스를 삭제해야 하는 임시 환경의 경우:

    packages/infra/src/stacks/application-stack.ts
    import { RemovalPolicy } from 'aws-cdk-lib';
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    deletionProtection: false,
    removalPolicy: RemovalPolicy.DESTROY,
    });

    Performance Insights는 기본적으로 Aurora 라이터 인스턴스에서 활성화됩니다(클러스터의 KMS 키로 암호화됨). Aurora 엔진 로그를 CloudWatch Logs로 내보낼 수도 있습니다(Aurora PostgreSQL의 경우 postgresql; Aurora MySQL의 경우 audit, error, generalslowquery). 데이터베이스별로 로그 내보내기를 활성화하세요:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableCloudwatchLogs: true,
    enablePerformanceInsights: false, // disable if not required
    });

    Aurora 클러스터와 자격 증명 시크릿을 암호화하는 데 사용되는 KMS 키는 기본적으로 자동 키 교체가 활성화되어 있습니다. 보안 정책에서 외부적으로 교체를 관리하는 경우 이를 비활성화하세요.

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableKeyRotation: false,
    });

    connection 생성기를 사용하여 이 프로젝트를 워크스페이스의 다른 프로젝트와 통합합니다. 다음 연결은 이 프로젝트와 관련이 있습니다:

    Strands AgentsPythonAmazon AuroraPython
    Python Agent to Relational DatabasePython Agent를 Aurora 관계형 데이터베이스에 연결
    FastAPIAmazon AuroraPython
    FastAPI to Relational DatabaseFastAPI를 Aurora 관계형 데이터베이스에 연결
    Model Context ProtocolPythonAmazon AuroraPython
    Python MCP Server to Relational DatabasePython MCP Server를 Aurora 관계형 데이터베이스에 연결