최근에 AWS 위에서 서버리스 환경을 직접 구축하는 것을 공부하고 있다.
예전엔 회사에서 이미 다 세팅된 환경 위에 lambda 위에 올라갈 코드만 짜면 됐었는데 처음부터 세팅하려고 보니 API Gateway 없이는 lambda 자체를 HTTP로 호출할 방법이 없었다.
그래서 API Gateway를 세팅하면서 내가 이상하게 착각을 해서 시행착오를 겪었는데, 내 도메인(jaewook.me
)과 API Gateway, lambda를 연결하는 방법을 정리해 보려고 한다.
준비 사항
- (당연하게도) AWS 계정
- 연결할 Lambda
- API Gateway (설명은 REST API 방식 기준. HTTP API 방식이라고 큰 차이는 없다.)
API Gatway, HTTP API vs. REST API 어떤 걸 선택해야 할까?
우선, REST 혹은 HTTP 방식의 API Gateway가 필요한데, 두 방식에 요금 차이가 있다. 다시 말해서 두 방식 간에 기능적 차이가 존재한다. REST API 방식이 HTTP API 방식보다 요금이 비싸니 기능은 REST API가 더 많을 것이다.
Lambda 내부에서 라우팅을 하고 싶다면 REST API 방식으로
기능적 차이가 한두가지가 아니지만 lambda를 연결하는 관점에서만 기능적 차이를 살펴보자면, HTTP API 방식은 proxy 리소스로 하위 path에 대한 요청을 lambda에 전달할 수 없다.
예를 들어, lambda를 /lambda/api
라는 경로로 호출하도록 설정했다면, proxy를 통해 /lambda/api/ping
, /lambda/api/pong
과 같은 하위 리소스는 호출이 안된다.
HTTP API 방식으로는 proxy기능이 안되기 때문에 한번에 하나의 API밖에 연결을 못하는 것 같다. 여러 리소스에 대해서 같은 lambda를 연결해 봤지만 원하는 대로 작동할 턱이 없었다.
나는 이메일을 보내는 lambda를 하나 만들었는데, 원래 Golang 으로 작성하려다가 익숙하지 않아서 자주 쓰던 Node.js + express 기반으로 AWS SES 서비스를 사용해서 작성했다. 이 lambda에는 두개의 API가 있는데, HTTP API 방식으로는 두개의 API를 처리할 수 없으니, REST API 타입으로 만들어줬다.
그래서 나는 lambda proxy를 이용하여 아래와 같이 /email
경로 밑으로 email-service lambda를 호출하도록 설정했다.
API Gatway에 내 도메인과 연결하기
내가 원하는 API 호출 url 형태는 api.jaewook.me/email/{api-name}
형태이다. 각자 원하는 API의 호출 형태는 다르겠지만, 연결을 원하는 도메인을 API Gateway에 연결하는 과정은 동일하다.
도메인 SSL/TLS 인증서 추가하기
도메인을 AWS API Gateway에 연결하려면 ACM 서비스에 도메인 SSL/TLS 인증서를 등록해야 한다. 이 부분에서 나의 멍청함이 십분 발휘됐는데, 나는 CloudFlare DNS로 도메인을 관리하고 있다. 그래서 도메인 인증서는 CloudFlare에서 인증서를 발급받아서 ACM에 import해야 되는 줄 알았다... 결론적으로 그럴 필요가 없었다. 아니 그러면 안됐다. 거하게 헛짓을 했다. 이거 잘못해서 3일을 내다 버렸다.
특별한 경우가 아니라면, ACM에서 인증서를 발급받아서 쓰자
CloudFront(CDN) 엣지 네트워크로 API를 배포하는게 아니라면, 리전 원본 인증서(Origin Certificate)가 필요하다.
"DNS는 CloudFlare인데 어떻게 인증서를 발급받지?" (무려 내가 했던 생각이다.) 그냥 ACM에서 Request a certificate 버튼 누르고 인증서 만들 도메인 (내 경우엔 api.jaewook.me
) 입력하고, DNS 인증 선택해서 AWS에서 추가하라는 CNAME 레코드 추가하면 끝난다.
DNS 레코드에 추가하라는 CNAME 레코드를 추가하고 몇 분 기다리면 Verified 상태로 바뀐다. 이제 API Gateway custom domain을 생성할 준비는 마쳤다.
Custom domain name 추가하기
나는 CDN까지 필요 없어서 Regional type 으로 도메인을 생성했다. ACM Certificate는 방금전에 발급받은 인증서를 선택하면 된다.
위와 같이 도메인을 추가하게 되면, API Gateway domain name 이라는 url이 하나 나온다. 이 url도 DNS에 추가해주자.
나의 경우는 api.jaewook.me
주소로 CNAME 레코드를 추가해줬다.
AWS 문서상으론 커스텀 도메인이 활성화되는데 40분 정도 걸린다고 한다. 나의 경우는 10분정도 기다리니 사용 가능해졌다.
API mapping 하기
이제 거의 다 됐다. 조금 귀찮긴 하지만 나름 간단하게 연결할 수 있다. 아까 위에서 만들어 둔 API Gateway의 API를 매핑하면 끝이다.
나는 jaewook-api 라는 이름의 API를 만들었고, 이 API는 /email
아래의 경로에 lambda proxy를 이용하여 email-service lambda가 호출되도록 설정되어 있다.
API 배포는 v1 이라는 스테이지에 했는데, 솔직히 v2 는 안 만들 것 같다. 그냥 이름 막 지었다. 아무튼 스테이지와 API를 선택하고 저장하면 진짜 끝이다.
호출 URL은 어떻게 될까?
위 설명대로 API Gateway와 custom domain을 연결하면, (나의 경우엔) api.jaewook.me/email/*
경로로 API를 호출하면 실질적으로는 api.jaewook.me
에 연골되어 있는 CNAME 레코드 값으로 요청이 전달되고, 다시 {apiId}.execute-api.{regionId}.amazonaws.com/{stage}/email/*
형식의 url로 요청이 전달된다. 즉 커스텀 도메인을 연결해서 stage를 생략할 수 있다. 아까 API mapping 할 때 매핑할 stage도 선택했기 때문이다.
정리
막상 하고보니 별로 어렵지 않은 작업이었는데, 나는 CloudFlare에서 발급받은 Origin Certificate를 가지고 삽질하느라 3일이나 걸렸다. 어디에서 문제가 생겼을까 아무리 생각해도 모르겠었는데 그냥 종합적으로 총체적 난국이었던 것이다. (이렇게 쉽게 할 수 있었는데...)
아, API Gateway 요청은 HTTPS 강제인 것 같다. 기본으로 나오는 URL 자체도 https 요청만 받는다. 왜 안되지? 싶으면 http://
로 요청을 보내고 있는 나를 발견할 수 있었다.
아무튼 이 작업 하면서 SSL/TLS 인증서 공부도 많이 하고, 잘 정리되지 않은 AWS 문서 보는것도 많이 적응하고 유익했다.
아무쪼록 이 글을 보는 누군가도 도움이 됐으면 좋겠다.