[Hands On] AWS 환경에서 서버리스 OCR 애플리케이션 구축

1. 서버리스란?

서버리스(Serverless)는 클라우드 제공업체가 기반 서버 인프라를 전적으로 관리하는 클라우드 네이티브 모델입니다. 개발자는 서버 인프라를 프로비저닝하거나 관리할 필요 없이 애플리케이션 코드를 실행할 수 있습니다. 이러한 환경에서는 클라우드 제공 업체가 애플리케이션의 요구 사항에 따라 자동으로 인프라를 확장하고 구성합니다. 이로써 개발자는 서버 인프라 관련 작업을 신경 쓸 필요가 없고 애플리케이션 로직에 집중할 수 있으며, 사용한 리소스에 대해서만 비용을 지불합니다.


서버리스의 장점

  • 운영 비용 절감
    • 사용한 리소스에 대해서만 요금이 부과되므로 효율적인 비용 관리가 가능합니다.
  • 유연한 확장성
    • 서버리스 플랫폼은 요청량에 따라 자동으로 애플리케이션을 확장합니다.
    • 이는 트래픽 증가 시 자원을 동적으로 할당하여 성능과 응답 시간을 유지하는 데 도움이 됩니다.
  • 운영 부담 감소
    • 서버 관리와 유지 보수 작업(예: 패치 설치, 시스템 업그레이드)은 클라우드 제공업체에 의해 처리되므로 개발자는 애플리케이션 코드에 집중할 수 있습니다.
  • 빠른 배포 속도
    • 함수 기반의 아키텍처로 인해 작은 단위로 개발하고 테스트할 수 있으며, 변경 사항에 대한 빠른 반응이 가능합니다.
  • 이벤트 기반 아키텍처
    • 이벤트 트리거 기능을 사용하여 외부 이벤트(예: 메시지 큐, 데이터 업데이트 등)에 응답하는 함수형 코드를 작성할 수 있습니다.
  • 다양한 통합 및 서비스
    • 서버리스 플랫폼은 다양한 클라우드 서비스와의 통합을 제공합니다.
    • 예를 들어, 데이터베이스, 메시징 서비스, 인증 및 인가 서비스 등과 쉽게 통합할 수 있습니다.


아키텍처클라우드 벤더가 관리이용자가 관리
서버리스– 데이터 소스의 통합
– 보안 구성, 업데이트
– 네트워크 구성, 태스크 관리
– 스케일링
– 프로비저닝
– 서버 관리
– 물리 하드웨어, 소프트웨어, 네트워크, 시설
– 애플리케이션 코드
컨테이너– 컨테이너 오케스트레이션
– 클러스터 스케일링
– 프로비저닝
– 서버 관리
– 물리 하드웨어, 소프트웨어, 네트워크, 시설
– 애플리케이션 코드
– 데이터 소스의 통합
– 보안 구성, 업데이트
– 네트워크 구성, 태스크 관리
가상머신(VM)– 물리 하드웨어, 소프트웨어, 네트워크, 시설– 애플리케이션 코드
– 데이터 소스의 통합
– 보안 구성, 업데이트
– 네트워크 구성, 태스크 관리
– 클러스터 스케일링
– 프로비저닝
– 서버 관리
각 아키텍처 별 관리해야 하는 영역


서버리스의 단점

  • 제한된 실행 시간
    • 서버리스 플랫폼에서 제공하는 실행 시간에는 한계가 있습니다. 예를 들어 AWS Lambda의 경우, 최대 실행 시간은 15분입니다.
  • 로컬 디버깅의 어려움
    • 로컬 컴퓨터에서 직접 코드를 디버깅하기 어려울 수 있으며, 원격 디버깅 도구나 로그 분석 등의 추가 도구가 필요합니다.
  • 벤더 종속성
    • 각 클라우드 공급자마다 독특한 구현 방식과 기능이 있으므로 특정 플랫폼 및 기술 스택에 종속될 가능성이 커집니다.
  • 제약사항
    • 일부 서비스에서 파일 시스템 접근 등 몇 가지 기능 및 자원 사용에 제약 사항이 있는 경우도 있어서 모든 유형의 애플리케이션이 적합하지 않을 수 있습니다.
  • 초기 부하 지연
    • 처음 호출될 때 인터넷 연결 및 컨테이너 시작 등 초기 부하 지연 시간(Cold Start) 문제가 발생할 가능성이 있습니다.
  • 상태 유지 문제
    • 서버리스 함수는 일반적으로 “stateless”이므로 각 요청은 독립적으로 처리되며 이전 요청의 상태를 기억하지 못합니다.
    • 상태를 유지해야 하는 애플리케이션(예: 웹 소켓 또는 실시간 스트리밍 등)에는 적합하지 않을 수 있습니다.
  • 비용 추정과 관리
    • 비용이 사용량에 따라 변동되므로 예상치 못한 비용 발생 가능성이 있으며 비용 추정과 관리도 어려울 수 있습니다.

그러나 모든 애플리케이션이 서버리스 아키텍처를 사용하기 적합한 것은 아닙니다. 서버리스의 특성을 파악하여 개발할 애플리케이션의 요구사항, 복잡성, 예상 트래픽 패턴 등을 고려하여 서버리스가 적절한 선택인지를 결정해야 합니다.


여러 특징을 가진 서버리스 서비스를 실습으로 알아보기 위해 AWS 클라우드 환경에서 서버리스 OCR 애플리케이션을 구성해보도록 하겠습니다. 참고로 OCR(Optical Character Recognition)은 광학 문자 인식을 뜻하며 텍스트 이미지를 컴퓨터가 읽을 수 있는 포맷의 텍스트로 변환하는 과정을 의미합니다.


2. Hands-On

사용할 서비스: S3, Lambda, Rekognition, DynamoDB

시나리오 워크플로는 다음과 같습니다.

  1. 사용자가 텍스트가 있는 이미지 파일을 S3 버킷에 올립니다.
  2. 그러면 Lambda 함수가 트리거되어 파일을 읽고 Rekognition 서비스를 이용하여 이미지 내의 텍스트를 추출합니다.
  3. 추출된 텍스트를 DynamoDB 테이블에 작성합니다.


1. 이미지를 업로드할 S3 버킷 생성

  1. A mazon S3 > 버킷 > 버킷 만들기를 클릭합니다.
  2. 버킷 이름을 지정하고 나머지 옵션은 기본으로 두고 생성합니다.


2. Lambda 실행에 필요한 IAM 역할 생성

1. s3-trigger 정책 생성

  1. IAM > 정책 > 정책 생성를 클릭합니다.

2. 정책 편집기에서 JSON을 클릭하고 아래의 JSON를 붙여 넣어줍니다.

{
"Version": "2012-10-17",
    "Statement": [
        {
"Effect": "Allow",
            "Action": [
                "logs:PutLogEvents",
                "logs:CreateLogGroup",
                "logs:CreateLogStream"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
"Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*/*"
        }
    ]
}

3. 정책의 이름을 기입 후, 정책에 정의된 권한을 검토하고 생성합니다.


2. lambda 역할 생성

  1. IAM > 역할 > 역할 만들기를 클릭합니다.

2. 신뢰할 수 있는 엔터티 [AWS 서비스], 사용 사례 [Lambda]를 클릭하고 다음으로 넘어갑니다.

3. 이전에 만든 [s3-trigger-policy]와, [AmazonDynamoDBFullAccess], [AmazonRekognitionFullAccess] 권한을 추가합니다

4. 역할의 이름을 lambda_role_for_s3_dynamodb_rekognition이라고 기입하고, 추가한 권한이 제대로 들어갔는지 확인 후 생성합니다.


3. Lambda 함수 생성하기

Lambda 함수를 생성하는 3가지 방법
  • 새로 작성: 처음부터 새로 함수를 작성하는 경우에 사용합니다.
  • 블루프린트 사용: AWS에서 제공하는 템플릿으로, 주로 Lambda와 다른 AWS 서비스를 연동하는 내용들이 샘플 형태로 제공됩니다.
  • 컨테이너 이미지: 함수에 대해 배포할 컨테이너 이미지를 선택하는 것입니다. (함수에 사용할 컨테이너 이미지를 ECR에서 지정해야 합니다)


  1. 함수 이름은 rekognition_function, 런타임은 Python 3.11, 아키텍처는 x86_64로 선택합니다.
  2. 실행 역할은 위에서 생성한 [lambda_role_for_s3_dynamodb _rekognition] 을 선택합니다.


고급 설정에서 적용할 수 있는 4가지 옵션
  • 코드 설명 활성화
    • 코드 서명 구성을 사용하여 함수에 대한 코드 서명을 활성화합니다.
    • 코드 서명을 사용하면 코드가 승인된 소스에 의해 서명되었고 서명 이후 변경되지 않았는지와 코드 서명이 만료되거나 취소되지 않았는지 확인할 수 있습니다.
  • 함수 URL 구성
    • 함수 URL은 함수의 전용 HTTP(S) 엔드포인트입니다.
    • 함수 URL이 구성되면 이를 사용하여 브라우저, curl, Postman 또는 HTTP 클라이언트를 통해 함수를 호출할 수 있습니다.
  • 태그 활성화
    • Lambda 함수에 연결할 수 있는 선택적 키-값 페어(태그)입니다.
  • VPC 활성화
    • Lambda 함수가 사용자 지정 VPC의 리소스에 액세스하도록 구성할 수도 있습니다.
    • 사용자 지정 VPC는 데이터베이스, 캐시 인스턴스, 내부 서비스 등과 같은 리소스의 프라이빗 네트워크를 정의합니다.


본 실습에서는 고급 설정은 선택하지 않고(기본으로 두고) 함수 생성을 하겠습니다.


4. Lambda 함수에 트리거 추가

  1. 위에서 만든 Lambda 함수에 트리거를 추가합니다.

  • Recursive invocation(재귀 호출)
    • 함수가 S3 버킷에 오브젝트를 작성(생성)하는 경우, 입력과 출력에 서로 다른 S3 버킷을 사용하고 있는지 확인해야 합니다.
    • 동일한 버킷에 작성(생성)하면 재귀 호출이 생성될 위험이 커지고, 이에 따라 Lambda 사용량이 증가하고 비용이 증가할 수 있습니다.

Lambda 함수에 S3 버킷을 트리거로 추가하여 버킷에 오브젝트를 write하는 경우, 입력과 출력이 모두 같은 버킷일 시 재귀 호출이 만들어질 위험이 커지고 이는 사용량 및 비용 증가로 이어지기 때문에 위와 같은 주의 문구(재귀 호출이 발생하면 Lambda 사용량이 증가하여 비용이 증가할 수 있음)가 뜹니다.


5. DynamoDB 테이블 생성

  1. DynamoDB > 테이블 > 테이블 생성을 클릭합니다.
  2. 테이블 이름은 rekognition_db로 입력합니다.
  3. 파티션 키는 이미지의 이름(image_id)로 입력합니다.

4. 테이블 설정은 기본 설정을 클릭합니다.

세세한 설정이 필요하신 분은 설정 사용자 지정을 클릭하여 자신이 원하는 값으로 테이블 클래스, 용량 모드 등 설정을 변경할 수 있습니다.


6. Lambda 함수 코드 수정

  1. 위에서 만든 Lambda 함수에서 [코드]탭을 클릭하고 아래의 소스 코드로 수정합니다.
  2. Ctrl + S를 눌러 저장하고 Deploy를 눌러 코드를 배포합니다.
import json
import urllib.parse
import boto3

s3 = boto3.client('s3')

def detect_text(photo, bucket):
    client = boto3.client('rekognition')
    response = client.detect_text(Image={'S3Object': {'Bucket': bucket, 'Name': photo}})
    lst=[]
    textDetections = response['TextDetections']
    for text in textDetections:
        if 'ParentId' in text:
            continue
        lst.append(text['DetectedText'])
    return ' '.join(lst)

def insert_data(image_id,detect_text):
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('rekognition_db')
    data = {"image_id":image_id,"detect_text":detect_text}
    response = table.put_item(Item=data)

def lambda_handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    photo = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    text = detect_text(photo,bucket)
    try:
        insert_data(photo,text)
    except Exception as e:
        raise Exception


7. S3 버킷에 이미지 업로드

  1. S3 버킷에 위의 이미지를 업로드 합니다.


8. DyanmoDB 테이블 항목 확인

2. Dynamom,DB > 테이블 > 항목 탐색을 클릭합니다.

3. 위에서 생성한 rekognition_db 테이블을 클릭하고 [항목 스캔 또는 쿼리]에서 스캔을 실행하면 S3에 업로드된 이미지에서 텍스트를 추출한 것을 볼 수 있습니다.

4. 반환된 항목은 편집, 복제, 삭제, CSV로 다운로드의 작업도 가능합니다.


9. Lambda 함수 지표 확인

성공적인 호출 및 함수 오류를 유발하는 호출을 포함하여 함수 코드가 호출된 횟수가 1입니다. (S3에 이미지 파일을 업로드해서 함수가 호출됨)

추가로 함수 코드가 이벤트를 처리하는 데 소요되는 시간이 2.6s가 걸린 것을 알 수 있습니다.


3. 마무리

이처럼 AWS Lambda를 사용하여 S3 버킷에 업로드된 이미지에서 텍스트를 인식하고, 그 결과를 DynamoDB에 저장하는 서버리스 OCR(Optical Character Recognition) 애플리케이션을 구축해보았습니다.

서버리스 서비스를 사용하여 애플리케이션을 구성하게 되면 클라우드 네이티브한 이점을 취할 수 있어 클라우드 환경에서 더욱더 최적화되고 효율적으로 구축, 배포, 운영할 수 있습니다.

이처럼 서버리스 아키텍처는 많은 이점을 제공하지만, 그러한 이점이 모든 애플리케이션에 적합하다는 의미는 아닙니다. 서버리스 아키텍처의 특성상 일부 애플리케이션 유형에 대해서는 제약 사항이나 불편함을 초래할 수 있습니다. 따라서 서버리스 아키텍처를 도입하기 전에 애플리케이션의 특성을 잘 파악하고, 서버리스 아키텍처의 장단점을 고려하여 적절한지 아닌지를 결정해야 합니다.


참고:

https://docs.aws.amazon.com/ko_kr/rekognition/latest/dg/text-detecting-text-procedure.html

https://docs.aws.amazon.com/rekognition/latest/APIReference/API_DetectText.html

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다