|
| 1 | +# Lambda란? |
| 2 | + |
| 3 | +서버리스를 의논하면 절대 빠지지 않는 AWS리소스 Lambda |
| 4 | + |
| 5 | +### Lambda의 정의 |
| 6 | + |
| 7 | +서버리스를 이해했다면 Lambda는 쉽게 이해 가능! Lambda는 서버리스의 특징과 장점을 모두 가지고 있다. |
| 8 | + |
| 9 | +람다는 이벤트를 통해 실행된다. 여기서 이벤트란 '주어 + 동사' 형태에서 동사라고 생각하면 쉽다. 밑줄 친 부분들이 바로 이벤트! |
| 10 | + |
| 11 | +- S3 버킷에 파일을 <u>업로드 한다.</u> |
| 12 | +- 데이터베이스에서 특정 레코드를 <u>삭제한다.</u> |
| 13 | +- CloudWatch에서 경보가 울렸으며 Amazon SNS로 메시지가 <u>전송된다.</u> |
| 14 | +- HTTP에서 API PUT요청이 <u>발생했다.</u> |
| 15 | + |
| 16 | +개발자가 Lambda에서 코드를 작성한 후 배포하면 이벤트가 발생할 경우 Lambda함수가 실행된다. |
| 17 | + |
| 18 | + |
| 19 | + |
| 20 | +- Lambda 함수가 호출되면 코드로 원하는 로직을 실행시킬 수 있을 뿐만 아니라 또다른 AWS 리소스를 불러올 수 있다. |
| 21 | +- Java, Go, PowerShell, Node.js, C#, Python 및 Ruby 코드를 지원하며, 그 밖에 프로그래밍 언어를 사용해 함수를 작성할 수 있도록 Runtime API도 제공한다. ( Runtime API : Lambda 함수의 실행 환경과 상호작용하기 위한 API) |
| 22 | + |
| 23 | +### Lambda 비용 측정 |
| 24 | + |
| 25 | +먼저 Lambda는 함수를 생성하고 배포했으나 실행되지 않는다면 어떠한 비용도 들지 않는다. 이벤트가 발생하고 Lambda함수가 호출될 때만 비용이 발생한다. |
| 26 | + |
| 27 | +AWS애서는 매달 1,000,000개의 Lambda함수 호출까지 무료이며, 이 이상부터 비용을 지불한다. 1000000번의 Lambda 호출 시 드는 비용은 약 0.20달러이다. 이는 스타트업이나 개인프로젝트에서 사용할 결우 거의 무료나 다름없다. |
| 28 | + |
| 29 | +앞에서 Lambda함수가 다른 AWS리소스를 호출한다고 설명했었다. 만약 Lambda함수로인 다른 리소스가 사용된다면 이렇게 발생한 비용은 따로 지불해야 한다. |
| 30 | + |
| 31 | +예시) |
| 32 | +Lambda함수 호출 예로 Amazon SNS메시지를 사용한다고 가정해본다면, Lambda함수 호출 비용은 없으나 Amazon SNS메시지를 전송할 때 유료 기능을 사용하고 있다면 비용이 발생하게 된다. |
| 33 | + |
| 34 | +보통 AWS Lambda와 API Gateway는 함께 사용되는 경우가 많은데, 당연한 소리지만 각각의 서비스에 대해 별도로 요금이 청구된다. 이러한 점들을 유의하면서 사용해야 한다. |
| 35 | + |
| 36 | +### Lambda의 특징 |
| 37 | + |
| 38 | +**람다함수의 런타임** |
| 39 | + |
| 40 | +로컬에서 코딩 했을 때 런타임이 얼마나 오래 걸리든 컴퓨터는 일을 마칠 때까지 돌아간다. 하지만 Lambda함수는 오래 기다려주지 않는다. |
| 41 | + |
| 42 | +최대 300초(5분)의 런타임만 허용한다. 시간이 지나면서 더 방대한 양의 데이터를 처리할 때 타임아웃 에러가 발생할 수 있는데 이는 Lambda함수가 5분 이상 돌아가게 되는 경우이다. 이 점도 사용 시 유의하자. |
| 43 | + |
| 44 | +**람다함수 공간 제공** |
| 45 | + |
| 46 | +Lambda함수는 최대 512MB의 가상 디스크 공간을 제공한다. Lambda함수가 구동할 때 가상 컨테이너를 통해 가상 공간이 만들어지며 여기서 Lambda함수를 실행하면서 일시적으로 파일을 보관할 수 있다. |
| 47 | + |
| 48 | + |
| 49 | +Lambda 함수 실행이 종료되면 모두 사라지지만, 임시 저장소에 보관된 파일을 다른 AWS 리소스에 서서 콘텐츠를 안전하게 옮기면 된다. 주로 데이터 전처리 시 거치는 중간 단계 과정을 디스크이 임의로 보관하고 다시 꺼내서 사용하는 데 활용된다. |
| 50 | + |
| 51 | +**/tmp/** |
| 52 | + |
| 53 | +- 람다 함수는 /tmp/와 같은 파일 경로를 활용하여 파일을 읽고 쓸 수 있다. |
| 54 | +- tmp폴더에 쓰인 정보는 Lambda 함수 실행이 종료되면 모두 삭제되다. |
| 55 | +- 똑같은 Lambda 함수를 돌려도 새로운 컨테이너가 생성되어 돌아가기 때문에 기존에 만들어진 정보는 존재하지 않는다. |
| 56 | + |
| 57 | +**허용 배포 패키지** |
| 58 | + |
| 59 | +Lambda 함수는 최대 50MB배포 페키지를 허용한다. 직접 AWS 콘솔에서 원하는 언어를 선택한 후 Lambda 함수를 만들 수 있으며 로컬에서 다수의 파일을 하나의 압축 파일로 만든 후 배포 과정을 통해 Lambda 함수를 만들 수도 있다. |
| 60 | + |
| 61 | +만약 패키지 크기가 50MB를 초과할 시 배포는 이루어지지 않는다. 이럴 때는 S3버킷에 업로드한 후 AWS 콘솔에서 직접 명시해줘야 한다. |
| 62 | + |
| 63 | +### Lambda 사용 사례 |
| 64 | + |
| 65 | +Lambda 함수가 실제로 어떻게 사용되는지 몇 가지 사용 사례를 알아보자! |
| 66 | + |
| 67 | +### 사례 1 |
| 68 | + |
| 69 | + |
| 70 | + |
| 71 | +- S3 버킷에 파일 업로드, 파일 업로드는 사람이 직접 업로드를 하거나 파이프라인을 거쳐 업로드 되는 두 가지 방법이 있다. |
| 72 | +- 이때 'PutObject'라는 이벤트가 발생되며 즉시 람다 함수를 실행한다. |
| 73 | +- 람다함수는 어떤 파일이, 어디에 업로드되었는지 살펴보고 필요하다면 전처리기를 실행한다. (전처리기(Preprocessor)는 소스 코드가 컴파일되기 전에 수행되는 프로세스를 관리하는 프로그램) 전처리기를 사용하면 불필요한 데이터를 삭제하거나 수정할 수 있다. |
| 74 | +- 람다 함수는 가공된 데이터를 데이터베이스에 업로드한다. |
| 75 | + |
| 76 | +-> 이런 일련의 과정을 가능하게 해주는 것이 람다 함수 |
| 77 | + |
| 78 | + |
| 79 | +더 구체적인 파이프라인 구축 사례로 봐보자 |
| 80 | + |
| 81 | +위의 데이터는 크게 '주행 데이터'와 '사고 데이터'로 분류할 수 있다. |
| 82 | + |
| 83 | +- 주행 데이터 : 운전할 때 생성되는 데이터 |
| 84 | +- 사고 데이터 : 급정거나 충돌 사고가 발생했을 때 생성되는 데이터 |
| 85 | + |
| 86 | +위의 2가지 데이터는 모두 S3버킷에 업로드, 데이터 유형에 따라 다른 버킷으로 업로드 된다. |
| 87 | + |
| 88 | +❗️평소에 비어있던 버킷에 갑자기 사고데이터가 업로드 됐다. 이때 이벤트가 감지외더 함다 함수가 실행된다.❗️ |
| 89 | + |
| 90 | +사고 데이터가 정말 사고가 발생해서 생긴데이터인지 아니면 기계의 오작동으로 불량 데이터가 생성된 것인지 판독하는 로직을 거친다. |
| 91 | + |
| 92 | +이 후 정말 사고가 일어난 거라면 사고 데이터를 정리해서 데이터 베이스에 업로드 하고, 다른 AWS 리소스를 호출하여 주행 대시보드를 업데이트하고, Amazon SNS를 거쳐 사고 조치를 취한다. |
| 93 | + |
| 94 | +### 사례 2 |
| 95 | + |
| 96 | +사물 인터넷은 '토픽'이라 불리는 개념이 다양한 이벤트를 처리한다. 아두이노 사례를 통해 람다 함수 사례를 알아보자 |
| 97 | + |
| 98 | + |
| 99 | +간단히 보면 매초 온도 데이터가 들어오면 온도의 범위에 근거하여 다른 토픽으로 데이터가 전송되는 과정. |
| 100 | + |
| 101 | +람다함수는 온도 데이터를 전달받으며 전처리를 실행한다. 만약 온도가 너무 춥거나 덥다면 데이터 전처리뿐만 아니라 Amazon SNS기능까지 사용해 경고 메시지를 보낼 수 있다. |
| 102 | + |
| 103 | +데이터 전처리에서 단순 분량 데이터만 걸러내는 건 아니고 온도 단위를 섭씨에서 화씨로 변환하는 전처리 과정까지 람다 함수에 포함되어 있다. |
| 104 | + |
| 105 | +> 💡 위의 두 사례에서 람다함수가 어떻게 사용? 공통점? |
| 106 | +
|
| 107 | +람다함수는 바로 중간에서 다리 역할을 담당하고 있다는 것! |
| 108 | + |
| 109 | +이벤트에 의해서 실행되기 때문에 자기 스스로 돌아가는 것이 아니라 반드시 전제 조건이 성립해야한다. |
| 110 | + |
| 111 | +첫 번째의 경우에는 데이터가 특정 버킷에 업로드된 경우, 두 번째는 사물데이터에서 온도데이터가 업로드될 때가 해당된다. |
| 112 | + |
| 113 | +### Lambda 실습 |
| 114 | + |
| 115 | +람다 함수를 통해 GDSC 커밋짱을 알아보자! |
| 116 | + |
| 117 | +[콘솔 페이지] |
| 118 | + |
| 119 | + |
| 120 | + |
| 121 | +- AWS -> Lambda |
| 122 | + |
| 123 | +[함수 생성] |
| 124 | + |
| 125 | + |
| 126 | +- 함수 이름은 자유 |
| 127 | +- 런타임 실습에서는 파이썬 선택 |
| 128 | + |
| 129 | +[코드 작성] |
| 130 | + |
| 131 | +``` |
| 132 | +import json |
| 133 | +import os |
| 134 | +import urllib.request |
| 135 | +from datetime import datetime, timedelta |
| 136 | +
|
| 137 | +def get_total_commits(username): |
| 138 | + since_date = (datetime.now() - timedelta(days=90)).isoformat() |
| 139 | + url = f"https://api.github.com/users/{username}/events?per_page=100&since={since_date}" |
| 140 | + total_commits = 0 |
| 141 | + headers = {'User-Agent': 'Mozilla/5.0'} |
| 142 | +
|
| 143 | + while url: |
| 144 | + req = urllib.request.Request(url, headers=headers) |
| 145 | + with urllib.request.urlopen(req) as response: |
| 146 | + if response.status == 200: |
| 147 | + events = json.loads(response.read().decode()) |
| 148 | + for event in events: |
| 149 | + if event['type'] == 'PushEvent': |
| 150 | + total_commits += len(event['payload']['commits']) |
| 151 | + links = response.headers.get('Link') |
| 152 | + if links and 'rel="next"' in links: |
| 153 | + for link in links.split(','): |
| 154 | + if 'rel="next"' in link: |
| 155 | + url = link.split(';')[0].strip('<> ') |
| 156 | + break |
| 157 | + else: |
| 158 | + url = None |
| 159 | + else: |
| 160 | + break |
| 161 | + return total_commits |
| 162 | +
|
| 163 | +def lambda_handler(event, context): |
| 164 | + query_params = event.get("queryStringParameters", {}) |
| 165 | + username = query_params.get("username") |
| 166 | +
|
| 167 | + if not username: |
| 168 | + return { |
| 169 | + 'statusCode': 400, |
| 170 | + 'body': json.dumps({'error': 'Username is required'}) |
| 171 | + } |
| 172 | +
|
| 173 | + total_commits = get_total_commits(username) |
| 174 | +
|
| 175 | +
|
| 176 | + return { |
| 177 | + 'statusCode': 200, |
| 178 | + 'body': json.dumps({'GdscCommitGGang!!': username, 'total_commit': total_commits}) |
| 179 | + } |
| 180 | +``` |
| 181 | + |
| 182 | + |
| 183 | + |
| 184 | +- 작성 후 Depoly 클릭! |
| 185 | + |
| 186 | +[테스트 코드 작성] |
| 187 | + |
| 188 | + |
| 189 | +``` |
| 190 | +{ |
| 191 | + "queryStringParameters": { |
| 192 | + "username": "candosh" |
| 193 | + } |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +[테스트 출력] |
| 198 | + |
0 commit comments