lambda란
AWS lambda는 이벤트에 대한 응답으로 코드를 실행하고 자동으로 기본 컴퓨팅 리소스를 관리하는 서버리스 컴퓨팅 서비스입니다. 이러한 이벤트에는 전자 상거래 웹 사이트에서 사용자가 장바구니에 항목을 배치하는 것과 같은 상태 변경 또는 업데이트가 포함될 수 있습니다.
또한 lambda는 가용성이 뛰어난 컴퓨팅 인프라에서 코드를 실행하고 컴퓨팅 리소스 관리를 모두 수행합니다. 여기에는 서버 및 운영체제 유지 관리, 용량 프로비저닝 및 자동 크기 조정, 코드 및 보안 패치 배포와 코드 모니터링 및 로깅이 포합됩니다. 개발자는 코드만 제공하기만 하면 됩니다.
링크 : https://aws.amazon.com/ko/lambda/features/
API Gatewy란
Amazon API Gatewaya는 어떤 규모에서든 개발가 API를 손쉽게 생성, 게시, 유지 관리, 모니터링 및 보안 유지할 수 있도록 하는 완전 관리형 서비스입니다.
API Gateway를 사용하면 실시간 양방향 통신 애플리케이션이 가능하도록 하는 RESTful API 및 WebSocket API를 작성할 수 있습니다. API Gateway는 컨테이너식 서버리스 워크로드 및 웹 애플리케이션을 지원합니다.
링크 : https://aws.amazon.com/ko/api-gateway/
S3란
먼저 S3는 AWS 서비스 콘솔에서 스토리지 서비스로 분류 되어있습니다. 클라우드 공급자가 저장 공간을 서비스로 관리하고 운영하며 인터넷에 데이터 저장 공간을 제공하는 '클라우드 스토리지 서비스 모델' 입니다.
AWS에서 세팅하기
lambda 세팅하기
- 함수이름을 입력해줍니다
- 파이썬을 이용해서 코드를 구현해서 런타임환경은 python 3.9를 선택하겠습니다.
- 역할(role)은 기본 lambda를 선택했습니다. 만약에 사용하는 역할이 있으면 사용하던 역할 선택
python 라이브러리를 사용하기 위해 계층 생성
이제 이미지와 같은 데이터를 읽기 위해서 multipart 데이터를 decode해야하는데 이것을 위해 requests_toolbelt를 설치하겠습니다.
그 전에 python 가상환경을 생성해준 후 설치하겠습니다.
python3 -m venv myven
pip isntall requests_toolbelt
그러면 myvenv/lib/python3.9에 site-packages라는 폴더가 있는것을 확인할 수 있습니다. 이제 이 폴더명을 python으로 바꾼 후 압축하겠습니다.
그 후 aws lambda → 추가 리소스 → 계층에 들어가서 계층 생성을 해주겠습니다.
- 이름과 설명을 입력해줍니다.
- 그 후 아까 만들었던 파이썬 압축 파일을 업로드하고 생성해주겠습니다. 여기서 중요한것은 python.zip파일이여야 합니다.
- 호환 런타임은 파이썬 환경들을 선택하겠습니다
- 그다음 생성버튼을 누르면 새로운 계층이 생성된 것을 확인할 수 있습니다.
- 그 후 아까만든 람다에 들어가서 맨아래 보면 계층이라는 항목이 있습니다. [add a layer]를 클릭해서 계층을 추가하면 다음과 같이 레이어가 잘 추가된 것을 확인할 수 있습니다.
layer 추가 참고 링크
lambda 코드 구현하기
먼저 코드먼저 보여드리겠습니다
import boto3
import json
import base64
import hashlib
from datetime import datetime, timedelta
from requests_toolbelt.multipart import decoder
BUCKET_NAME = '{버킷 이름}'
response = {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true'
},
'body': ''
}
def lambda_handler(event, context):
s3 = boto3.client('s3')
hash_salt = str(datetime.utcnow())
file_path = '{저장하고 싶은 경로}'
file_salt = hashlib.sha224(hash_salt.encode()).hexdigest()
file_name = f'000{file_salt[:10].upper()}-{file_salt[10:15].upper()}-{file_salt[15:20].upper()}-{file_salt[20:25].upper()}'
full_name = file_path + file_name + '.jpg'
res_data = ''
content = ''
headers = ''
print(event)
body = base64.b64decode(event['body'])
if 'content-type' in event['headers']:
content_type = event['headers']['content-type']
else:
content_type = event['headers']['Content-Type']
decode = decoder.MultipartDecoder(body,content_type)
for part in decode.parts:
content = part.content
headers = part.headers
print(part.__dict__)
print(content)
print(headers)
try:
s3_response = s3.put_object(Bucket=BUCKET_NAME, Key=full_name, Body=content)
except Exception as e:
raise IOError(e)
response['body'] = json.dumps({'url' : f'{"s3 image url 경로"}/{file_path}{file_name}.jpg'})
return response
- s3 = boto3.client(’s3’) : s3와 연동
- hash_salt = str(datetime.utcnow()) : 현재 시간을 salt로 지정해줬습니다
- 아래 코드는 파일이름을 난수화 하는 코드입니다
file_salt = hashlib.sha224(hash_salt.encode()).hexdigest()
file_name = f'000{file_salt[:10].upper()}-{file_salt[10:15].upper()}-{file_salt[15:20].upper()}-{file_salt[20:25].upper()}'
full_name = file_path + file_name + '.jpg'
- print(event) : 나중에 API gateway와 cloudwatch를 연동하면 request요청시 어떤 response를 받아오는지 확인하기 위해 설정해 두었습니다.
- body = base64.b64decode(event['body']) : 들어오는 body데이터는 base64로 암호화 되어 있는데 이것을 decode를 통해 복호화 시키겠습니다
- 아래 코드는 headers가 content-type과 Content-Type이렇게 두케이스가 있어서 이렇게 설정해 두었습니다
if 'content-type' in event['headers']:
content_type = event['headers']['content-type']
else:
content_type = event['headers']['Content-Type']
- decode = decoder.MultipartDecoder(body,content_type) : 이렇게 들어온 값은 또 content-type과 body를 multipartDecoder를 통해 복호화하겠습니다(이미지 파일)
- 아래 코드는 content와 headers가 잘 들어왔는지 print로 확인하기 위한 코드입니다.
for part in decode.parts:
content = part.content
headers = part.headers
print(part.__dict__)
print(content)
print(headers)
- 마지막으로 중요한 s3에 파일을 넣어주고 response하는 코드입니다
try:
s3_response = s3.put_object(Bucket=BUCKET_NAME, Key=full_name, Body=content)
except Exception as e:
raise IOError(e)
response['body'] = json.dumps({'url' : f'{"s3 image url 경로"}/{file_path}{file_name}.jpg'})
return response
API Gateway와 연동하기
API Gateway에 들어간 후 REST API항목에서 구축을 클릭하겠습니다.
그 다음 다음과 같이 설정하겠습니다 그 후 API 생성을 누르면 다음과 같은 화면이 나오는 것을 확인할 수 있습니다.
그 후 다음과 같이 원하는 경로명을 입력한 후 리소스 생성을 클릭하겠습니다.
그 다음 저장 버튼을 누르겠습니다
이제 제일 중요한 설정입니다. multipart/form-data를 통해 데이터를 받아야하므로 다음과 같은곳에서 설정해주겠습니다.
multipart/form-data
그 다음 다시 메인으로 돌아와서 통합요청을 설정하겠습니다
매핑테이블에서도 마찬가지로 multipart/form-data로 설정한후 저장하겠습니다
이렇게하면 배포전까지
S3 정책 설정하기
먼저 정책 설정 전에 모든 액세스 퍼블릭 차단을 비활성화 하겠습니다.
그 후 아래 내리면 버킷 정책 항목이 있는데 여기서 편집버튼을 클릭하겠습니다.
그 후 정책 생성기를 클릭하기 전에 버킷 ARN이 필요하므로 미리 복사하겠습니다.
그 다음 다음과 같이 설정하겠습니다
- Action
- GetObject
- PutObject
- ARN : 아까 복사한 ARN
그 후 Add statement를 클릭하면 아까 선택한 항목을 다시 한번 더 확인할수 있는것이 나옵니다 여기서 확인한 후 Generate Policy를 클릭해서 정책을 생성한 후 복사한다음 아래 정책에 붙여넣기 하겠습니다.
그 다음 변경사항을 저장하겠습니다
API Gateway 배포
이제 다시 API Gateway로 돌아간 후 배포를 하겠습니다.
그 후 스테이지 이름을 설정한 후 배포를 클릭하겠습니다.
그럼 다음과 같이 호출 API 가 나오는 것을 확인할 수 있습니다.
Postman으로 테스트 하기
Postman에서 key : file, value에서 이미지를 넣은 후 send버튼을 누르면 다음과 같이 URL을 받아오는 것을 확인할 수 있습니다
AWS 설정 참고 링크 : https://devlog-wjdrbs96.tistory.com/331
참고 : 보안을 위한 API키를 통한 API요청 만들기
다시 API Gateway에 들어간 후 아까 만들어둔 메서드를 클릭한 후 메서드 요청을 클릭하겠습니다.
다음과 같이 API 키가 필요함에 true로 설정하겠습니다.
그 후 API 키를 생성해 주겠습니다.
이러면 자동으로 API key가 생성됩니다.
그 후 사용량계획을 누른 후 생성버튼을 클릭해서 생성하겠습니다.
저는 이런식으로 설정해두었는데 서비스 사용량 or 유저수를 계산해서 입력하시길 바랍니다
그 다음 다음버튼을 눌러서 API 스테이지를 연동할 수 있지만 저는 메인페이지에서 처리하겠습니다
저렇게 설정한 후 추가 버튼을 누르면 이제 이 API는 이만큼 할당 됩니다.
그 후 위에보면 API 키 설정이 있는데 그 항목에 들어가겠습니다.
그러면 여기에 api key도 등록할 수 있습니다.
마지막으로 API키를 header에 적용시킨 후 API 테스트를 진행하겠습니다
API키가 있을경우 아래와 같이 결과가 잘 나오는 것을 확인할 수 있습니다.
만약 API key가 없을경우 다음과 같이 금지되었다는 경고문이 나오는 결과가 나옵니다.
참고한 링크
'기타 > 클라우드' 카테고리의 다른 글
RDS, EC2, Openvpn, TablePlus을 이용해서 VPN 터널링구현하기 (2) | 2024.03.01 |
---|---|
009. 서버리스, Lambda (0) | 2019.10.15 |
008. AWS - 빅데이터를 위한 데이터베이스 (0) | 2019.10.15 |
007. AWS - S3정의 (0) | 2019.10.13 |
006. 라이트세일 개념 및 실습하기(간단 블로그 만들기) (0) | 2019.10.13 |
댓글