2017년 5월 10일 수요일

[AWS] AWS API Gateway와 Lambda를 이용한 REST API 만들기

AWS API Gateway와 Lambda를 이용한 REST API 만들기

이번 포스팅에서는 AWS의 API Gateway와 Lambda를 이용해서 REST API를 만들어보겠습니다.
또한, REST API는 AWS Cognito로 로그인한 사용자에게만 사용 가능하도록 할 것입니다.
실습 과정에서 Cognito로 만든 User Pool이 필요합니다. 미리 만들고 본 포스팅을 보시면 좋을 것 같습니다.
AWS Cognito로 로그인 시스템을 만드는 방법은 이전 포스트에서 다루었습니다. 아래 링크를 참고해주시기 바랍니다.
(AWS Cognito 사용법 : https://walkinpcm.blogspot.kr/2017/05/aws-aws-cognito.html)
기초적인 실습이라서 입문자에게 도움이 되는 글일 듯 싶습니다.
(제가 입문자라서 입문용 글을 쓰고 있습니다..ㅎㅎ)

1. API Gateway와 Lambda의 개념

1-1. API Gateway

AWS API Gateway는 손 쉽게 REST API의 URI 주소를 생성할 수 있고, 유지 관리, 모니터링 할 수 있는 서비스입니다.
톰캣의 서블릿으로 예를 들면,
http(s)://{서버의 주소}/{서블릿명} 처럼 Resource에 접근할 수 있는 인터페이스라고 할 수 있습니다.
다만, API Gateway는 웹서버가 필요 없고, API 호출에 대한 로그도 쉽게 볼 수 있는 등 여러 장점이 있는 서비스라고 할 수 있습니다.

1-2. Lambda

Lambda는 최근 인기가 상승하고 있는 Serverless Compute Service입니다.
역시 톰캣으로 예를 들면, 서블릿의 역할을 수행하는 서비스라고 할 수 있습니다.
즉, 기존의 서버에서 동적으로 수행되는 특정 기능을 서버 없이 만들 수 있는 서비스인 것입니다. (엄밀히는 AWS가 서버를 운영하는 거겠지만, 사용자 입장에서 서버가 없다는 것입니다.)

2. 실습 상황

이번 포스팅에서 진행할 실습의 상황은 다음과 같습니다.

  1. 웹브라우저에서 사용자 인증을 위한 Token과 데이터를 가진 Payload를 붙여서 POST 요청을 보냅니다.
    (API의 호출 권한을 Open으로 해 놓으면 Token은 필요없습니다. Token을 API Gateway의 API Key로도 설정할 수 있지만, 본 포스팅에서는 AWS Cognito를 이용한 User의 Token으로 설정할 것입니다.)
  2. API Gateway는 Token을 확인하여 적법한 사용자라고 판별되면 Lambda Function을 호출하여 POST 요청에 대한 동작을 수행하게 합니다.
  3. Lambda는 적절한 동작을 수행 한 뒤 응답을 API Gateway로 보냅니다.
  4. API Gateway는 Lambda에게 받은 응답을 그대로 웹브라우저에게 응답합니다.

3. 실습

이제 step by step으로 정리해보겠습니다.

3-1. Lambda function과 API 만들기를 시작합니다.

AWS Lambda를 만드는 과정에서 API Gateway를 바로 연결 시켜서 API까지 만들 수 있습니다.
그래서 가장 먼저, AWS Lambda 서비스로 들어가서 'Get Started Now'를 클릭합니다.
이미 만들어본 적이 있으시면 Function을 새로 만드는 버튼을 찾아서 누르시면 됩니다.

3-2. Function 탬플릿을 선택합니다.

AWS Lambda는 맨땅부터 코딩할 수도 있지만, 목적에 따라 미리 만들어진 탬플릿을 골라서 생성할 수도 있습니다.

보시다시피 탬플릿이 참 많은데요. Filter부분에 키워드를 검색하시면 알맞은 탬플릿을 금방 찾으실 수 있습니다.


본 포스팅은 입문을 위하여 정리하기에 탬플릿 중에 'hello-world' 탬플릿을 선택하겠습니다.
파이썬으로 된 탬플릿도 있지만 저는 노드를 선택했습니다.

3-3. Lambda의 Trigger로 API Gateway를 선택합니다.

Lambda를 생성하면서 바로 Trigger를 선택하고 함께 생성할 수 있습니다.
빨간색 네모박스 부분을 클릭하시면 Trigger로 사용할 수 있는 종류가 나옵니다.
저는 API Gateway를 선택했습니다.

3-4. API Gateway 이름을 지정합니다.

'API name'에 원하는 API이름을 입력합니다. 이 이름으로 나중에 URL이 만들어 지지는 않습니다. URL은 Lambda function 이름으로 설정됩니다. 그러니 여기서는 API를 구분할 목적으로 입력하시면 되겠습니다.
'Deployment stage'는 나중에는 API의 버전 관리를 하게되면 세분화 해서 나누지만 본 포스팅에서는 입문을 빠르게 할 목적으로 일단 prod 하나만 사용하겠습니다.
'Security'는 Open으로 하셔도 되고 아무거나 하셔도 됩니다. 나중에 Cognito로 변경할 것이기 때문입니다. 저는 그래도 Open은 아무나 막 쓸수 있다는 생각에 Open with access key를 선택했습니다.

3-5. Lambda Function 이름을 지정합니다.

API 설정 다음으로 Lambda Function에 대한 설정을 합니다.
'Name'에 원하는 이름을 입력해주세요. 이 이름이 URL에 사용됩니다.
'Runtime'은 저는 노드를 선택했습니다. 여러분은 원하는 것을 선택하셔도 좋습니다.

3-6. Lambda Function의 코드를 보기만하고 넘어갑니다.

일단 코드는 보기만 하고 넘어갑니다. 뒤에서 수정할 것입니다.
코드를 간략히 설명하자면, Input으로 들어온 Body에서 key1, key2, key3의 값을 로그로 출력하고 Lambda Function의 응답으로 key1의 값을 반환합니다.
부가적으로 밑에 'Environment Variables'가 있는데, 이는 자주 또는 가끔 변경이 잘 되는 변수를 하드코딩하지 않고 환경변수로 두어서 값의 변경이 일어나도 코드 수정없이 반영할 수 있게 해주는 기능입니다.
Tip을 드리자면 노드 기준으로 환경변수를 사용하기 위해서는 process.env.환경변수명으로 코드에서 사용하실 수 있습니다.
보기만하고 지나간다고했는데 말이 길었네요 ㅎㅎ

3-7. Role을 설정합니다.

Role은 Lambda Function에서 다른 AWS 서비스에 접근하기 위하여 필요합니다.
기본적으로 Lambda에서는 Log를 남길수 있는 Role(권한)을 가지고 있습니다. 여기서 설정하는 Role은 추가적으로 필요한 Role을 설정하는 것입니다.
처음에는 만들어진 Role이 없을 것이므로 'Create new role from template(s)'를 선택합니다.
'Role name'은 적절하게 원하는 이름 붙여주시면 됩니다.
'Policy templates'는 그림에 써넣은대로 더 추가하고 싶은 Role을 여러개 선택할 수 있는데, 본 포스팅에서는 hello world 실습이므로 다른 AWS 서비스에 접근할 일이 없어서 아무것도 선택하지 않았습니다.
부가적인 설명으로, 맨 위에 'Handler'는 요청이 Lambda로 들어올 때 처리할 handler를 지정해 주는 것입니다.
'index.handler'라고 되어 있는 이유는, 지금 생성중인 Lambda가 index.js가 되고 index.handler가 지금 생성중인 Lambda에 명시된 handler라고 하네요.

3-8. 설정들 Review합니다.

최종적으로 설정들을 Review합니다.
저도 아직 깊숙히 몰라서 설정하지 않은 항목들이 있는데, 나중에 깊숙히 알게 되면 다시 포스팅을 하도록 하겠습니다.
'Create function'을 클릭합니다.

3-9. 첫번째 API 테스트

생성하자마자 Lambda의 Trigger 탭 페이지가 보이고 누르고 싶게 생긴 URL이 있습니다.
저게 바로 방금 생성한 Lambda를 실행시킬 수 있는 REST API URL입니다.
한번 눌러보죠.

Forbidden 에러가 발생합니다.

에러가 발생한 이유는, 아까 'Security'를 'Open with access key'로 설정했는데 지금 링크를 누른건 아무 access key없이 요청이 보내졌기 때문에 발생한 에러입니다.
아래 그림에서 빨간색 네모칸이 쳐진 'Test'는 Lambda function 자체만 테스트 하는 것입니다. 그래서 아무 문제없이 정상적인 출력이 나오죠. 이게 출력이 잘 나온다고 API Gateway+Lambda가 정상작동한다고 생각하시면 안됩니다.
URL 밑에 'ANY'를 클릭해서 API Gateway 설정 페이지로 이동합니다.

3-10. API의 인증방법으로 Cognito를 설정합니다.

본 포스팅에서는 API를 호출할 수 있는 권한을 Cognito로 로그인한 유저에게만 주려고 합니다.
좀 더 자세히 말씀드리면, API를 정상적으로 호출하려면 Token이 필요하게 할 것이고, 이 Token은 Cognito를 이용한 로그인 시스템에서 유저가 로그인하면 발급 받는 idToken입니다.
(본 포스팅 상단의 Cognito 사용방법을 정리한 링크를 함께 보시면 좋을 것 같습니다.)
아래 그림에서 'Method Request'를 클릭합니다.

그러면 아래와 같은 설정화면이 나옵니다.
파란색 네모칸이 API 호출 권한에 대한 곳인데 여기서 'Authorization'과 'API Key Required'를 수정할 것입니다.

왼쪽의 'Authorizers'를 클릭합니다.
이동 된 페이지에서 상단의 'Create'-'Cognito User Pool Authorizer'를 선택합니다.

그러면 아래와 같은 설정 페이지가 나타나는데, 여기에 미리 만들어 놓은 User Pool의 정보를 기입하면 됩니다.

'Cognito region'은 User Pool을 만들어 놓은 리전을 선택합니다.
'Cognito user pool'은 미리 만들어 놓은 user pool을 선택합니다. 선택된 user pool에 있는 유저들만 지금 만들고 있는 API를 호출 할 수 있습니다.
'Authorizer name'은 적절히 원하는 이름으로 기입하시면 됩니다.
'Create'를 눌러서 Authorizer를 생성합니다.
만들면 아래 그림처럼 Authorizer가 하나 생성됩니다.

이제 만든 Authorizer를 API의 인증방법으로 선택하러 갑니다.
왼쪽에 있는 'Resources'를 누르고 'ANY'를 누르고 'Method Request'를 눌러서 아까 인증 설정 화면으로 이동합니다.

이제 'Authorization'의 목록을 보면 방금 생성한 Cognito user pool authorizer가 있습니다.
그것을 선택합니다.

그리고 'API Key Required'는 false로 선택합니다. 저는 처음에 Cognito에서 획득한 Token이 Key로 쓰인다고 생각해서 여기를 true로 했는데, 그랬더니 Cognito로 획득한 Token도 필요하고 API Gateway에서 만든 Key도 필요한 상황이 되었었습니다.
선택을 하고나면 네모칸의 체크모양 버튼을 꼭 눌러주셔야합니다.

API Gateway는 API에 변경사항이 발생하고나면 반드시 Deploy를 해야 반영됩니다. 이거때문에 안된다고 생각하고 난관을 겪는분들이 꽤 있다고 하네요.

'Deployment stage'는 prod로 합니다.(아직 심화가 아니라서 배포 단계를 나누진 않았습니다.)
'Deploy'해주세요.

3-11. 두번째 API 테스트

API도 설정했으니 테스트를 해봅시다.
최초 Lambda function의 기능이 위에서 언급한 것 처럼 body에 전해오는 key1의 값을 그대로 반환한다고 했습니다. 그러니 테스트를 위해서는 요청에 body가 껴야하고, 그러려면 POST 요청을 해야합니다.
그래서 테스트에 크롬 확장프로그램인 Postman을 이용합니다.
아래 그림처럼 요청방식을 POST로 선택해주시고, URL에는 API의 URL을 넣어주시고, Header에는 Cognito로 만든 로그인 시스템에서 로그인하여 획득한 idToken 값을 넣어줍니다.
그리고 body에는 key1, key2, key3를 json 형식으로 값과 함께 입력해줍니다.
그리고 'Send'를 눌러서 요청을 보내봅니다.

네, 에러가 발생합니다. Internal server error입니다. 이거는 Lambda function에서 난 에러입니다.

3-12. Lambda function 코드를 수정합니다.

만들어 놓은 Lambda function에 가서 아래 그림처럼 코드를 수정합니다.

주요 변경된 부분은 event에서 body의 내용을 추출하는 부분과 callback의 응답을 수정하는 부분입니다.
API Gateway의 API를 통해서 Lambda에 전달되는 요청은 body뿐만 아니라 다양한 이상한 값들과 함께 넘어갑니다. 그래서 body를 추출하려면 저렇게 해주셔야합니다.
그리고 API Gateway를 통해서 반환되는 응답에는 statusCode와 headers, body가 있어야 정상적인 응답이 보내집니다. headers는 상황에 따라서 적절히 더 추가하시면 됩니다.

3-13. 세번째 API 테스트

이제 마지막 테스트 입니다.
두번째 테스트와 동일하게 POST 요청을 보내봅니다.
짜잔~ 성공적으로 Request body의 첫번째 key인 key1의 value가 되돌아 왔습니다.

이 길고 긴 글을 읽어주셔서 너무 감사드립니다.
부디 이 입문자의 글이 다른 입문자 분들께 도움이 되었으면 좋겠습니다.
내용 중에 틀리거나 보완되야하거나 궁금한 내용은 댓글을 달아주시면 아는 지식 총 동원해서 포스팅을 수정하거나 답글을 달아드리겠습니다.
감사합니다

2017년 5월 8일 월요일

[AWS] AWS Cognito 입문 가이드

AWS Cognito 입문 가이드

본 포스팅에서는 AWS에서 제공하는 회원 관리 서비스인 AWS Cognito를 입문하는 방법에 대해 정리해보려 합니다.
제가 시작하면서 경험한 내용을 바탕으로 작성하여 미래의 저 스스로와 다른 분들께 도움이 되면 좋겠습니다.

0. AWS Cognito의 사용 예

저는 Cognito 입문자이기 때문에 매우 단순하게 사용하려 합니다.
AWS에서 제시하는 Cognito의 사용 예는 3가지 정도가 있으나, 이 중에서 가장 간단한 첫번째 사용 예를 실습해보았습니다.
아래 그림이 가장 간단한 Cognito의 사용 예 입니다.
(출처 : AWS Summit 2017 Seoul 발표자료)

사용 예의 상황은 다음과 같습니다.
사용자(User)가 사용하고 싶은 API(AWS API Gateway로 만들어진)가 있는데, 이 API를 이용하기 위해서는 사용이 인가된 사용자여야합니다.
그래서 사용자(User)는 S3에서 웹호스팅 된 회원가입 및 사용자 인증, 로그인 페이지에 접속해서 회원가입을 하고 로그인을 해서 Token을 획득한 뒤에 해당 Token을 이용해서 API를 호출하는 상황입니다.
그림에 표시된 번호대로 설명하면 아래와 같습니다.
  1. 먼저 서비스 제공자가 AWS S3에서 웹페이지(가입, 인증, 로그인이 가능한 웹페이지)를 웹호스팅을 하고 있는 상태입니다.
    사용자(User)는 자신의 기기(Client)에서 해당 웹페이지에 접속합니다.
  2. 접속한 웹페이지에서 회원가입(Sign-up)을 합니다.
  3. 회원가입만 한 상태에서는 사용자 인증이 되어있지 않습니다. 경우에 따라서 이메일 또는 핸드폰 번호로 인증번호가 발송됩니다.
  4. 사용자는 이 코드를 웹페이지에 입력해서 사용자 인증을 받습니다.
    사용자 인증을 받고나면 로그인을 할 수 있습니다. 로그인에 성공하면 응답으로 Token을 받을 수 있습니다.
  5. 드디어 사용자는 사용하고 싶은 API를 호출합니다. 이때, 로그인하면서 받은 Token을 헤더에 같이 넣어서 호출합니다.
  6. API Gateway는 이 Token이 유효한 Token인지 Cognito에 확인합니다.
  7. Cognito는 Token의 유효성을 응답해줍니다.
  8. API Gateway가 Cognito로부터 유효한 사용자라고 응답을 받으면 API 호출에 대한 적절한 응답을 사용자에게 반환합니다.
이 사용 예에서 가장 중요한 것은 Token을 획득하는 일입니다.
본 포스팅에서는 이 Token을 Cognito로 부터 획득하기 위해서 Cognito를 준비하고 회원가입, 인증, 로그인 페이지에서 어떻게 코드를 작성해야 하는가를 정리해보겠습니다.

1. 실습

본 실습에서는 html로 회원가입, 인증, 로그인 폼을 만들고, javascript로 각각의 동작을 구현합니다.
절차는 크게 아래와 같습니다.
  • Cognito에 사용자(User)를 받을 수 있는 User Pool 준비
  • 준비한 User Pool에 사용자(User)를 가입, 인증, 로그인 시킬 수 있는 웹페이지 구현

1-1. AWS Cognito 준비하기

(1) AWS Cognito 서비스에 들어갑니다.
그럼 아래와 같은 화면이 나오는데, 여기서 'Manage your User Pools'를 클릭합니다.

'User Pool'이라는 것은 간단히 사용자 데이터베이스 라고 생각할 수 있습니다.
회원의 ID(Username), email, phone number 등의 정보를 저장할 수 있습니다.
(2) 'Create a User Pool'을 클릭합니다.  


(3) User Pool의 이름을 입력하고, 'Review defaults'를 클릭합니다.
(4) 여러 Setting 값들을 적절하게 수정합니다. (아래에서 하나씩 설명하겠습니다.)

1번은 필수로 입력받아야할 속성들을 선택할 수 있습니다. 기본적으로 모든 항목에 대해서 회원가입 시에 데이터를 입력시킬 수 있는데, 이때 필수로 입력 받아야 하는 항목을 선택하는 것입니다.
Alias는 해당 속성을 ID(Username)으로도 사용 할 수 있게 해주는 것입니다.
User Pool을 생성한 이후에는 필수입력 속성을 더 선택하거나 빼거나 하는 수정이 되지 않습니다. 신중히 체크하셔야 합니다.

2번은 암호의 규칙을 설정하는 곳입니다. 최소 글자수, 특수문자, 대문자, 소문자를 필수로 포함해야 하는지 아닌지를 선택할 수 있습니다.

3번은 사용자 인증 방법을 선택하는 곳입니다.
Email 또는 Phone number를 이용해서 사용자 인증을 할 수 있습니다.
Email을 선택하면 사용자가 회원가입 시에 입력한 메일로 인증 코드가 발송되며, Phone number로 하면 핸드폰 번호로 인증코드가 발송됩니다. 핸드폰 번호를 입력 받으실 때는 국제번호 포맷으로 저장해야합니다.(ex. +821012345678)
그리고 'Create role'을 눌러서 Cognito에서 알아서 인증 메세지를 보낼 수 있게 권한을 만들어줘야합니다.

4번은 'App Client'를 만드는 곳입니다. App Client를 만들면 고유번호가 생성되는데 이 고유번호를 회원가입 페이지에서 알고 있어야지 지금 생성하는 User Pool을 이용할 수 있습니다.
'Add an app client'를 누릅니다.

'App client name'을 입력하고, 반드시! 'Generate client secret'의 체크를 해제합니다.

Client secret의 정확한 의미를 찾으려 했으나.. 잘 안보이네요.. 아마 이 App Client를 사용할 때 추가적으로 암호를 사용하려는거 같은데, 어떤 문서를 봐도 이걸 해제라고 되어있고 아직 활성화된 기능이 아니라는 등의 말만 나오네요..
그리고 무엇보다도 Javascript에서 Cognito를 사용할 때는 'Generate client secret'을 무조건 체크 해제 해야합니다. 그렇지 않으면 사용하려할 때 에러가 발생한다고 하네요.

App Client를 만들었으면 'Return to pool details'를 클릭해서 설정 리뷰 화면으로 돌아갑니다.
부가적인 설명으로, 아마 App Client는 여러개를 만들 수 있는 것 같습니다. 그래서 여러 App에서 하나의 User Pool에 접근할 수 있게 하는 것 같습니다.

다 만들고나면 User Pool 생성 성공 메세지가 나타나고 'Pool Id'와 'Pool ARN'이 표시됩니다.
여기서 'Pool Id'가 Javascript에서 필요합니다.

(5) 그리고 왼쪽에 'App clients'를 누르면 'App client Id'가 나오는데, 이것도 Javascript에서 필요합니다.

이제 User Pool은 준비가 되었습니다! 회원을 맞을 할 준비가 된 것이죠 ㅎㅎㅎ


1-2. Html과 Javascript를 이용해서 웹페이지 구현

이제 회원을 받을 수 있는 웹 페이지를 만들어야합니다.
(1) html 페이지 작성
폼은 그냥 일반적인 input text와 button으로 만들면 됩니다.
너무나 일반적이라서 AWS에서 설명도 안해줍니다...
대강 아래처럼 필요한 정보를 입력할 수 있게만 input 폼을 만들고 버튼만 만들면 됩니다.
중요한 것은 버튼을 클릭했을 때 Javascript 함수가 동작하게 하고 해당 함수 내에서 Cognito 함수들을 사용하는 것입니다.


그리고 Cognito를 사용하기 위해서는 3개의 js 파일을 로드해와야합니다.
2개는 다운받아서 넣어줘야하고 1개는 url로 입력하시면 됩니다.
다운로드는 아래 링크에 들어가셔서 'amazon-cognito-identity.min.js'와 'aws-cognito-sdk.min.js'를 받습니다.
(링크 : https://github.com/aws/amazon-cognito-identity-js/tree/master/dist)

다운 받으시면 아래처럼 html의 head에 js를 추가해줍니다.
'/path/to'는 아시다시피 본인의 경로에 맞게 대체해주시면 됩니다.
<script src="/path/to/aws-cognito-sdk.min.js"></script>
<script src="/path/to/amazon-cognito-identity.min.js"></script>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.7.20.min.js"></script>

(2) javascript 함수 구현
javascript 함수는 3개를 만듭니다. 회원가입(Sign up), 인증(Activate code), 로그인(Sign in) 이 3개입니다.
우선, 범용적으로 사용될 설정값을 하나의 js파일에 넣어둡니다.(ex. aws-cognito-config.js)
작성되야할 내용은 아래와 같습니다.

region은 user pool을 생성한 리전이고, userPoolId과 appClientId는 User Pool을 만들고 나서 생성된 고유값입니다.
apiGWEndpoint는 Token을 얻은 후에 api를 호출할 주소인데, 본 포스팅에서는 사용하지 않습니다.
이렇게 변수로 만들어 놓고 앞으로 구현할 함수에서 해당 값이 필요할 때 불러다 쓰시면 됩니다.

이제 버튼 클릭 이벤트를 처리할 함수를 담을 js 파일을 만들고 아래의 방법으로 코드를 작성합니다.

우선, 다수 함수에서 공통적으로 사용할 변수를 전역변수로 작성해 놓습니다.
// AWSCognito 객체를 계속해서 사용하는데 여기에 리전 정보를 저장합니다.
// CognitoConfig.region이 위에서 별도의 js 파일에 넣어둔 설정값입니다.
AWSCognito.config.region = CognitoConfig.region;

// 사용할 User Pool의 정보를 담고있는 변수입니다.
var poolData = {
  UserPoolId : CognitoConfig.userPoolId,
  ClientId : CognitoConfig.appClientId
};

// 입력한 User Pool 정보를 가지고 실제 User Pool에 접근할 수 있는 객체를 만듭니다.
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);

// 아래 변수는 회원가입을 하고 가입이 성공했을 때 사용자 정보를 반환받는 변수인데,
// 회원가입 함수와 인증 함수에서 같은 객체를 사용해야하기 때문에 전역변수로 뺐습니다.
var cognitoUser;
그럼 첫번째, 가입 함수입니다.
function submitSignUp() {
  // 가입할 때 사용자가 입력한 정보들을 저장할 배열입니다.
  var attributeList = [];

  // 입력 폼에서 입력된 값을 받아오는 부분입니다. 일반적인 javascript입니다.
  var user_Name = document.getElementById("signup_username").value;
  var user_PhoneNumber = document.getElementById("signup_phonenumber").value;
  var user_Pw = document.getElementById("signup_pwd").value;
  console.log('user data : ', user_Name, ', ', user_PhoneNumber, ', ', user_Pw);

  // 이 변수가 사용자가 입력한 정보 중 하나를 입력하는 변수입니다.
  // 저는 핸드폰 번호만 입력받았습니다.
  // 변수명은 자유롭게 사용가능하나, Name은 AWS Cognito에서 정해주는대로 써야합니다.
  // 목록 : address, birthdate, email, family_name, gender, given_name, locale
  //   , middle_name, name, nickname, phone_number, picture, preferred_username
  //   , profile, timezone, updated_at, website
  var dataPhoneNumber = {
    Name: 'phone_number',
    Value : user_PhoneNumber
  };

  // Attribute를 AWS Cognito가 알아들을 수 있는 객체로 만듭니다.
  var attributePhoneNumber = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataPhoneNumber);

  // 방금 위에서 만든 Attribute 객체를 Attribute List에 추가시킵니다.
  // 이렇게 배열에 다 추가시키고 한번에 Cognito에 넘길겁니다.
  attributeList.push(attributePhoneNumber);

  // 전역변수로 만들어 놓은 User Pool 객체에서는 signup 함수를 제공합니다.
  // 인자는 User name(ID 인것 같네요.), Password, Attribute List, null(무슨 자리인지 모르겠어요..확인해야합니다.ㅎㅎ), 처리 결과가 오면 수행 될 callback 함수 입니다.
  userPool.signUp(user_Name,user_Pw, attributeList, null, function(err, result) {
    if(err) {
      // error가 발생하면 여기로 빠집니다.
      alert(err);
      return;
    }

    // 가입이 성공하면 result에 가입된 User의 정보가 되돌아 옵니다.
    // 인증 함수에서 사용해야하기에 위에서 만든 전역변수인 cognitoUser에 넣어놓습니다.
    cognitoUser = result.user;
    console.log('user name is '+cognitoUser.getUsername());
  });
}
두번째, 인증 함수입니다.
function submitActivateCode() {
  // 회원가입을 하면 User Pool을 어떻게 만들었냐에 따라서 email 또는 phone으로 인증코드가 발송됩니다.
  // 사용자로부터 인증코드를 입력받아옵니다.
  var user_activatecode = document.getElementById("activate_code").value;

  // cognitoUser는 가입함수에서 가입 성공 후 되돌아온 사용자 정보가 담겨있습니다.
  // 이 변수에서 바로 confirmRegistration함수를 수행하면 AWS Cognito로 인증 요청을 합니다.
  // 인자는 인증코드, true(이것도 알아봐야합니다..ㅎㅎ), callback 함수 입니다.
  cognitoUser.confirmRegistration(user_activatecode, true, function(err, result){
    if(err) {
      alert(err);
      return;
    }
    // 인증이 성공하면 SUCCESS 문자가 되돌아 옵니다.
    console.log('call result : ' + result);
  });
}
세번째, 로그인 함수입니다. 이 함수를 수행하면 드디어 Token을 얻을 수 있습니다.
function submitSignin() {
  // 입력 폼에서 ID와 비밀번호를 입력받습니다.
  // 저는 phone number를 alias로 설정해서 ID 처럼 사용할 수 있게 했습니다.
  var user_PhoneNumber = document.getElementById("signin_phonenumber").value;
  var user_Pw = document.getElementById("signin_pwd").value;

  // ID와 Password를 정해진 속성명인 Username과 Password에 담습니다.
  var authenticationData = {
    Username : user_PhoneNumber,
    Password : user_Pw
  };

  // 여기에는 ID와 User Pool 정보를 담아 놓습니다.
  var userData = {
    Username : user_PhoneNumber, // your username here
    Pool : userPool
  };

  // 로그인을 위해 Cognito 객체 2개를 준비합니다.
  var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
  var cognitoSignedUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);

  // authenticateUser 함수로 로그인을 시도합니다.
  cognitoSignedUser.authenticateUser(authenticationDetails, {
    onSuccess: function (result) {
      // 로그인에 성공하면 Token이 반환되어 옵니다.
      console.log('access token + ' + result.getAccessToken().getJwtToken());
      // API Gateway로 만든 API에 Request를 보낼 때는 Authorization 헤더의 값으로 idToken을 넣어야합니다.
      console.log('idToken + ' + result.idToken.jwtToken);
    },
    onFailure: function(err) {
      alert(err);
    }
  });
}
이번 포스팅에서는 Token을 획득한 것으로 마치겠습니다.
다음 포스팅에서 이 Token을 가지고 API Gateway로 만든 API를 호출하고, 연결된 Lambda함수를 실행해서 응답을 받는 실습을 정리해보겠습니다.

* API Gateway+Lambda 사용 방법 링크
https://walkinpcm.blogspot.kr/2017/05/aws-aws-api-gateway-lambda-rest-api.html