다음과 같은 API 요청과 API 응답을 가지는 REST API를 Lambda 함수와 API Gateway를 이용하여 구축해본다.
API 요청
GET /devices
API 응답
{
"things": [
{
"thingName": "string",
"thingArn": "string"
},
...
]
}
–
생성된 ListingDeviceLambda의 build.gradle 파일을 열고, 다음 의존성을 추가하고, 변경사항을 반영합니다.
dependencies {
...
implementation platform('com.amazonaws:aws-java-sdk-bom:1.12.529')
implementation 'com.amazonaws:aws-java-sdk-iot'
...
}
src/main/java/helloworld/App.java 파일을 다음 코드로 바꿉니다.
package helloworld;
import java.util.List;
import com.amazonaws.services.iot.AWSIot;
import com.amazonaws.services.iot.AWSIotClientBuilder;
import com.amazonaws.services.iot.model.ListThingsRequest;
import com.amazonaws.services.iot.model.ListThingsResult;
import com.amazonaws.services.iot.model.ThingAttribute;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
public class App implements RequestHandler<Object, String> {
@Override
public String handleRequest(Object input, Context context) {
// AWSIot 객체를 얻는다.
AWSIot iot = AWSIotClientBuilder.standard().build();
// ListThingsRequest 객체 설정.
ListThingsRequest listThingsRequest = new ListThingsRequest();
// listThings 메소드 호출하여 결과 얻음.
ListThingsResult result = iot.listThings(listThingsRequest);
return getResultStr(result);
}
/**
* ListThingsResult 객체인 result로 부터 ThingName과 ThingArn을 얻어서 Json문자 형식의
* 응답모델을 만들어 반환한다.
* {
* "things": [
* {
* "thingName": "string",
* "thingArn": "string"
* },
* ...
* ]
* }
*/
private String getResultStr(ListThingsResult result) {
List<ThingAttribute> things = result.getThings();
String resultString = "{ \"things\": [";
for (int i =0; i<things.size(); i++) {
if (i!=0)
resultString +=",";
resultString += String.format("{\"thingName\":\"%s\", \"thingArn\":\"%s\"}",
things.get(i).getThingName(),
things.get(i).getThingArn());
}
resultString += "]}";
return resultString;
}
}
–
작성된 Lambda함수가 정상적으로 동작하는 지를 테스트해 보기 위해서 다음 절차를 수행합니다.
IntelliJ IDEA IDE의 화면 상단 타이틀 바에서 “[Local] HelloWorldFunction” 옆의 연두색 실행 버튼 (삼각형)을 클릭
[Edit Configuration] 다이얼로그 화면에서 Text – Event Templates – 부분의 드롭다운 메뉴 중에서 API Gateway AWS Proxy를 선택
Console 창에 다음과 같은 형식의 메시지가 마지막에 출력되는 지 확인합니다. (본인의 aws 계정에 생성된 사물 목록이 Json 형식으로 반환됨)
...
"{ \"things\": [{\"thingName\":\"MyMKRWiFi1010\", \"thingArn\":\"arn:aws:iot:ap-northeast-2:884579964612:thing/MyMKRWiFi1010\"}]}"
–
ListingDeviceLambda 프로젝트 탐색창에서 template.yaml을 찾아서 선택하고, 선택된 상태에서 오른쪽 마우스 클릭하여 SyncServerless Application (formerly Deploy) 메뉴를 선택
[Confirm development stack] 다이얼로그 화면에서 Confirm 선택
[SyncServerless Application (formerly Deploy)] 다이얼로그 화면에서, Create Stack에 적절한 이름(예, ListingDeviceLambda)을 입력 하고, CloudFormation Capabilities: 에서 IAM 체크박스를 선택한 후, Sync 클릭
콘솔 창에 다음 결과가 맨 마지막 줄에 출력되는 지를 확인
...
Stack creation succeeded. Sync infra completed.
Process finished with exit code 0
–
AWS Lambda함수가 다른 AWS 서비스 (예, DynamoDB)를 사용하기 위해서는 필요한 권한이 Lambda함수에 연결된 실행 역할 정책(Execution Role Polcity)에 포함되어 있어야 합니다.
람다함수의 실행 역할 정책 업데이트
원격 테스트를 위해서 AWS Toolkit 창의 탐색기에서 Lambda를 확장하여 ListDeviceLambda-HelloWorldFunction-XXX선택하고, 오른쪽 마우스 클릭하여 Run ‘[Remote] HelloServer…‘메뉴를 선택
–
테스트를 클릭하고, 아무 입력 없이 테스트버튼을 클릭하여 다음과 같은 결과가 나오는 지 확인합니다.
/devices - GET 메서드 테스트 결과
요청
/devices
지연 시간
6399
상태
200
응답 본문
{"statusCode":200,"headers":{"X-Custom-Header":"application/json","Content-Type":"application/json"},"body":"{ \"things\": [{\"thingName\":\"MyMKRWiFi1010\", \"thingArn\":\"arn:aws:iot:ap-northeast-2:884579964612:thing/MyMKRWiFi1010\"}]}"}
응답 헤더
{
"Content-Type": "application/json",
"X-Amzn-Trace-Id": "Root=1-653e463c-0518263d2fe5ca0ab5d5bf9b;Sampled=0;lineage=ff092584:0"
}
...
–
JavaScript는 Cross-Origin Resource Sharing (CORS) 요청을 기본적으로 제한합니다. 즉, JavaScript 코드가 동일 서버 내의 리소스를 접근하는 것은 허용하지만, 다른 서버의 리소스를 사용하고자 하는 경우에는 CORS 헤더 정보가 포함되어 있어야 합니다.
REST API 리소스에 대해 CORS 지원 활성화
2단계를 완료하면 API를 생성했지만 아직 실제로 사용할 수는 없습니다. 배포해야 하기 때문입니다.
–
list_devices.html 시작 html 페이지
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AWS Open API Sample</title>
<!-- JQuery 라이브러리 설정 -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<!-- 디바이스 조회 자바스크립트 로딩-->
<script src="list_devices.js"></script>
</head>
<body>
<h3>My AWS API Sample</h3>
<h4> 나의 디바이스 목록 <input type="button" value="조회" onclick="Start();" />
</h4>
<table id="mytable">
<thead style="background-color:lightgrey">
<th>디바이스 명</th>
<th>디바이스 ARN</th>
</thead>
<tbody> </tbody>
</table>
<div id="result">No Data</div>
</body>
</html>
list_devices.js: JQuery 기반 Javascript 코드 (API_URI 변수를 API gateway에서 생성한 URI로 수정해야 합니다.)
// API 시작
function Start() {
invokeAPI();
emptyTable();
}
var invokeAPI = function() {
// 디바이스 조회 URI
// prod 스테이지 편집기의 맨 위에 있는 "호출 URL/devices"로 대체해야 함
var API_URI = 'https://XXXXXXXXXX.execute-api.ap-northeast-2.amazonaws.com/prod/devices';
$.ajax(API_URI, {
method: 'GET',
contentType: "application/json",
success: function (data, status, xhr) {
var result = JSON.parse(data);
setDataList(result.things); // 성공시, 데이터 출력을 위한 함수 호출
console.log(data);
},
error: function(xhr,status,e){
// document.getElementById("result").innerHTML="Error";
alert("error");
}
});
};
// 테이블 데이터 삭제
var emptyTable = function() {
$( '#mytable > tbody').empty();
document.getElementById("result").innerHTML="조회 중입니다.";
}
// 데이터 출력을 위한 함수
var setDataList = function(data){
$( '#mytable > tbody').empty();
data.forEach(function(v){
var tr1 = document.createElement("tr");
var td1 = document.createElement("td");
var td2 = document.createElement("td");
td1.innerText = v.thingName;
td2.innerText = v.thingArn;
tr1.appendChild(td1);
tr1.appendChild(td2);
$("table").append(tr1);
})
if(data.length>0){
// 디바이스 목록 조회결과가 있는 경우 데이터가 없습니다 메시지 삭제
document.getElementById("result").innerHTML="";
} else if (data.length ==0) {
document.getElementById("result").innerHTML="No Data";
}
}
초기화면
조회 버튼을 클릭한 후