진짜 개발자
본문 바로가기

AWS/SDK & Programming

AWS SDK - Java에서 AWS S3 사용하는 법

728x90
1. Guide

이번 포스팅에서는 JAVA에서 AWS의 S3 스토리지를 이용하는 방법을 알아 보도록하겠습니다.

 

 

1. Guide

Java AWS SDK 가이드

https://docs.aws.amazon.com/ko_kr/sdk-for-java/v1/developer-guide/aws-sdk-java-dg.pdf

위의 링크로 이동하시면 Java용 AWS SDK를 사용하는 방법에 대한 문서를 참조할 수 있습니다. 필자도 저 가이드를 참조하여 진행하였으며, 저 글을 따라 한다면 별 문제 없이 진행이 가능합니다.

 

 

 

 

2. Credentials (IAM)

2.1 비용 (Cost)

우선 AWS를 이용한다면 당연히 Cost에 대한 고려를 하게 될것입니다. 우선 IAM에 대한 비용은 다행히 무료입니다. 대신 IAM 사용자가 이용하는 서비스에 대한 비용은 당연하게 내야합니다.

 

 

 

2.2 IAM 사용자 생성

JAVA에서 AWS의 서비스를 이용하기 위해서는, 프로그램에서 사용할 AWS 사용자를 생성해야 합니다.

 

당연합니다. 간단히 생각해보면, JAVA 프로그램에서 AWS 서비스를 이용하는데, 이에 대한 비용을 지불하기 위해서는 이 사용자가 어떤 Account(계정) 인지를 식별할 수 있어야하기 때문입니다.

 

 

사용자 생성


우선 AWS 콘솔에 로그인 한 뒤, 사용자 탭으로 이동하여 사용자 추가를 클릭합니다.

 

사용자 이름은 간단히 "test" 로 짓고, 액세스 유형에서 프로그래밍 방식 엑세스를 체크합니다.

 

이 탭에서는 해당 사용자에 대해 권한을 부여합니다. JAVA에서 사용할 최소한의 권한을 주는 것이 원칙이지만, 우리는 IAM을 다루는 방법을 배우는 것이 아니고, S3 SDK를 사용하는 방법을 공부할 것 이므로 우선, FullAccess 권한을 줍니다.

 

태그는 건너 띄고, 사용자 생성을 누르면 자동으로 생성된 액세스 키 ID, 비밀 액세스 키가 발급됩니다. .csv파일을 다운로드합니다.

 

 

 

 

3. Dependency

이제 부터 문서를 참고하여 확실히 해야하는 부분입니다. 문서에는 의존성을 관리하는 방법을 2가지로 나누고 있습니다. (여기서 말하는 2가지는 build tool(gradle, maven 등..)을 의미하는 것이 아닙니다. )

 

1번째 방법은 BOM을 이용한 개별 의존성 지정 방법과, 각 AWS 서비스별 별도 sdk를 사용하는 방법, 2번째 방법은 전체 SDK를 추가하는 방법 입니다.

 

 

3.1 개별 SDK 모듈 사용(BOM)

전체 AWS 서비스의 SDK를 로드하고 싶지 않은 경우에는 BOM을 이용해야 합니다. BOM을 이용한다면 document에서 말하는것과 같이 지정하는 각각의 별도 SDK 모듈들이 서로간의 버전이 자동으로 BOM에 의해 호환이 됩니다. 위 그림에서는 maven을 이용했으나 저는 gradle을 사용했습니다.

 

솔직히 전체 SDK를 다 사용할 일은 매우 드뭅니다. 따라서 이번 포스팅에서도 이 방법을 이용했습니다.

 

bom 의존성을 추가하고 난뒤에는, 각 모듈의 의존성을 추가해주면 됩니다. s3를 사용할 것 이므로, s3를 추가해주면 됩니다.

 

 

3.2 전체 모듈 사용

복잡한게 조금이라도 싫으시다면 (bom이 관리해주니 복잡할 것도 없지만.) 그냥 전체 SDK를 모두 로드해도 됩니다. 위의 의존성을 추가하면 되는데요, 실제로 해봤는데 dependency 추가하는 시간에만 몇분이 걸렸습니다..

 

 

 

 

 

4. S3 이용

드디어 S3를 이용해보도록 하겠습니다. 너무나 간단합니다.

 

4.1 ClientBuilder

첫째로 우선 AWS에 요청을할 Client 객체를 생성해야합니다. 권장되는 방법은 Builder를 사용하는 것 입니다. 보통 Amazon + service 이름 + ClientBuilder의 형태를 띄고 있습니다.

 

생성하는 방법은 AmazonsS3ClientBuilder의 standart()를 통해 AmazonS3 Client를 생성하며, credentialsregion정보를 넘겨줍니다.

 

credentials에는 앞서 IAM에서 생성한 S3 사용자에 대한 AccessKey, SecretKey 정보가 담겨있는 객체이며, Region은 S3Client가 사용할 Region을 지정하는 역할을 합니다.

 

 

credentials


Credentials는 AWSCredentials인터페이스 형을 띄며 구현 객체로는 BasicAWSCredentials()를 사용합니다. 저의 경우에는 test용도로 생성한 사용자이기 때문에 accessKey, secretKey를 공개했지만, 절대로 노출되어서는 안됩니다. 위의 정보를 안다면 AWS S3 서비스를 마음대로 이용이 가능합니다. 물론 사용자 정책에 허용된 범위에 한해서요.

 

*accessKey, secretKey를 모르고 노출했다면?

조심하라고 말씀은 드렸지만, 버전관리시스템을 이용하다보면 나도 모르게 credentials 정보들이 코드에 노출된 상태로 하나의 버전이 생성되었을 수도 있습니다. gitlab과 같이 private이 무료로 제공되는 repository를 이용했다면 모르겠지만, github의 경우에는 private이 유료이기 때문에, 아마도 public한 repository를 사용하고 계실 겁니다. 이럴때에는 accessKey, secretKey를 재발급 받는 방법이 있습니다.

 

IAM으로 접속한 뒤 사용자 탭 - 보안 자격 증명 탭 하단의 액세스 키 만들기라는 버튼을 클릭하면 새로운 액세스키를 발급 받을 수 있습니다. 물론, 기존에 노출된 액세세스 키는 제거를 해줍니다.

 

 

자, 이제 위의 코드들을 합쳐보면 client를 생성하는 코드는 위와 같습니다.

 

 

 

4.2 S3 Bucket 작업

S3를 이용하기 위해서 첫번째로 해야할 작업은 Bucket을 생성하는 것 입니다. 우리가 업로드할 파일들은 S3에서 Object라고 불릐우며, 이 Object를 담는 그릇(디렉토리?) 를 Bucket이라고 합니다.

 

4.2.1 Bucket 생성

s3Client.createBucket() 메소드에는 2개의 오버로딩된 메소드가 존재합니다.

 

createBucket(CreateBucketRequest createBucketRequest)


첫번째 CreateBucketRequest를 매개변수로 받는 createBucket() 메소드의 경우에는 Bucket을 만들때 AWS에서 설정할 수 있는 상세한 설정들을 담아 생성 요청을 할 수 있습니다.

 

예를 들면 위와 같이 CreateBucketRequestwithAccessControlList()메소드를 이용하여 Access 권한에 대한 설정을 담아 Bucket생성 요청을 보낼 수 있습니다.

 

 

createBucket(String bucketName)


두번째 메소드는 정말 간단합니다. 매개변수로 bucket의 이름만을 전달 받고 나머지 상세한 설정들은, 모두 defulat 값으로 생성이 됩니다.

 

 

Bucket 이름 주의점


주의할 점은 UpperCase를 사용하지 못하는 것과, Bucket이 저장되는 곳은 AWS Service의 모든 사용자와 공유하기 때문에, 고유한 bucket이름을 사용해야 한다는 것 입니다.

 

저는 2번째 createBucket(String bucketName) 메소드를 이용해 간단히 테스트를 해보겠습니다. 앞서 생성한 client code에 추가적으로 생성 코드만 넣어주면 끝입니다.

 

버킷이 성공적으로 생성되었습니다.

 

 

 

4.2.2 Object 업로드

object를 업로드하는 메소드도 Bucket생성처럼 크게 보면 2가지 방법이 존재합니다. putObject(PutObjectRequest), putObject(String, String, File) 이번에도 2번째 방법으로 간단히 요청을 해보겠습니다.

 

putObject(String bucketName, String key, File file)


우선 1번째로 실제로 업로드에 사용될 file을 생성해야합니다. file생성시에는 user의 home디렉토리에 생성되도록하기 위해, System.getProperty("user.home")을 이용해 운영체제로 부터 user의 home디렉토리 경로를 얻어오도록 했습니다.

 

2번째로 s3Client의 putObject메소드를 이용합니다. 첫번째 매개변수로는 앞서 만든 Bucket의 이름, 두번째 매개 변수로는 key라는 값인데, 실제 bucket안에 저장될 경로를 의미 합니다.

 

조금 더 자세히 설명 드리면 Bucket안에는 또 다시 하나의 fileSystem처럼 우리가 원하는 디렉토리 구조를 만들어 낼 수 있습니다. key는 그 경로의 file의 위치를 의미합니다. 중요한 점은 경로+file이름의 형태여야 한다는 것입니다.

 

세번째 매개변수로는 업로드할 file을 넣어주면 됩니다.

 

위의 코드를 실행하면 실제 bucket에 해당 경로가 생성되고, 파일이 업로드 된것을 볼 수 있습니다.

 

 

*object 업로드시 투명한 경로가 생성되는 경우


bucket에 object를 업로드하고 확인하니 중간에 투명한 경로가 생성된 분들이 있을 것입니다. 이는 putObject() 메소드의 2번재 매개변수인 key를 잘못 입력하여 나타나는 현상입니다.

 

바로 key의 제일 앞에 /를 포함하는 경우 발생하는 현상입니다. 즉, test/test.txt로 지정하면 해결됩니다.

 

 

 

4.3 환경변수로 부터 Credentials 얻어오기

앞서 말씀드렸던 것처럼 Credentials은 중요한 정보이기 때문에 코드상에 포함이 되면 안됩니다. 따라서, 별도로 Credentials(AccessKey)를 얻어올 방법이 필요한데, 이 방법 역시 AWS에서 제공하고 있습니다. 위 그림 처럼 여러가지 방법을 제공하는데 저는 이중, 환경변수로 부터 AccessKey를 얻어오는 방법을 사용할 것입니다.

 

 

4.3.1 환경변수에 AccessKey 등록

우선 환경변수로 부터 AccessKey를 불러오려면, 당연히 환경변수에 등록이 되어있어야합니다. Document를 참조하여 각 OS에 맞는 방법을 이용하여 등록을 합니다.

 

SDKGlobalConfiguration 클래스에 들어가보면 AWS에서 어떤 변수이름으로 환경변수에서 값을 가져오는지 확인 할 수 있습니다. 각 값에 맞추어 환경변수를 설정해줍니다.

 

 

4.3.2 AWSClient에서 환경변수를 통해 Credentials 불러오도록 설정

위와 같이 withCredentials() 메소드에 EnvironmentVariableCredentialsProvider() 를 넘겨주면 해당 객체가 자동으로 알맞은 환경변수를 불러와 AccessKey를 설정합니다.

 

 

환경변수를 등록했지만 아래와 같은 오류가 나타나는 경우

이는 IDE를 실행하는 시간에 환경변수를 미리 불러오기 때문입니다. 즉, IDE를 실행한 뒤 설정한 환경변수는 IDE에서 인식을 하지 못합니다. 따라서 IDE를 재시작하면 해결됩니다.