서버 없는 클라우드 프로그래밍 도전기
AWS Lambda 이벤트 기반 클라우드 함수
아마존웹서비스(AWS, Amazon Web Service)는 인터넷을 통해 IT 리소스와 애플리케이션을 필요할 때만 사용하는 대표적인 클라우드 컴퓨팅 서비스로, 사용한 만큼만 비용을 내는 효율적인 IT 인프라를 제공하고 있다.
이러한 클라우드 환경에서 실행되는 응용 프로그램은 개발자들이 코드와 기능 구현에만 집중할 수 있도록 확장성과 신뢰성이 담보되면서 런타임
효율도 우수한 클라우드 중심 개발 환경이 필요하다.
2014년
11월 발표된 AWS Lambda는 클라우드에서 애플리케이션을 실행하는 새로운 개발 플랫폼이다. 기존 프로그래밍과 AWS 지식을 활용해 서버
백엔드를 운영하고 관리할 필요가 없는 게 큰 특징이다. 3회에 걸친 연재를 통해 AWS Lambda의 기본 개념과 이를 이용한 서버 없는 모바일
앱 개발, 자바와 스칼라로 람다 함수를 구현하는 방법 등을 살펴보겠다.
AWS Lambda의 개념
애플리케이션을 구동하기 위해서는 AWS에서 가상서버인 EC2 인스턴스를 만들고 그 위에 운영체제(OS)와 프로그래밍 개발 환경을 설치해야
한다. 일반적으로 서버 프로그램은 확장성과 트래픽 등의 탄력성을 고려해 서버 용량을 미리 요청하거나 확보해야 한다. 클라우드 컴퓨팅 환경에서는
이를 좀 더 빠르고 유연하게 처리할 수 있다. 그러나 클라우드 함수인 AWS Lambda는 람다 함수(Lambda function)를 통해
개발자가 이러한 준비를 전혀 하지 않아도 외부에서 오는 다양한 이벤트(이미지 업로드, DB 업데이트)의 발생 시점에 특정 처리를 할 수
있다.
Lambda에서 가장 중요한 개념은 ‘람다 함수’다. 이 람다 함수는 Node.js(자바스크립트로 개발된 이벤트 기반 서버
구현)와 자바8 언어로 구현하고 실행할 수 있다. 람다 함수는 실행 환경(구현 언어, 필요한 메모리 제한 기간이나 인증 자격)을 지정하는
콘텍스트 정보와 실제 코드를 업로드하는데, 콘솔에서 직접 편집하거나 클래스 파일 혹은 아마존 S3(Simple Storage
Service)로부터 업로드할 수 있다. 필요할 경우 타사 라이브러리도 업로드에 포함할 수 있다. 참고로 람다 함수는 하나의 ZIP 파일
형식으로 돼 있다.
업로드 이후 람다 함수 자신과 AWS 리소스(특정 S3 버킷, 아마존 다이나모DB(DynamoDB) 테이블
또는 아마존 키네시스(Kinesis) 실시간 스트림)을 연결한다. AWS Lambda는 람다 함수에 이벤트(일반적으로 자원이 변경된 경우
실행)를 함께 연결한다.
예컨대
<그림 2>처럼 모바일 앱에서 아마존 S3 스토리지에 신규 이미지를 올릴 경우 관련 썸네일을 생성하려면 기존 서버에 설정된
애플리케이션이 있어야 한다. 그러나 이제는 람다 함수가 이를 대신할 수 있다. 또한 아마존 다이나모DB에 새로운 데이터가 추가됐을 때 다른
테이블을 수정하거나 사용자에게 알림을 보낼 수도 있다.
AWS Lambda는 AWS 관리 콘솔(Management Console),
AWS SDK 및 AWS CLI(Command Line Interface)에서 접근할 수 있다. Lambda API는 모두 문서화돼 있으며 기존
코드 편집기 및 기타 개발 도구를 Lambda에 연결해 사용할 수도 있다.
AWS Lambda 프로그래밍의 실행 환경
람다 함수는 연결된 AWS 서비스의 리소스가 변경될 때 활성화된다. 즉 지정된 Node.js나 자바 클래스 함수가 실행되고서야 작업이
처리된다. 함수는 (POST와 함께 전달 된 매개 변수를 통해) JSON 형식의 데이터 구조에 접근할 수 있다. 이 데이터 구조는 람다 함수를
활성화하는 계기가 되는 변경 또는 기타 이벤트에 대한 자세한 정보를 가지고 있다.
Lambda는 리소스 변경 속도에 뒤쳐지지 않도록
필요에 따라 람다 함수의 추가 복사본을 활성화한다. 람다 함수는 컴퓨팅 인스턴스에 상태를 영구적으로 저장할 수 없다. 만약 저장을 원하면 S3나
다이나모DB를 사용해야 한다.
여러분의 코드는 Node.js 및 리눅스 환경 그리고 자바8에서 내재된 기능을 사용할 수 있다. 다른
AWS 서비스를 호출하기 위해 AWS SDK for JavaScript in Node.js를 쓸 수도 있다. 각 람다 함수에 지정된 콘텍스트
정보에는 함수의 최대 실행 시간이 지정돼 있다. 일반적으로 짧게 설정되어 있지만 (몇 초 정도에 대부분 실행 가능하므로) 필요에 따라 최대
60초까지 지정 가능하다.
Lambda는 AWS가 제공하는 사용자 권한을 지정하는 IAM 역할(role)을 사용해 람다 함수에 대한
접근과 AWS 리소스를 관리한다. 이러한 호출 역할(Invocation role)은 Lambda에서 특정 람다 함수를 수행할 권한을 부여한다.
실행 역할(Execution role)은 특정 AWS 리소스에 대한 접근 권한을 부여한다. 또한 람다 함수의 실행을 감시하고 요청 수, 지연
시간, 가용성 및 오류 비율 통계를 아마존 클라우드워치(CloudWatch)에 저장한다. 이는 30일 동안 보관되며 콘솔에서도 볼 수 있다.
이제 Lambda를 사용할 때 고려해야 할 몇 가지 사항을 살펴보자.
● 람다 함수 콘텍스트 정보에는 실행에 필요한 메모리 양을
지정한다. 128MB에서 1??GB까지 원하는 값을 지정하면 된다. 메모리 설정에 따라 람다 함수를 사용 가능한 인스턴스의 CPU 능력,
네트워크 대역폭, IO 대역폭이 결정된다.
● 각 람다 함수의 시작은 최대 256개의 프로세스나 스레드를 사용할 수 있다. 최대
512MB의 로컬 스토리지와 102개 이상의 파일 디스크립터도 사용 가능하다. 또한 최대 10개의 동시 아웃 바운드 연결을 생성할 수
있다.
● Lambda는 각 AWS 계정에서 관리상 제한할 수 있다. 미리보기 기간 동안에는 동시 실행 요청을 최대 25개까지
처리할 수?? 있다.
AWS Lambda 함수 만들기
지금부터는 AWS 관리 콘솔을 사용해 간단한 람다 함수를 만드는 과정을 살펴보자. 우선 콘솔에서는 8개 정도의 기본 예제를 이용할 수
있는데, 이 중 하나를 람다 함수로 만들고 실행해 보자. 먼저 [Create a Lambda function]나 기본 예제 중 ‘Hello
World’를 선택한다(<그림 3> 참조). 이름과 설명을 입력하고 Node.js와 자바8 클래스 등 실행 환경을 선택한다. 아직
2개의 프로그래밍 언어만이 지원하지만 향후에는 다양한 언어 지원이 추가될 예정이다. 람다 함수는 콘솔에서 직접 작성하거나 패키지가 포함된 ZIP
파일 혹은 S3로부터 직접 업로드할 수도 있다. 예컨대 새로운 이미지가 업로드됐을 때 문자를 인식하는 라이브러리를 ZIP에 포함해 람다 함수를
작성한 후 인식된 결과를 다이나모DB에 넣을 수 있다.
다음으로
람다 함수 실행 시 어떤 IAM 역할을 사용할지 여부를 지정하고 메모리 요구 사항 조정과 실행 시간 제?진 권한 중 하나를 선택해 바로 만들 수
있다.
이제
[Next]를 누르면 간단한 Hello World 람다 함수가 만들어진다. 이렇게 만든 람다 함수는 콘솔에서 반복 편집 테스트할 수 있다.
<그림 5>처럼 람다 함수를 편집하고, 실제 데이터를 넣어 테스트해 볼 수도 있다. 참고로 테스트 시에는 테스트 실행 시간 결과 로그
등을 확인할 수 있다 . 앞서 설명했듯 Lambda는 각 람다 함수마다 통계 정보를 수집하고 이를 아마존 클라우드워치로 보낸다. 관련 통계는
콘솔에서 확인 가능하다.
자바 언어 지원
람다 함수는 Node.js와 마찬가지로 자바8로 코드를 작성할 수 있다. 물론 개발에 자바 라이브러리도 사용할 수 있으며, AWS SDK for Java를 이용해 AWS API를 호출할 수도 있다. 자바를 이용한 람다 함수 제작에는 aws-lambda-java-core라는 함수 핸들러, 콘텍스트 객체, aws-lambda-java-events라는 AWS 리소스의 이벤트 두 가지 라이브러리가 쓰인다. 자바 기반의 람다 함수를 만드는 방법은 두 가지다. 객체를 입출력하는 높은 수준의 모델(자바 POJO나 프리미티브 입출력 형식 사용 가능)을 이용하는 게 대표적이다. 만약 POJO를 사용하지 않거나 Lambda 시리얼리제이션 모델이 요구 조건을 충족하지 않을 경우 스트림 모델을 쓸 수 있다. 자바로 람다 함수 개발 방법은 차후 예제와 함께 자세하 다루니 참고하자.
<리스트 1> POJO를 이용한 Lambda 입출력 모델 public lambdaHandler(input, Context context) throws IOException; public lambdaHandler(input) throws IOException;
<리스트 2> 스트림을 이용한 Lambda 입출력 모델 public void lambdaHandler(InputStream input, OutputStream output, Context context) throws IOException;
AWS Lambda는 개발자가 현재 사용하는 개발 도구를 그대로 사용할 수 있다. 컴파일된 자바 코드를 람다 함수에서 사용하기 위해서는
ZIP 또는 JAR 파일에 컴파일된 클래스 파일을 넣고 업로드하면 된다. 참고로 Lambda 패키지 업로드의 크기는 50MB 이하로 제한된다.
핸들러 함수는 자바 디렉터리 구조에 따라 구성돼 있어야 한다(예 : com/mypackage/MyHandler.class). 또한 JAR 파일은
lib 서브 디렉터에 위치해야 하며, 배포를 쉽게 하기 위해 메이븐(Maven)이나 그래들(Gradle)와 같은 자바 개발 도구를 이용해도
된다. ZIP 파일을 업로드할 때에는 ‘java8’이라고 지정해야 한다. 만약 핸들러 인터페이스를 구현했으면 클래스명도 넣어야 한다. 그렇지
않을 경우 com.mypackage.LambdaHandler::functionHandler처럼 전체 메소드 레퍼런스를 입력해야 한다. AWS
Toolkit for Eclipse 플러그인을 이용하면 ZIP 파일 생성과 업로드를 자동화할 수 있다. 또한 이클립스 AWS 메뉴에서
Lambda 프로젝트를 만들 수도 있다. 이를 통해 손쉽게 함수를 만들고 한 번 클릭만으로 실행까지 할 수 있다.
AWS
Lambda는 람다 함수가 실행된 만큼만 과금하는 요금 체계로 운영된다. 만약 우리가 원하는 요구 사항이 람다 함수로 구현 가능할 경우
애플리케이션 배포, 실행을 위한 가상 서버가 필요 없으며, 이를 관리하는 데 드는 비용 또한 없다. AWS Lambda는 한 달에 100만 건의
실행 요청과 최대 320만 초 컴퓨팅 처리 시간까지는 무료로 서비스되고 있다.
AWS Lambda는 AWS 서비스 이벤트에 따라
코드를 실행하고 컴퓨팅 리소스를 자동으로 관리하는 클라우드 서비스다. 서버 없이도 기능을 수행하는 애플리케이션을 쉽고 빠르게 개발할 수 있어
기대를 모으고 있다. 다음 시간에는 람다 함수를 이용해 서버 없이 모바일 앱을 효과적으로 만드느 방법과 Node.js 활용에 대해 좀 더 깊이
살펴보겠다.