Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

AWS Lambda를 이용해서 HTTP API 만들기 #2

이 글은 AWS Lambda를 이용해서 HTTP API 만들기 #1에서 이어진 글이다.

API Gateway

Amazon API Gateway는 API 서비스의 입구를 담당해 주는 서비스로 보통 웹 애플리케이션을 만들 때 컨트롤러 혹은 라우팅 부분에서 URL과 Method를 정의하고 각 파라미터 등을 정의한 뒤 어디에 연결할지를 지정할 수 있는 서비스이다. API Gateway를 다양하게 사용할 수 있겠지만(많이 써보진 안 써봤다.) 여기서는 Lambda function에 연결하는 목적으로만 사용하겠다.

HTTP POST API

AWS API Gateway 콘솔

Lambda를 만들기 위해 새로운 API를 만들어 보자.

AWS API Gateway 콘솔

새로 API를 만들었으므로 루트 경로 /만 존재한다. 이제 API를 구성하기 위해 리소스(Resource)와 메소드(Method)를 만들 수 있다. 보통 Restful API를 만들 때 /teams, /teams/:team-name, /players처럼 URL을 구성할 리소스 기반으로 정의하게 되는데 그때의 그 리소스이다. 사실 별로 의식하고 있지 않아서 그렇지 URL, URI도 각각 Uniform Resource Locator, Uniform Resource Identifiers이다. Method는 리소스에 액션을 정의하기 위해서 사용하는 GET, POST, PUT, DELETE를 의미한다.

AWS API Gateway 콘솔

간단한 테스트이므로 리소스를 따로 만들지 않고 루트에 POST 메서드를 만들고 앞에서 만든 HelloWorld Lambda Function과 연결했다.

AWS API Gateway 콘솔

방금 만든 POST API가 간단히 도식화해서 나타난다. 화살표대로 따라가면 Client가 요청을 보내면 Method에서 요청을 받아서 Lambda에 연결한 뒤 Lambda Function이 응답을 그대로 클라이언트에 보내준다. 응답은 모델을 만들어서 연결하고나 형식을 정의할 수 있다.

AWS API Gateway 콘솔

Client에 있는 "Test" 버튼을 누르면 API를 바로 테스트해볼 수 있다. POST 요청의 바디에 JSON을 넣어서 테스트하면 Lambda Function이 실행되어 아까와 같은 결과가 반환되는 것을 볼 수 있다. 이제 API 동작을 확인했으므로 실제 사용할 수 있게 해야 하는데 그전에 먼저 인증을 걸어야 한다. 앞의 스크린샷에서 눈치챘는지 모르지만, 방금 만든 POST 메서드는 Auth설정이 NONE으로 되어 있다. 누구나 사용해도 된다면 상관없지만 보통 Lambda 사용량에 따라 돈을 내야 하므로 인증을 걸어서 원하는 곳에서만 사용 가능하게 해야 한다.

AWS API Gateway 콘솔

위의 메서드 도식화면에서 Method Request 부분 클릭하면 요청에 대해 설정을 할 수 있다. 여기서 원하는 쿼리스트링이나 헤더도 설정할 수 있지만, 지금은 인증만 설정했다. 여기서 AWS의 IAM을 사용하려면 Authorization를 설정하면 되는데 HTTP API 목적으로 만들 예정이므로 API 키를 true로 설정했다.

이제 다 만들었으므로 API를 배포하면 된다. 지금까지처럼 메서드를 추가하고 구성한다고 바로 적용되는 것이 아니라 직접 API 서버를 구축했을 때처럼 배포해야 적용이 된다.

AWS API Gateway 콘솔

배포를 하려면 스테이지를 만들어서 배포해야 하는데 기존에 만들어 놓은 스테이지가 없다면 새로 만들어서 배포해야 한다. 여기서 스테이지는 서비스를 만들 때 소스를 개발 서버, 스테이지 서버, 리얼 혹은 프로덕션 서버 순으로 배포하듯이 원하는 스테이지를 만들어 놓고 똑같이 사용할 수 있다. 여기서는 test라는 스테이지를 만들었다.

AWS API Gateway 콘솔

새로운 스테이지를 만들고 API를 배포했으므로 URL이 할당되었다. 여기서 만들어진 URL이 이 API의 URL이고(이 글이 나갈 때쯤에 삭제된 API이므로 시도해 보지 않아도 된다.) 캐시나 로깅, 스로틀링 등을 설정할 수 있다. 해보진 않았지만, iOS나 Android의 SDK도 만들어 준다.

AWS API Gateway 콘솔

앞에서 API 키를 연결했지만 API 키는 아직 안 만들었다. 상단 메뉴에서 API Keys에 가면 API 키를 생성할 수 있다.

AWS API Gateway 콘솔

API를 생성하고 활성화한 뒤에 앞에서 만든 API와 스테이지에 연결설정을 하면 해당 API에서 API 키를 사용할 수 있다.

$ curl -X POST https://edzgyy0dx8.execute-api.ap-northeast-1.amazonaws.com/test \
    -d "{"myname":"Outsider"}"

{"message": "Forbidden"}


$ curl -X POST https://edzgyy0dx8.execute-api.ap-northeast-1.amazonaws.com/test \
    -d '{"myname":"Outsider"}' \
    -H "x-api-key: XXXXXXXXXXXXXXXXXXXXXXXXXXXX"

"Hello World, Outsider"

curl로 API를 테스트해보면 정상 동작을 한다. API 키가 없으면 403으로 막히고 API 키를 헤더로 보내면 Lambda가 연동된 결과가 잘 반환된다. API 키는 x-api-key헤더에 담아서 보내야 한다.

HTTP GET API

GET 메서드보다 POST 메서드를 먼저 만든 이유는 Lambda에서 JSON을 받게 되어 있으므로 POST에서는 JSON을 body에 바로 전달하면 설정이 훨씬 간단하기 때문이다. GET 요청의 경우 쿼리스트링으로 데이터를 보내므로 이 값이 Lambda에 전환되지 않는다. 이제 POST와 같게 GET 메서드를 만들어 보자.

AWS API Gateway 콘솔

GET 메서드를 추가한 뒤 Method Request에 들어가면 URL Query String Parameters을 설정할 수 있다. 값을 자동으로 받지 않으므로 필요한 파라미터를 여기서 설정해야 한다.(API 키는 POST처럼 true로 설정한다.) name이라는 쿼리스트링을 추가했다. Lambda에서는 myname이라는 값을 쓰지만 쿼리스트링에서는 보통 간단한 이름을 사용하기도 하고 헷갈리지 않게 다른 이름을 사용했다. 이 쿼리스트링은 Lambda function에 전달할 JSON으로 변환하기 위한 설정을 해야 한다.

AWS API Gateway 콘솔

이 설정은 API 메서드를 Lambda와 연결하는 Integration Request에서 설정할 수 있다. Body Mapping Templates에서 application/jsonContent-Type를 가진 매핑템플릿을 추가한다. 기본은 Input Passthrough로 하는 경우 그냥 전달되지만 여기서는 변환을 해야 하므로 Mapping Template를 선택하고 템플릿 내용을 다음 코드로 설정하면 된다.

{ "myname": "$input.params('name')" }

이는 Lamdba function에 보내는 {"myname":""}의 형태를 만든 것인데 myname의 값을 입력으로 받은 $input.params('name')로 설정한 것이다. 이 값에는 GET 요청의 name 쿼리스트링으로 전달받은 값이 들어간다.

AWS API Gateway 콘솔

설정이 완료하고 테스트를 해보면 잘 동작하는 것을 알 수 있다. 이제 다시 배포만 하면 된다. 앞에서 만든 test 스테이지에 배포를 하고 HTTP 요청을 보내면 확인해 볼 수 있다.

$ curl https://edzgyy0dx8.execute-api.ap-northeast-1.amazonaws.com/test?name=Outsider \
    -H "x-api-key: XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"Hello World, Outsider"

아주 간단한 API 두 개를 만드는데 아주 긴 설명을 했지만, 서버를 하나도 띄우지 않고 HTTP API를 만들었다. 설명은 아주 길게 했지만 실제로 하면 간단한 설정일 뿐이다.(초기에는 삽질이 좀 필요하겠지만 ) 예제는 아주 간단한 API였지만 실제로는 꽤 수준 높은 부분까지도 서버 구성을 하나도 하지 않고 이 조합으로 만들 수 있을 거라고 생각한다. 그래서 요즘 이 serverless 아키텍처에 관심이 있다.

2016/03/27 02:56 2016/03/27 02:56