...
- AWS 관리 콘솔에서 Lambda 서비스로 이동합니다.
- Create a function 버튼을 클릭하여 Lambda 함수를 하나 만들겠습니다. 또는 좌측 메뉴를 열고, Dashboard나 Functions 메뉴를 선택하고, 우측의 Create function 버튼을 클릭합니다.
- 새로운 함수의 Name은 PostNews 라고 만듭니다. Runtime은 Python 3.8 을 선택합니다. Role은 Choose an existing role 을 선택하고, 위에서 생성한 IAM Role인 NewsRole 을 선택합니다. 그리고 우측 하단의 Create function 버튼을 클릭합니다.
Lambda 함수가 정상적으로 만들어진 것을 확인할 수 있습니다. Lambda의 실행 구조는 Function Overview 메뉴 에서 볼 수 있습니다. 트리거 되면, PostNews가 실행되고, 코드 안에서 특정 서비스로 접근하기 위한 권한을 Role을 통해서 할당 받은 것을 알 수 있습니다.
Designer Function Overview 탭을 클릭해서 접으면접고, 아래 Function Code를 볼 수 있습니다보겠습니다. Lambda 함수 코드 편집기는 AWS Cloud9 IDE가 내장되어 있어서 코드 편집을 웹 브라우저에서도 쉽게 할 수 있는 환경을 제공합니다. 좌측 하단의 lambda_function.py 파일을 클릭하면 기본 파이썬 소스 코드가 나오는걸 볼 수 있습니다. Runtime으로 Python 23.7이 8이 선택되어져 있는 것을 볼 수 있습니다. Handler는 함수가 시작하기 위한 파일의 위치와 함수의 이름을 의미합니다.
아래 코드를 이 Lambda 함수의 코드로 변경합니다. 해당 함수의 로직은 Polly에 TTS 작업을 요청하고, 요청 작업에 대한 ID 값을 DynamoDB에 등록합니다.
코드 블럭 # -*- coding: utf-8 -*- from __future__ import print_function import boto3 import os import json import uuid import datetime import re def lambda_handler(event, context): if "body" in event: parmas = json.loads(event['body']) voice = parmas["voice"] originText = parmas["text"] timbre = parmas["timbre"] pitch = parmas["pitch"] updateDate = datetime.datetime.now().strftime("%Y%m%d") polly = boto3.client('polly') removeBrackets = re.sub(r'\([^)]*\)', '', originText) repTextBlock = re.sub('[·…]', '<break time="100ms"/>', removeBrackets) ssmlBlock = "<speak><amazon:effect vocal-tract-length=\"" + timbre + "\"><prosody pitch=\"" + pitch + "\">" + repTextBlock + "</prosody></amazon:effect></speak>" ssmlBlock = ssmlBlock.replace('철수현수', '<amazon:effect vocal-tract-length="+80%"><prosody pitch="-70%">안녕하세요? 저는 서연 친구 철수에요현수에요.</prosody></amazon:effect>') ssmlBlock = ssmlBlock.replace('귀신', '<amazon:effect name="whispered"><amazon:effect vocal-tract-length="-30%"><prosody volume="loud">나 꿍꼬또, 기싱꿍꼬또</prosody></amazon:effect></amazon:effect>') print (ssmlBlock) response = polly.start_speech_synthesis_task( OutputFormat= 'mp3', OutputS3BucketName= os.environ['BUCKET_NAME'], # OutputS3KeyPrefix='polly/', SampleRate='22050', SnsTopicArn=os.environ['SNS_TOPIC'], Text=ssmlBlock, TextType='ssml', VoiceId=voice ) print (response) data = response['SynthesisTask'] # Creating new record in DynamoDB table dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ['DB_TABLE_NAME']) table.put_item( Item = { 'id' : data['TaskId'], 'updateDate': data['CreationTime'].strftime("%Y-%m-%d %H:%M:%S"), 'voice' : voice, 'originText': originText, 'pollyStatus' : data['TaskStatus'], 'timbre': timbre, 'pitch': pitch, 'mp3Url': data['OutputUri'], 'RequestCharacters': data['RequestCharacters'] } ) result = { 'statusCode': 200, 'body': json.dumps({'recordId': data['TaskId']}), 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' } } return result
- 아래와 같이 함수 코드를 변경하고 나면 우측 상단의 Save Deploy 버튼을 눌러서 환경을 저장합니다. 저장 되면 저장된 정보가 배포가 된 것을 확인 할 수 있습니다.
- PostNews Lambda 함수에는 코드에 외부의 환경 변수 값을 넣을 수 있습니다있는 방법을 제공합니다. 메타 데이터가 저장될 DynamoDB 테이블( DB_TABLE_NAME ), Polly가 작업을 완료하면 다음 Lambda 함수를 트리거 시키기 위한 SNS Topic( SNS_TOPIC ), Polly에 의해서 만들어지는 mp3가 저장될 S3의 버켓( BUCKET_NAME )의 이름을 지정해야 합니다. 이 값을 환경 변수로 함수에 전달할 수 있는 기능을 사용하기 위하여 Environment variables를 사용할 수 있습니다. 아래와 같이 Lamba Function Code 하단으로 스크롤을 내려서, Configuration 탭으로 이동하고, Environment varialbes를 선택한 후, Edit 버튼을 클릭하면 해당 메뉴로 진입합니다. S3 버킷 이름(
polly-mp3.studydev.com)과, NewsTopic 의 ARN 값( , DynamoDB 테이블의 NewsTable 값을 아래와 같이 입력합니다. - Tags 탭에서는 추가로 하단의 Basic settings에서 Lambda의 실행 시간을 지정할 수 있습니다. Timeout 값을 1 min 으로 수정합니다. Tags에는 Key 값으로 Name 을 Value 값을 NewsApp 을 입력하고, 우측 상단의 Save 버튼을 버튼을 클릭하여 환경을 저장합니다.
- 추가로 하단의 General configuration 에서 Lambda의 실행 시간을 지정할 수 있습니다. Timeout 값을 1 min 으로 수정하고 Save 합니다.
7. GetNews Lambda 함수 만들기
- PostNews와 같이 Create function 버튼을 클릭해서 새로운 함수를 생성합니다.
- GetNews 함수를 생성합니다. Runtime과 Role 설정은 기존과 동일합니다.
GetNews 의 함수 코드를 아래 코드로 대체합니다.
코드 블럭 from __future__ import print_function import boto3 import os import json import decimal from boto3.dynamodb.conditions import Key, Attr # https://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/GettingStarted.Python.04.html # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): if o % 1 > 0: return float(o) else: return int(o) return super(DecimalEncoder, self).default(o) def lambda_handler(event, context): if "queryStringParameters" in event: parmas = event['queryStringParameters'] print (parmas) postId = parmas["postId"] dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ['DB_TABLE_NAME']) if postId == "*": items = table.scan() else: items = table.query(KeyConditionExpression=Key('id').eq(postId)) response = { 'statusCode': 200, 'body': json.dumps(items["Items"], cls=DecimalEncoder), 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' } } return response
- Environment variables는 key로 DB_TABLE_NAME 에 value로 NewsTable 를 입력하고, Tags에 key에 Name과 value에 NewsApp 을 입력하고, Timeout을 1 min 으로 수정한 후, 상단 우측의 Save 버튼을 클릭합니다.
8. UpdateNews Lambda 함수 만들기
PostNews와 같이 Create function 버튼을 클릭해서 UpdateNews 함수를 생성합니다. Runtime과 Role 설정은 기존과 동일합니다.
UpdateNews 의 함수 코드를 아래 코드로 대체합니다.
코드 블럭 from __future__ import print_function import boto3 import os import json from contextlib import closing from boto3.dynamodb.conditions import Key, Attr import re def lambda_handler(event, context): polly_message = event["Records"][0]["Sns"]["Message"] print (polly_message) polly_response = json.loads(polly_message) # Updating the item in DynamoDB dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ['DB_TABLE_NAME']) response = table.update_item( Key={ 'id': polly_response["taskId"] }, UpdateExpression="set pollyStatus = :s", ExpressionAttributeValues={ ':s': polly_response['taskStatus'] } ) print(response) s3 = boto3.client('s3') s3.put_object_acl( ACL = 'public-read', Bucket = os.environ['BUCKET_NAME'], Key = polly_response["taskId"] + ".mp3" ) return
Environment variables는 DB_TABLE_NAME에 NewsTable 값을 입력하고, BUCKET_NAME에는 S3 버킷 이름(
polly-mp3.awsdemo.kr)을 지정합니다. Tags에 Name과 NewsApp 을 입력하고, Timeout을 1 min 으로 수정한후, 우측 상단의 Save 버튼을 클릭하여 저장합니다.- UpdateNews Lambda 함수는 SNS Topic에 의해서 트리거 되어 동작이 되어야 합니다. 따라서 Designer 메뉴를 열고 좌측의 Function Overview에서 좌측 하단의 Add trigger 버튼을 클릭합니다.
- 트리거를 위하여 SNS를 클릭합니다. SNS topic 으로 NewsTopic 을 지정합니다. 해당 SNS에서 맞는지 확인하고 Add 버튼을 클릭하여 트리거를 등록하고 확인합니다.
9. DeleteNews Lambda 함수 만들기
...