AWS 기술 블로그
Amazon Aurora PostgreSQL에서 Amazon Bedrock으로 벡터 임베딩 생성 자동화
본 블로그는 Domenico di Salvia와 Andrea Filippo La Scola가 작성한 블로그인 Automating vector embedding generation in Amazon Aurora PostgreSQL with Amazon Bedrock를 번역, 편집하였습니다.
벡터 임베딩은 생성형 AI를 활용하여 애플리케이션에서 비정형 데이터를 다루는 방식을 근본적으로 변화시켰습니다. 임베딩은 텍스트, 이미지 및 기타 콘텐츠의 본질을 머신이 효율적으로 처리할 수 있는 형태로 변환하는 수학적 표현 방식으로, 시맨틱 검색, 추천 시스템, 그리고 다양한 자연어 처리 작업을 가능하게 합니다.
Retrieval-Augmented Generation (RAG) 또는 기타 AI 기반 솔루션을 활용하는 애플리케이션을 구축하는 조직에게 벡터 임베딩을 최신 상태로 유지하는 것은 필수적입니다. 데이터베이스에 새로운 데이터가 삽입되거나 기존 데이터가 수정될 때, 해당 임베딩이 신속하고 정확하게 생성되도록 보장하는 것이 AI 기반 기능의 품질과 관련성을 유지하는 핵심입니다.
Amazon Bedrock은 임베딩 생성과 검색을 자동으로 처리하는 관리형 RAG 솔루션을 제공하지만, 많은 조직에서는 고유한 요구 사항으로 인해 커스텀 벡터 데이터베이스 솔루션을 직접 구현하는 경우가 있습니다. 이는 오픈 소스 pgvector 확장을 활용한 PostgreSQL을 통해 구현할 수 있습니다. 이러한 요구 사항에는 기존 애플리케이션과의 긴밀한 통합, 특정 성능 최적화, 또는 고유한 데이터 처리 워크플로 등이 포함될 수 있습니다.
이 게시글에서는 Amazon Aurora PostgreSQL 호환 에디션에서 데이터가 삽입되거나 수정될 때 벡터 임베딩 생성을 자동화하는 여러 가지 접근 방식을 살펴봅니다. 각 접근 방식은 복잡성, 지연 시간, 안정성, 확장성 측면에서 서로 다른 트레이드오프를 제공하므로, 여러분의 특정 애플리케이션 요구 사항에 가장 적합한 방식을 선택할 수 있습니다.
솔루션 개요
Aurora PostgreSQL에서 pgvector 확장을 사용하여 벡터 데이터베이스를 구현할 때, 데이터 변경이 발생할 때마다 임베딩을 생성하고 업데이트하는 안정적인 시스템이 필요합니다. 일반적인 워크플로는 다음 단계로 구성됩니다:
- 새로운 데이터 또는 수정된 데이터에 임베딩이 필요한지 감지합니다.
- 해당 콘텐츠를 Amazon Bedrock 임베딩 모델로 전송합니다.
- 생성된 임베딩 벡터를 수신합니다.
- 이러한 벡터를 원본 데이터와 함께 저장합니다.
이 게시글에서는 Amazon Titan foundation model (FM)과 함께 Amazon Bedrock을 사용합니다. Amazon Titan은 추가 인프라를 관리할 필요 없이 프로덕션 수준의 벡터 임베딩을 제공하기 때문입니다. Amazon Titan 임베딩은 텍스트 데이터의 시맨틱 관계를 효과적으로 포착하므로, 데이터가 저장된 곳에서 바로 유사성 검색과 추천 기능을 구현할 수 있습니다.
이 게시글에서는 대부분의 프로덕션 워크로드에 적합한 성능과 간편성의 균형을 제공하는 Amazon Titan을 선택했지만, Amazon Bedrock에서 지원하는 Cohere Embed 또는 Anthropic의 Claude와 같은 다른 모델을 선택할 수도 있습니다. 따라서 특정 시맨틱 검색 또는 문서 검색 요구 사항에 가장 적합한 임베딩 솔루션을 유연하게 선택할 수 있습니다. 또한, 특수한 사용 사례에는 커스텀 모델을 활용한 Amazon SageMaker AI를, 소규모 데이터셋을 다루는 경우에는 Sentence Transformers와 같은 오픈 소스 옵션도 대안으로 고려해 볼 수 있습니다.
사전 준비 사항
이 게시글의 구현 방식을 진행하기 전에 다음 사전 요구 사항을 충족했는지 확인하세요:
- pgvector 확장이 설치된 Aurora PostgreSQL 클러스터
- Amazon Bedrock 액세스를 위한 적절한 AWS Identity and Access Management (IAM) 역할 및 정책 구성
- AWS Lambda 기반 솔루션의 경우, Lambda 함수가 데이터베이스와 Amazon Bedrock 모두에 액세스할 수 있도록 적절한 Virtual Private Cloud (VPC) 구성
aws_ml확장 방식의 경우, 사용 중인 데이터베이스 버전과의 호환성 확인pg_cron의경우, 확장이 활성화되어 있고 올바르게 구성되어 있어야 함
이러한 요구 사항을 충족하는 사전 구성된 환경을 배포하기 위해 GitHub 리포지토리를 사용할 수 있습니다. 이 리포지토리에는 프로비저닝하는 AWS Cloud Development Kit (AWS CDK) 애플리케이션이 다음과 같이 포함되어 있습니다:
- Amazon Aurora Serverless v2 for PostgreSQL 클러스터
- 보안 데이터베이스 액세스 및 마이그레이션 스크립트 실행을 위한 Amazon Elastic Compute Cloud (Amazon EC2) 배스천 호스트
- 데모 접근 방식을 지원하도록 구성된 필수 AWS 인프라 구성 요소:
- Lambda 함수
- Amazon Simple Queue Service (Amazon SQS) 대기열
- 관련 IAM 역할 및 보안 그룹
- 네트워킹 리소스 (VPC, 서브넷, 라우팅 테이블)
자세한 배포 지침 및 이 게시물에서 참조된 소스 코드에 액세스하려면 리포지토리의 README.md 파일을 참조하세요.
구현 접근 방식
이 워크플로를 자동화하기 위한 5가지 구현 접근 방식을 살펴보겠습니다. 각 접근 방식은 고유한 특성을 가지고 있습니다:
- 데이터베이스 트리거와 aws_ml 확장을 사용한 직접 동기 호출은 트랜잭션 중 성능 저하를 감수하는 대신 단순성과 즉각적인 일관성을 제공합니다.
- 데이터베이스 트리거와 aws_lambda 확장을 사용한 AWS Lambda 오케스트레이션 동기 호출은 트랜잭션 중 성능 저하를 감수하는 대신 더 나은 관심사 분리를 제공합니다.
- 이벤트 기반 호출을 사용한 Lambda 오케스트레이션 비동기 호출은 일시적인 데이터 불일치를 감수하는 대신 데이터베이스 성능을 향상시킵니다.
- Amazon SQS와 배치 처리를 사용한 큐 기반 비동기 처리는 아키텍처 구성 요소가 추가되지만, 대용량 시나리오에서 최고 수준의 확장성과 복원력을 제공합니다.
- pg_cron 확장을 사용한 예약 기반 주기적 비동기 업데이트는 실시간 임베딩 업데이트가 필수적이지 않은 애플리케이션에 적합한 간단한 접근 방식을 제공합니다.
테스트를 위해 두 개의 데이터베이스 테이블을 사용합니다:
documents: 제목, 내용, 처리 상태 추적 (PENDING/PROCESSING/COMPLETED/ERROR) 필드와 함께 문서 메타데이터 및 내용을 저장합니다.document_embeddings: 외래 키를 통해 문서에 연결된 벡터 임베딩 (Amazon Titan의 경우 1,536차원)을 저장합니다.
클라이언트 애플리케이션이 documents 테이블에서 텍스트를 저장하고 수정한다고 가정합니다. GitHub 리포지토리에서 이 설정에 대한 참조 코드를 확인할 수 있으며, 리포지토리에는 다음이 포함되어 있습니다:
- Amazon EC2 배스천 호스트와 함께 Aurora Serverless PostgreSQL 데이터베이스를 배포하기 위한 AWS CDK 스택
데이터베이스 스키마에 데이터베이스 확장을 설치하기 위한public스크립트init-public.sql- 각 접근 방식에 대한 AWS CDK, SQL 및 Lambda 코드가 포함된 전용 폴더
이제 5가지 접근 방식을 자세히 살펴보고, 각각의 장점과 한계를 분석해 보겠습니다.
설계 고려 사항
이러한 접근 방식을 프로덕션 환경에 구현할 때는 특정 요구 사항을 신중하게 평가하고, 요구 사항에 가장 적합한 아키텍처를 설계하기 위해 다음 제한 사항을 고려하는 것을 권장합니다:
- API 속도 제한 – Amazon Bedrock에는 모델 및 계정에 따라 다른 속도 제한이 있습니다. 대용량 애플리케이션의 경우 요청 스로틀링 또는 배치 처리가 필요할 수 있습니다.
- 토큰 제한 – 텍스트 임베딩 모델에는 최대 토큰 제한이 있습니다. 매우 긴 텍스트 필드의 경우 이 예제에서 다루지 않는 청킹 전략이 필요할 수 있습니다.
- 비용 영향 – 각 접근 방식은 API 호출 빈도, Lambda 호출 횟수, 사용되는 추가 AWS 서비스에 따라 서로 다른 비용 영향을 미칩니다.
- 지연 시간 요구 사항 – 실시간 임베딩 생성과 시스템 성능 간의 트레이드오프는 애플리케이션 요구 사항과 비즈니스 요구 사항에 따라 평가해야 합니다.
- 데이터베이스 성능 – 동기 방식의 접근 방식은 특히 피크 부하 시 데이터베이스 처리량과 데이터 수집 시간에 영향을 줄 수 있습니다.
- 오류 처리 – 더 복잡한 접근 방식일수록 더 나은 오류 처리 및 재시도 기능을 제공합니다.
접근 방식 1: aws_ml 확장을 사용한 데이터베이스 트리거 (동기식)
이 접근 방식은 PostgreSQL 트리거를 사용하여 데이터 변경을 감지하고, aws_ml 확장을 통해 Amazon Bedrock을 즉시 호출하여 임베딩을 생성합니다. 다음 다이어그램은 이 워크플로를 보여줍니다.
이 트리거는 documents 테이블의 text 열을 모니터링합니다. 콘텐츠가 변경될 때마다 트리거가 store_embedding 함수를 호출하며, 이 함수는 다음 작업을 수행합니다:
generate_embedding함수를 호출하여 벡터 임베딩을 생성합니다.- 임베딩 결과를
document_embeddings테이블에 저장합니다.
generate_embedding 함수는 수정된 텍스트와 레코드 식별자를 파라미터로 전달하여 Amazon Bedrock에 동기 호출을 수행합니다.
이 프로세스와 각 구성 요소 간의 상호 작용을 더 잘 시각화하기 위해, 다음 시퀀스 다이어그램은 단계별 워크플로를 보여줍니다. 이 다이어그램은 데이터와 제어의 흐름을 표현하며, 함수가 Amazon Bedrock과 어떻게 상호 작용하고 임베딩이 어떻게 생성되어 반환되는지를 보여줍니다.
PostgreSQL 트리거는 다음과 같은 특정 데이터베이스 이벤트에 대한 응답으로 자동 실행됩니다:
- 데이터 삽입 (INSERT)
- 기존 레코드 변경 (UPDATE)
이 임베딩 생성 워크플로에서는 content 열에 대한 데이터 삽입 또는 업데이트 이후에 실행되도록 트리거를 구성합니다. 프로젝트 리포지토리의 전용 폴더 01_rds_bedrock에서 예제와 전체 구현을 확인할 수 있습니다.
데이터베이스 트리거는 aws_ml PostgreSQL 확장을 사용하는 함수를 호출합니다. 이 확장은 Aurora 데이터베이스 내에서 직접 Amazon Bedrock에 동기 호출을 수행하는 편리한 방법을 제공합니다. 이를 구현하려면 클러스터에 Amazon Bedrock에 대한 필요한 권한이 연결된 역할이 있는지 확인하세요.
aws_ml 확장의 최소 필수 버전인 2.0을 지원합니다. aws_ml 2.0은 Amazon Bedrock 서비스를 호출하는 데 사용할 수 있는 두 가지 추가 함수를 제공합니다: aws_bedrock.invoke_model과 aws_bedrock.invoke_model_get_embeddings. 다음 코드 스니펫은 데이터베이스 함수 내에서 aws_ml 확장을 사용하고, 그 결과를 활용하여 전용 데이터베이스 테이블에 벡터 임베딩을 저장하는 방법을 보여줍니다:
이 섹션의 접근 방식은 기능을 데이터베이스 워크플로에 통합하여 단순성과 실시간 일관성을 결합합니다. 추가 인프라 없이도 콘텐츠와 벡터 표현이 항상 동기화된 상태를 유지할 수 있습니다.
동기 처리 모델은 트랜잭션 시간에 영향을 미치고 확장성 측면에서 고려 사항이 있지만, 최소한의 개발 노력으로 간단하게 구현할 수 있는 경로를 제공합니다. 다음 표는 이 첫 번째 접근 방식의 추가적인 장단점을 정리한 것입니다.
| 장점 | 단점 |
| 최소한의 구현 방식: 이 솔루션은 이 게시글에서 언급된 다른 솔루션에 비해 가장 적은 구성 요소를 필요로 하며, 외부 서비스나 미들웨어 계층이 불필요하여 디버깅 프로세스가 더 간단합니다. | 트랜잭션 시간 증가: 임베딩 생성이 데이터베이스 트랜잭션 내에서 동기적으로 수행되므로, 삽입 및 업데이트 작업의 완료 시간이 상당히 길어질 수 있습니다. 이로 인해 잠금 경합이 증가하고, 특히 여러 행을 동시에 수정하는 작업에서 애플리케이션 성능에 눈에 띄는 영향을 줄 수 있습니다. |
| 실시간 일관성: 데이터가 기록되는 시점에 임베딩이 생성되며, 데이터베이스 엔진이 벡터 표현이 항상 기본 콘텐츠와 동기화되도록 보장합니다. 이를 통해 오래된 임베딩이 존재하는 시나리오를 줄이고, 콘텐츠 변경 직후 더 정확한 검색 및 추천 결과를 제공합니다. | 타임아웃 위험: 대용량 문서 또는 높은 볼륨의 트랜잭션을 처리할 때, 임베딩 생성에 필요한 시간이 데이터베이스 연결 타임아웃 설정을 초과할 수 있습니다. 이는 상당한 운영 위험을 초래하며, 트랜잭션이 중단될 때 애플리케이션 오류 또는 데이터 불일치를 유발할 수 있습니다. |
| 단순성: 이 아키텍처는 데이터베이스와 Amazon Bedrock 외에 추가 AWS 서비스 없이 운영되므로, 복잡성과 운영 비용을 모두 줄일 수 있습니다. 이는 DevOps 리소스가 제한된 조직에 특히 적합합니다. | 제한적인 오류 복원력: 트리거 기반 접근 방식은 API 오류, 속도 제한, 재시도 로직을 처리하는 기능이 제한적입니다. 임베딩 생성 시도가 실패하면 내장된 대체 메커니즘 없이 중요한 데이터베이스 작업을 차단할 수 있으며, 별도의 커스텀 오류 처리 구현이 필요합니다. |
| 확장성 제한: 임베딩 생성 워크로드가 데이터베이스 쓰기 작업에 비례하여 확장되므로, 데이터베이스 활동과 API 사용 간에 긴밀한 결합이 발생합니다. 트래픽이 많은 시간대에는 Amazon Bedrock API 스로틀링 또는 할당량 초과 문제가 발생하여 데이터베이스 성능에 직접적인 영향을 줄 수 있습니다. |
접근 방식 2: aws_lambda 확장을 사용한 데이터베이스 트리거 (동기식)
이 방식은 PostgreSQL 트리거를 사용하여 Lambda 함수를 동기적으로 호출하고, Lambda 함수가 Amazon Bedrock을 호출하여 임베딩을 생성합니다.
이 접근 방식을 사용하면 다음 프로세스를 통해 새로운 콘텐츠에 대한 임베딩을 자동으로 생성할 수 있습니다:
documents테이블에 새로운 콘텐츠가 삽입되거나 업데이트될 때마다 데이터베이스 트리거가 활성화됩니다.- 새로 삽입되거나 업데이트된 각 행에 대해 시스템이 Lambda 함수를 동기적으로 호출합니다.
- Lambda 함수가 Amazon Bedrock을 사용하여 임베딩을 생성합니다.
- 생성된 임베딩 벡터가 데이터베이스 트리거 함수로 반환됩니다.
- 임베딩 데이터가
document_embeddings테이블에 저장됩니다.
이 과정은 동일한 데이터베이스 트랜잭션 내에서 수행되므로, 데이터베이스와 AI 구성 요소 간의 분리는 유지하면서, 문서는 즉시 처리됩니다.
외부 시스템이 데이터베이스 변경에 반응해야 하는 경우, PostgreSQL 내에서 Lambda 함수를 호출하는 것은 임베딩 벡터 생성 로직을 데이터베이스로부터 분리하는 효과적인 접근 방식이 될 수 있습니다.
Amazon Relational Database Service (Amazon RDS) for PostgreSQL과 Aurora PostgreSQL 호환 에디션 모두 invoke 메서드를 제공하는 aws_lambda 확장을 통해 이 통합을 지원합니다. 이 기능을 통해 중간 폴링 메커니즘이나 추가 애플리케이션 로직이 필요하지 않습니다.
이 접근 방식에서는 aws_lambda PostgreSQL 확장의 invoke 메서드를 RequestResponse 호출 유형 파라미터와 함께 사용합니다. 이를 통해 동기 실행이 가능하므로, 데이터베이스는 후속 작업을 진행하기 전에 Lambda 함수가 응답을 반환할 때까지 대기합니다. 이를 실제 코드로 살펴보겠습니다:
다음 Lambda 함수 코드는 Amazon Bedrock을 통해 Amazon Titan 모델을 호출합니다. 이 패턴은 데이터베이스를 large language model (LLM)로부터 분리하여, 필요에 따라 다양한 API와 서비스를 사용하여 임베딩 벡터를 생성할 수 있는 유연성을 제공합니다.
aws_lambda 확장을 사용한 데이터베이스 트리거 접근 방식은 동기 처리를 유지하면서도 임베딩 생성을 핵심 데이터베이스 기능으로부터 분리합니다. 이 아키텍처는 Lambda를 통해 더 정교한 처리와 향상된 오류 처리를 가능하게 하지만, 여전히 트랜잭션 지속 시간 문제가 있으며 콜드 스타트와 같은 Lambda 고유의 고려 사항이 추가됩니다. 다음 표는 이 두 번째 접근 방식의 추가적인 장단점을 정리한 것입니다.
| 장점 | 단점 |
| 로직 분리: 임베딩 생성 로직을 데이터베이스 코드로부터 분리하여, 각 구성 요소를 독립적으로 업데이트하고 관리할 수 있습니다. | 트랜잭션 차단: Lambda 실행과 Amazon Bedrock API 응답을 모두 기다리는 동안 여전히 데이터베이스 트랜잭션을 차단합니다. |
| 향상된 처리 기능: PL/pgSQL 대신 완전한 프로그래밍 언어를 사용하여 Lambda에서 더 복잡한 전처리 및 후처리 작업을 수행할 수 있습니다. | Lambda 콜드 스타트: Lambda 함수가 콜드 스타트에서 초기화해야 할 때 추가 지연 시간이 발생하며, 특히 쓰기 빈도가 낮은 경우에 두드러집니다. |
| 향상된 모니터링: Amazon CloudWatch 로그, 지표, 경보를 통해 더 나은 오류 처리와 운영 가시성을 확보할 수 있습니다. | 타임아웃 위험: 임베딩 생성 중 Lambda 실행이 구성된 타임아웃을 초과하면 데이터베이스 작업이 실패할 수 있습니다. |
| 추가 구성 필요: 데이터베이스와 Lambda 간의 IAM 권한, VPC 구성, 네트워크 액세스 설정이 필요합니다. |
접근 방식 3: aws_lambda 확장을 사용한 데이터베이스 트리거 (비동기식)
이 접근 방식은 PostgreSQL 트리거를 사용하여 Lambda 함수를 비동기적으로 호출하고, Lambda 함수가 임베딩을 생성한 후 데이터베이스에 다시 기록합니다. 다음 다이어그램은 이 워크플로를 보여줍니다.
이 접근 방식에서는 데이터베이스 트리거가 Lambda 함수를 비동기적으로 호출하므로, 데이터베이스 트랜잭션을 차단하지 않고 즉시 반환됩니다. 즉, Amazon Bedrock이 임베딩 벡터 생성을 완료할 때까지 기다리지 않고 데이터베이스 작업을 계속 진행할 수 있습니다. 이 접근 방식은 데이터베이스 트랜잭션의 오버헤드를 최소화해야 할 때 유용합니다.
Amazon Bedrock이 벡터 임베딩을 생성한 후, Lambda 함수는 Amazon Relational Database Service (Amazon RDS) Data API를 사용하여 결과를 document_embeddings 테이블에 기록합니다.
이 워크플로에 대한 자세한 이해를 위해, 다음 시퀀스 다이어그램에서 임베딩 프로세스의 각 단계를 확인할 수 있습니다.
Amazon RDS Data API는 Lambda 함수에서 벡터 임베딩을 업데이트합니다. 이 API는 연결을 관리할 필요 없이 Amazon RDS 데이터베이스에 액세스할 수 있는 HTTP 기반 인터페이스이므로, 데이터베이스에 대한 영구 연결이 필요하지 않습니다. Amazon RDS Data API를 사용하면 AWS Secrets Manager에 저장된 데이터베이스 자격 증명을 사용하므로, API 호출 시 자격 증명을 전달할 필요가 없습니다.
Amazon RDS Data API를 사용하는 주요 이점은 연결 관리 복잡성 제거, 자격 증명 관리 없이 간소화된 IAM 기반 인증, 함수 유휴 기간 동안의 데이터베이스 리소스 절약이며, 이 모든 것이 서버리스 아키텍처에서 확장성 향상과 복잡성 감소에 기여합니다. 이를 실제로 확인하기 위해 Lambda 함수 구현 코드를 살펴보겠습니다:
이 비동기 Lambda 접근 방식은 임베딩 생성을 트랜잭션 처리로부터 분리하여 데이터베이스 성능을 우선시합니다. 이를 통해 논블로킹 아키텍처가 구현되어 쓰기 작업 속도가 크게 향상되고 타임아웃 위험이 제거되지만, 최종 일관성 (eventual consistency)과 더 복잡한 오류 처리 패턴이 도입됩니다. 이 설계는 즉각적인 임베딩 가용성이 반드시 필요하지 않은 대용량 쓰기 시나리오에 특히 적합합니다. 다음 표는 이 세 번째 접근 방식의 추가적인 장단점을 정리한 것입니다.
| 장점 | 단점 |
| 논블로킹 트랜잭션: 임베딩 생성 완료를 기다리지 않고 데이터베이스 작업이 빠르게 완료되어, 전반적인 애플리케이션 응답성이 향상됩니다. | 최종 일관성: 임베딩 없이 데이터가 일시적으로 존재하므로, 벡터 검색 결과가 불완전하거나 부정확할 수 있는 시간 구간이 발생합니다. |
| 향상된 쓰기 성능: 데이터베이스 쓰기 작업이 더 빠르게 완료되며, 콘텐츠 생성 및 업데이트에 대한 더 높은 처리량을 지원합니다. | 복잡한 오류 처리: 즉각적인 피드백 루프가 없어 실패한 Lambda 호출을 관리하고 재시도하기가 더 어렵습니다. |
| 타임아웃 제거: 처리가 데이터베이스 커밋 이후에 수행되므로, Amazon Bedrock API 지연 시간으로 인한 트랜잭션 타임아웃 위험이 없습니다. | 상태 추적 복잡성: 임베딩 생성 진행 상황을 모니터링하고, 임베딩 생성에 실패하는 엣지 케이스를 처리하기가 더 어렵습니다. |
| 대용량 확장성: 임베딩 생성 워크로드가 시간에 걸쳐 분산되므로, 대용량 삽입 및 업데이트 시나리오에서 더 나은 확장성을 제공합니다. |
접근 방식 4: Amazon SQS 대기열과 Lambda 배치 처리 (비동기식)
이 접근 방식은 데이터베이스 트리거를 사용하여 Amazon SQS 대기열에 메시지를 전송하고, Lambda 함수가 이를 배치 처리하여 여러 레코드에 대한 임베딩을 한 번에 생성합니다. 다음 다이어그램은 이 워크플로를 보여줍니다.
이 솔루션에서도 트리거는 Lambda 함수를 비동기적으로 호출하여, documents 테이블에 텍스트를 삽입한 후의 트랜잭션 시간을 단축합니다. Amazon SQS를 도입함으로써 LLM 요청의 배치 처리가 가능해지고, 재시도 메커니즘이 강화되며, 대용량 트래픽 기간에 각 시스템이 독립적으로 운영되고 확장될 수 있습니다.
이 접근 방식을 구현하려면 리포지토리의 04_rds_lambda_sqs 섹션에 있는 지침을 사용할 수 있으며, 여기에서 다음을 확인할 수 있습니다:
- 이 패턴을 구현하기 위한 AWS CDK 코드
- 트리거 및 프로시저를 위한 SQL 코드
- Lambda 함수를 위한 TypeScript 코드
Amazon SQS의 유연한 배치 기능을 활용하여 함께 처리할 메시지 수와 메시지를 축적하는 시간 구간을 모두 구성할 수 있습니다. 다음 AWS CDK 코드에서 볼 수 있듯이, SQS 통합이 포함된 Lambda 함수를 생성할 때 이러한 파라미터를 특정 요구 사항에 맞게 조정할 수 있습니다:
Amazon SQS 대기열과 Lambda 배치 처리 아키텍처를 사용하여 메시지 큐잉과 배치 처리를 도입함으로써 확장성과 복원력을 최적화했습니다. 이 설계는 대용량 임베딩 요청을 처리할 때 비용 효율성과 처리량을 개선하는 동시에, Amazon SQS의 내장 재시도 메커니즘을 통해 강력한 오류 처리를 제공합니다.
트레이드오프로는 콘텐츠 생성과 임베딩 가용성 사이의 지연 시간이 더 길어진다는 점이 있으며, 이로 인해 운영 안정성이 우선시되는 대규모 프로덕션 시스템에 더 적합합니다. 다음 표는 이 네 번째 접근 방식의 추가적인 장단점을 정리한 것입니다.
| 장점 | 단점 |
| 확장성: 트래픽 급증과 지속적인 대용량 트래픽을 처리할 수 있는 높은 확장성과 복원력을 갖춘 아키텍처입니다. | 임베딩 지연 시간 증가: 큐잉과 배치 처리로 인해 데이터 삽입과 임베딩 가용성 사이의 지연이 더 길어집니다. |
| 효율적인 리소스 사용: Amazon Bedrock에 대한 임베딩 요청을 배치 처리하여 API 호출을 줄이고, 비용과 처리량 제한을 최적화합니다. | 운영 오버헤드: 추가 AWS 서비스로 인해 모니터링 요구 사항과 운영 복잡성이 증가합니다. |
| 내장된 복원력: Amazon SQS는 구성 가능한 가시성 타임아웃과 dead-letter queue (DLQ) 지원을 통해 자동 재시도 메커니즘을 제공합니다. | 통합 복잡성: 오류 케이스를 적절히 처리하기 위해 세심한 모니터링과 DLQ 구성이 필요합니다. |
| 비용 최적화: 배치 처리와 효율적인 리소스 활용을 통해 대용량 시나리오에서 더 비용 효율적입니다. | |
| 워크로드 관리: 구성 요소의 분리를 통해 시스템 전반에 걸쳐 더 나은 속도 제한과 부하 관리가 가능합니다. |
접근 방식 5: pg_cron 확장을 사용한 예약 기반 주기적 업데이트 (비동기식)
이 접근 방식은 pg_cron을 사용하여 새로운 레코드 또는 수정된 레코드를 확인하고 배치 단위로 임베딩을 생성하는 주기적 작업을 예약합니다.
pg_cron은 데이터베이스의 확장으로 실행되는 PostgreSQL용 오픈 소스 cron 기반 작업 스케줄러입니다. 익숙한 Linux cron 스타일의 구문을 사용하여 SQL 명령이나 저장 프로시저 호출을 예약하고 실행할 수 있습니다. 다음 다이어그램은 이 워크플로를 보여줍니다.
이 접근 방식에서는 문서가 향후 처리를 위해 표시되도록 status 열이 PENDING으로 설정된 상태로 기록됩니다. pg_cron 작업은 주기적으로 (이 경우 2분마다, 구성 가능) 실행되도록 예약되어 다음 작업을 수행합니다:
- 처리가 필요한 모든 행을 가져옵니다 (SELECT … FOR NO KEY UPDATE SKIP LOCKED … WHERE Status = ‘PENDING’ LIMIT <x>). 배치 크기를 표준화하기 위해 제한된 수의 행을 가져오도록 (LIMIT 절) 작업을 구성할 수 있습니다.
- 가져온 행의 상태를
PROCESSING으로 표시합니다. - Amazon Bedrock을 사용하여 임베딩 벡터를 생성합니다.
- 결과 임베딩 값으로
document_embedding테이블을 업데이트합니다. - 처리된 각 행에 대해
documents테이블의 상태를COMPLETED로 업데이트합니다.
이 접근 방식을 통해 데이터베이스 측에서 배치 처리를 도입하며, 추가 cron 작업을 예약하여 더 많이 확장할 수 있습니다. 이 구현은 데이터베이스 트리거를 사용하지 않으므로, 데이터베이스에 문서를 기록하는 원래 데이터베이스 트랜잭션에 성능 영향이 없습니다. 다만, 이 접근 방식과 관련된 몇 가지 단점이 있으며, 이는 이 섹션 끝에 정리되어 있습니다.
이 설정의 구현 세부 사항은 리포지토리의 05_rds_polling 섹션에서 제공되는 SQL 코드를 참조하세요.
다음 코드에서 볼 수 있듯이, pg_cron 스케줄을 2분마다 실행되도록 구성했습니다. pg_cron은 작업 주기를 사용자 정의할 수 있는 유연한 스케줄링 옵션을 제공합니다. 표준 cron 표현식, @hourly 또는 @daily와 같은 편의 이름의 스케줄, 또는 1 minute이나 1 day와 같은 간단한 간격 구문을 사용할 수 있습니다. cron.schedule 함수를 통해 이러한 파라미터를 조정하여 워크로드 요구 사항과 처리 시간대에 따라 실행 빈도를 제어할 수 있습니다.
또한, pg_cron 확장은 다음을 수행할 수 있는 다양한 관리 명령을 제공합니다:
- 현재 예약된 작업 조회
- 작업 실행 출력 및 세부 정보 확인
- 필요 시 예약된 작업 제거
앞서 언급한 바와 같이, PENDING 상태의 모든 행을 검색하는 전용 함수를 사용한 다음, 각 문서에 대해 임베딩 벡터를 생성하기 위해 반복 처리합니다. 이 과정에서 처리 오류를 추적하고, 문서 상태를 업데이트하며, 오류 카운터를 유지합니다.
처리 완료 시 오류가 감지되면 PostgreSQL의 RAISE 함수를 사용하여 관리자에게 문제를 알립니다. 프로덕션 환경에서는 지수 백오프를 사용한 자동 재시도 메커니즘, 알림 시스템, 또는 전용 오류 로깅과 같은 더 정교한 오류 처리 전략을 구현하여 모든 문서의 안정적인 처리를 달성할 수 있습니다.
이러한 개념을 더 잘 이해하기 위해 데이터베이스 함수의 전체 구현을 살펴보겠습니다:
pg_cron 접근 방식은 실시간 일관성보다 데이터베이스 성능과 운영 단순성을 우선시하는 균형 잡힌 솔루션을 제공합니다. 예약된 배치 단위로 임베딩을 처리함으로써 API 부하를 줄이고 강력한 오류 처리를 제공하면서, 전체 솔루션을 데이터베이스 에코시스템 내에 유지합니다.
주요 트레이드오프는 콘텐츠 업데이트와 임베딩 가용성 사이의 지연 시간이 증가한다는 점이며, 이로 인해 준실시간 벡터 검색이 허용되고 운영 단순성이 중요한 시스템에 적합합니다. 다음 표는 이 다섯 번째 접근 방식의 추가적인 장단점을 정리한 것입니다.
| 장점 | 단점 |
| 자체 완결형 아키텍처: 최소한의 외부 종속성으로 구현을 단순화하며, 전체 솔루션을 데이터베이스 내에 유지합니다. | 업데이트 지연 시간 증가: 예약된 빈도에 따라 데이터 변경과 임베딩 업데이트 사이의 지연이 더 길어집니다. |
| 효율적인 배치 처리: 최적화된 배치 요청을 통해 Amazon Bedrock API의 처리량과 비용 효율성을 개선합니다. | 데이터베이스 부하 영향: 리소스 집약적인 주기적 스캔이 바쁜 시간대에 데이터베이스 성능에 영향을 줄 수 있습니다. |
| 강력한 오류 관리: 운영 가시성을 위한 상세한 상태 추적과 함께 내장된 오류 처리 및 재시도 로직을 제공합니다. | 쿼리 복잡성: 과도한 테이블 스캔 없이 변경된 레코드를 효율적으로 식별하기 위해 신중하게 최적화된 쿼리가 필요합니다. |
| 처리 제어: 리소스 사용량과 지연 시간의 균형을 맞추기 위해 처리 빈도와 배치 크기를 세밀하게 제어할 수 있습니다. | |
| API 보호: 제어되고 예측 가능한 API 호출 패턴을 통해 속도 제한이나 스로틀링 위험을 줄입니다. |
의사결정 트리
Aurora PostgreSQL 호환 에디션에서 임베딩을 생성하기 위한 5가지 접근 방식을 살펴본 후, 특정 사용 사례에 어떤 방법이 가장 적합한지 궁금할 수 있습니다. 다음은 선택에 도움이 되는 실용적인 의사 결정 트리입니다:

접근 방식 1이나 5와 같은 간단한 방식으로 시작한 후, 요구 사항이 증가함에 따라 더 정교한 솔루션으로 발전시킬 수 있다는 점을 기억하세요. 주요 차이점은 확장성, 안정성, 운영 복잡성을 처리하는 방식에 있습니다.
참고: 성능과 관련하여, 이 맥락에서 인덱스는 매우 중요합니다. 벡터 임베딩을 인덱싱하기 위해 선택한 인덱스 유형에 따라, 이러한 인덱스의 성능과 관련성을 유지하기 위해 주기적인 유지 관리가 필요할 수 있습니다. 그렇지 않으면 성능이 점진적으로 저하되거나 시맨틱 검색의 재현율 (recall) 비율이 떨어질 수 있습니다.
구현 세부 사항과 코드 예제는 GitHub 리포지토리와 이 게시글에 나열된 추가 리소스를 참조하세요.
리소스 정리
불필요한 비용이 발생하지 않도록, 이 게시글의 접근 방식을 구현하면서 배포한 AWS 리소스를 정리하세요:
- CloudFormation 콘솔에서 AWS CloudFormation 스택을 삭제합니다.
- 추가로 생성한 리소스를 삭제합니다.
결론
Aurora PostgreSQL에서 벡터 검색을 위한 임베딩 생성을 자동화하면 AI 기능을 활용하는 애플리케이션에 상당한 이점을 제공할 수 있습니다. 벡터 임베딩을 데이터와 동기화된 상태로 유지함으로써, 검색 결과, 추천, 기타 AI 기반 기능이 관련성 있고 정확한 상태를 유지하도록 보장할 수 있습니다.
이 게시글에서는 임베딩 생성 자동화를 위한 다양한 접근 방식을 소개했습니다. 애플리케이션에 최적인 솔루션은 일관성, 지연 시간, 확장성, 운영 복잡성에 대한 특정 요구 사항에 따라 달라집니다.
전체 솔루션은 GitHub 리포지토리에서 확인할 수 있습니다. 이슈 또는 풀 리퀘스트를 통한 기여와 피드백을 환영합니다.









