기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
Amazon Rekognition과 Lambda를 사용하여 Amazon S3 버킷의 자산에 태그 지정
이 자습서에서는 Amazon S3 버킷에 있는 디지털 자산에 자동으로 태그를 지정하는 AWS Lambda 함수를 생성합니다. Lambda 함수는 지정된 Amazon S3 버킷에서 모든 객체를 읽습니다. 버킷의 각 객체에 대해 Amazon Rekognition 서비스로 이미지를 전달하여 일련의 레이블을 생성합니다. 각 레이블은 이미지에 적용되는 태그를 생성하는 데 사용됩니다. Lambda 함수를 실행하면 주어진 Amazon S3 버킷의 모든 이미지를 기반으로 태그를 자동으로 생성하여 이미지에 적용합니다.
예를 들어, Lambda 함수를 실행하고 Amazon S3 버킷에 이 이미지가 있다고 가정해 보겠습니다.

그러면 애플리케이션이 자동으로 태그를 생성하여 이미지에 적용합니다.

참고
이 자습서에서 사용하는 서비스는 AWS 프리 티어의 일부입니다. 자습서를 모두 마치면 요금이 부과되지 않도록 자습서를 따라하는 중에 만든 모든 리소스를 종료하는 것을 권장합니다.
이 자습서에서는 AWS SDK for Java 버전 2를 사용합니다. 추가 Java V2 자습서를 보려면 AWS 설명서 SDK 예제 GitHub 리포지토리
사전 조건
시작하기 전에 AWS SDK for Java 설정의 단계를 완료해야 합니다. 그 후 다음 항목들이 있는지 확인하세요.
Java 1.8 JDK
Maven 3.6 이상
5~7개의 자연 이미지가 들어 있는 Amazon S3 버킷 Lambda 함수가 이 이미지를 읽습니다.
IAM Lambda 역할 구성
이 자습서에서는 Amazon Rekognition 및 Amazon S3 서비스를 사용합니다. Lambda 함수에서 이러한 서비스를 간접적으로 호출할 수 있는 정책을 포함하도록 lambda-support 역할을 구성합니다.
역할을 구성하려면
에 로그인 AWS Management Console 하고 https://console.aws.amazon.com/iam/
IAM 콘솔을 엽니다. -
탐색 창에서 역할을 선택한 후 역할 생성을 선택합니다.
-
AWS 서비스와 Lambda를 차례대로 선택합니다.
-
권한 탭을 선택합니다.
-
AWSLambdaBasicExecutionRole을 검색합니다.
-
다음 태그를 선택합니다.
-
검토를 선택합니다.
-
역할 이름을 lambda-support로 지정합니다.
-
역할 생성을 선택합니다.
-
lambda-support를 선택하여 개요 페이지를 봅니다.
-
정책 연결을 선택합니다.
-
정책 목록에서 AmazonRekognitionFullAccess를 선택합니다.
-
정책 연결을 선택합니다.
-
AmazonS3FullAccess를 검색한 다음 정책 연결을 선택합니다.
프로젝트 생성
새 Java 프로젝트를 생성한 다음 필요한 설정과 종속성을 사용하여 Maven pom.xml를 구성합니다. pom.xml 파일이 다음과 같은지 확인합니다.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>WorkflowTagAssets</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>java-basic-function</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.10.54</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.2.1</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.6</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.13.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j18-impl</artifactId> <version>2.13.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>com.googlecode.json-simple</groupId> <artifactId>json-simple</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>rekognition</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.2</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
코드 쓰기
AWS Lambda 런타임 Java API를 사용하여 Lambda 함수를 정의하는 Java 클래스를 생성합니다. 이 예제에는 Handler라는 Lambda 함수의 Java 클래스 1개와 이 사용 사례에 필요한 추가 클래스가 있습니다. 다음 그림은 이 프로젝트의 Java 클래스를 보여 줍니다. 참고로 모든 Java 클래스는 com.example.tags라는 이름의 패키지에 들어 있습니다.

코드에 사용할 다음과 같은 Java 클래스를 생성합니다.
핸들러는 Lambda Java 런타임 API를 사용하고이 AWS 자습서에 설명된 사용 사례를 수행합니다. 실행되는 애플리케이션 로직은 handleRequest 메서드에 있습니다.
S3Service는 Amazon S3 API를 사용하여 S3 작업을 수행합니다.
AnalyzePhotos는 Amazon Rekognition API를 사용하여 이미지를 분석합니다.
BucketItem은 Amazon S3 버킷 정보를 저장하는 모델을 정의합니다.
WorkItem은 Amazon Rekognition 데이터를 저장하는 모델을 정의합니다.
Handler 클래스
이 Java 코드는 Handler 클래스를 나타냅니다. 클래스는 Lambda 함수에 전달된 플래그를 읽습니다. S3Service.ListBucketObjects 메서드는 List 객체를 반환하며 여기서 각 요소는 객체 키를 나타내는 문자열 값입니다. 플래그 값이 true인 경우 s3Service.tagAssets 메서드를 직접 호출하여 목록을 반복하고 태그를 각각의 객체에 적용함으로써 태그를 적용합니다. 플래그 값이 false이면 태그를 삭제하는 s3Service.deleteTagFromObject 메서드가 간접적으로 호출됩니다. 또한 LambdaLogger 객체를 사용하여 Amazon CloudWatch 로그에 메시지를 기록할 수 있다는 점도 참고하세요.
참고
반드시 bucketName 변수에 버킷 이름을 할당해야 합니다.
package com.example.tags; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.LambdaLogger; import java.util.ArrayList; import java.util.List; import java.util.Map; public class Handler implements RequestHandler<Map<String,String>, String> { @Override public String handleRequest(Map<String, String> event, Context context) { LambdaLogger logger = context.getLogger(); String delFlag = event.get("flag"); logger.log("FLAG IS: " + delFlag); S3Service s3Service = new S3Service(); AnalyzePhotos photos = new AnalyzePhotos(); String bucketName = "<Enter your bucket name>"; List<String> myKeys = s3Service.listBucketObjects(bucketName); if (delFlag.compareTo("true") == 0) { // Create a List to store the data. List<ArrayList<WorkItem>> myList = new ArrayList<>(); // loop through each element in the List and tag the assets. for (String key : myKeys) { byte[] keyData = s3Service.getObjectBytes(bucketName, key); // Analyze the photo and return a list where each element is a WorkItem. ArrayList<WorkItem> item = photos.detectLabels(keyData, key); myList.add(item); } s3Service.tagAssets(myList, bucketName); logger.log("All Assets in the bucket are tagged!"); } else { // Delete all object tags. for (String key : myKeys) { s3Service.deleteTagFromObject(bucketName, key); logger.log("All Assets in the bucket are deleted!"); } } return delFlag; } }
S3Service 클래스
다음 클래스는 Amazon S3 API를 사용하여 S3 작업을 수행합니다. 예를 들어 getObjectBytes 메서드는 이미지를 나타내는 바이트 배열을 반환합니다. 마찬가지로, listBucketObjects 메서드는 List 객체를 반환하며 여기서 각 요소는 키 이름을 나타내는 문자열 값입니다.
package com.example.tags; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectTaggingRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.model.ListObjectsResponse; import software.amazon.awssdk.services.s3.model.S3Object; import software.amazon.awssdk.services.s3.model.GetObjectTaggingResponse; import software.amazon.awssdk.services.s3.model.ListObjectsRequest; import java.util.ArrayList; import java.util.List; import software.amazon.awssdk.services.s3.model.Tagging; import software.amazon.awssdk.services.s3.model.Tag; import software.amazon.awssdk.services.s3.model.GetObjectTaggingRequest; import software.amazon.awssdk.services.s3.model.DeleteObjectTaggingRequest; public class S3Service { private S3Client getClient() { Region region = Region.US_WEST_2; return S3Client.builder() .region(region) .build(); } public byte[] getObjectBytes(String bucketName, String keyName) { S3Client s3 = getClient(); try { GetObjectRequest objectRequest = GetObjectRequest .builder() .key(keyName) .bucket(bucketName) .build(); // Return the byte[] from this object. ResponseBytes<GetObjectResponse> objectBytes = s3.getObjectAsBytes(objectRequest); return objectBytes.asByteArray(); } catch (S3Exception e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } return null; } // Returns the names of all images in the given bucket. public List<String> listBucketObjects(String bucketName) { S3Client s3 = getClient(); String keyName; List<String> keys = new ArrayList<>(); try { ListObjectsRequest listObjects = ListObjectsRequest .builder() .bucket(bucketName) .build(); ListObjectsResponse res = s3.listObjects(listObjects); List<S3Object> objects = res.contents(); for (S3Object myValue: objects) { keyName = myValue.key(); keys.add(keyName); } return keys; } catch (S3Exception e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } return null; } // Tag assets with labels in the given list. public void tagAssets(List myList, String bucketName) { try { S3Client s3 = getClient(); int len = myList.size(); String assetName = ""; String labelName = ""; String labelValue = ""; // Tag all the assets in the list. for (Object o : myList) { // Need to get the WorkItem from each list. List innerList = (List) o; for (Object value : innerList) { WorkItem workItem = (WorkItem) value; assetName = workItem.getKey(); labelName = workItem.getName(); labelValue = workItem.getConfidence(); tagExistingObject(s3, bucketName, assetName, labelName, labelValue); } } } catch (S3Exception e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } // This method tags an existing object. private void tagExistingObject(S3Client s3, String bucketName, String key, String label, String LabelValue) { try { // First need to get existing tag set; otherwise the existing tags are overwritten. GetObjectTaggingRequest getObjectTaggingRequest = GetObjectTaggingRequest.builder() .bucket(bucketName) .key(key) .build(); GetObjectTaggingResponse response = s3.getObjectTagging(getObjectTaggingRequest); // Get the existing immutable list - cannot modify this list. List<Tag> existingList = response.tagSet(); ArrayList<Tag> newTagList = new ArrayList(new ArrayList<>(existingList)); // Create a new tag. Tag myTag = Tag.builder() .key(label) .value(LabelValue) .build(); // push new tag to list. newTagList.add(myTag); Tagging tagging = Tagging.builder() .tagSet(newTagList) .build(); PutObjectTaggingRequest taggingRequest = PutObjectTaggingRequest.builder() .key(key) .bucket(bucketName) .tagging(tagging) .build(); s3.putObjectTagging(taggingRequest); System.out.println(key + " was tagged with " + label); } catch (S3Exception e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } // Delete tags from the given object. public void deleteTagFromObject(String bucketName, String key) { try { DeleteObjectTaggingRequest deleteObjectTaggingRequest = DeleteObjectTaggingRequest.builder() .key(key) .bucket(bucketName) .build(); S3Client s3 = getClient(); s3.deleteObjectTagging(deleteObjectTaggingRequest); } catch (S3Exception e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } } }
AnalyzePhotos 클래스
다음 Java 코드는 AnalyzePhotos 클래스를 나타냅니다. 이 클래스는 Amazon Rekognition API를 사용하여 이미지를 분석합니다.
package com.example.tags; import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.rekognition.RekognitionClient; import software.amazon.awssdk.services.rekognition.model.Image; import software.amazon.awssdk.services.rekognition.model.DetectLabelsRequest; import software.amazon.awssdk.services.rekognition.model.DetectLabelsResponse; import software.amazon.awssdk.services.rekognition.model.Label; import software.amazon.awssdk.services.rekognition.model.RekognitionException; import java.util.ArrayList; import java.util.List; public class AnalyzePhotos { // Returns a list of WorkItem objects that contains labels. public ArrayList<WorkItem> detectLabels(byte[] bytes, String key) { Region region = Region.US_EAST_2; RekognitionClient rekClient = RekognitionClient.builder() .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .region(region) .build(); try { SdkBytes sourceBytes = SdkBytes.fromByteArray(bytes); // Create an Image object for the source image. Image souImage = Image.builder() .bytes(sourceBytes) .build(); DetectLabelsRequest detectLabelsRequest = DetectLabelsRequest.builder() .image(souImage) .maxLabels(10) .build(); DetectLabelsResponse labelsResponse = rekClient.detectLabels(detectLabelsRequest); // Write the results to a WorkItem instance. List<Label> labels = labelsResponse.labels(); ArrayList<WorkItem> list = new ArrayList<>(); WorkItem item ; for (Label label: labels) { item = new WorkItem(); item.setKey(key); // identifies the photo. item.setConfidence(label.confidence().toString()); item.setName(label.name()); list.add(item); } return list; } catch (RekognitionException e) { System.out.println(e.getMessage()); System.exit(1); } return null ; } }
BucketItem 클래스
다음 Java 코드는 Amazon S3 객체 데이터를 저장하는 BucketItem 클래스를 나타냅니다.
package com.example.tags; public class BucketItem { private String key; private String owner; private String date ; private String size ; public void setSize(String size) { this.size = size ; } public String getSize() { return this.size ; } public void setDate(String date) { this.date = date ; } public String getDate() { return this.date ; } public void setOwner(String owner) { this.owner = owner ; } public String getOwner() { return this.owner ; } public void setKey(String key) { this.key = key ; } public String getKey() { return this.key ; } }
WorkItem 클래스
다음 Java 코드는 WorkItem 클래스를 나타냅니다.
package com.example.tags; public class WorkItem { private String key; private String name; private String confidence ; public void setKey (String key) { this.key = key; } public String getKey() { return this.key; } public void setName (String name) { this.name = name; } public String getName() { return this.name; } public void setConfidence (String confidence) { this.confidence = confidence; } public String getConfidence() { return this.confidence; } }
프로젝트 패키지화
다음 Maven 명령을 사용하여 프로젝트를.jar(JAR) 파일로 패키징합니다.
mvn package
JAR 파일은 대상 폴더(프로젝트 폴더의 하위 폴더)에 있습니다.

참고
프로젝트의 POM 파일에 maven-shade-plugin 사용된 것을 볼 수 있습니다. 이 플러그인은 필수 종속성을 포함하는 JAR을 만드는 역할을 합니다. 이 플러그인 없이 프로젝트를 패키지화하려고 하면 필수 종속성이 JAR 파일에 포함되지 않아 ClassNotFoundException이 발생합니다.
Lambda 함수 배포
Lambda 콘솔
을 엽니다. 함수 생성을 선택합니다.
새로 작성을 선택합니다.
기본 정보 섹션에서 이름으로 cron을 입력합니다.
런타임에서 Java 8을 선택합니다.
기존 역할 사용을 선택한 다음, lambda-support(생성한 IAM 역할)를 선택합니다.
함수 생성(Create function)을 선택합니다.
코드 항목 유형에서 .zip 또는 .jar 파일 업로드를 선택합니다.
업로드를 선택한 다음 생성한 JAR 파일을 찾아보세요.
핸들러의 경우 정규화된 함수의 전체 이름, 예를 들어 com.example.tags.Handler:handleRequest(com.example.tags는 패키지를 지정하고, 핸들러는 :: 및 메서드 이름 앞에 오는 클래스입니다)를 입력합니다.
저장(Save)을 선택합니다.
Lambda 메서드 테스트
자습서의 이 시점에서 Lambda 함수를 테스트할 수 있습니다.
Lambda 콘솔에서 테스트 탭을 클릭한 후 다음 JSON을 입력합니다.
{ "flag": "true" }
참고
true 태그를 전달하면 디지털 자산에 태그를 지정하고 false를 전달하면 태그가 삭제됩니다.
간접 호출 버튼을 선택합니다. Lambda 함수가 간접 호출되면 성공 메시지를 확인할 수 있습니다.
축하합니다. Amazon S3 버킷에 있는 이영 자산에 태그를 자동으로 적용하는 AWS Lambda 함수를 생성했습니다. 이 자습서의 시작 부분에서 설명한 것처럼, 요금이 부과되지 않도록 하려면 이 자습서를 진행하는 동안 생성한 모든 리소스를 종료해야 합니다.
자세한 AWS 다중 서비스 예제는 AWS 설명서 SDK 예제 GitHub 리포지토리