AWS Lambda Java로 API 서비스 개발

David Jeon·2023년 12월 27일
1

AWS Lambda 개발

목록 보기
2/2

본 블로그에서는 Java 를 이용하여 PostgreSql의 Data를 조회하는 Lambda Class를 생성하고 API Gateway 호출시 Json으로 HTTP Response 하는 흐름의 API 구현 방법을 설명한다.

<사전 준비 사항>

  • AWS 계정 생성
  • PostgreSql RDS를 생성
  • Host 정보, 계정 정보, Table 생성 필요

<개발 환경>

  • 개발 언어 : Java
  • AWS Service : Lambda, API Gateway
  • DB : PostgreSql

1. Java Lambda 생성

1.1 PostgreSql의 Data를 조회하는 Java Lambda 생성

1) AWS Lambda 화면으로 이동
2) 함수 생성 버튼을 클릭하여 생성할 함수의 정보를 입력 후

  • 함수 이름 : lambdaJavaSample
  • 런타임 : Java8 on Amazon Linix1
  • 아키텍쳐 : x86_64
  • 실행 역할 : 기본 Lambda 권한을 가진 새 역할 생성

3) 생성된 Lambda 화면

2. Eclipse에서 Java Project 생성 및 Lambda Coding

2.1 lambdaJava Proejct 생성

1) Eclipse Project : New > Project 생성

2) Maven Project 선택 후 Next 클릭

3) New Maven project : Use default Workspace location > Next 클릭

4) Filter에 maven을 입력 후 검색된 목록에서 maven-archetype-quickstart 를 선택 > Next 클릭

5) Group Id, Artifact Id, Version을 입력 후 "Finish" 클릭하면 프로젝트가 생성됨

2.2 Lambda Java 구현

  • JDBC를 이용하여 RDS인 PostgreSql의 데이터를 조회하여 Return 하는 API 구현

1) pom.xml 수정

  • 생성된 프로젝트의 Dependency에 소스에서 사용할 Library Dependency 추가하고 Build 시 모든 Dependency Library의 Jar를 같이 Package 되도록 설정 필요
  • 수정한 pom.xml
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.lambdajava</groupId>
  <artifactId>postgresql</artifactId>
  <version>0.0.1</version>

  <name>postgresql</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.6.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.28</version>
    <scope>provided</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.15.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-core -->
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-core</artifactId>
    <version>1.2.3</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-events -->
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-events</artifactId>
    <version>3.11.3</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-log4j -->
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-log4j</artifactId>
    <version>1.0.1</version>
</dependency>
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <!-- any other plugins -->
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

2) Maven Update Project 실행

3) postgresql Project를 선택하고 OK 클릭 (프로젝트에 표시된 빨간X 가 사라짐)

4) API Gateway로 호출될 때 HTTP Response를 할 수 있도록 APIResponse Class 생성 및 구현

package com.lambdajava.postgresql;

import java.util.Map;
import lombok.Data;

/*
 * API Gateway에 Response 하기 위한 Class
 */
@Data
public class APIResponse {
	String body;
	Integer statusCode;
	Map<String, String> headers;
}

5) DB에서 조회하여 정보를 저장할 DTO SockerPlayer Class 생성 및 구현

package com.lambdajava.postgresql;

import lombok.Data;

@Data
public class SockerPlayer {
	private int seq_p_id;
	private String c_code;
	private String p_name;
	private String position;
	private int height;
	private String reg_date;
}

6) API Gateway에 의해 호출될 Class 인 App Class 구현

package com.lambdajava.postgresql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.fasterxml.jackson.databind.ObjectMapper;

public class App {
	// AWS APIGateway에 의해 호출될 Method 구현
	public APIResponse handleRequest(Context context) throws Exception {

		// Use LambdaLogger
		LambdaLogger logger = context.getLogger();
		logger.log("LambdaPostgressSqlHandler is invoked.!!!!");

		// Get Player List from PostgreSql
		List<SockerPlayer> players = getPlayers(logger);
		logger.log("players count = [" + players.size() + "]");

		// Create Response Object
		APIResponse apiResponse = new APIResponse();
		apiResponse.setStatusCode(200);
		ObjectMapper objectMapper = new ObjectMapper();
		// 조회한 Player List를 Json String으로 변환하여 HTTP Response Body에 추가
		apiResponse.setBody(objectMapper.writeValueAsString(players));

		return apiResponse;
	}

	private List<SockerPlayer> getPlayers(LambdaLogger logger) {
		String url = "jdbc:postgresql://postgre-test.clwu7owg973t.us-east-2.rds.amazonaws.com:1432/postgreDB";
		String user = "usr";
		String password = "abcd1234";

		String query = "select seq_p_id, c_code, p_name, position, height, reg_date from player order by seq_p_id";

		List<SockerPlayer> players = new ArrayList<SockerPlayer>();
		try (Connection connection = DriverManager.getConnection(url, user, password);
				PreparedStatement preparedStatement = connection.prepareStatement(query);) {

			logger.log("PSql preparedStatement = [" + preparedStatement + "]");

			ResultSet rs = preparedStatement.executeQuery();
			while (rs.next()) {
				SockerPlayer player = new SockerPlayer();
				player.setSeq_p_id(rs.getInt("seq_p_id"));
				player.setC_code(rs.getString("c_code"));
				player.setP_name(rs.getString("p_name"));
				player.setPosition(rs.getString("position"));
				player.setHeight(rs.getInt("height"));
				player.setReg_date(rs.getString("reg_date"));

				logger.log("Query Result = [" + player.toString() + "]");
				players.add(player);
			}
		} catch (SQLException e) {
			logger.log("SQLState: " + e.getSQLState());
			logger.log("Error Code: " + e.getErrorCode());
			logger.log("Message: " + e.getMessage());
		}
		return players;
	}
}

2.3 Labmda Java Jar 생성

  • Jar를 만들때 중요한 것은 Dependency로 선언된 Library들을 모두 한번에 Package로 만들어야 하는데 해당 설정은 pom.xml 에 설정할 수 있다.

...
<build>
    <plugins>
      <!-- any other plugins -->
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

1) Project 위에서 우측버튼을 클릭하여 Run as > Maven build ... 클릭

2) Goals 에 "clean package" 를 입력후 "Run" 버튼을 클릭

3) Build가 SUCCESS 되면 프로젝트 > target > postgresql-0.0.1-jar-with-dependencies.jar 파일이 생성된 것을 확인할 수 있다.

3. AWS Lambda 설정 변경 및 Jar 업로드

3.1 AWS Lambda 설정 변경

1) 생성한 lambdaJavaSample 의 상세화면이으로 이동

  • "런타임 설정" 부분의 핸들러 정보가 초기에 생성된 정보로 표시됨

2) 런타임 설정 편집을 위해 "편집" 버튼을 클릭하고 Java 소스의 정보를 이용하여 핸들러 정보를 수정 후 저장을 클릭

  • Package Name.Class Name::Method Name

=> com.lambdajava.postgresql.App::handleRequest

3) 수정된 런타임 설정 > 핸들러 정보를 확인(빨간색)

4) 상기 3)의 파란색 "에서 업로드"를 클릭 후 ".zip 또는 .jar 파일" 항목을 선택하면 업로드 창이 팝업됨

  • "업로드" 버튼을 클릭 후 "postgresql-0.0.1-jar-with-dependencies.jar" 파일을 선택하여 업로드 진행후 "저장"을 클릭

( 주의 - 이전 업로드된 파일을 덥어쓰기 때문에 원복이 불가함)

5) 업로드가 성공되고 코드 속성 정보가 변경된 것을 확인할 수 있다.

4. AWS Lambda를 호출할 "트리거" 추가 및 테스트

4.1 트리거 추가

1) "+ 트리거 추가" 버튼을 클릭하여 API Gateway 트리거를 선택한다

2) Intent 항목에서 "Create a new API"를 선택 후 "HTTP API"를 선택하고 Security 를 클릭하여 "Open"을 선택하고 "추가" 버튼을 클릭한다.
(Open은 인증없이 HTTP 요청이 가능하도록 하는 설정이다.)

3) API Gateway가 생성된다.

4.2 API 테스트
1) 상기 생성된 API Gateway 화면에서 API endpoint를 Copy 한다.

https://hlc5blups0.execute-api.us-east-2.amazonaws.com/default/lambdaJavaSample

2) Postman의 GET API를 생성하여 copy한 API endpoint를 paste 하고 "Send" 버튼을 클릭한다

상기 이미지와 같이 Body 부분에 PostgreSql 의 player Table에 있는 데이터를 조회하여 JSON Type으로 조회된 결과를 확인할 수 있다.

API Gateway를 통해 Java를 이용한 DB Data를 조회하는 Lambda 호출 성공~~!!!

4.3 API 테스트 결과를 CloudWatch에서 확인하기

Lambda 호출 시 에러가 발생하는 경우 어떤 문제가 발생했는지 알 수 없는데 이때 로그 확인을 할 수 있는 방법이 바로 CloudWatch Log를 확인하는 것이다.

CloudWatch Log를 남기기 위해서는 Java 소스에서 Lambda Context에서 LambdaLogger를 생성하여 log() 메소드를 이용하면 남길수 있다.

// 소스 일부 발췌

LambdaLogger logger = context.getLogger();

Lambda 호출 시 에러가 발생하는 경우 어떤 문제가 발생했는지 알 수 없는데 이때 로그 확인을 할 수 있는 방법이 바로 CloudWatch Log를 확인하는 것이다.

CloudWatch Log를 남기기 위해서는 Java 소스에서 Lambda Context에서 LambdaLogger를 생성하여 log() 메소드를 이용하면 남길수 있다.

// 소스 일부 발췌
// Use LambdaLogger
LambdaLogger logger = context.getLogger();
logger.log("LambdaPostgressSqlHandler is invoked.!!!!");

1) lambdaJavaSample 상세화면으로 이동하여 다이어그램 아랫부분의 "모니터링" 탭을 선택하여 "CloudWatch Logs 보기"를 클릭

2) CloudWatch 페이지가 새로운 화면에 표시되며 테스트했던 로그의 목록이 표시됨

3) 로그 스트림의 목록에서 최신에 생성된 로그를 클릭하면 lambdaJavaSample 이 실행될 때 남기 Log를 확인할 수 있음

("2.2 Labmda Java 구현 > 6)" 의 소스를 보면 LambdaLogger logger 로 남기고 있는 빨간색의 Log를 확인 가능)

본 Lambda Java를 구현을 위해 AWS Document의 설명이 부족하여 어려웠던 부분을 공유하자면 아래의 항목을 적용하는 부분이었다.

  1. Java 소스를 Dependency Library들 전부를 Package 하기

  2. 개발한 Java 파일의 Method 명과 Lambda 설정의 런타임설정 > 핸들러 정보를 일치 시키기

  3. 개발한 Java Method의 Return을 HTTP Response 형식의 Class를 구현하기

End~~!!

profile
코딩이 즐거운 아저씨

0개의 댓글