슬픈 날이네요.
구조에 많은 변화가 있었고, 많은 고민이 있었습니다.
http api로 구현 시도
저번에 말씀드렸듯 API Gateway의 성능과 비용을 고려하면 Http API가 좋습니다. (구현도 간단합니다. 간략화된 버전이기 때문에요)
그래서 다시 http api 써볼까? 했는데, 실패했습니다.
왜? -> API Gateway 통합 요청의 매핑 템플릿을 수정할 수 없기 때문입니다.
슬랙 API의 경우 요청이 application/x-www-form-urlencoded로 오는데요, 그렇기 때문에 매핑 템플릿을 통해 시리얼라이징을 해야 합니다.
그런데 http api는 해당 부분을 configure할 수 없습니다.. 그래서 지식을 얻고 시간을 버렸습니다.
step functions의 asynchronous request
자 그래서 step functions를 만들고 내부 함수를 설정하여 이렇게 돌아가는데요,
구현하면서 계속 궁금했던게, end로 간 응답을 그래서 어떻게 API Gateway에 건네주지? 였습니다.
End까지 잘 가면 알아서 반환이 될 줄 알았으나, 세상은 그렇게 호락호락하지 않습니다.
응답이.. 제가 기대한 바가 아닙니다. (arn은 지워버렸으니까 안심하세요 ^_^)
그렇습니다. API Gateway는 기본적으로 요청을 비동기적으로 보냅니다.
그렇기 때문에 응답이 제가 원하는대로 돌아오지 않습니다.
사실 Step Functions는 보통 EventBridge 규칙 등의 워크플로우를 수행하기 위해 존재하는 녀석으로 보통 비동기적으로 많이 사용한다고 하더군요.
하지만 동기적으로 수행하는 방법이 있답니다
타입을 EXPRESS로 설정하고, API Gateway에서 Step functions 호출 시 작업 이름을 StartSyncExecution로 설정하면 됩니다.
그럼 이제 해치웠나?
실제로 Postman으로는 응답이 오더군요. 기뻤습니다.
하지만.. 가장 큰 문제가 있었습니다. 바로 Lambda의 Cold Start 문제였습니다.
쉽게 말하면 람다 함수는 호출하지 않으면 잠을 자고 있습니다. 그래서 호출하면 그제서야 일어나서 일을 수행하는데요,
방금까지 주무시고 계시던 람다는 비몽사몽해서 일처리가 느립니다. ... . ..
게다가 저는 Step Functions로 여러개의 람다 함수를 호출하죠? -> 더 느립니다.
그래서.. Timeout 당합니다.
사실 프로젝트 시작부터 알고 있었습니다.
그냥 Step functions 없이 API 하나당 하나의 람다 매핑해두면 훨씬 간결한 환경을 구축할 수 있습니다.
인증부분이 겹치긴 하지만 그게 문제가 되진 않습니다.
그래서 결론적으로 그렇게 구현을 하려고 합니다.
그래도 결론적으로 공부가 많이 되었습니다.
API Gateway, Lambda, Step Functions에 대해서 익숙하게 사용할 수 있고 IAM 권한 주입, CloudWatch 로깅 정도는 질리도록 만져본 것 같습니다.
어떻게 보면 프로젝트 실패라서 기분이 썩 좋다고는 말할 수 없겠군요. 😢
하지만 정진하겠습니다.
밑에는 SAM 템플릿입니다.
SlackStateMachine:
Type: AWS::Serverless::StateMachine # More info about State Machine Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-statemachine.html
Properties:
Type: EXPRESS
DefinitionUri: statemachine/machine.asl.json
DefinitionSubstitutions:
OrderListPath: !Ref OrderListPath
OrderUpdatePath: !Ref OrderUpdatePath
Policies:
- LambdaInvokePolicy:
FunctionName: !Ref ValidatorFunction
- LambdaInvokePolicy:
FunctionName: !Ref ResultFunction
- LambdaInvokePolicy:
FunctionName: !Ref ChallengeFunction
- LambdaInvokePolicy:
FunctionName: !Ref OrderListFunction
- LambdaInvokePolicy:
FunctionName: !Ref OrderUpdateFunction
- LambdaInvokePolicy:
FunctionName: !Ref TestFunction
- CloudWatchLogsFullAccess
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "cloudwatch:*"
- "logs:*"
Resource: "*"
Events:
RootApi:
Type: Api
Properties:
Path: /
Method: POST
OrderListApi:
Type: Api
Properties:
UnescapeMappingTemplate: True
Path: /order-list
Method: POST
OrderUpdateApi:
Type: Api
Properties:
Path: /order-update
Method: POST
Logging:
Destinations:
- CloudWatchLogsLogGroup:
LogGroupArn: !GetAtt StateMachineLogGroup.Arn
IncludeExecutionData: false
Level: 'ALL'
진짜 SAM이 편하긴 합니다.
이런식으로 sam deploy를 통해 변경사항을 알아서 다 적용해줍니다. bb
ValidationFunction:
import hashlib
import hmac
import os
def lambda_handler(event, context):
if 'challenge' in event:
return {
"statusCode": 200,
"challenge": event['challenge'],
"valid": False
}
else:
slack_signing_secret = os.environ.get("SLACK_SIGNING_SECRET")
headers = event["headers"]
body = event["body"]
path = event["path"]
is_valid_request = verify_slack_signature(slack_signing_secret, headers, body)
if is_valid_request:
return {
'path': path,
'valid': True,
'body': body
}
else:
return {
'valid': False
}
def verify_slack_signature(slack_signing_secret, headers, body):
# X-Slack-Signature 헤더에서 Slack 서명 가져오기
if 'X-Slack-Signature' in headers:
slack_signature = headers["X-Slack-Signature"]
else:
return False
# 본문을 Slack 서명으로 검증
computed_signature = (
"v0=" + hmac.new(
bytes(slack_signing_secret, "latin-1"),
msg=bytes(f"v0:{headers['X-Slack-Request-Timestamp']}:{body}", "latin-1"),
digestmod=hashlib.sha256
).hexdigest()
)
# 서명 검증 결과 반환
return hmac.compare_digest(slack_signature, computed_signature)
verify_slack_signature : 헤더에서 슬랙 서명을 가져와 검증합니다.
challenge는 슬랙 API 써보시면 아시겠지만 이벤트 섭스크립션 할 때 challenge를 받아서 반환해줘야 해서 넣었습니다.
return값을 보면 특이한데요, 저런식으로 원하는 값을 넘겨주면서 State Machine의 Choice 부분에서 변수 값에 따른 분기 처리가 가능합니다.
그럼이만~
'AWS' 카테고리의 다른 글
AWS EC2, EBS: 스왑 메모리에 대한 실험과 모범 사례 (0) | 2024.04.18 |
---|---|
[AWS] AWS 사용요금을 매일 문자로 받아보기 (0) | 2023.11.30 |
[AWS] VPC Migration (0) | 2023.11.23 |
[AWS SAM] Slack API 슬랙 봇 서버리스로 마이그레이션 도전기 (2) (1) | 2023.11.14 |
[AWS SAM] Slack API 슬랙 봇 서버리스로 마이그레이션 도전기 (1) (1) | 2023.11.13 |