최근 채용 준비 과정에서 과제전형을 위한 간단한 api가 필요했다. 안그래도 운영중인 서비스의 서버 비용이 점점 늘어나 서버리스 아키텍쳐 도입을 검토하고 있었는데, 공부도 할 겸 AWS로 가벼운 api를 호출할 수 있는 환경을 구성해보았다.
AWS Lambda와 API Gateway를 이용해서 간단한 Serverless API 환경을 구축했는데, 글로도 남겨 놓으면 좋을 것 같아 오랜만에 포스팅을 작성하게 되었다😁
이미지 출처 : AWS 한국 블로그
우선 AWS Lambda에 대해 알아보자. Lambda는 주로 서버리스(serverless)라는 용어와 함께 사용된다. 서버리스란 '서버가 없음'을 의미하지만 사실 서버가 아예 없는것은 아니고 서버의 관리 주체가 aws로 넘어감을 의미한다.
람다는 백엔드를 작은 함수 단위로 쪼개어 aws 내부의 서버에 업로드 하는 방식이다. 그러면 aws는 해당 함수를 내부 서버에 업로드 하고 요청 발생시 요청에 맞는 람다함수를 실행시켜준다.
따라서 람다를 이용하면 별도의 서버 구성 없이 클라이언트의 요청에 따라 원하는 함수를 실행시킬 수 있다. 그리고 람다는 요청 수 기반으로 비용이 측정되기 때문에 24시간 켜놓아야 하는 EC2같은 서비스 대비 저렴하게 이용할 수 있다.
또한 AWS의 다른 서비스와도 연계하여 사용할 수 있는 등 다양한 장점이 있다.
API Gateway는 API의 소비자, 즉 클라이언트가 백엔드 서비스의 데이터 비즈니스 로직 또는 기능에 액세스할 수 있게 해주는 게이트 역할을 한다. 쉽게 말하면 백엔드의 HTTP 엔드포인트 역할을 제공하는 서비스라고 볼 수 있다.
앞서 말한 람다는 '함수'의 역할을 수행하기 때문에, 실제로 해당 람다에 접근할 수 있도록 하기 위해서는 API gateway를 연결하여 엔드포인트를 만들어 주어야 한다.
그러면 클라이언트는 API Gateway를 통해서 Lambda 함수를 호출할 수 있다. 예를 들면 만약 클라이언트가 GET /products HTTP 요청을 보내면, API Gateway가 이것을 받아서 해당 path에 매칭되는 람다 함수를 실행시켜 주는 방식으로 동작한다.
이제 이론적으로 살펴 보았으니, 실제로 동작하는 API를 만들어 보자. 간단한 쇼핑몰을 만든다 생각하고, 쇼핑몰에 필요한 두가지 API를 만들어 볼 예정이다. 만들 API 목록은 아래와 같다.
- 전체 상품 리스트 받아오기
- 특정 상품 상세 정보 받아오기
통신 경로는 아래 그림과 같이 API 소비자(클라이언트) <-> API 게이트웨이 <-> AWS 람다의 구조로 진행된다.
우선 API Gateway를 먼저 생성해주자. AWS 콘솔에서 API Gateway에 접근하면 아래와 같이 API 유형을 선택할 수 있다.
우리는 GET 메서드를 이용한 간단한 api만 생성할 것이므로 HTTP API를 골라주자. REST API는 HTTP API에 비해 조금 더 다양한 기능을 제공하는데, 자세한 내용이 궁금하신 분들은 여기를 참고하면 좋을 것 같다.
HTTP API를 선택하면 위와 같은 API 생성 페이지를 마주하게 된다. 이미지 중간을 보면 통합 추가라는 버튼이 있는데, 통합은 API Gateway가 연결할 서비스를 의미한다. 우리는 람다 함수를 만들어서 추후에 연결시켜 줄 것이므로 API 이름만 입력하고 다음으로 넘어가자.
다음으로는 스테이지를 정의해야 한다. dev, prod등 원하는 스테이지를 정의하고 각각 배포할 수 있다. 설정한 스테이지 이름이 해당 API 엔드포인트 url의 일부로 포함되게 되니, 이를 고려해서 원하는 스테이지 이름을 설정해주자.
스테이지까지 정의하면 API Gateway가 만들어진다. 이어지는 화면에서 API Gateway 세부정보를 볼 수 있는데, 생성한 API Gateway의 기본 정보(스테이지 이름, 엔드포인트 등)가 나타나있다.
앞서 스테이지 이름을 dev로 설정해서 실제 URL에도 dev가 포함되어 있는 모습을 확인할 수 있다.
다음으로는 API Gateway가 요청을 받았을때 적절히 요청을 배분할 수 있도록 path를 만들어주자. 좌측 탭에서 경로 탭에 들어가서 create 클릭한다.
path를 만들기 위해서는 경로와 사용할 메서드를 설정해야 한다. 처음으로 만들 API는 상품 리스트 조회 api이므로 경로는 /products, 메서드는 GET으로 설정해주었다.
설정한 /products 경로로 path가 설정이 된 모습이다. 이어서 이번에는 상품 상세 정보 api를 연결하기 위해 path를 하나 더 만들어 보자.
리소스 경로에 {}를 포함하면 있으면 경로 파라미터를 나타낼 수 있다. 뒤의 상품 id는 동적으로 받아 올 거기 때문에 {productId} 형식으로 넣어줬다.
products를 포함한 경로를 입력해주면 위와 같이 알아서 계층화를 시켜준다. 이로서 path를 완성했다! 이제 마지막으로 CORS 설정을 진행하자.
API Gateway의 디폴트 설정은 모든 값이 허용되지 않음으로 설정되어있다. 따라서 브라우저에서 해당 api 호출을 할 수 있도록 적절한 CORS 설정을 해줘야한다. 좌측의 CORS탭에서 CORS 관련 설정을 진행할 수 있다.
원하는대로 설정을 진행하면 되는데, 모든 브라우저에서 호출할 수 있도록 하려면 Access-Control-Allow-Origin에 '*'을 넣어주면 된다.
이제 API Gateway 관련 설정은 끝났다! 이제 람다 함수를 만들자.
람다 함수를 만들기 위해 다시 aws 콘솔에서 람다로 들어가 함수 생성을 클릭해주자.
함수 생성 탭에서는 함수 이름과 사용할 언어 등 람다 함수와 관련된 여러가지 설정들을 진행할 수 있다. 언어는 Node, python, go, java등 다양한 언어를 지원하며, 버전은 함수 생성 시점 해당 언어의 LTS 버전을 사용할 수 있다.
언어 선택 후 함수 이름을 입력하고 함수 생성을 클릭하면 람다함수가 만들어진다.
함수를 만든 뒤 함수 개요 탭에서는 람다의 트리거를 추가할 수 있는 버튼과 함수 코드 작성을 위한 코드 에디터가 노출되어 있다. 람다 함수에서 트리거는 핵심적인 개념인데, 트리거 이벤트를 설정하여 이벤트 발생 시 해당 람다 함수를 실행시킬 수 있다.
트리거는 추후에 API Gateway에서 설정해 줄 것이므로 코드만 수정하자.
모든 products를 반환해주는 함수이므로, products를 선언하고 해당 정보만 내려주었다.
함수 생성 부분은 앞과 동일하므로 코드 부분만 정리해보자.
상품 상세 api에서는 product 뒤에 동적으로 productId가 오게된다. 동적 parameter의 경우 람다 함수의 기본 parameter인 event의 pathParameters를 통해서 받아올 수 있다.
현재는 product 수가 많지 않으므로 전체 product option 배열에서 검색해서 내려주는 간단한 로직으로 구현하였다.
이제 람다함수 까지 생성을 마쳤으니, 마지막 스텝이다! 처음에 생성한 path에 람다 함수를 연결시켜 주는 작업을 진행하자.
다시 콘솔에서 API Gateway -> 경로 탭을 들어간다. 첫번째 함수부터 연결을 진행해보자.
/products 밑에 GET을 누르고 통합 연결을 클릭하자. 통합 연결은 해당 path로 요청을 수신했을때 호출하는 백엔드 리소스이다. 여기에 좀 전에 만든 람다 함수를 연결해 줄 것이다.
통합 대상에서 람다함수를 선택하고, 통합 세부 정보에서 연결할 람다 함수, 여기서는 productsAll을 누르고 통합 연결을 클릭해주자.
정상적으로 API Gateway의 path와 람다 함수가 연결이 되면 위 이미지와 같이 path 우측으로 AWS Lambda 뱃지가 노출된다.
이제 나머지 하나의 함수도 똑같이 연결해주자. 과정은 동일하므로 생략하겠다. 최종적으로 위와 같은 화면이 나오면 성공이다! API 게이트웨이에 두개의 람다 함수를 연결 완료했다.
이제 모든 준비가 끝났으니 호출이 잘 되는지 직접 테스트해보자. 우리가 만든 API들은 모두 Get 메소드이므로 경우 간단히 브라우저에서 호출해보자. 다른 요청의 경우 postman 같은 API platform을 이용하여 진행하면 된다.
정상 동작까지 확인 완료! 끗!
채용 과제를 계기로 람다와 API 게이트웨이 등 새로운 것들을 사용해 볼 수 있어서 좋았다. 다음에는 Authorizer나 DB등 AWS내 다른 서비스를 같이 이용해서 서버리스 환경을 구축해보고 싶다.
본 포스팅은 아래의 글들을 참고하여 작성되었습니다.
https://grip.news/archives/1397
http://labs.brandi.co.kr/2018/07/31/kwakjs.html