Spring Boot - testContainer를 활용한 AWS DynamoDB 테스트
Amazon DynamoDB를 비용 지불없이 쉽게 테스트하는 방법을 소개하려고 한다.
Amazon DynamoDB란 무엇입니까?
우선, Amazon DynamoDB
가 무엇인지 찾아보자. 공식문서에는 다음과 같이 적혀있다.
Amazon DynamoDB는 종합 관리형 NoSQL 데이터베이스 서비스로서 원활한 확장성과 함께 빠르고 예측 가능한 성능을 제공합니다. DynamoDB를 사용하면 분산 데이터베이스를 운영하고 조정하는 데 따른 관리 부담을 줄일 수 있으므로 하드웨어 프로비저닝, 설정 및 구성, 복제, 소프트웨어 패치 또는 클러스터 조정...
환경 구성하기
개발 프로세스상 dev
, qa
, stage
, test
, prod
같이 영역을 나누어 구성하는 것이 보통이다. 그러다보니 각 영역마다 별도의 인스턴스가 필요하게 되고 불가피하게 클라우드 비용이 늘어나게 상황에 직면하게 된다. 하지만, Amazon DynamoDB는 인스턴스를 만들지 않고도 테스트 가능하도록 제공한다. 즉, 비용이 발생하지 않는다.
여기서
test
정도는 데이터가 휘발성으로 있어도 되는 부분이라 생각한다.
Docker Container 실행
DockerHub에 amazon/dynamodb-local
퍼블릭 이미지로 제공되고 있다.
Spring Boot 설정
디펜던시 추가
DynamoDB를 포함한 다른 서비스(ex. Amazon S3, Amazon RedShift, ...)를 쉽게 사용할 수 있도록 라이브러리를 제공한다. 이를 디펜던시로 추가한다.
compile('com.amazonaws:aws-java-sdk-dynamodb:1.11.466')
// ...
AmazonDynamoDB
빈 등록
DynamoDB에 액세스할 클래스인 AmazonDynamoDB
를 빈으로 등록해준다.
@Configuration
public class DynamoDBConfig {
@Bean
public AmazonDynamoDB amazonDynamoDB(
@Value("${aws.region}") String region,
@Value("${aws.dynamo.endpoint}") String dynamoEndpoint,
@Value("${aws.access-key}") String accessKey,
@Value("${aws.secret-key}") String secretKey) {
return AmazonDynamoDBClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(dynamoEndpoint, region))
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
.build();
}
}
테스트 작성하기
당연한 얘기지만 AmazonDynamoDB
를 빈으로 등록해두었기 때문에 @Autowired
를 활용하여 인스턴스를 주입받을 수 있다. 그리고 테스트를 작성하면 된다. 코드는 도커를 활용하든, 실제 AWS 인스턴스를 활용하든 동일하므로 AWS 공식문서의 예제를 참고하거나, 간단한 CRUD 예제가 있으니 참고하자.
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootDynamoApplicationTests {
// ...
@Autowired
private AmazonDynamoDB dynamoDB;
// ...
}
하지만, 테스트를 위해 매번 docker run -p 8000:8000 amazon/dynamodb-local
를 치는 것은 귀찮기도 하고 약간(?) 수동적이다. testcontainers
를 사용하면 이를 해결할 수 있다.
testcontainers 적용
testcontainers
는 자바코드에서 docker container를 실행시켜주는 라이브러리이다. 직접 run
을 실행시킬 수 도 있고, Dockerfile
이나 docker-compose.yml
을 활용할 수도 있다. 물론, docker가 설치되어 있어야 한다.
디펜던시 추가
testCompile('org.testcontainers:testcontainers:1.10.2')
// ...
AbstractIntegrationTest
작성
다행히 Spring Boot에서 활용 가능한 예제 샘플을 제공한다. 아래 샘플을 참고하여 다음과 같이 작성해볼 수 있다. testcontainers/testcontainers-java-examples - AbstractIntegrationTest
// ...
public abstract class AbstractIntegrationTest {
private static final String DOCKER_IMAGE = "amazon/dynamodb-local";
private static final String DOCKER_TAG = "latest";
private static final int EXPOSED_PORT = 8000;
@ClassRule
public static GenericContainer dynamodb =
new GenericContainer(String.format("%s:%s", DOCKER_IMAGE, DOCKER_TAG)).withExposedPorts(EXPOSED_PORT);
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
String endpoint = String.format("aws.dynamo.endpoint=http://%s:%s",
dynamodb.getContainerIpAddress(),
dynamodb.getMappedPort(EXPOSED_PORT));
// ...
예제에도 나와있듯이, 다른 docker container도 활용 가능하다.
테스트 작성하기 (수정)
// ...
public class SpringBootDynamoApplicationTests extends AbstractIntegrationTest {
// ...
}