7. 머신러닝 데이터 플랫폼
1. Data Management
2. Visualization + Analytics
3. Integrate with your ML DevOps cycle
대량, 대용량의 데이터 처리가 필요
“서버리스로 해보면 어떨까?”
Introduction
Motivation
29. 데이터 플로우
What is a dataflow?
Dataflow
“The idea of disconnecting computational actors into stages”
https://en.wikipedia.org/wiki/Dataflow
30. 데이터 플로우
What is a dataflow?
Dataflow
“The idea of disconnecting computational actors into stages”
https://en.wikipedia.org/wiki/Dataflow
31. 데이터 플로우
Why do we need one?
“The idea of disconnecting computational actors into stages”
• Concurrency
• Scalability
• Reusability
https://en.wikipedia.org/wiki/Dataflow
32. 데이터 플로우
Why do we need one?
“The idea of disconnecting computational actors into stages”
Serverless Architecture
https://en.wikipedia.org/wiki/Dataflow
• Concurrency
• Scalability
• Reusability
35. AWS Step Functions
클라우드 오케스트레이션 서비스
- 다양한 서비스를 하나의 워크플로우로
엮어줌
- 유연한 병렬/분기 흐름 제어
- 시각적 워크플로우
Application Integration
Step Functions
Service Introduction
40. Step Functions
Service Introduction
State Machine
• Possible States
• Lambda, Fargate Task같은 작업
• Choice, Parallel, Map같은 Flow Logic
• Succeed, Fail같은 최종 결과
• 각 “상태”는 스텝 펑션의 플로우 로직에 따라
순차적, 혹은 병렬적으로 실행됨
• Amazon States Language (JSON)
• 쉽고 빠르게 개발
43. Step Functions
Amazon States Language
Resizer
• Type
• Task = 실행 가능한 작업
• Resource
• Resizer Lambda ARN
• End
• True = 다음 상태 없음
• (OR) Next
• 다음 상태 지정
44. Step Functions
Amazon States Language
Input Output using JSON Path
• InputPath
• 전체 Input의 어느부분을 입력값으로 받을
까?
• $ = Root path
• ResultPath
• 결과를 어떻게 저장할까?
• $.result.resized
• OutputPath
• 다음 상태에게 결과에 어느 부분을 전달할
까?
50. Workflow Control
• Choice
• 실행 결과값에 기반한 분기 로직
• Parallel (정적 병렬 처리)
• 고정된 수의 여러 Task를 동시에 실행
• Map (동적 병렬 처리)
• Iterator를 이용해 리스트형 입력값을 Task에 Mapping
Step Functions
Service Introduction
52. Workflow Control
• Choice
• 실행 결과값에 기반한 분기 로직
• Parallel (정적 병렬 처리)
• 고정된 수의 여러 Task를 동시에 실행
• Map (동적 병렬 처리)
• Iterator를 이용해 리스트형 입력값을 Task에
Mapping
Step Functions
Service Introduction
뭐가 다른걸까?
53. Step Functions
Service Introduction
Workflow Control
• Choice
• 실행 결과값에 기반한 분기 로직
• Parallel (정적 병렬 처리)
• 고정된 수의 여러 Task를 동시에 실행
• Map (동적 병렬 처리)
• Iterator를 이용해 리스트형 입력값을 Task에
Mapping
← 다양한 입력을 동일하게 처
리
← 하나의 입력을 다양하게 처
리
56. Step Functions
Pricing
Pricing
ST = 10 State transitions per execution
Exec = 100,000 Requests per month
(10 x 100,000)/1000 x $0.025 =
~$25/month
57. Workflow Control
• Choice
• 실행 결과값에 기반한 분기 로직
• Parallel (정적 병렬 처리)
• 고정된 수의 여러 Task를 동시에 실행
• Map (동적 병렬 처리)
• Iterator를 이용해 리스트형 입력값을 Task에 Mapping
← 하나의 이벤트로 여러가
지 처리를 병렬로 실행
한다면?
Step Functions
Service Introduction
63. Lambda의 한계, 그리고 Fargate
AWS Lambda Hard Limits
- Function memory allocation
- Max 3,008MB
- Function timeout
- 900 seconds (15 minutes)
64. AWS Lambda Hard Limits
- Function memory allocation
- Max 3,008MB
- Function timeout
- 900 seconds (15 minutes)
← 메모리 용량보다 큰 대용량 데이터
는?
← 15분 보다 오래걸리는 작업은
?
Lambda의 한계, 그리고 Fargate
65. AWS Fargate
서버리스 컨테이너 서비스
- 완전관리형
- EC2 인스턴스 설정 X
- Service / Task based
operation
컨테이너계의 람다
Compute
Lambda의 한계, 그리고 Fargate
Service Introduction
66. 개발자는 Task Definition만 작성
• 사용할 컨테이너 이미지
• 필요한 컴퓨팅 자원
• Task에 필요한 환경변수 등
Lambda의 한계, 그리고 Fargate
Service Introduction
67. Lambda의 한계, 그리고 Fargate
Is Fargate better than Lambda?
AWS Lambda vs AWS Fargate
AWS Lambda
- Function memory allocation
- Max 3,008MB
- Function timeout
- 900 seconds (15 minutes)
- Local File System
- 512MB
AWS Fargate
- Container memory allocation
- Max 30GB
- Container Timeout
- Until a task finishes
- Local File System
- 10GB
<
68. Lambda의 한계, 그리고 Fargate
Is Fargate better than Lambda?
그러나...
AWS Lambda
- Max concurrency
- 1,000 (soft limit)
- Faster initiation time
- Deploy code to an idle
worker
가볍고 빠른 처리에 적합
AWS Fargate
- Max concurrency
- 50 (soft limit)
- Slow initiation time
- Task request/scheduling
- Image pull + Container startup
시간과 자원이 많이 필요한 작업에 적
합
>
76. Superb AI 적용 예제
Superb AI Suite: Export
LabelData
77. "objects": [
{
"id": 1,
"class": "Car",
"shape": {
"polygon": [
. . .
]
{
"label_id": "car",
"label_path":
"labels/car.json",
"data_key":"car.jpg",
}
Label Info Meta Info Mask
78. Superb AI 적용 예제
Superb AI Suite: Export
Export in Steps
1. 내려받을 결과물 받아오기
2. Info, meta 추출 및 mask 생성
3. 모든 결과물 압축
4. 작업 완료 메시지 및 작업물 경로 반환
79. Superb AI 적용 예제
Superb AI Suite: Export
1. 내려받을 결과물 받아오기
2. Info, meta 추출 및 mask 생성
적게는 수십개에서 많게는 수십만, 수백만개의 라벨 처리
= 분산 처리가 필요
80. Superb AI 적용 예제
Superb AI Suite: Export
Workflow Control
• Choice
• 실행 결과값에 기반한 분기 로직
• Parallel (정적 병렬 처리)
• 고정된 수의 여러 Task를 동시에 실행
• Map (동적 병렬 처리)
• Iterator를 이용해 리스트형 입력값을 Task에 Mapping
• List Length / Max Concurrency
← Parallel을 이용하면 어떨
까?
81. Superb AI 적용 예제
Superb AI Suite: Export
100 Requests
람다 하나 당 20개 = 합리
82. Superb AI 적용 예제
Superb AI Suite: Export
1,000,000 Requests
람다 하나 당 200,000개 =
???
83. Superb AI 적용 예제
Superb AI Suite: Export
Workflow Control
• Choice
• 실행 결과 값에 기반한 분기 로직
• Parallel (정적 병렬 처리)
• 고정된 수의 여러 Task를 동시에 실행
• Map (동적 병렬 처리)
• Iterator를 이용해 리스트형 입력값을 Task에
Mapping
• List Length / Max Concurrency← 그렇다면 Map은?
84. Superb AI 적용 예제
Superb AI Suite: Export
1,000,000 / 1,000 =
100
1. 각 람다 함수는 1,000개씩
처리
2. 끝나면 다음 1,000개
동시에 5,000개씩 처리
[1000, 1000 …
1000]100
Elements
85. Superb AI 적용 예제
Superb AI Suite: Export
https://gist.github.com/roycoding/b11b650d3ed8d4e8
6c39
86. Superb AI 적용 예제
Superb AI Suite: Export
3. 모든 결과물 압축
병렬처리 불가능
실행시간이 김
= 람다엔 적합하지 않음
87. Superb AI 적용 예제
Superb AI Suite: Export
AWS Fargate
- Container memory allocation
- Max 30GB
- Container timeout
- Until a task finishes
- Local File System
- 10GB
← 실행시간이 오래걸리는
압축 작업에 적합
첫번째로 제 소개와, 사용한 AWS 서비스들, 그리고 프로젝트 계기 먼저 소개해드리겠습니다.
저는 AI 스타트업 Superb AI에서 소프트웨어 엔지니어로 근무중인 김재현입니다
뉴욕 대학교에서 컴퓨터과학과 4학년으로써 이제 졸업을 앞두고있구요
학기중에는 학업과 업무를 병행해야해서 모든 개발자의 꿈인 원격 근무를 하게 되었네요.
그리고 실력도 중요하지만, 무엇보다 동료들에게 신뢰를 줄수있는 믿음직한 개발자를 목표로 하고있습니다.
마지막으로 저는 2019년 10월에 서버리스 데이터 플로우를 주제로 마이크로 소프트웨어 398호, Something Cloud에 기고를 했고
오늘 발표는 그 내용을 기반으로 만들었습니다.
본격적인 발표에 들어가기에 앞서, 우선 제가 사용한 서비스들을 소개합니다.
AWS Lambda, Fargate, Step Functions가 주요 서비스이고 추가적으로
S3, Dynamo DB, 그리고 SQS가 있습니다
Lambda, Fargate 그리고 Step functions는 추후 조금 더 자세히 소개해드리고, 우선 다른 세가지 서비스 먼저 간략하게 소개해드리겠습니다
SQS는 완전관리형 메시지 대기열 서비스입니다. 저는 주로 데이터 플로우를 가동시키기 위한 대기열로 활용했고.
s3는 아시다시피 스토리지 서비스로, 다양한 데이터를 S3에 올려서 관리하고있습니다.
마지막으로 여러가지 처리의 결과물을 한곳으로 모으기 위해 NoSQL 기반인 DynamodB를 활용했습니다
제 프로젝트를 설명하려면 우선 그 배경부터 말씀드려야 합니다.
저희 Superb AI는 머신러닝 데이터 플랫폼을 만들고 있는 스타트업입니다.
여러가지 딥러닝 기술들로 데이터 레이블링 및 분석을 어시스트하고,
나아가, 데이터 관리와 협업 등에 관련된 기능들을 UI/UX 적으로 최적화하고 있는 플랫폼입니다.
머신러닝을 위한 데이터 플랫폼인만큼, 필연적으로 대량의 대용량 데이터를 빠르고 효과적으로 처리해야 합니다.
Superb AI 개발자분들은 어떤 솔루션이 데이터 처리에 적합할까 고민하던 와중, “서버리스로 해보면 어떨까?” 라는 생각을 떠올렸습니다.
때마침 2019년 여름, 인턴십 프로그램을 통해 제가 Superb AI에 입사했고, 저는 서버리스 데이터 처리의 프로토타입을 만들어보는 업무를 맡았습니다.
이 프로토타이핑의 목적은 과연 서버리스가 데이터 처리에 적합한지 알아보기 위해서였죠.
그래서 제가 가장 먼저 시도해본것은, 가장 많이 쓰이는 비정형 데이터중 하나인 이미지를 AWS람다로 간단한 전처리를 해보는 것이었습니다.
그렇다면 저희는 왜 서버리스를 선택했을까요?
우선 많은 분들이 알고계시다시피 서버리스 아키텍처의 장점은
서버관리가 불필요하고
높은 가용성을 가지며
필요에 따라 자유롭게 기능을 확장하거나
수요에 따라 Capacity를 늘릴수있습니다
그리고 오직 사용한 시간에 대해서만 요금을 지불하면 됩니다.
이중에서 제가 생각하기에 서버리스의 가장 큰 매력은 바로
서버관리가 불필요하단 점이였습니다.
저는 2019년도 여름에 Superb AI 인텁십을 하면서 AWS를 처음 본격적으로 다뤄봤습니다.
그래서 AWS 초보인 저에게는 서버관리 지식은 없어도 코드만 써도된다는 장점이 제일 컸습니다.
쉽게 말해서 진입 장벽이 낮다고 말씀드리면 좋을것같습니다.
그렇다면 제가 어떻게 이미지 처리를 만들었는지 말씀드리기 전에
서버리스 설계의 핵심인 람다를 소개해드리겠습니다.
우선 람다를 소개해드리자면
람다는 AWS의 Function as a Service입니다
완전 관리형 서버리스 컴퓨팅 서비스로서
개발자는 코드만 작성해서 올리면 해당 코드에 대한 요청이 있을때만 AWS가 실행시켜줍니다.
매니지드 서비스로서 따로 상시 가동하는 지정된 서버가 없고 요청이 있을때만 프로비저닝 한 후 실행시켜주므로. 한계를 넘지 않는이상 요청횟수만큼 병렬로 실행 가능합니다.
람다를 적극 활용하면서 저는 코드에만 집중할수있게되었습니다.
그렇게 람다를 이용해 가장 처음 만들어본 이미지 처리는 썸네일 생성입니다
람다를 사용해보신분이라면 아시다시피 워낙 예제도 많고, 엄청 간단해서 쉽게 만들수있었습니다.
구조를 보시면 사용자가 S3 버킷에 이미지를 올리고, 이 업로드 이벤트 트리거를 통해 람다를 호출해줍니다.
람다는 해당 이미지의 썸네일을 만들어서 다시 버켓에 저장해줍니다.
썸네일은 간단했습니다.
하지만 리사이즈, 용량 압축 등 다양한 처리를 더 추가해보면 어떨까요?
예를 들어 한 이미지가 업로드 되면, 다양한 용도로 쓸수있게끔 사이즈 조절이 필요할수도 있고, 로딩 속도를 개선하기 위해서 용량 압축을 해줘야 할수도있습니다.
한 이미지에 대해 여러가지 처리를 해야할때, 하나의 이벤트로는 람다를 동시에 실행시킬수 없습니다.
그래서 우선 이런 설계가 나왔습니다.
이미지 업로드 이벤트 트리거로 우선 리사이즈 함수를 호출하고, 리사이즈 람다가 순차적으로 컴프레스를 호출해주고, 최종적으로는 컴프레스 람다가 썸네일을 호출해주는 형태입니다.
우측 하단에 보시면 여러가지 처리 결과를 종합해서 저장하기위해서 DynamoDB도 넣었죠.
한눈에 보아도 그렇게 좋은 설계는 아니었지만, 심각한 문제점이 있다는걸 깨달았습니다
데이터 처리는 필요에 따라 변화할수도 있다는것이였습니다.
예를들어 한가지 람다를 제거한다거나
아니면 새로운 람다를 추가해야 한다던가
이런 상황이 올수도 있지 않을까? 라는 생각이 들었습니다.
그래서 한번 고민해봤습니다.
이미지 처리는 리사이즈, 컴프레스 썸네일 뿐만아니라
크롭, 그레이스케일등 여러가지가 있을수있고
이 람다들은 아까 이미지 예제처럼 병렬로 실행될수도
아니면 이렇게
이렇게
혹은 이런식으로 다양한 루트로 순차 처리될수도있고
이렇게 순차, 병렬 처리가 합쳐질수도있습니다.
그렇다면 이 모든 로직을 람다함수에 넣는게 가능할까요?
정답은 사실 가능은 합니다. 아까 보여드린 람다가 서로 호출하는 이미지 처리 구조가 그렇죠.
하지만 이런 방법은 모든 플로우 로직을 람다내부에 코드로써 포함해줘야 하기때문에 변화에 매우 약한 설계라는걸 깨달았습니다
서로 구조적인 의존성이 생기게되면, 단순히 람다 하나를 추가하거나 제거하려고 해도 쉽지 않겠죠.
그렇다면 어떤 방법이 있을까요? 해결책은 두가지가 있었습니다.
모든 처리 기능을 하나의 큰 기능으로 합치는 방법과, 이전처럼 분리해두고, 새로운 방법을 찾는것입니다.
저는 후자가 더 좋은 방향이라고 판단했고, 그렇다면 단순히 람다를 이어서 처리할게 아니라, 좀더 제대로된 데이터 플로우를 설계하는것이 맞다고 생각했습니다
그렇다면 우선 데이터 플로우란 무엇일까요?
제 생각엔 이 한줄로 정의가 가능합니다
여기서 중요한것은 Disconnect 즉 분리한다는것입니다.
그렇다면 왜 분리를 해야 할까요?
왜냐하면 분리를 함으로써 다양한 이득을 볼수있기때문입니다.
복잡한 데이터 처리를 모듈화 하여 분리하게 되면 병렬성, 확장성, 재활용성이 늘어나고, 결과적으로 관리를 더 쉽고 체계적으로 할수있게 됩니다.
장점들을 나열해보니 저는 MSA와 서버리스의 장점들과 비슷하다고 생각했고,
서버리스 아키텍처로 데이터 플로우를 만든다면 시너지를 낼수있다 결론을 지었습니다.
그렇다면 결과적으로 다양한 클라우드 서비스를 워크플로우로 이어줄수있는 매니지드 서비스가 필요합니다.
그런게 AWS에 있을까요?
바로 step functions입니다.
Step functions는 aws의 클라우드 오케스트레이션 서비스로서
람다와 같은 aws서비스를 엮어서 하나의 워크플로우를 만들수있게 해주는 서비스입니다.
단순히 입력과 출력을 이어주는것 뿐만 아니라, 분기라던가 병렬처리 같은 다양한 Flow Control 로직을 지원합니다.
그리고 완성된 스텝펑션은 이런식으로 웹 콘솔에서 시각적 워크플로우로 확인이 가능합니다.
이렇게 콘솔로 확인할수있는 시각적 워크플로우는 다양한 장점이 있는데,
이런식으로 실행된 태스크의 현재 상태를 볼수도 있습니다.
현재 보이는 예제는 성공적으로 실행되어 완료된 예제인데
이런식으로 한 부분에서 실패 한다면, 어느 부분에서 실패했는지 빠르게 확인할수있습니다.
추가적으로 스텝펑션 이벤트도 웹 콘솔에서 확인 할수있습니다.
이 부분을 확인하면 보다 자세하게, 어떤 상태가 무슨 인풋을 받아, 무슨 결과를 반환했는지 알수있고
또 옆에 실행시간도 표기해주기때문에, 어떠한 인풋에 대해 시간이 걸리는지 측정할수도있습니다.
Step functions는 상태머신의 형태로 동작합니다.
각 상태는 lambda 혹은 파게이트 태스크 같은 작업을 실행 시킬수도 있고
필요에따라 Flow가 바뀌는 flow control logic도 넣을수있습니다.
마지막으로 이러한 스텝펑션 스테이트 머신은 amazon states langauge, 아마존 상태 언어로 작성할수있습니다.
Amazon states Language는 JSON형태의 상태머신 정의 언어 입니다.
복잡한 인프라 리소스 관리 없이 JSON만으로도 쉽게 필요한 워크플로우를 만들수있어서, 사용법을 빠르게 익힐수있는게 저는 가장 좋은 장점중 하나였던거같네요.
ASL로 어떻게 상태머신을 정의하는지 간단하게 보여드리겠습니다.
우선 가장 간단한 Hello World 라는 람다를 호출하고 끝내는 스텝 펑션입니다.
StartAt은 이 상태머신의 시작 지점을 지정합니다.
이 예제에서는 Hello World라는 스테이트에서 시작하네요.
밑에는 가장 중요한 상태를 정의해두는 States 필드입니다.
그럼 이 States 필드 안에 들어가는 상태들을 자세히 살펴볼게요
우선 상태 이름을 선언해야합니다
이 예제에선 Resizer입니다.
그리고는 타입을 선언합니다.
타입은 말 그대로 해당 상태의 타입입니다.
어떤 작업을 수행하는 Task가 될수도있고, 분기를 담당하는 Choice, 병렬 처리 로직인 Parallel이나 Map. 아무것도 하지 않는 state인 pass. 상태머신의 성공이나 실패 여부인 success 와 fail state. 등등 상태의 타입은 다양합니다.
예제에서는 Task 상태니까, 람다를 실행해서 어떤 작업을 한다고 볼수있죠
리소스는 해당 상태가 필요로 하는 리소스를 추가해줄수있습니다.
예를 들어 이 예제에서는 람다를 호출해서 사진을 리사이즈 하는것같습니다. 그렇다면 리사이즈 람다 함수가 리소스로써 필요하겠죠.
해당 람다의 Amazon resource name, 즉 ARN 주소로 넣어줍니다.
밑에 path들은 다음 슬라이드에서 좀 더 자세하게 설명하겠습니다
그리고 마지막으로 End, 다음 상태를 표기합니다. 이 경우에는 End가 참이니까, 해당 워크플로우는 여기서 끝이 난다는걸 알수있습니다. 다음 상태가 없기 때문이죠
보통 다음 상태가 끝이 아닌경우는 next로 다음으로 넘어갈 상태의 이름을 표기해줍니다.
Step functions의 장점중 하나인 Jsonpath를 이용한 input output 프로세싱입니다. 이걸 이용해서 입력 출력값을 조정할수있습니다.
제일 첫번째로 InputPath는 받은 Input 전체 페이로드 중에서, 어떤 하위 정보만 사용할지 정할수있습니다.
예를들어 이미지 사이즈 조절에 필요한 Input값은 사실 해당 이미지가 어떤 경로에 저장되어 있는지, 그리고 어떤 사이즈로 변경할건지 이 두가지만 있으면 됩니다.
그러나 꼭 인풋이 그것만 들어오진 않다고 보는게 통상적이죠. 세션 아이디, 타임 스탬프 등 여러가지 무관한 정보가 같이 붙어있을수있습니다. 이런 input을 선택적으로 받을수있게끔 전체 Input에 대해 jsonpath로 상대 경로를 줄수있습니다.
이 인풋에서 이 정보만 필요해! 라고 하는것이죠. 우선 해당 예제에선 루트 경로를 사용해서 인풋의 전부를 받았습니다.
Result path는 해당 task의 결과물을 input payload 어느 부분에 저장할지 지정해줍니다.
마지막으로 output path입니다. 저는 처음에 result와 output의 차이를 잘 몰라 어려워했는데, 기본적으로 result path는 “어떻게” 저장할지 구조를 정하고, 이렇게 만들어진 최종 결과물의 어떤 일부분만 전달할지 정할수있는게 output path입니다.
예제로 보여드리겠습니다.
이런식으로 리사이즈 처리 요청 메시지가 왔다고 생각해볼게요.
이미지 리사이즈 하는데 세션이나 타임스탬프같은 부가적인 정보는 필요없습니다.
이런식으로 InputPath를 이용해 필요한 부분만 Input으로 받을수있습니다
그렇게 리사이즈 처리를 한 후, 결과를 저장해야하는데
이런식으로 results 하위에 resize 키에다가 저장을 해줍니다.
그리고 만약에 추가적으로 다른 처리 모듈에 넘겨줄수있으려면, 처음 받았던 인풋을 다시 넘겨줘야 합니다.
그렇기때문에 output path는 이렇게 루트 패스 지정으로 페이로드 전체를 다음 상태로 넘겨줄수있습니다.
위 예제들은 어떤식으로 상태머신이 정해지는지, 어떤 변수들로 이루어져있는지 간단하게 보여드리는 용도였습니다.
사실 아마존 상태 언어는 훨씬 더 다양한 문법이나 체계가 있기때문에 이를 잘 활용하면 복잡한 데이터 처리도 아주 효율적인 워크플로우로 만들수있죠.
링크로 들어가셔서 더 자세히 읽어보시는걸 추천해 드리고 싶습니다.
저는 스텝펑션이 단순히 람다를 호출하는 서비스가 아니라 워크플로우로서 강력한 기능성을 제공하는것은 이런 워크플로우 컨트롤에서 기인한다고 생각합니다.
제가 자주 활용한 Workflow 컨트롤은 세가지인데,
각각 결과에 따라 플로우를 분기시켜주는 Choice
여러가지 작업를 한번에 실행시켜주는 Parallel
그리고 최근에 추가된 Map, 이 세가지 입니다.
우선 Choice는 단어 그 자체에서도 알수있듯이 이전 상태의 결과값에 따라 flow를 분기할수있게 해줍니다.
간단하게 예제로 보여드리자면
썸네일을 생성하려면 우선 S3에 업로드된 파일이 이미지여야 하겠죠?
우선 확장자가 이미지 확장자가 맞는지 확인한후,
맞다면 썸네일쪽으로 플로우가 흐르고, 아니라면 실패합니다.
왼쪽의 코드같은 느낌이죠.
간단하게 설명드리자면 Parallel은 하나의 입력에 대해 다양한 처리
그리고 Map은 다양한거나 큰 입력을 나눠서 동일하게 처리하는 용도로 많이 사용합니다.
마지막으로 요금에 대해서 설명을 드리겠습니다.
기본 단위는 한 상태에서 다음 상태로 넘어가는걸 State transition이라고 정의하고,
이 상태전환 횟수에 기반하여 과금이 됩니다.
프리티어 기준으로 월 4000번 까지는 무료이고, 이후 1000 당 0.025 달러 만큼 부과됩니다.
그럼 간단하게 이렇게 월 요금을 계산해볼수있는데요
우선 하나의 데이터 플로우가 몇번의 상태전환이 필요한지 계산한후
한달에 해당 데이터 플로우가 몇번이나 호출되는지 계산합니다.
이 둘을 곱해서 1000으로 나누고, 1000회당 요금인 0.025 달러를 곱하면, 한달 요금을 아주 간략하게라도 파악할수있습니다.
예제를 들자면
어떤 워크플로우가 평균적으로 10회의 상태전환이 일어나고
이 워크플로우는 한달에 10만번 호출된다고 가정을 해봅시다.
그러면 한달에 $25 달러 정도 요금이 나온다고 볼수있겠네요.
그렇다면 한번 스텝펑션을 아까 보여드린 이미지 처리에 적용해보겠습니다
처음에 원했던건 병렬 실행이였습니다.
하나의 이미지를 넣으면, 각각 고정된 사이즈의 썸네일, 가변 사이즈의resized, 그리고 용량 압축된 이미지가 나오는 처리가 원래 목표였죠
그래서 스텝펑션을 이용하면 이렇게 설계가 가능합니다.
제일 먼저 사용자가 S3에 이미지를 업로드 합니다.
이 이벤트가 input handler를 실행시키고, input handler는 이미지 데이터 플로우 스텝펑션을 호출해줍니다.
각종 처리가 병렬로 실행되면서 각 결과물은 다시 S3에 저장되고, 최종적으로 결과물들의 경로는 DB에 저장해줍니다.
사용자는 DB를 참조하면 다양한 결과물을 찾을수있게됩니다.
상당히 간단해 보이는데, 굳이 스텝펑션으로 만들어야 할까? 라고 물으실수도 있지만
이렇게 데이터 플로우로 만들면 분명한 장점이 있습니다.
각 람다는 모듈화되어 서로에게 의존성 없이 분리가 되기때문에,
이렇게 스텝펑션을 고치는것만으로 새로운 람다도 쉽게 추가 할수있고
기존의 로직을 쉽게 수정할수도 있습니다.
이미지 처리로 우선 감을 잡았으니, 비디오 처리도 해보기로했습니다
비디오 처리는 우선 비디오를 프레임으로 나눠주는 디코딩, 그리고 프레임 시퀀스를 다시 비디오로 합쳐주는 인코딩, 이 두가지를 만들어 보기로했습니다
근데 문제가 생겼는데, 이런 작업들은 람다만으로는 어렵거나, 아예 불가능하다는 판단을 내렸습니다.
람다에는 여러가지 제약 사항이있습니다
소프트 리미트는 비록 제약이긴 하지만, AWS에 요청하면 상한을 늘릴수있는 리미트입니다.
하지만 하드 리미트는 요청해도 상한을 늘릴수없는 리미트입니다.
그 중 제가 부딪혔던 벽은 바로
메모리 한계와 실행시간이였는데요
그래서 쓰기 시작한게 ECS 파게이트 입니다
완전 관리형 서버리스 컨테이너 서비스인데
100%는 아니지만, 저는 컨테이너계의 람다라고 말하고싶네요
Fargate 서비스가 클러스터같은 인프라를 관리해주고 개발자는 코드를 작성해서 이미지를 만들어서 이를 기반으로 태스크 작성만 해주면 준비는 끝납니다.
해당 Task Definition으로 Task를 실행 해주게 되면, 파게이트가 컨테이너를 올려서 Task를 수행합니다.
개발자는 코드만 작성하고 매니지드 서비스가 해당 코드를 적절한 리소스에 프로비저닝해서 실행시켜주는게 람다와 어느정도 비슷하다고 할수있죠.
왜 람다의 대체재로 파게이트를 선택했는지 설명해드리겠습니다.
파게이트는 컨테이너 서비스다 보니
메모리도 압도적으로 크고
실행시간 제약으로 인한 타임아웃도 없습니다
비디오 처리를하기에 아주 적합하죠
그렇다면 파게이트는 만능일까요?
아쉽게도
최대 동시 실행 갯수라던지
아니면 실행에 필요한 cold start에 걸리는 시간이라던지,
파게이트도 람다에 비교했을때 단점이 있습니다.
결론은 하나가 다른것보다 좋다 보다는, 용도가 다른것같습니다.
람다는 가볍고 빠른 작업
파게이트 태스크는 시간과 자원이 많이 드는 작업에 적합하다고 말씀드리면 될거같네요
그리고 스텝펑션을 이용한 데이터 플로우를 구축할때는, 이 둘을 필요에 따라 적용하는게 중요합니다.
아까 말씀드렸듯, 비디오 처리의 가장 크고 무거운 부분은 바로 인코딩 디코딩입니다.
그래서 비디오 처리의 인코딩 디코딩은 파게이트로, 나머지 핸들러는 람다로 하는것으로 해결했습니다
여기서 다시 한번 스텝펑션이 좋은 이유, 혹은 활용하는법을 보여드리면
이런식으로 워크플로우끼리 연결도 가능합니다.
예를 들어 디코딩해서 나온 프레임들을 다시 이미지 처리를 거친다던지
이런식으로 가능합니다
사실 여기까지는 제가 인턴십동안 프로토타이핑을 해보면서 얻은 경험, 교훈들입니다.
그렇다면 Superb AI에서는 실제로 어떻게 활용하고 있을까요?
저희 데이터 플랫폼에선 이렇게 다양한 처리를 스텝펑션을 활용한 데이터 플로우로 만들었는데요
그중에서도 오늘 소개해드린 지식이 종합적으로 많이 들어간 어노테이션 결과물 내려받기 데이터 플로우를 공유해보겠습니다
우선 무얼 내려받는건지 먼저 설명을 드려야겠죠.
이건 저희 플랫폼 작업 툴 화면인데요
저희 라벨링 툴을 이용해서 사용자는 데이터 라벨링을 할수있습니다
이렇게 말이죠
사용자는 이제 만들어진 라벨을 머신러닝 데이터로 활용하려면, 해당 라벨을 다운로드해야 합니다.
이 결과물을 사용자에게 전달하려면 여러가지 작업을 거칩니다
우선 실질적인 라벨 정보가 담겨있는 라벨 인포
경로나 이미지 정보같은게 들어있는 메타데이타
그리고 라벨을 Visualize한 마스크까지 만들어서 전달해야합니다
그래서 간단하게 순서를 설명드리면
...
우선 1,2번 부터 보겠습니다.
라벨은 갯수가 보통 엄청 많습니다. 적게는 수십개에서, 많게는 수십만, 수백만개 까지 다뤄야합니다
이걸 하나의 컴퓨팅 서비스가 처리는하는건 비효율적일테니
그렇다면 분산/병렬처리가 필요하겠다! 라고 생각했습니다
그러면 parallel을 쓰는게 정답일까요?
한번 예시를 들어보겠습니다.
5개의 람다에 100개 요청을 분산시키면, 개당 20 요청정도로, 나쁘지 않은 효율을 보여줍니다.
하지만 100만개 요청이 들어온다면?
100만개 나누기 5, 즉 20만개씩 각 람다에서 부담해야 합니다.
이렇게 되면 람다가 메모리 리미트나 타임아웃에 걸릴수있죠.
Map으로 해본다면 어떨까요
우선 인풋을 적절한 사이즈로 나눠서 리스트를 만듭니다
그렇게 만든 리스트를 이터레이터가 순회하면서 Idle한 람다에게 할당해줍니다.
이렇게 되면 대량의 데이터도 람다가 감당 가능한 수준에서 병렬처리를 할수있습니다.
Export 데이터 플로우에선 Map이 정답이였습니다.
대량의 데이터 처리를하고, 하나의 압축파일을 만드는건 사실
Map reduce패턴이니까, Map이 맞는 솔루션인건 당연하다고도 볼수있겠네요.
그렇다면 이제 Reduce할 차례입니다.
압축파일은 그 특성상 여러군데서 다루는것도 어렵고
s3는 read write만 지원하고 append가 없어서
여러 람다로 분산처리할수없습니다
또한 필연적으로 긴 작업이고, 그러면 람다에는 적합하지 않겠죠
그러면 파게이트를 쓰자! 라는 결론이 났습니다
최종적인 export 데이터 플로우 설계는 이렇습니다.
조금 그림이 크니, 나눠서 보여드리면
이 부분이 아까 설명드린 1,2번
여기가 3번
그리고 마지막 4번입니다.
나머지는
에러 핸들링이나, 큐로 작업을 받아서 실행시키거나 하는 그런 부가적인 프로세스입니다
이런식으로 복잡한 작업도 데이터 플로우를 설계해서 만들면
확실히 관리도 쉽고, 필요에 따라 병렬, 분산처리도 가능하고 여러가지 이점이있습니다.
최종적으로 결론은 서버리스로 데이터 플로우를 구축하는것은 서버리스 특성상 낮은 진입장벽으로 빠르게 설계해서 사용할수있으며, 처리에 있어서 병렬성, 확장성, 그리고 재활용성을 얻을수있습니다.
저는 이번 발표를 통해 AWS의 다양한 서버리스 혹은 매니지드 서비스들로도 이렇게 데이터 플로우를 만들수있구나 라고 여러분과 공유하는것이 목표였습니다.
꼭 데이터 플로우는 서버리스로 구현해야된다! 라고 주장하는것은 아니지만.
서버리스 기반의 데이터 플로우는 분명 매력적인 장점이 있다고 자신있게 말할수있습니다.
하나의 서버리스 애플리케이션은 수십개, 수백개의 서버리스 서비스로 이루어져있을수있습니다.
이러한 서버리스 모델에서 다양한 서비스들이 자연스럽게 이어지거나, 데이터를 공유하거나, 효율적으로 운용하려면 한곳에서 관리를 할수있는 워크플로우가 필요하다고 분명 느끼실거고.
이런 워크플로우를 쉽게 구현하게 해주고, 이렇게 만들어진 워크플로우를 통해 애플리케이션 데이터 처리에 병렬성, 확장성 그리고 재활용성을 더해줄수있는 서비스가 바로 스텝펑션이라고 생각합니다..
그래서 저는, 여러분도 만약 데이터 플로우를 만들어야 하는상황이 오면, step functions, lambda, fargate를 사용해 서버리스로 만들어보면 어떨까합니다
이로써 서버리스 트랙 마지막 발표, 서버리스 데이터 플로우 개발기를 마치겠습니다.