Lambda Layers를 통해 코드 재사용해보기

2022.01.07

안녕하세요, 임채정입니다.
저번 블로그를 통해 람다 성능 개선을 위한 람다의 다양한 기능을 정리했습니다.
그래서 이번에는 람다의 코드 작성 시 코드의 재사용을 위한 Lambda Layers에 대해 정리해보려고 합니다.

아젠다

  1. Lambda Layers (계층) 기능이란
  2. AWS 계층의 예시
  3. 사용자, ARN 지정 계층의 예시

1. Lambda Layers (계층) 기능이란

  • 추가 코드 또는 데이터를 보존할 수 있는 .zip 파일 아카이브
  • 람다 계층에는 라이브러리, 커스텀 라이브러리, 데이터, 또는 설정 파일이 포함 가능
  • 계층을 사용해서 배포 패키지의 사이즈를 줄여 코드의 공유와 책임의 분산해서 비지니스 로직을 신속하게 반복할 수 있음

2. Lambda Layers의 예시

실제로 Lambda Layers를 사용해봅시다.
람다 함수의 [코드]탭의 가장 밑에 계층목록을 확인할 수 있는 곳이 있습니다.
아직 아무것도 작성하지 않았기 때문에 아무것도 들어가 있지 않습니다.
새로운 계층을 추가해봅시다.

계층 소스로 선택할 수 있는건 여러가지 방법이 있는데 그중에서 AWS에서 제공하고 있는 소스를 선택해서 진행해보겠습니다.

과학기술계산을 위한 Python 라이브러리인 SciPy 라이브러리는 NumPy, Matplotlib, pandas, SymPy 라이브러리와 연계되어 있습니다.
SciPy 라이브러리를 선택해줍니다.

버전까지 선택해주고 추가를 해주면 계층이 추가된 걸 확인 할 수 있습니다.

계층을 추가해주면 함수 개요 부분에서도 함수의 밑의 Layers 부분에 (1)로 되어 하나의 계층이 있는것으로도 확인할 수 있습니다.

이번에는 실제로 코드를 사용해서 라이브러리가 잘 계층에 들어갔는지 확인해보겠습니다.
SciPy 라이브러리를 사용해서 행렬의 곱셈을 하는 예시입니다.

import numpy as np
import scipy.linalg as linalg

A = np.array([[1,2,-1],
              [2,7,4],
              [0,4,-1]])

# matrix-matrix multiplication
B = np.array([[1,2,3,4],
              [-1,2,3,1],
              [3,-2,5,9]])

C1 = np.matmul(A,B)
C2 = np.dot(A,B)
C3 = A.dot(B)

def lambda_handler(event, context):
    print(C1)
    return "layers_test"

함수를 실행시켜서 로그를 확인해보면 결과도 잘 출력됩니다.

Test Event Name
LayersTest

Response
"layers_test"

Function Logs
START RequestId: e08c9535-a56b-4bfc-b618-826dbbda8c4c Version: $LATEST
[[-4  8  4 -3]
[ 7 10 47 51]
[-7 10  7 -5]]
END RequestId: e08c9535-a56b-4bfc-b618-826dbbda8c4c
REPORT RequestId: e08c9535-a56b-4bfc-b618-826dbbda8c4c	Duration: 31.41 ms	Billed Duration: 32 ms	Memory Size: 128 MB	Max Memory Used: 84 MB	Init Duration: 849.80 ms

Request ID
e08c9535-a56b-4bfc-b618-826dbbda8c4c

이걸로 라이브러리가 잘 적용되어 있는 걸을 확인할 수 있습니다.

3. 사용자, ARN 지정 계층의 예시

이번에는 AWS 계층이 아닌 사용자 계층의 사용법을 알아봅시다.
일단 함수에 존재하지 않은 라이브러리를 사용해보겠습니다.

import jwt

def lambda_handler(event, context):
    return "layers_test"

라이브러리가 없다는 에러 문구와 함께 실패 결과를 출력합니다.

Test Event Name
LayersTest

Response
{
  "errorMessage": "Unable to import module 'lambda_function': No module named 'jwt'",
  "errorType": "Runtime.ImportModuleError",
  "stackTrace": []
}

Function Logs
START RequestId: e3cb05a5-6c02-4dab-8550-bc4594e300ee Version: $LATEST
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'jwt'
Traceback (most recent call last):END RequestId: e3cb05a5-6c02-4dab-8550-bc4594e300ee
REPORT RequestId: e3cb05a5-6c02-4dab-8550-bc4594e300ee	Duration: 1.59 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 39 MB	Init Duration: 133.12 ms

Request ID
e3cb05a5-6c02-4dab-8550-bc4594e300ee

그럼 라이브러리를 계층에 추가하기 위해 먼저 로컬에 라이브러리를 만들어 줍니다.
1. python파일 생성 (함수의 런타임이 python이기 때문에 이름을 꼭 python으로 설정)

mkdir python

2. python파일로 이동해서 라이브러리 생성
여기서는 jwt 라이브러리를 생성했지만 원하면 다른 라이브러리를 생성하거나 커스텀도 가능

cd python
pip3 install PyJWT -t .
# pip install (모듈 이름) –t (생성할 경로)

3. 생성되는 파일 확인

ls
# PyJWT-2.3.0.dist-info 
# jwt

4. python파일 밖으로 이동해서 python파일을 압축하기

cd ..
zip -r python.zip .

그러면 python.zip이라는 파일이 생성됩니다.
여기서 중요한건 파일의 구조가 아래의 구조식으로 되어야 되고 파일을 압축할 때 생성된 파일 2개가 아니라 python 파일 자체를 압축해야 하는 것입니다.

.
└── python
    ├── PyJWT-2.3.0.dist-info
    │   ├── AUTHORS.rst
    │   (생략...)
    │   └── top_level.txt
    └── jwt
        ├── __init__.py
        ├── __pycache__
        │   ├── __init__.cpython-39.pyc
        │   ├── algorithms.cpython-39.pyc
        │   (생략...)
        ├── algorithms.py
        ├── api_jwk.py
        (생략...)

이제 AWS콘솔화면으로 돌아가 압축된 라이브러리 파일을 계층에 저장하겠습니다.
람다의 [콘솔]탭에서 새로운 계층을 생성합니다.

python.zip을 업로드 하고 다음과 같이 계층을 생성했습니다.
이름 : Python-PyJWT
설명 : Python Moudle - PyJWT
.zip 파일 업로드 선택
호환 런타임으로 파이썬 버전을 선택

그 후에 람다 함수로 돌아가서 다시 한번 계층을 추가 해주겠습니다.
이번에는 사용자 지정 계층이나 ARN 지정을 통해 계층을 생성합니다.
[사용자 지정 계층]

[ARN 지정]

계층 목록을 보면 성공적으로 새로운 계층이 생성됐습니다.

그 후 아까 위에서 에러가 난 코드를 다시 한 번 실행시켜보면 아래와 같이 성공적으로 함수가 실행된 것을 확인할 수 있습니다.

Test Event Name
LayersTest

Response
"layers_test"

Function Logs
START RequestId: 5b0c6939-ba58-4619-8853-59929906d935 Version: $LATEST
END RequestId: 5b0c6939-ba58-4619-8853-59929906d935
REPORT RequestId: 5b0c6939-ba58-4619-8853-59929906d935	Duration: 1.38 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 42 MB	Init Duration: 147.91 ms

Request ID
5b0c6939-ba58-4619-8853-59929906d935