서버리스
고친 사람 github-actions[bot]
서버리스는 코드를 올려 두면 돌아가게 하고, 그 코드를 돌릴 컴퓨터는 빌려주는 쪽이 맡는 방식입니다. 요청이 들어오면 실행 환경이 만들어지고 일이 끝나면 없어집니다. 이름과 달리 서버가 없어지는 것이 아니라 서버를 돌보는 일이 넘어갑니다.
쉽고 빠른 이해
무슨 일을 하나 — 코드를 돌릴 컴퓨터를 준비하고 지키는 일을 넘깁니다. 하루에 몇 번만 도는 이미지 변환 코드를 올려 두면 그 몇 번만 돌고 나머지 시간에는 아무것도 떠 있지 않습니다.
왜 이렇게 하나 — 컴퓨터를 직접 두면 요청이 없는 시간에도 켜 두어야 합니다. 몰리는 날에 맞춰 대수를 잡으면 한가한 날에 대부분이 놀고, 한가한 날에 맞추면 몰리는 날에 넘칩니다.
어떻게 도나
- 코드를 함수 단위로 올리고 무엇이 오면 깨울지를 정해 둡니다
- 그 신호가 오면 빌려주는 쪽이 실행 환경을 만들어 코드를 넣고 돌립니다
- 일이 끝나면 환경은 잠깐 남았다가 없어지고, 다음 신호에 다시 만들어집니다
대가 — 내가 못 만지는 것이 늘어납니다. 처음 깨어날 때 걸리는 시간, 한 번에 돌 수 있는 시간의 상한, 어디서 시간이 갔는지 들여다보는 방법이 전부 빌려주는 쪽의 규칙 안으로 들어갑니다.
상세
쓸 때만 들르는 스터디카페를 떠올려 봅시다. 책과 노트북은 내가 들고 가고, 책상과 전기와 냉난방은 주인이 챙겨 둡니다. 앉아 있던 시간만큼 값을 치르고, 나올 때는 짐을 하나도 남기지 않습니다.
서버리스는 서버를 이렇게 쓰는 방식입니다. 컴퓨터를 미리 잡아 두지 않고, 할 일이 생긴 순간에만 만들어 쓰고 돌려줍니다. 준비하고 지키는 일은 빌려주는 쪽이 맡습니다.
이 방식이 나온 까닭은 미리 잡아 두는 쪽에 늘 낭비가 따라붙기 때문입니다. 몇 대가 필요한지는 요청이 와 봐야 아는데 대수는 오기 전에 정해야 합니다. 그래서 대개 넉넉하게 잡고, 넉넉한 만큼은 아무 일도 안 하면서 켜져 있습니다.
정하는 일 자체를 없애 보자는 것이 서버리스의 발상입니다. 몇 대를 둘지 사람이 고르지 않고, 들어온 요청 수가 곧 띄울 벌 수가 되게 합니다.
이름이 잘못 읽히는 대목
서버리스라는 이름은 서버가 없다는 뜻으로 읽힙니다. 코드는 여전히 누군가의 컴퓨터에서 돕니다. 사라진 것은 서버가 아니라 그 서버를 내가 신경 쓰는 일입니다.
넘어간 일을 늘어놓으면 이 이름이 무엇을 말하려 했는지가 보입니다. 기계를 몇 대 둘지 고르는 일, 운영체제와 보안 패치를 올리는 일, 요청이 몰릴 때 대수를 늘리는 일이 전부 빌려주는 쪽으로 갑니다.
그래서 서버리스는 기술의 이름이라기보다 관리 책임이 어디까지 넘어갔는지를 가리키는 이름입니다. 같은 코드라도 내 컴퓨터에서 돌리면 서버리스가 아니고, 남이 만들어 주는 환경에서 요청마다 돌리면 서버리스입니다.
관리 책임이 갈리는 선
가르는 선은 하나입니다. 요청 하나를 처리하는 코드 안쪽은 내 몫이고, 그 코드를 무엇에 실어 언제 몇 벌 돌릴지는 남의 몫입니다.
| 내가 맡습니다 | 빌려주는 쪽이 맡습니다 |
|---|---|
| 함수 안의 코드 | 코드를 돌릴 기계와 운영체제 |
| 무엇이 오면 깨울지 정하는 것 | 신호를 받아 실행 환경을 만드는 것 |
| 함수에 주는 권한의 범위 | 요청이 몰릴 때 몇 벌을 동시에 띄울지 |
| 함수가 남길 로그와 지표의 내용 | 그 로그와 지표를 모으는 통로 |
이 선은 가상 머신이나 컨테이너를 쓸 때보다 훨씬 위에 그어져 있습니다. 컨테이너는 이미지를 내가 만들고 몇 개를 띄울지도 내가 정합니다. 서버리스에서는 둘 다 내 손을 떠납니다.
실행 환경의 일생
서버리스 함수는 늘 떠 있지 않습니다. 요청이 오는 동안만 살아 있고 조용해지면 사라집니다.
stateDiagram-v2
[*] --> 없음
없음 --> 준비: 요청이 왔는데 쓸 환경이 없다
준비 --> 실행: 코드를 올리고 초기화를 마친다
실행 --> 대기: 요청 하나를 처리했다
대기 --> 실행: 다음 요청이 곧 왔다
대기 --> 없음: 한동안 아무 요청도 없었다
준비를 거쳐 처음 깨어날 때는 환경을 만들고 코드를 올리는 시간이 붙습니다. 이 시간을 콜드 스타트라고 부릅니다. 이미 대기 중인 환경이 받으면 그 시간은 들지 않습니다.
한 벌이 요청 하나를 처리합니다. 동시에 열 개가 들어오면 열 벌이 뜹니다. 대수를 늘리는 일이 없어진 것이 아니라 요청 단위로 잘게 쪼개져 저절로 일어나는 것입니다.
환경이 없어진다는 것은 그 안에 남긴 것도 같이 없어진다는 뜻입니다. 그래서 서버리스 함수는 무상태로 짭니다. 다음 요청이 앞 요청의 메모리를 이어받는다고 기대할 수 없습니다.
쓴 만큼 내는 요금
요금은 부른 횟수와 한 번에 걸린 시간으로 매깁니다. 아무도 안 부른 시간에는 아무것도 안 떠 있으므로 낼 것도 없습니다.
컴퓨터를 직접 두면 요금은 시간을 따라 흐릅니다. 요청이 하나도 없어도 켜 둔 만큼 냅니다. 이 차이가 서버리스를 고르는 가장 흔한 이유입니다.
대신 요청이 아주 많아지면 셈이 뒤집힙니다. 쉬는 시간이 거의 없는 서비스라면 기계를 잡아 두고 꽉 채워 쓰는 편이 쌉니다.
함수 바깥의 서버리스
서버리스는 함수를 돌리는 방식으로 먼저 알려졌습니다. 이 갈래를 FaaS(Function as a Service, 서비스로서의 함수)라고 부릅니다.
같은 성질을 다른 물건에도 붙입니다. 서버리스 데이터베이스는 용량을 미리 잡지 않고 질의한 만큼 냅니다. 서버리스 큐도 몇 대를 둘지 고르지 않습니다.
그래서 서버리스는 함수만 가리키는 말이 아닙니다. 「대수를 안 고르고 안 쓰면 안 낸다」는 성질을 가리키는 말이고, 함수는 그 성질이 가장 먼저 붙은 물건입니다.
대가
고를 수 있는 폭이 좁아집니다. 한 번에 돌 수 있는 시간에 상한이 있고, 메모리도 미리 정해진 값 가운데에서 고릅니다.
콜드 스타트는 응답 시간의 꼬리를 늘립니다. 대부분의 요청은 이미 대기 중인 환경이 받지만, 한 동안 조용했던 함수는 첫 요청에서 준비 시간을 물게 됩니다.
들여다보기도 어려워집니다. 기계에 들어가 볼 수 없으므로 함수가 남긴 로그와 지표만으로 판단해야 합니다. 분산 추적이 없으면 함수 여럿을 거치는 요청에서 어느 함수가 시간을 먹었는지 못 가립니다.
옮기기도 어렵습니다. 깨우는 신호의 모양, 권한을 주는 법, 로그가 쌓이는 방식이 빌려주는 쪽마다 다릅니다. 함수 안의 코드는 손대지 않아도 그 바깥은 다시 짜야 합니다. 이것을 벤더 종속이라고 부릅니다.
맞는 일감과 안 맞는 일감
띄엄띄엄 오는 일에 맞습니다. 파일이 올라올 때마다 도는 변환, 하루 한 번 도는 정리 작업, 다른 서비스가 보내는 웹훅을 받는 일이 그렇습니다.
오르내림이 심한 일에도 맞습니다. 평소에는 조용하다가 특정 시각에만 몰리는 서비스라면 몰리는 만큼 늘어나고 끝나면 줄어듭니다.
쉬지 않고 도는 일에는 안 맞습니다. 요금도 불리하고, 늘 떠 있어야 하는 것이라면 거둬 가는 방식이 이점을 주지 않습니다.
응답이 한결같아야 하는 일에도 안 맞습니다. 첫 요청에 준비 시간이 붙어도 괜찮은지를 먼저 물어야 합니다. 오래 걸리는 계산은 실행 시간 상한에 걸립니다.
관련 항목
서버리스를 실제로 제공하는 제품
AWS Lambda · Azure Functions · Cloudflare Workers · Knative · OpenFaaS
서버리스라고 부르는 하위 갈래
FaaS · BaaS · 서버리스 데이터베이스 · 서버리스 컨테이너 · 엣지 컴퓨팅
서버리스 코드를 담아 돌리는 실행 환경
컨테이너 · WebAssembly · 마이크로VM · 샌드박스 · 런타임 · 가상화
서버리스 함수를 깨우는 입구와 신호
API 게이트웨이 · 웹훅 · 이벤트 · 메시지 · 큐 · 트리거
서버리스와 같은 일을 두고 겨루는 운영 방식
가상 머신 · Kubernetes · 애플리케이션 서버 · PaaS · 마이크로서비스 · 모놀리식
서버리스 함수가 지켜야 하는 성질
서버리스를 쓸 때 먼저 부딪히는 문제
콜드 스타트 · 벤더 종속 · 동시 실행 한도 · 꼬리 지연 · 썬더링 허드
서버리스를 굴리며 따로 챙기는 운영 과제
관측성 · 분산 추적 · 감사 로그 · 시크릿 관리 · 최소 권한 · 공격 표면
서버리스 요금과 확장을 재는 지표
다른 이름: Serverless · 서버리스 컴퓨팅 · 서버리스 아키텍처