Ruby Lambda 함수 핸들러 정의하기
Ruby Lambda 함수 핸들러 정의하기 (Define Lambda function handler in Ruby)
Lambda 함수 핸들러(handler)는 함수 코드에서 이벤트를 처리하는 메서드예요. 함수가 호출되면 Lambda가 핸들러 메서드를 실행하고, 핸들러가 응답을 반환하거나 종료하거나 타임아웃될 때까지 함수가 실행돼요.
본문
Ruby 핸들러 기본
다음 예시에서 function.rb 파일은 handler라는 핸들러 메서드를 정의해요. 핸들러 함수는 두 객체를 입력으로 받아 JSON 문서를 반환해요.
예제 function.rb
require 'json'
def handler(event:, context:)
{ event: JSON.generate(event), context: JSON.generate(context.inspect) }
end
함수 구성에서 handler 설정은 Lambda에 핸들러를 찾을 위치를 알려줘요. 위 예시에서 이 설정의 올바른 값은 function.handler예요. 점으로 구분된 두 개의 이름, 즉 파일 이름과 핸들러 메서드 이름을 포함해요.
클래스 안에서 핸들러 메서드를 정의할 수도 있어요. 다음 예시는 LambdaFunctions라는 모듈의 Handler라는 클래스에 process라는 핸들러 메서드를 정의해요.
예제 source.rb
module LambdaFunctions
class Handler
def self.process(event:,context:)
"Hello!"
end
end
end
이 경우 handler 설정은 source.LambdaFunctions::Handler.process예요.
핸들러가 받는 두 객체는 호출 이벤트와 context예요. 이벤트는 호출자가 제공한 payload를 담은 Ruby 객체예요. payload가 JSON 문서라면 이벤트 객체는 Ruby 해시이고, 그렇지 않으면 문자열이에요. context 객체는 호출, 함수, 실행 환경에 대한 정보를 제공하는 메서드와 속성을 가져요.
함수 핸들러는 Lambda 함수가 호출될 때마다 실행돼요. 핸들러 밖의 정적 코드는 함수 인스턴스마다 한 번 실행돼요. 핸들러가 SDK 클라이언트나 데이터베이스 연결 같은 리소스를 사용한다면, 여러 호출에 재사용하도록 핸들러 메서드 밖에서 만들 수 있어요.
함수의 각 인스턴스는 여러 호출 이벤트를 처리할 수 있지만, 한 번에 한 이벤트만 처리해요. 특정 시점에 이벤트를 처리하는 인스턴스 수가 함수의 동시성(concurrency)이에요.
Ruby Lambda 함수 코드 모범 사례
Lambda 함수를 빌드할 때 다음 지침을 따르세요.
- Lambda 핸들러를 핵심 로직과 분리하세요. 이렇게 하면 더 단위 테스트가 쉬운 함수를 만들 수 있어요. Ruby에서는 다음과 같을 수 있어요.
def lambda_handler(event:, context:) foo = event['foo'] bar = event['bar'] result = my_lambda_function(foo:, bar:) end def my_lambda_function(foo:, bar:) // MyLambdaFunction logic here end - 함수 배포 패키지의 의존성을 제어하세요. AWS Lambda 실행 환경에는 여러 라이브러리가 포함돼 있어요. Ruby 런타임에는 AWS SDK가 포함돼요. 최신 기능과 보안 업데이트를 지원하기 위해 Lambda는 이 라이브러리를 주기적으로 업데이트해요. 이 업데이트로 Lambda 함수 동작에 미묘한 변화가 생길 수 있어요. 함수가 사용하는 의존성을 완전히 제어하려면 모든 의존성을 배포 패키지에 패키징하세요.
- 의존성의 복잡성을 최소화하세요. 실행 환경 시작 시 빠르게 로드되는 더 단순한 프레임워크를 선호해요.
- 배포 패키지 크기를 런타임 필수 요소로 최소화하세요. 이렇게 하면 호출 전에 배포 패키지를 다운로드·압축 해제하는 시간이 줄어들어요. Ruby로 작성한 함수에서는 전체 AWS SDK 라이브러리를 배포 패키지의 일부로 업로드하지 마세요. 대신 필요한 SDK 구성 요소를 제공하는 gem을 선택적으로 의존하세요(예: DynamoDB 또는 Amazon S3 SDK gem).
실행 환경 재사용을 활용해 함수 성능을 개선하세요. SDK 클라이언트와 데이터베이스 연결을 함수 핸들러 밖에서 초기화하고, 정적 자산을 /tmp 디렉토리에 로컬로 캐시하세요. 같은 인스턴스가 처리하는 이후 호출은 이 리소스를 재사용할 수 있어요. 함수 실행 시간을 줄여 비용을 절약해요.
호출 간 잠재적 데이터 누출을 피하기 위해 실행 환경에 사용자 데이터, 이벤트, 보안에 영향이 있는 기타 정보를 저장하지 마세요. 함수가 핸들러 내에서 메모리에 저장할 수 없는 변경 가능한 상태에 의존한다면, 사용자별로 별도의 함수나 함수 버전을 만드는 것을 고려해요.
Keep-alive 지시어를 사용해 영구 연결을 유지하세요. Lambda는 시간이 지나며 유휴 연결을 정리해요. 함수를 호출할 때 유휴 연결을 재사용하려고 하면 연결 오류가 발생해요. 영구 연결을 유지하려면 런타임에 연결된 keep-alive 지시어를 사용하세요.
환경 변수로 운영 파라미터를 함수에 전달하세요. 예를 들어 Amazon S3 버킷에 쓴다면 버킷 이름을 하드코딩하지 말고 환경 변수로 구성하세요.
Lambda 함수에서 재귀 호출을 피하세요. 함수가 자신을 호출하거나 함수를 다시 호출할 수 있는 프로세스를 시작하면 의도치 않은 호출량과 비용 증가로 이어질 수 있어요. 의도치 않은 호출량이 보이면 함수의 reserved concurrency를 즉시 0으로 설정해 함수에 대한 모든 호출을 제한하면서 코드를 업데이트하세요.
Lambda 함수 코드에서 문서화되지 않은 비공개 API를 사용하지 마세요. AWS Lambda 관리 런타임의 경우 Lambda는 내부 API에 보안·기능 업데이트를 주기적으로 적용해요. 이 내부 API 업데이트는 하위 호환되지 않을 수 있으며, 함수가 이런 비공개 API에 의존하면 호출 실패 같은 의도치 않은 결과가 생길 수 있어요.
멱등(idempotent) 코드를 작성하세요. 함수에 멱등 코드를 작성하면 중복 이벤트가 같은 방식으로 처리되게 보장할 수 있어요. 코드는 이벤트를 올바르게 검증하고 중복 이벤트를 우아하게 처리해야 해요.