콘텐츠로 이동

Bluetape4k AWS Part 2: 핵심 모듈과 AWS 서비스 지원 현황

작은 로봇 작업자들이 Kotlin 작업대에서 aws-java, aws-kotlin, CRT 엔진, S3 TransferManager 블록을 연결하는 일러스트
클라이언트 생성 방식뿐 아니라 HTTP 엔진과 자원 수명 주기, 런타임 의존성의 소유 경계도 함께 정해야 합니다.

이 글은 bluetape4k-aws 시리즈의 2편입니다. Part 1에서는 프로젝트 개요와 기본 모델을 다뤘습니다. 이번 글에서는 핵심 모듈인 bluetape4k-aws-javabluetape4k-aws-kotlin이 어떤 반복 작업을 줄이는지 살펴봅니다.

핵심은 AWS SDK를 다시 구현하는 것이 아닙니다. AWS Java SDK v2와 AWS Kotlin SDK는 그대로 쓰되, Kotlin/JVM 서비스에서 반복되는 클라이언트 생성과 코루틴 연결, 요청 모델 구성을 편의 함수로 제공합니다. Java SDK v2 쪽에서는 CompletableFuture 기반 비동기 클라이언트를 suspend 함수로 연결하고, S3 대용량 전송에는 CRT 기반 비동기 클라이언트와 S3TransferManager를 조합합니다. Kotlin SDK 쪽에서는 네이티브 suspend 클라이언트를 유지하면서 공유 HTTP 엔진 선택지, withXxxClient 생명주기 도우미, 서비스별 DSL 빌더를 제공합니다.

aws-java와 aws-kotlin이 각각 Java SDK v2와 Kotlin SDK를 거쳐 AWS 서비스로 이어지는 두 API 계층
두 SDK의 실행 모델은 다르지만, 핵심 모듈은 애플리케이션에 일관된 서비스별 편의 API를 제공합니다.

AWS Java SDK v2를 직접 사용하면 동기 클라이언트와 비동기 클라이언트의 실행 모델을 나눠야 하고, 비동기 클라이언트에서는 HTTP 클라이언트 선택과 CompletableFuture 조합이 따라옵니다. S3처럼 파일 크기와 처리량이 중요한 작업에서는 CRT 기반 S3 비동기 클라이언트와 TransferManager 구성까지 함께 고려해야 합니다.

bluetape4k-aws-java는 이 결정을 숨기지 않습니다. 대신 반복되는 조립 지점을 미리 준비합니다. 일반 비동기 클라이언트 팩터리의 기본 HTTP 클라이언트는 현재 Netty입니다. SdkAsyncHttpClientProvider.AwsCrtawsCrtAsyncHttpClientOf를 사용하면 CRT 비동기 HTTP 클라이언트를 명시적으로 선택할 수 있습니다. S3 대용량 전송은 CRT 중심으로 구성합니다. S3ClientFactory.CrtAsync.createS3AsyncClient.crtBuilder()를 사용하고, S3ClientFactory.TransferManager.create는 이 CRT 기반 비동기 클라이언트를 만들어 S3TransferManager에 연결합니다.

또 하나의 기본값은 실행기입니다. Java 버전의 TransferManager.createExecutors.newVirtualThreadPerTaskExecutor()를 기본 실행기로 사용합니다. 파일 전송처럼 블로킹 작업과 비동기 완료 처리가 섞이는 지점에 가상 스레드를 적용할 수 있습니다.

import io.bluetape4k.aws.s3.S3ClientFactory
import io.bluetape4k.aws.s3.transfer.downloadFile
import io.bluetape4k.aws.s3.transfer.uploadFile
import software.amazon.awssdk.regions.Region
import java.nio.file.Path
suspend fun mirrorObject(bucket: String, key: String, source: Path, target: Path) {
val transferManager = S3ClientFactory.TransferManager.create(
region = Region.AP_NORTHEAST_2,
)
transferManager.uploadFile(bucket, key, source)
transferManager.downloadFile(bucket, key, target)
}

TransferManager 자체는 AWS SDK가 제공합니다. bluetape4k-aws-java는 CRT 기반 S3 비동기 클라이언트, 가상 스레드 실행기, 비동기·코루틴 확장 함수를 서비스 코드에서 반복해 조립하지 않도록 팩터리와 도우미를 제공합니다.

작은 객체나 문자열 중심의 S3 작업은 코루틴 확장 함수를 사용할 수 있습니다. Java SDK v2 비동기 클라이언트는 CompletableFuture를 반환하지만, 확장 함수는 .await()로 완료를 기다리는 suspend API를 제공합니다.

import io.bluetape4k.aws.s3.S3ClientFactory
import io.bluetape4k.aws.s3.getAsString
import io.bluetape4k.aws.s3.putAsString
suspend fun writeAndRead(bucket: String, key: String): String {
val client = S3ClientFactory.Async.create()
client.putAsString(bucket, key, "hello from bluetape4k-aws")
return client.getAsString(bucket, key)
}

이 패턴은 S3에만 적용되지 않습니다. DynamoDB Enhanced Async Table의 스캔·쿼리를 Flow로 받거나 SQS 송신·수신·삭제, SNS 발행, SES 메일 전송, KMS 암호화·복호화, CloudWatch 메트릭·로그, Kinesis 레코드, STS 자격 확인·역할 위임 같은 작업도 같은 방식으로 제공합니다. Java SDK v2의 서비스 지원 범위를 유지하면서 코루틴 기반 Kotlin 서비스에서 사용할 수 있게 하는 것이 목적입니다.

bluetape4k-aws-kotlin은 출발점이 다릅니다. AWS Kotlin SDK의 서비스 연산은 이미 suspend 함수입니다. 그래서 Java SDK v2처럼 CompletableFuture를 코루틴으로 바꾸는 일이 중심이 아닙니다. 여기서는 클라이언트 생성, HTTP 엔진 소유권, 요청 모델 빌더, 자원 생명주기를 명확히 하는 일이 더 중요합니다.

HttpClientEngineProvider.defaultHttpEngine은 명시적으로 공유할 수 있는 CRT 엔진을 반환하고, HttpClientEngineProvider.OkHttp.httpEngine은 공유 OkHttp 엔진을 제공합니다. 두 엔진은 외부에서 관리하는 싱글턴이므로 여러 클라이언트가 의도적으로 전송 계층을 공유할 때만 전달해야 합니다. 단일 클라이언트에서는 httpClient를 생략해 AWS Kotlin SDK가 엔진 생명주기를 소유하게 하거나 withXxxClient 도우미를 사용합니다.

import aws.smithy.kotlin.runtime.net.url.Url
import io.bluetape4k.aws.kotlin.s3.putFromPath
import io.bluetape4k.aws.kotlin.s3.withS3Client
import java.nio.file.Path
suspend fun uploadReport(path: Path) {
withS3Client(
endpointUrl = Url.parse("http://localhost:4566"),
region = "ap-northeast-2",
) { client ->
client.putFromPath("reports", "daily/report.csv", path)
}
}

withS3Client, withSqsClient, withDynamoDbClient 같은 도우미는 클라이언트를 만들고 블록을 실행한 뒤 클라이언트를 닫습니다. 장기 사용 클라이언트가 필요하면 s3ClientOf, sqsClientOf 같은 팩터리를 직접 사용하고 애플리케이션 종료 시 명시적으로 닫아야 합니다. 일회성 클라이언트와 애플리케이션 범위 클라이언트의 수명 주기를 구분한 것입니다.

Kotlin 쪽 서비스 도우미는 파일·바이트·문자열 중심의 S3 함수, 큐 URL 중심의 SQS 송수신 함수, DynamoDB 항목 매핑·배치 실행·요청 빌더를 제공합니다. Kinesis의 recordFlow는 샤드 하나를 지속해서 폴링하고 Flow<Record>로 내보냅니다. 샤드 반복자 만료와 조절 제한 재시도도 이 처리 흐름 안에서 다룹니다.

import io.bluetape4k.aws.kotlin.kinesis.KinesisStartingPosition
import io.bluetape4k.aws.kotlin.kinesis.recordFlow
suspend fun consumeShard(client: aws.sdk.kotlin.services.kinesis.KinesisClient) {
client.recordFlow(
streamName = "orders",
shardId = "shardId-000000000000",
position = KinesisStartingPosition.TrimHorizon,
).collect { record ->
println(record.data.decodeToString())
}
}

핵심 모듈은 S3, SQS, SNS, DynamoDB, KMS, SES/SESv2, CloudWatch, CloudWatch Logs, Kinesis, STS뿐 아니라 EventBridge, EventBridge Scheduler, Bedrock Runtime, Secrets Manager, Parameter Store의 반복 호출 패턴도 다룹니다. Java 모듈은 S3 Vectors와 RDS IAM 토큰 도우미도 제공합니다. Spring Boot와 Ktor 모듈은 이 핵심 API 위에 프레임워크별 진입점을 추가합니다.

aws-java, aws-kotlin, aws-spring-boot, aws-ktor, 예제의 AWS 서비스 지원 범위를 비교한 구성표
핵심 모듈은 서비스별 SDK 도우미를 제공하고, 프레임워크 모듈은 애플리케이션에서 자주 사용하는 진입점을 추가합니다.
서비스Java SDK v2Kotlin SDK대표 편의 기능
S3동기·비동기·코루틴, CRT 비동기, TransferManagersuspend 클라이언트, 파일·문자열·바이트 도우미대용량 전송, 파일 업로드·다운로드, 객체 목록 조회
S3 Vectors선택적 코루틴 파사드미지원벡터 버킷·인덱스 조회와 벡터 쓰기·조회·검색
DynamoDBEnhanced Client, 비동기 테이블, 코루틴·Flow테이블·항목·배치 도우미, 모델 DSL항목 변환, 배치 쓰기, 스캔·쿼리
SQS비동기·코루틴 큐 작업suspend 송신·수신·배치 도우미큐 URL 중심 송신·수신·삭제
SNS주제 발행, SMS, 푸시suspend 발행·구독 도우미주제 생성, 발행, 구독
SES/SESv2메일 전송 도우미일반·원시·템플릿·대량 전송 도우미메일 요청 빌더와 전송 API
KMS동기·비동기 클라이언트 빌더, 요청 DSL암호화·복호화·데이터 키 도우미키 작업 DSL
CloudWatch/Logs메트릭·로그 이벤트 코루틴 확장metricDatum·inputLogEvent DSL메트릭과 로그 이벤트 발행
Kinesis레코드 쓰기·조회 코루틴 확장recordFlow, putRecord 도우미샤드 폴링, 재시도·지수 백오프
EventBridge/Scheduler이벤트 발행·일정 작업 도우미이벤트 발행·일정 작업 도우미이벤트 요청과 일정 작업 모델 DSL
Bedrock Runtime동기·비동기·코루틴 호출 도우미네이티브 suspend 호출 도우미모델 호출 요청·응답 처리
Secrets Manager/Parameter Store비동기·코루틴 조회 도우미네이티브 suspend 조회 도우미시크릿·파라미터 조회와 요청 DSL
STS역할 위임, 호출자 자격, 세션 토큰suspend STS 도우미자격 확인, 임시 자격 증명
RDS IAM인증 토큰 도우미미지원Java SDK 기반 RDS IAM 인증 토큰 생성

라이브러리가 여러 서비스의 도우미를 제공하더라도 애플리케이션은 실제 사용하는 AWS 서비스 아티팩트만 선택해야 합니다.

aws-javaaws-kotlin 빌드 파일은 서비스별 AWS SDK 의존성을 compileOnly로 선언합니다. Java 모듈은 Bedrock Runtime, DynamoDB Enhanced, S3, S3 Vectors, S3 Transfer Manager, SES/SESv2, Secrets Manager, SNS, SQS, Parameter Store, KMS, CloudWatch, CloudWatch Logs, Kinesis, EventBridge, Scheduler, RDS, STS를 이 방식으로 선언합니다. Kotlin 모듈도 S3 Vectors와 RDS를 제외한 대응 서비스 의존성을 compileOnly로 둡니다.

이 구조에서는 핵심 모듈이 여러 서비스의 도우미를 컴파일할 수 있지만 실제 런타임 클래스패스는 애플리케이션이 결정합니다. S3와 SQS만 사용하는 서비스는 Kinesis와 SES 의존성을 추가할 필요가 없습니다. BOM은 지원 아티팩트의 버전을 정렬하고, 애플리케이션은 사용하는 AWS SDK 아티팩트만 implementation으로 선택합니다.

BOM, compileOnly 핵심 모듈, 애플리케이션이 선택하는 런타임 의존성의 소유 경계를 보여 주는 다이어그램
compileOnly는 핵심 모듈의 컴파일 경계를 제공하고, 런타임 서비스 의존성은 애플리케이션이 선택합니다.

Java SDK v2의 서비스 지원이 필요하거나 S3 대용량 전송을 TransferManager, CRT 비동기 클라이언트, 가상 스레드와 함께 사용하려면 bluetape4k-aws-java를 선택합니다. S3 전송에 필요한 HTTP 클라이언트, 비동기 클라이언트, 실행기, 코루틴 연결을 공통 팩터리로 구성할 수 있습니다.

AWS Kotlin SDK의 네이티브 suspend 연산을 유지하려면 bluetape4k-aws-kotlin을 선택합니다. SDK 소유 엔진과 명시적으로 공유하는 CRT·OkHttp 엔진을 구분할 수 있고, withXxxClient 생명주기 도우미와 서비스별 DSL 빌더를 사용할 수 있습니다.

Spring Boot 4나 Ktor 3에서 속성 바인딩, 자동 구성, 리스너 런타임 같은 프레임워크 연결이 필요하면 Part 3에서 다루는 통합 모듈을 사용합니다. Part 2의 핵심 모듈은 SDK와 프레임워크 사이의 반복 코드를 줄이고, 런타임에 포함할 서비스 의존성은 애플리케이션이 선택하게 합니다.

bluetape4k-aws-javabluetape4k-aws-kotlin은 같은 통합 문제를 서로 다른 SDK 실행 모델에서 해결합니다. Java 모듈은 Java SDK v2 비동기 API를 코루틴으로 연결하고 CRT 기반 S3 전송과 가상 스레드 실행기를 구성합니다. Kotlin 모듈은 네이티브 suspend 모델을 유지하면서 클라이언트 생명주기, 공유 HTTP 엔진, 요청 DSL을 제공합니다.

다음 글에서는 이 핵심 모듈 위에 Spring Boot 4와 Ktor 3가 제공하는 자동 구성, SQS 리스너, Ktor SigV4 플러그인, 예제 애플리케이션의 프레임워크 연결을 살펴봅니다.

댓글

GitHub 계정으로 의견을 남기거나 reaction을 남길 수 있습니다.