본문으로 건너뛰기

Spring Boot - testContainer를 활용한 AWS DynamoDB 테스트

· 약 5분

Amazon DynamoDB를 비용 지불없이 쉽게 테스트하는 방법을 소개하려고 한다.

Amazon DynamoDB란 무엇입니까?

우선, Amazon DynamoDB가 무엇인지 찾아보자. 공식문서에는 다음과 같이 적혀있다.

AWS 공식문서 - Amazon DynamoDB란 무엇입니까?

Amazon DynamoDB는 종합 관리형 NoSQL 데이터베이스 서비스로서 원활한 확장성과 함께 빠르고 예측 가능한 성능을 제공합니다. DynamoDB를 사용하면 분산 데이터베이스를 운영하고 조정하는 데 따른 관리 부담을 줄일 수 있으므로 하드웨어 프로비저닝, 설정 및 구성, 복제, 소프트웨어 패치 또는 클러스터 조정...

환경 구성하기

개발 프로세스상 dev, qa, stage, test, prod 같이 영역을 나누어 구성하는 것이 보통이다. 그러다보니 각 영역마다 별도의 인스턴스가 필요하게 되고 불가피하게 클라우드 비용이 늘어나게 상황에 직면하게 된다. 하지만, Amazon DynamoDB는 인스턴스를 만들지 않고도 테스트 가능하도록 제공한다. 즉, 비용이 발생하지 않는다.

  • jar 파일을 제공하여 java가 있는 환경에서 실행 [link]
  • docker container 실행 [link]

여기서 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 {
// ...
}

참고