콘텐츠로 이동
AWS 문서0.4

AWS 연동 테스트와 운영

최신 안정판 AWS 0.4.0 릴리스 기준

운영에서 실패할 수 있는 경계를 테스트해야 한다. Request mapping, endpoint와 credential 선택, retry와 ack 동작, client 소유권과 종료 과정이 여기에 해당한다. Mock client는 순수한 위임 로직을 검증할 때 유용하지만 transport, serialization, emulator 호환성이나 lifecycle까지 증명하지는 않는다.

Floci 우선 emulator 테스트 흐름

단계확인할 수 있는 것확인할 수 없는 것
Unit/mock testRequest mapping, 분기, 변환, retry 분류실제 SDK transport, endpoint, IAM, lifecycle
Floci 통합 테스트Testcontainers로 지원되는 AWS API를 빠르게 검증하는 기본 경로Floci가 지원하지 않는 operation, AWS 운영 환경의 동작
LocalStack fallbackLocalStack이 지원하는 operation 또는 service 간 연동AWS IAM, quota, latency, managed service policy, 완전한 의미 일치
AWS 환경 smoke test현재 credential, region, endpoint와 선택한 service가 함께 동작함반복 가능한 장애 복구, 규모나 넓은 policy 범위
Load/resilience test명시한 workload와 장애 조건보편적인 처리량이나 비용 결론

기본은 Floci, LocalStack은 명시적으로

섹션 제목: “기본은 Floci, LocalStack은 명시적으로”

저장소 테스트는 bluetape4k.aws.emulator 기본값으로 floci를 사용한다. Floci가 지원하는 빠른 경로는 그대로 유지한다. 지원하지 않는 operation이나 여러 service를 묶은 연동 때문에 LocalStack이 필요하면 command에 분명히 적는다.

Terminal window
./gradlew :bluetape4k-aws-java:test \
-Dbluetape4k.aws.emulator=localstack
./gradlew :aws-spring-boot-sqs-examples:test \
-Dbluetape4k.aws.emulator=localstack

Emulator가 지원하지 않는다고 assertion을 빼서 통과시키면 안 된다. 지원 범위를 기록하고 mock 또는 fallback 테스트를 그 빈틈에 연결한다. 어느 emulator에서 성공하더라도 운영 IAM과 service limit까지 검증된 것은 아니다.

Terminal window
./gradlew :aws-ktor-s3-examples:test
./gradlew :aws-ktor-dynamodb-examples:test
./gradlew :aws-ktor-sqs-examples:test
./gradlew :aws-ktor-exposed-examples:test
./gradlew :aws-spring-boot-s3-examples:test
./gradlew :aws-spring-boot-dynamodb-examples:test
./gradlew :aws-spring-boot-sqs-examples:test
./gradlew :aws-spring-boot-exposed-examples:test

Service 코드에는 실패 조건도 넣는다. SQS 중복 전달, visibility timeout 만료, DynamoDB 조건부 쓰기 실패, S3 일부 전송 실패, 만료된 presigned URL, secret source 장애와 작업 중 shutdown을 검증한다.

  • Credential과 region — 배포 환경에 맞는 provider chain을 사용한다. Access key, session token, secret payload와 signed header를 log에 남기지 않는다.
  • Retry와 idempotency — Business effect를 반복해도 안전한 operation만 재시도한다. 중복 가능성이 있는 consumer와 write에는 idempotency key를 전달한다.
  • Timeout — Connect, request, polling, handler와 shutdown 시간을 service budget에 맞춘다.
  • Readiness — 필요한 client, queue, table, bucket 또는 database pool이 실제 요청을 처리할 수 있을 때 ready로 전환한다.
  • 관측성 — Service, operation, 결과, retry 횟수, latency, queue phase와 low-cardinality resource 식별자를 기록한다. Bucket key, message body, secret name이 사용자 데이터를 드러낼 수 있다면 tag나 log에 넣지 않는다.
  • 종료 — Polling을 멈추고 진행 중인 작업을 끝내거나 취소한다. 정해진 범위에서 buffer를 flush한 다음 client와 pool, 명시적으로 공유한 HTTP engine을 닫는다.

Component가 client를 직접 만들 수도 있고 외부에서 받을 수도 있다면 lifecycle test를 추가한다. 소유한 client는 정확히 한 번 닫히고, 주입받은 client는 열린 채로 남는지 확인한다. Kotlin SDK 공유 engine은 다른 client가 쓰는 동안 유지되고, 모든 client가 멈춘 뒤 애플리케이션이 닫는지도 검증한다.