본문 바로가기

프로그래밍/배포

[AWS] AWS StepFunction을 이용한 이미지 처리

serverless

개요

2017년 11월 6일(월) 강남 메가존에서 열린 서버리스(serverless) 실습 교육과 아마존 서버리스 4주차 교육을 듣고 다시 복기해보는 포스팅입니다. 실습 코드는 https://github.com/awskrug/aws-serverless-workshops/tree/master/ImageProcessing 을 보고 참고했습니다.

서버리스

2014년도 AWS 람다 서비스가 시작되면서, 서비스 사이의 접착제의 기능을 해왔다. 람다는 람다가 서버 없이 이벤트라고 표현하는 작은 코드들을 올려 중간중간에 데이터를 넘기거나 붙이는 방식으로 활용하고 있다.

개발자들은 서버 없이도 애플리케이션을 만들수 있겠다고 생각했고, API 게이트웨이가 나오면서 더더욱 그런 생각들을 했왔다. 서버리스라는 용어는 아마존이 만든 말은 아니지만, 람다 등의 아키텍쳐를 가지고 개발자들이 서버리스의 형태로 만들기 시작했다.

서버리스 마이크로서비스 애플리케이션

람다가 원래 애플리케이션을 만드려고 했던 것이 아님. 그냥 앱의 이벤트가 발생하면 '동작시켜라!' 또는 ''이미지가 업로드되면 썸네일 만들어!' 이런거였는데, 사실 앱 내에는 다양한 트랜잭션이나 여러 이벤트들이 있음. 그러다보니 많은 사람들이 드는 의문이, 람다함수를 몇 개를 쪼개야 하는건지, 큰 함수를 다 써야 하는건지 의문이 생기기 시작함.

그래서 개발자들이 서버리스를 잘 배포할 수 있도록 오픈소스들을 만들어왔다(서버리스, APEC, ZAPPA 등 3가지가 많이 쓰이고 있음). 그래서 AWS는 SAM(Serverless Application Model)을 내놓았다. 아마존은 개발자들을 follow-up하면서 서버리스 오픈소스를 도와주는 서비스들을 빠르게 만들고 있다.

Step Functions

함수들 간에 실행 순서가 있을텐데, 함수를 얼마만큼 잘라야 하는지 등의 care방법이 화두가 되어서 AWS가 step function을 만들었다. Step Funciton이란 용어가 의미하는 것처럼 잘라진 함수들의 순서도를 그려준다.

AWS X-Ray

람다 함수의 성능 측정을 위한 서비스. 각 함수의 속도, 성능을 볼 수 있음. 본 실습에서는 이를 이용하진 않지만 아마존 교육에서 언급하고 간 서비스였다. 기존의 CloudWatch는 시각적으로 볼 수 없다. 데이터의 flow를 보기 위해서 Xray를 활용하면 좋다. 람다를 위해서만 만들어진게 아니고 서버 기반의 애플리케이션에서도 활용 가능하다.

실습을 진행하기 전

  1. 실습지역을 버지니아 북부로 변경
    스크린샷, 2017-11-09 16-54-40

  2. AWS CLI가 설치되어 있어야 함

    • 설치되지 않았다면 터미널 창을 열고 pip install awscli 명령어를 입력해 설치한다.
  3. IAM User 만들기

    • AWS CLI를 이용해서 Rekognition 컬렉션을 생성하거나 다른 명령어를 실행하기 위함

1. Amazone Rekognition 컬렉션 생성하기

터미널 창에서 아래 명령어를 실행

aws rekognition create-collection --region REPLACE_WITH_YOUR_CHOSEN_AWS_REGION --collection-id rider-photos

코드 입력 예

aws rekognition create-collection --region us-east-1 --collection-id rider-photos
aws rekognition create-collection --region us-west-2 --collection-id rider-photos
aws rekognition create-collection --region eu-west-1 --collection-id rider-photos

출력결과

{
  "CollectionArn": "aws:rekognition:us-west-2:012345678912:collection/rider-photos",
  "StatusCode": 200
}

2. AWS CloudFormation 사용하기

cloudformation은 아마존 자원을 뭉텅이로 일단 실행시키고, 반복되는 작업을 또 만들 수 있다는 장점이 있다.
JSON 또는 YAML 형식으로 작성된 템플릿(template)이라는 단위를 사용한다. 이 템플릿은 CloudFormation스택에서 프로비저닝 하려는 리소스를 의미한다. 프로비저닝(provisioning) 이란 특정 서비스를 제공받기 위하여 서비스 실행부터 시작해 서비스를 제공받기 전까지 처리되는 일련의 절차를 의미한다.
Working with AWS CloudFormation Templates

리전 실행하기
US East (N. Virginia) Launch Module in us-east-1
US West (Oregon) Launch Module in us-west-2
EU (Ireland) Launch Module 1 in eu-west-1

리전을 선택해서 Launch Stack을 눌러서 AWS CloudFormation을 실행했다.

스크린샷, 2017-11-06 20-03-15

위 과정을 진행하면 S3 Bucket도 자동으로 생성해주고, 다양한 많은 람다 함수들을 만들어준다.

스크린샷, 2017-11-06 20-04-09
create_in_progress 란 상태가 띄워지면서 만들어지기 시작함.

이로써, Amazone Rekognition 딥 러닝 기반의 이미지 분석 API를 활용한 함수가 만들어졌다.
스크린샷, 2017-11-07 15-50-12

출력(output) 탭을 눌러 값이 잘 출력되는지 확인해보자. 앞으로 이 값을 이용해 코드를 작성하기 때문에 이 창을 켜두고 있는 것이 좋다.

1단계(얼굴 인식)

얼굴 인식 알고리즘을 통해 인식 가능한 얼굴이 있는지 살펴본다. (단, 선글라스나 마스크를 껴서 얼굴을 인식할 수 없거나 얼굴이 여러개라면 접근을 허락하지 않는다.)

rider-photo-state-machine.json

{
  "Comment": "Rider photo processing workflow",
  "StartAt": "FaceDetection",
  "States": {
    "FaceDetection": {
      "Type": "Task",
      "Resource": "REPLACE_WITH_FaceDetectionFunctionArn",
      "ResultPath": "$.detectedFaceDetails",
      "End": true,
      "Catch": [
        {
          "ErrorEquals": [
            "PhotoDoesNotMeetRequirementError"
          ],
          "ResultPath": "$.errorInfo",
          "Next": "PhotoDoesNotMeetRequirement"
        }
      ]
    },
    "PhotoDoesNotMeetRequirement": {
      "Type": "Task",
      "Resource": "REPLACE_WITH_NotificationPlaceholderFunctionArn",
      "End": true
    }
  }
}

위 코드를 복사해 코드를 생성한다
스크린샷, 2017-11-09 15-18-19

코드 생성에 성공했을 때 출력 메시지
스크린샷, 2017-11-09 15-18-57
성공적으로 코드를 등록하고 나면 성공적으로 생성되었다는 메시지를 보여준다.
이제 New Execution을 눌러서 아래 내용을 추가해보자.

{
  "userId": "user_a",
  "s3Bucket": "REPLACE_WITH_YOUR_BUCKET_NAME",
  "s3Key": "1_happy_face.jpg"
}

s3Bucket에 대한 내용은 CloudFormation에서 생성한 stack을 누르고 출력에서 RiderPhotoS3Bucket에 대한 값을 사용하면 된다.
스크린샷, 2017-11-09 15-44-46

최종 결과는 위와 같다.

실습해보기

before (사본)yoon
내가 가지고 있는 파일로 실험을 해봤다. 두 사진이 있다. 왼쪽 사진은 2명의 인물이 있고, 오른쪽 사진은 1명의 인물이 있다. FaceDetection의 검사 조건은 '인식 가능한 얼굴이어야 하며, 여러 사람이 존재하면 안된다.'라고 위에서 언급했었다. 그러면 두 사진은 서로 다른 워크플로우로 진행되어야 한다. 두 사진을 S3 버킷에 업로드하고 검사를 진행해보겠다.
스크린샷, 2017-11-09 16-10-42
비포 선라이즈의 사진은 두 명이 인식되었기 때문에 PhotoDoesNotMeetRequirement 조건을 띄운다.

스크린샷, 2017-11-09 16-10-23
반면, 윤계상의 사진은 정상적인 1명으로 인식되었다. (선글라스도 착용하지 않았기 때문에!)

중복 가입 방지하기

rider-photo-state-machine.json 위에서 작성했던 json파일에 아래 내용을 추가로 넣도록 한다.

,
"CheckFaceDuplicate": {
  "Type": "Task",
  "Resource": "REPLACE_WITH_FaceSearchFunctionArn",
  "ResultPath": null,
  "End": true,
  "Catch": [
    {
      "ErrorEquals": [
        "FaceAlreadyExistsError"
      ],
      "ResultPath": "$.errorInfo",
      "Next": "PhotoDoesNotMeetRequirement"
    }
  ]
}

바꿔야 하는 ResourceCloudFormation의 스택의 output에서 확인할 수 있다. 또, FaceDetection의 상태 머신의 종료를 표시하는 라인을 아래와 같이 수정한다.
기존

     	 "End": true,

변경 후

  		"Next": "CheckFaceDuplicate",

자원 삭제 방법

  1. AWS Step Function에 대쉬보드에 들어가서 상태머신을 삭제한다.

  2. AWS S3 버킷을 비운다(empty). delete 하면 안된다!

  3. AWS CloudFormation에서 Delete Stack을 한다

  4. AWS Rekognition 컬렉션을 삭제한다.

    aws rekognition delete-collection --region REPLACE_WITH_YOUR_CHOSEN_AWS_REGION --collection-id rider-photos
    

    터미널 창에서 지역에 맞는 코드를 선택하면 된다.

    aws rekognition delete-collection --region us-east-1 --collection-id rider-photos
    aws rekognition delete-collection --region us-west-2 --collection-id rider-photos
    aws rekognition delete-collection --region eu-west-1 --collection-id rider-photos
    

    성공한 경우 StatusCode 200을 받으면 성공이다.

발생했던 버그(?)

Pasted image at 2017_11_07 04_59 PM
코드 생성 당시에 IAM role이 제대로 출력되지 않았다. 위 스크린샷처럼 드롭다운에서 검은 밑줄만 뜬다. 원인은 CloudFormation 실습을 마친 후 잘못 삭제해서 그런 것이 아닐까 싶다.

해결방법

스크린샷, 2017-11-11 19-53-11
IAM 콘솔로 들어가서 roles 탭에서 권한(role)을 추가시킨다. 생성해야할 권한은 SWF(Simple WorkFlow)다. 생성이 완료되면 방금 만든 권한을 클릭해서 Trust relationships 탭에 들어가 코드를 수정해준다. 그다음 아래와 같이 수정한다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "swf.amazonaws.com",
          "states.us-east-1.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

미국 동부 버지니아 리전을 사용하고 있기 때문에 us-east-1을 적어주었다. 자세한 문서는 아마존 공식 문서를 참고했다.