[Spring Boot] DynamoDB에서 데이터 읽어오기

CHR·2024년 3월 29일
0

AWS 시크릿 매니저

파트 별로 따로 관리하고 있던 키 값을 한 번에 관리하기 위해 AWS Secret Manager를 사용했다.
먼저 AWS 시크릿매니저에 보안 암호 등록을 하고 AWS CLI 설치와 권한 설정을 했다.

AWS 시크릿 매니저 보안 암호 등록


보안 암호를 등록하면 이렇게 샘플 코드를 준다.

AWS CLI 설치와 권한 설정

설치

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install

권한 설정

$ aws configure
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: 
Default output format [None]:

확인

$ aws sts get-caller-identity

Spring Boot에서 DynamoDB 데이터 읽기

build.gradle


    implementation platform('software.amazon.awssdk:bom:2.21.44')
    implementation 'software.amazon.awssdk:secretsmanager'
    implementation 'software.amazon.awssdk:regions'
    implementation platform('com.amazonaws:aws-java-sdk-bom:1.11.1000')
    implementation 'com.amazonaws:aws-java-sdk-dynamodb'

필요한 라이브러리를 추가해준다.


DynamoDB에 저장되어있는 이 데이터를 읽어 올 것이다.

먼저 AWSConfig 파일을 작성해준다.

@Getter
@Configuration
public class AWSConfig {

    private final String accessKey;
    private final String secretKey;
    private final String region;

    public AWSConfig() {
        String key = getSecret();
        this.accessKey = key.substring(19, 39);
        this.secretKey = key.substring(66, 106);
        this.region = "ap-northeast-2";
    }

    public static String getSecret() {

        String secretName = "MySecretName";
        Region region = Region.of("ap-northeast-2");

        // Create a Secrets Manager client
        SecretsManagerClient client = SecretsManagerClient.builder()
                .region(region)
                .build();

        GetSecretValueRequest getSecretValueRequest = GetSecretValueRequest.builder()
                .secretId(secretName)
                .build();

        GetSecretValueResponse getSecretValueResponse;

        try {
            getSecretValueResponse = client.getSecretValue(getSecretValueRequest);
        } catch (Exception e) {
            // For a list of exceptions thrown, see
            // https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
            throw e;
        }

        return getSecretValueResponse.secretString();
    }
}

AWS 시크릿 매니저에서 access key를 가져오는 코드다. 위에서 말한 보안 암호를 등록하면 주는 샘플 코드를 사용했다.
리턴 값이 "AWS_ACCESS_KEY:키 값, AWS_SECRET_ACCESS_KEY:시크릿 키 값"의 형태인 String으로 반환돼서 파싱을 해야한다. 찾아보니 해쉬 맵으로 하는 방법이 있는 거 같은데?? 자바 문법을 잘 몰라서;;; 일단은 substring으로 처리했다. 최악의 코드.

+) 수정한 코드 추가 (4/10)

    public AWSConfig() {
        Map<String, String> awsKey = stringToMap(getSecret());
        this.accessKey = awsKey.get("AWS_ACCESS_KEY");
        this.secretKey = awsKey.get("AWS_SECRET_ACCESS_KEY");
        this.region = "ap-northeast-2";
    }

    private Map<String, String> stringToMap(String value) {
        ObjectMapper objectMapper = new ObjectMapper();
        TypeReference<Map<String, String>> typeReference = new TypeReference<Map<String, String>>() {
        };

        Map<String, String> awsKey = new HashMap<>();
        try {
            awsKey = objectMapper.readValue(value, typeReference);
        } catch (JsonMappingException e) {
            log.error("JSON 구조와 매핑 문제 발생: {}", e.getMessage());
        } catch (JsonProcessingException e) {
            log.error("JSON 처리 중 예외 발생: {}", e.getMessage());
        }
        return awsKey;
    }

아니면 https://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/patterns/manage-credentials-using-aws-secrets-manager.html 를 참고해서

     String  host  =  secretsJson.get("host").textValue();
     String  port  =  secretsJson.get("port").textValue();
     String  dbname  =  secretsJson.get("dbname").textValue();
     String  username  =  secretsJson.get("username").textValue();
     String  password  =  secretsJson.get("password").textValue();

이런 식으로 해도 됨

다음으로 DynamoDBConfig 파일을 작성한다.


@Configuration
public class DynamoDBConfig {

    @Autowired
    private AWSConfig awsConfig;

    @Bean
    public DynamoDBMapper dynamoDBMapper() {
        return new DynamoDBMapper(amazonDynamoDBClient());
    }

    private AmazonDynamoDBClient amazonDynamoDBClient() {
        BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsConfig.getAccessKey(), awsConfig.getSecretKey());
        return (AmazonDynamoDBClient) AmazonDynamoDBAsyncClientBuilder.standard()
                .withRegion(awsConfig.getRegion())
                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                .build();
    }
}

DynamoDBMapper로 DynamoDB에 CRUD를 할 수 있는데, Bean으로 등록해서 하나의 객체만 생성되게 해준다.
(참고: https://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/DynamoDBMapper.CRUDExample1.html)

DynamoDB에서 데이터를 읽어올 테이블을 지정하고 데이터의 값을 매핑할 클래스를 만든다.

@Getter
@Setter
@Component
@NoArgsConstructor
@AllArgsConstructor
@DynamoDBTable(tableName = "MyTable")
public class DynamoDBResponse {

    @DynamoDBHashKey(attributeName = "month")
    private Integer month;

    @DynamoDBRangeKey(attributeName = "timestamp")
    private String timestamp;

    @DynamoDBAttribute(attributeName = "id")
    private String id;

    @DynamoDBAttribute(attributeName = "description")
    private String description;
}

HashKey(Partition Key)만 있으면 HashKey가 기본키 역할을 하고, HashKey랑 RangeKey가 같이 있으면 둘이 복합키로 기본키 역할을 한다.
(참고: https://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey)

이제 드디어 데이터를 읽어오는 DynamoDBService 파일을 작성한다.

@Service
public class DynamoDBService {

    @Autowired
    private DynamoDBMapper mapper;

    public DynamoDBResponse getData() {
        DynamoDBResponse response = mapper.load(DynamoDBResponse.class, 0, "1");
        if (response == null) {
            throw new RuntimeException("Data not found for id: ");
        }
        return response;

    }
}

mapper.load()에 들어가는 파라미터는 위에서 만든 데이터 클래스, 파티션 키 값, 정렬 키 값이다. 파라미터로 넣은 키 값으로 DynamoDB에서 데이터를 찾는다. 물론 파티션 키만 있는 테이블이면 파라미터로 파티션 키만 넣어주면 된다.
(참고: https://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html#DynamoDBMapper.Methods.load)

Service 파일에서

String description = dynamoDBService.getData().getDescription();

이런 식으로 쓰면 된다.

포스트맨으로 테스트 해보니 성공이다!

되는 건 확인했는데... 고쳐야 할 것들이 많다~
1. key 파싱 방법 바꾸기
2. yml 파일에 key를 저장할 순 없을까?
3. DynamoDB 데이터의 값 중 List 타입을 가져오려고 클래스에 List로 정의했는데 TypeError로 데이터를 가져오지 못 했음

그래도 DynamoDB에서 데이터 읽는 건 처음이었는데 구현해보고 작동하는 걸 확인해서 좋았다!!

참고자료:
(https://www.theprogrammerguide.com/post/aws-dynamodb_spring/)

profile
🍷

0개의 댓글

관련 채용 정보