44 min read

(번역) 서버리스 아키텍처

Justin Yoo

이 글은 마틴 파울러의 웹사이트에 올라온 Serverless Architectures을 번역한 글입니다. 원문이 계속 업데이트 되기 때문에 번역본과 원문을 함께 보시면 더욱 도움이 될 겁니다.


2016년 6월 17일 마이크 로버츠 Mike Roberts 마이크는 뉴욕에 사는 엔지니어링 리더이다. 요즘엔 팀 매니지먼트가 주요 업무이긴 하지만 여전히 클로저 Clojure 쪽에서 코딩도 하고 소프트웨어 아키텍처 쪽에서도 활발한 의견 개진을 하고 있다. 그는 지금 사람들이 서버리스 아키텍처에 대해 주목하는 현상에 대해 꽤 긍정적이다.   아래 태그를 통해 비슷한 문서들을 찾을 수 있다:
application architecture

목차


서버리스는 요즘 소프트웨어 아키텍처 세상에서는 아주 핫한 토픽입니다. 책들도 나왔고, 오픈소스 프레임워크도 있고, 수많은 벤더들이 프레임워크를 내놨죠. 게다가 아예 서버리스만을 주제로 하는 컨퍼런스까지 생겼습니다. 그런데, 도대체 서버리스가 뭘까요? 그리고 어째서 이 서버리스를 고려해야 (혹은 고려하지 말아야) 할까요? 이 계속 업데이트 되는 문서를 통해 저는 당신이 이러한 질문들에 대한 답을 구할 수 있기를 바랍니다.

서버리스란 무엇인가?

소프트웨어 업계에서 늘상 그렇듯이, 서버리스에 대한 명확한 관점은 없습니다. 그리고 아래 두 가지의 다르지만 겹치는 부분이 있는 이러한 견해들 역시도요:

  1. 서버리스는 서버단 로직이나 상태 등을 관리하기 위한 써드파티 애플리케이션 혹은 클라우드 서비스에 현저히 또는 온전히 의존하는 애플리케이션들을 설명하기 위해 쓰였습니다. 주로 리치 클라이언트 애플리케이션(예를 들자면 단일 페이지 웹 애플리케이션이나 모바일 앱 같은 것들)을 가리키는데, 클라우드에서 접근 가능한 ParseFirebase 같은 데이터베이스라든가, Auth0, AWS Cognito 같은 인증 서비스들 같은 거대한 생태계를 사용하는 것들입니다. 예전에는 이러한 서비스들을 (Mobile) Backend as a Service라고 불렀으니, 여기에서는 이들을 그냥 BaaS라고 부르도록 하죠.
  2. 또한 서버리스는 개발자들이 서버단 로직을 개발자들이 짜긴 하지만, 전통적인 아키텍처와는 달리 상태를 저장하지 않는 Stateless 컴퓨팅 컨테이너에 넣고 돌리는 애플리케이션을 의미하기도 합니다. 이러한 애플리케이션은 보통 이벤트 기반으로 작동하고, 한 번 쓰고 버리고, 써드파티에 의해 관리되죠(ThoughtWorks는 최근 포스트에서 이렇게 정의했습니다). 이런 방식으로 생각해 볼 수 있는 한가지 방법은 Functions as a Service(또는 FaaS)입니다. AWS 람다는 현재 이 FaaS계의 가장 인기있는 구현체지요. 하지만 다른 것들도 더 있습니다. 여기서는 바로 이 FaaS서버리스의 의미로 사용하도록 하겠습니다.

저는 주로 두 번째 얘기를 할텐데요, 조금 더 새롭기도 하고 우리가 흔히 기술적인 아키텍처에 대해 생각하는 것과 현격한 차이가 있기도 합니다. 게다가 요즘 서버리스라는 것에 대한 수많은 얘기들이 오고가기 때문이기도 하구요.

하지만, 이러한 개념들이 사실은 모두 관련이 있고 하나로 모여들고 있습니다. Auth0가 하나의 좋은 예가 될 수 있겠네요. 처음에 BaaS 형태인 Authentication as a Service로 시작했다가 지금은 Auth0 Webtask를 통해 FaaS 영역으로 들어왔습니다.

게다가 BaaS 형태의 애플리케이션을 개발하는 많은 경우, 특히 모바일 앱과 반대로 리치 웹 앱을 개발하는 경우, 어느 정도 서버단의 커스텀 기능들이 여전히 필요합니다. 특히 당신이 사용하고 있는 BaaS 서비스와 어느 정도 통합을 한다면 FaaS 가 이런 경우 좋은 솔루션이 될 수 있습니다. 이러한 기능들의 좋은 예로는 데이터 유효성 검사(악성 클라이언트로부터 보호하기 위한)라든가 많은 계산 용량을 필요로 하는 작업들(이미지나 비디오 프로세싱 같은 것들)이 있겠지요.

몇 가지 예제

UI 주도 애플리케이션

서버단에 로직이 있는 전통적인 쓰리티어 클라이언트 시스템을 봅시다. 전자상거래 시스템들 같은 것이 좋은 예가 되겠네요. 예를 들자면 온라인 애완동물 용품 사이트 같은 것.

전통적으로 이런 아키텍처는 이런 식으로 생겼습니다. 서버단은 자바로 구현하고, 클라이언트단에는 HTML과 자바스크립트로 구현하죠.

이런 아키텍처에서 클라이언트는 상대적으로 그다지 똑똑하지 않습니다. 대부분의 로직들 – 인증, 페이지 네비게이션, 검색, 트랜잭션 등은 서버단에서 구현을 해놨으니까요.

서버리스 아키텍처에서는 이렇게 보일 겁니다:

엄청나게 간단하게 그린 모델인데요, 그럼에도 불구하고 여전히 수많은 변화들이 일어난 것을 볼 수 있습니다. 여기서 잠깐! 이건 단순히 서버리스 개념을 보여주기 위한 도구로서 만든 그림이지 이게 이런 식으로 아키텍처를 이전해야 한다고 추천하는 건 아니라는 것을 기억해 두세요!

  1. 최초 애플리케이션에서 인증 로직 부분을 빼고 써드파티 BaaS 서비스로 교체했습니다.
  2. 또다른 BaaS의 예로, 상품 리스트 출력을 위해서 클라이언트단이 직접 데이터베이스를 접속하게 했습니다. 이 데이터베이스는 AWS의 Dynamo DB 같이 전적으로 써드파티 데이터베이스가 됩니다. 클라이언트단에서 데이터베이스에 접속할 수 있는 다른 보안 프로파일을 적용하는 방식으로 다른 서버 리소스에서도 데이터베이스에 접근할 수 있게도 할 수 있습니다.
  3. 앞서 언급한 두 가지 포인트는 굉장히 중요한 이 세번째 포인트를 암시합니다 – 쇼핑몰 서버단에 있던 로직들이 이제는 클라이언트단으로 옮겨갔다는 거죠. 예를 들자면 사용자 세션 추적이라든가, 페이지 네비게이션 같은 애플리케이션의 UX 구조를 이해하는 로직이라든가 데이터베이스에서 읽어들인 자료를 사용자 뷰에 맞는 형식으로 변환하는 것들이라든가 하는 것들 말입니다. 이렇게 되면 사실 클라이언트단은 이제 단일 페이지 애플리케이션이 되는 셈입니다.
  4. UX관련 기능 중 어떤 것들은 서버단에 계속 두고 싶을 거예요. 예를 들자면 많은 계산 용량을 필요로 한다든가 대용량 데이터에 접근을 해야 한다든가 하는 것들이죠. 검색 기능을 예로 들 수 있을텐데요, 검색 기능을 위해서 항상 서버를 돌리기 보다는 API 게이트웨이(나중에 다시 설명합니다)를 이용한 FaaS 펑션을 구현해서 HTTP 리퀘스트에 응답하게끔 하면 됩니다. 그렇게 함으로써 우리는 클라이언트단과 서버단에 기능을 두고 상품 데이터가 있는 같은 데이터베이스에서 읽어들이게 할 수 있습니다.

    원래 서버단 기능들을 자바로 구현했고, 이 포스트에서 선택한 FaaS 제공자로서 AWS 람다 서비스를 자바를 지원하기 때문에, 온라인 쇼핑몰의 검색 기능 관련 코드를 서버단에서 람다로 코드를 다시 쓰지 않고도 쉽게 옮길 수 있습니다.

  5. 마지막으로 상품구매 기능을 다른 FaaS 펑션으로 대체할 수 있습니다. 보안상의 이유로 클라이언트단으로 옮기기 보다는 서버단에 이 기능들을 놓는 것이 낫기 때문입니다. 물론 API 게이트웨이를 그 앞에 놓았습니다.

메시지 주도 애플리케이션

다른 예를 하나 더 들자면 백엔드에서 돌아가는 데이터 프로세싱 서비스가 될 겁니다. 지금 당신이 사용자 중심의 애플리케이션을 하나 개발하고 있다고 치죠. 이 애플리케이션은 UI 리퀘스트에 재빨리 반응을 해야 합니다. 하지만 동시에 현재 일어나는 모든 종류의 액티비티들을 로그로 저장하고 싶어합니다. 온라인 광고 시스템을 한 번 생각해 봅시다 – 사용자가 광고를 클릭할 때 사용자를 재빨리 해당 광고의 타겟으로 보내고 싶습니다. 동시에 사용자 클릭이 발생했다는 것을 잡아내서 광고주에게 과금할 수 있어야 합니다.

전통적으로 이런 아키텍처는 보통 광고 서버가 동기적으로 사용자에게 반응(여기서는 그 반응이 어떤 것인지에 대해서는 상관하지 않습니다)하는 동시에 채널을 통해 메시지를 보내서 비동기적으로 클릭 프로세서를 실행시켜 데이터베이스를 업데이트합니다. 데이터베이스 업데이트에는 광고주 예산에서 광고만큼 금액을 집행하는 것들이 있을 수 있겠죠.

그런데, 서버리스 세상에서는 위의 모델이 아래와 같이 바뀝니다.

앞서 예를 든 것과는 차이가 그렇게 많이 나는 것처럼 보이지는 않네요. 우리는 여기서 계속 돌아가는 서버단의 프로세스를 이벤트 주도 형태의 콘텍스트 안에서 돌아가는 FaaS로 바꿨습니다. FaaS 서비스 제공자는 우리에게 서로 연결되어 있는 메시지 브로커(Message Broker)와 FaaS 환경을 제공합니다.

또한 이 FaaS 환경은 동시에 일어나는 클릭들도 펑션 코드를 클릭 이벤트 숫자에 맞게 감지해서 처리합니다. 기존 애플리케이션의 프로세스에 이런 병렬코드 진행 부분이 없었다면 이 새로운 개념을 적용시켜야 할 수도 있습니다.

Function as a Service 뒤집어보기

우리는 이미 FaaS에 대해 여러번 언급을 해 왔습니다. 이제부터는 도대체 그게 뭔지 좀 더 파고 들어갈 때가 됐습니다. 우선 아마존의 람다 서비스에 대한 설명을 좀 보도록 하죠. 번호를 군데군데 매겨놨는데요, 잠시 후에 설명하도록 하겠습니다.

AWS 람다는 서버를 만든다거나 관리할 필요 없이 당신의 코드를 실행시킬 수 있다. (1) ... 람다와 함께라면 당신은 어떤 형태의 애플리케이션이나 백엔드 서비스에서도 코드를 돌릴 수 있다. (2) – 관리 비용은 전혀 필요가 없다. 그저 당신의 코드를 업로드하면 람다가 실행에 필요한 모든 것들을 알아서 관리해 주고 (3), 필요하면 스케일링도 해주면서 (4) 계속 높은 가용성을 유지시켜 준다. 당신은 다른 AWS 서비스로부터 자동으로 트리거링을 받게끔 코드를 작성할 수도 있고 (5) 어떤 웹이나 모바일 앱등에서도 이를 직접 호출하여 실행시킬 수 있다. (6)

  1. 기본적으로 FaaS는 당신이 서버 시스템들 없이 또는 서버 애플리케이션 없이 백엔드 코드를 실행시키는 것입니다. 서버 애플리케이션이라는 구절이 바로 핵심적인 차이인데, 이 서버 애플리케이션은 현대적인 아키텍처의 흐름, 즉 컨테이너라든가 PaaS(Platform as a Service) 등을 의미합니다.

    만약 다시 위의 클릭 처리 예제로 돌아간다면, FaaS는 클릭 처리를 담당하는 서버(물리적 머신일 수도 있지만 어쨌거나 실제 그 용도로 쓰이는 애플리케이션)를 서버 프로비저닝이 필요하거나 항상 돌아가야 하는 애플리케이션이 아닌 다른 무언가로 바꾸는 것입니다.

  2. FaaS는 굳이 특정 프레임워크나 라이브러리에 의존해서 코딩하는 것을 필요로 하지 않습니다. FaaS 펑션은 아무 언어 혹은 환경에서도 작동하는 하나의 애플리케이션입니다. 예를 들어, AWS 람다 펑션은 자바스크립트라든가, 파이쎤 혹은 자바, 클로저, 스칼라 등의 아무 JVM 언어들로 구현할 수 있습니다. 또한 당신의 람다 펑션은 설치 아티팩트와 함께 묶여있기만 한다면 다른 프로세스를 통해서 아무 언어나 실행시킬 수 있습니다. 유닉스 혹은 리눅스 환경에서 컴파일이 가능하다면 말이죠(나중에 Apex를 다뤄보겠습니다). FaaS 펑션은 상태라든가 하는 쪽에서 굉장히 제한적인 아키텍처를 갖고 있습니다. 상태라든가 실행 시간 같은 것들을 고려해야 한다면 말이지요. 이건 잠시 후에 다시 설명하기로 하죠.

    다시 앞서의 클릭 프로세스로 돌아가 봅시다. FaaS로 옮겨갈 때 코드를 변경해야 하는 유일한 부분은 바로 main 메소드 혹은 startup 코드 부분입니다. 이 부분은 필요가 없고, 대신 최상위 계층의 (메시지 리스너 인터페이스를 구현한) 메시지 핸들러로 변경하면 됩니다. 이 부분이 유일한 코드 변경점이죠. 코드의 나머지 부분은 (예를 들어 데이터베이스에 접근한다든가 하는 부분) FaaS 세상에서도 변함없이 똑같습니다.

  3. 이제 우리는 실행시킬 서버 애플리케이션이 없습니다. 그래서 설치 과정 역시도 전통적인 애플리케이션과 굉장히 달라지게 됩니다. 그저 코드를 FaaS 제공자로 업로드하면 나머지는 그쪽에서 다 알아서 하게 되죠. 지금 현재로서는 이것은 새로 수정한 코드 혹은 새로 만든 코드를 .zip 파일 혹은 JAR 파일로 묶어서 올리는 것을 의미하구요, 개별 FaaS 서비스 제공자의 내부 API를 통해 이 수정 사항을 실행시키게끔 호출하는 것으로 보면 됩니다.
  4. 수평적 스케일링은 이제 완전히 자동화가 됐구요, 서비스 제공자가 다 알아서 합니다. 만약에 당신의 시스템이 100개의 리퀘스트를 동시에 처리해야 한다면, 내 쪽에서 별도의 설정 같은 것을 하지 않아도 서비스 제공자가 알아서 다 합니다. 이렇게 당신의 펑션을 실행하는 컴퓨팅 컨테이너는 일시적으로 FaaS 제공자가 관리하고 파기하는 형태여서 순전히 런타임에서만 잠깐 필요한 정도가 됩니다.

    다시 우리의 클릭 프로세서 예제로 돌아가보죠. 사용자가 평소보다 한 열 배 정도는 광고 클릭을 더 많이 한다고 가정해 봅시다. 기존의 클릭 프로세싱 애플리케이션은 이걸 처리할 수 있을까요? 다시 말해서 당신의 코드는 한 번에 여러 개의 메시지를 처리할 수 있을까요? 심지어 우리가 할 수 있다고 해도 애플리케이션의 실행 인스턴스가 하나만 있다면 이걸 감당할 만큼 충분할까요? 만약 다중 프로세스를 돌릴 수 있다면 우리는 이걸 자동으로 오토 스케일링 설정을 해 놓아야 할까요 아니면 수동으로 그때그때 설정해야 할까요? FaaS라면 당신은 그저 펑션을 작성할 때 병렬 프로그래밍을 가정하고 작성하면 됩니다. 그러면 FaaS 제공자는 스케일링이 필요할 경우 알아서 다 해주죠.

  5. FaaS에 있는 펑션들은 서비스 제공자가 정의한 이벤트 타입에 의해 실행될 수 있습니다. 아마존 AWS의 경우에는 S3 파일 업로드 이번트, 스케줄링 작업에 따른 시간, Kinesis와 같은 메시지 버스에 메시지가 추가되는 이벤트 같은 것들이 있습니다. 이럴 경우 당신의 펑션은 보통 연결되어 있는 특정 이벤트에 대응하는 파라미터 값들을 제공해야 합니다. 예시로 든 클릭 프로세서의 경우에는 이미 FaaS에 대응하는 메시지 브로커를 사용하고 있다고 가정합니다. 만약 그렇지 않다면 바꿔야 하구요, 이 경우에는 메시지 생성하는 로직을 수정할 필요가 있습니다.
  6. 대부분의 서비스 제공자들은 펑션들이 HTTP 리퀘스트에 응답을 보내게끔 구현되어 있습니다. 예를 들자면 API 게이트웨이 같은 형식으로 말이지요. 이런 것들에는 AWS API 게이트웨이, Webtask 등이 있습니다. 우리는 앞서 예시로 든 애완동물 온라인 쇼핑몰에서 검색 기능과 구매 기능에 이용하고 있죠.

상태

FaaS 펑션을 내 로컬 머신 혹은 로컬 인스턴스에서 돌릴 때는 굉장히 제한적입니다. 즉, 어떤 펑션을 실행시킬 때 당신이 생성한 어떤 프로세스 혹은 호스트 상태가 다음에 이어지는 펑션으로 어떤 식으로든 전달되지 않는다고 가정해야 합니다. 이것은 RAM 안에 저장된 상태도 포함하구요, 로컬 디스크에 뭔가를 저장하는 어떤 형태의 상태 역시도 포함합니다. 다시 말해서 설치 유닛 관점에서 FaaS 펑션은 상태를 저장하지 않습니다(Stateless).

이것은 애플리케이션 아키텍처에 지대한 영향을 줍니다. FaaS가 유일한 건 아니지만요 – 12요소 앱 개념은 정확하게 똑같은 제한점을 갖고 있습니다.

그렇다면 이러한 제한요소를 인정한다고 할 때, 어떤 대안이 있을까요? 보통 FaaS 펑션은 원래 상태 저장기능이 없어서(Stateless) 단순히 입력값을 다른 출력값으로 변경시킨다거나 또는 데이터베이스, Redis 같은 크로스플랫폼 캐시, 혹은 S3 같은 네트워크 파일 스토리지 같은 것들을 통해 리퀘스트 전반에 걸쳐 상태를 저장시키고 그걸 이용해서 좀 더 사용자 요청을 처리합니다.

실행 기간

FaaS 펑션은 개별 실행에 있어 보통 제한시간이 있습니다. 현재 AWS 람다의 경우에는 5분 이상 걸리는 펑션은 실행에 실패하게끔 되어 있구요, 만약 5분 이상 걸릴 경우 자동으로 폐기됩니다.

이것은 오랜 시간을 필요로 하는 작업이라면 새롭게 아키텍처를 변경하지 않는 이상 FaaS 펑션에는 적합하지 않다는 것을 의미합니다. 다시 말해서 전통적으로는 하나의 큰 펑션으로 만들어서 그 안에서 모든 것을 다 처리하는 펑션으로 만들었다면 이제 FaaS에서는 이것을 잘게 쪼개서 각각 별도로 처리하는 형태로 구조를 변경해야 한다는 것이죠.

초기 실행 지연

현재 FaaS 펑션이 리퀘스트에 응답하는데 걸리는 시간은 여러 가지 요소들에 의해 결정되긴 하지만 대략 10ms 에서 2분 정도 사이가 될 겁니다. 딱히 좋은 얘기는 아닌 것 같기는 한데, 조금 더 구체적으로 들어가 보도로 하죠. AWS 람다의 예를 들어 봅시다.

만약에 자바스크립트나 파이썬으로 펑션을 구현했고 그 펑션의 크기가 대략 1천 줄 미만의 코드량으로 그다지 크지 않다면, 실행에 필요한 시간은 아무리 많아야 10ms 에서 100ms를 넘지 않을 겁니다. 펑션의 크기가 커진다면 아무래도 종종 시간이 오래 걸리겠죠.

만약 람다 펑션을 JVM 위에서 구현했다면 종종 10초 이상 걸리는 응답시간을 보일 겁니다. 아무래도 JVM이 구동되기 위해 필요한 시간이겠죠. 하지만, 이것은 아래와 같은 상황에서만 일어나는 상황입니다.

  • 펑션을 자주 실행시키지 않는 경우 – 각 실행 주기가 10분을 넘는 경우
  • 갑자기 트래픽이 늘어나는 경우 – 초당 10개의 리퀘스트를 처리하다가 갑자기 초당 100개의 리퀘스트를 처리하는 식으로 짧은 시간 안에 급격하게 트래픽이 증가하는 경우

전자 같은 경우에는 매 5분 정도마다 핑 리퀘스트를 날려서 계속 서버가 살아있게 하는 식의 핵으로 해결할 수 있습니다.

그렇다면 후자의 경우에 이런 것들이 문제가 될 수 있을까요? 애플리케이션이 트래픽을 처리하는 스타일에 따라 달라질 겁니다. 예전 팀에서는 자바로 비동기 방식의 메시지 처리 람다 애플리케이션을 만들어서 하루에도 수백만개의 메시지를 처리했습니다. 초기 실행 지연 같은 것에는 아무런 걱정이 없었지요. 그건 지연시간이 낮은 트레이딩 애플리케이션을 개발한다면 딱히 이 상황에서는 FaaS를 고려할 이유가 없습니다. 무슨 언어로 개발하든지간에요.

이런 문제가 당신이 개발한 애플리케이션에서 생길지 아닐지는 모르겠지만, 실제 운영 환경에서와 같은 트래픽으로 테스트를 해 볼 필요는 있어요. 그래야 실제 퍼포먼스를 측정할 수 있죠. 만약 당신의 유즈 케이스가 지금 잘 동작하지 않는다면 한 두어달 쯤 후에 다시 시도해 볼 수 있습니다. FaaS 서비스 공급자가 개발해야 할 영역이거든요.

API 게이트웨이

FaaS가 갖는 특징들 중 하나는 앞서 살짝 언급한 API 게이트웨이입니다. API 게이트웨이는 HTTP 서버로서 설정을 통해 라우팅 정보와 엔드포인트를 정의하고 각각의 라우트는 FaaS 펑션에 연결 시킵니다. API 게이트웨이가 리퀘스트를 받았을 때, 리퀘스트와 일치하는 라우팅 정보를 찾아서 그에 맞는 FaaS 펑션을 실행시킵니다. 보통 API 게이트웨이는 HTTP 리퀘스트 파라미터로부터 FaaS 펑션에 필요한 입력 인자를 매핑합니다. 그렇게 함으로써 API 게이트웨이는 FaaS 펑션의 결과값을 HTTP 응답객체에 실어서 최초 요청자에게 반환합니다.

AWS는 API 게이트웨이 서비스를 갖고 있구요, 다른 제공자 역시도 비슷한 기능을 보유하고 있습니다.

API 게이트웨이는 단순히 리퀘스트를 라우팅하는 기능 이외에도 인증 절차를 수행하고, 입력값에 대한 유효성 검사를 수행하며 응답 객체와 매핑을 시키는 등의 역할을 하기도 합니다. 당신의 거미줄 같은 감각은 어쩌면 이게 실제로 좋은 생각인지 아닌지 궁금해 할 수도 있습니다. 잠시 후에 다시 얘기해 보도록 하죠.

API 게이트웨이와 FaaS 조합의 한가지 유즈 케이스는 HTTP를 앞세운 마이크로서비스 형태가 될 겁니다. 서버리스는 여기서 스케일링과 관리 그리고 FaaS 펑션이 가져다 주는 여러가지 잇점을 담당하죠.

현 시점에서 API 게이트웨이 도구는 아직 처절할 정도로 성숙하지 않았습니다. 그렇긴 해도 API 게이트웨이와 함께 애플리케이션을 개발하는 것이 그다지 어렵거나 한 것은 아닙니다.

도구들

API 게이트웨이 도구들이 아직 성숙하지 않았다는 것은 이미 언급했구요, 이것은 전반적으로 서버리스 FaaS 시장에 있어서 공통적인 현상입니다. 하지만 예외는 있죠. 그 예가 바로 Auth0의 Webtask인데요 개발자 UX에서 엄청난 강점을 갖고 있습니다. Tomasz Janczuk은 최근에 있었던 서버리스 컨퍼런스에서 굉장히 좋은 데모를 보여준 적이 있습니다.

디버깅과 모니터링 역시 이 서버리스 애플리케이션에서는 해결해야 할 숙제들입니다. 이 포스트의 뒷부분에서 다뤄보도록 하죠.

오픈 소스

서버리스 FaaS 애플리케이션의 주요 잇점들 중 하나는 바로 투명한 실행 환경 공급에 있습니다. 아직 오픈 소스들은 현재 여기에 그다지 관련이 있지는 않습니다. 도커와 같은 컨테이너들 말이죠. 조만간 우리는 유명한 FaaS / API 게이트웨이 플랫폼이 회사내 on-premise에서 돌아간다거나 개발자의 컴퓨터에서 돌아간다거나 하는 것들을 볼 수 있을 겁니다. IBM의 OpenWhisk는 좋은 예가 될 수 있는데요, 이것이 어떤 대안이 될지 아닐지 지켜보는 것도 꽤 흥미로울 겁니다.

실행 환경 구성과는 별개로 FaaS 펑션을 정의하고, 설치하고 실행시키는데 도와주는 도구들과 프레임워크들은 이미 오픈 소스로 많이 나와 있습니다. 예를 들어 서버리스 프레임워크는 실제로 동작하는 API 게이트웨이와 람다를 AWS에서 제공하는 형태보다 훨씬 더 쉽게 사용할 수 있게 해줍니다. 자바스크립트를 좀 지나치게 쓰긴 했는데, 만약 자바스크립트와 API 게이트웨이 조합으로 애플리케이션을 개발한다면 꼭 한 번 봐 둘만 합니다.

또다른 예로는 Apex가 있습니다. 이 프로젝트는 AWS 람다 펑션들을 손쉽게 만들고, 설치하고, 관리하자라는 슬로건을 갖고 있습니다. Apex가 갖는 재미있는 요소들 중 하나는 아마존에서 직접 지원하지 않는 언어들을 람다 펑션 차원에서 지원하게끔 해준다는 겁니다. 예를 들자면 Go 언어 같은 것들이죠.

서버리스가 아닌 것은?

직금까지 이 글에서 저는 서버리스Backend as a Service (BaaS)Functions as a Service (FaaS)의 합집합이라고 정의했습니다. 또한 주로 FaaS 쪽을 중점으로 해서 이야기를 풀어나갔지요.

이제 가장 중요한, 무엇이 이득이고 무엇이 손해인지에 대해 얘기하기 전에 이 서버리스의 정의에 대해 조금만 더 살펴보고자 합니다. 적어도 무엇이 서버리스아닌지에 대해 얘기해 보죠. (최근의 저를 포함해서) 몇몇 사람들이 이러한 것들에 대해 혼동했던 것을 봐 왔고, 좀 더 명확하게 하는 것도 좋은 생각 같습니다.

PaaS와 비교

앞서 잠깐 서버리스 FaaS 펑션은 12요소 애플리케이션과 비슷하다고 했는데요, 그렇다면 Heroku와 같은 또다른 PaaS라고 할 수도 있을까요? 간단하게 대답하기 위해 Adrian Cockcroft의 트윗을 인용하겠습니다.

만약 당신의 PaaS가 20ms 이내에 인스턴스를 실행시켜서 0.5초 동안 원하는 기능을 실행시킬 수 있다면 그땐 그걸 서버리스라고 부르세요.

다른 말로, 대부분의 PaaS 애플리케이션들은 매 리퀘스트마다 애플리케이션 전체를 올렸다 내렸다할 수 있게끔 설계되지 않았습니다. 반면에 FaaS 플랫폼은 정확하게 그렇게 하죠.

좋습니다. 만약 제가 훌륭한 12요소 애플리케이션의 개발자라면 딱히 코딩을 하는데 있어서 별 차이점은 없을 거예요. 사실입니다. 하지만 가장 큰 차이는 어떻게 당신의 애플리케이션을 운영하는가에 있습니다. 우린 모두 데브옵스 관점에 충실한 엔지니어들이고 개발에 대해 생각하는 것 만큼 운영에 대해서도 생각하고 있습니다, 그렇죠?

운영 측면에서 FaaS와 PaaS의 핵심적인 차이는 바로 스케일링입니다. 대부분의 PaaS에서 당신은 여전히 스케일링을 고민해야 하죠. 헤로쿠의 예를 들자면 다이노스 Dynos 몇개를 돌리고 싶은가를 고민해봐야 합니다. FaaS 애플리케이션에서 이부분은 완전히 투명합니다. 심지어 당신이 PaaS 애플리케이션을 스케일링 완전 자동화로 설정한다 하더라도 개별 리퀘스트 수준에서 이런 스케일링을 하진 않아요(물론 당신이 굉장히 특별하게 트래픽 프로필을 설정해 놓았다면 얘긴 달라집니다). 따라서 FaaS 애플리케이션은 이렇게 비용이 연계가 될 때 굉장히 효율적입니다.

이런 잇점들이 있다면 왜 계속 PaaS를 쓰려고 하죠? PaaS를 쓸 이유들이 여러가지 있겠지만 아마도 도구들 그리고 API 게이트웨이의 성숙도가 가장 큰 이유들이 될 겁니다. 더군다나 PaaS에 구현한 12요소 애플리케이션들은 최적화를 위해 앱 내 읽기전용 캐시를 사용하겠죠. 이것은 FaaS 펑션에서는 사용할 수 없는 기능입니다.

#NoOps

서버리스NoOps를 의미하는 것은 아닙니다. 서버리스 토끼구멍을 얼마나 깊이 파고 들어가는가에 따라 아마도 내부 시스템 관리자가 없다는 것을 의미할 거예요. 여기서 우리는 두가지 중요한 것을 고려해야 합니다.

먼저 Ops는 서버 관리 이상의 그 무언가를 의미합니다. 적어도 모니터링, 설치, 보안, 네트워킹 등을 의미하기도 하죠. 그리고 종종 시스템 스케일링과 어느 정도의 운영 시스템 디버깅까지를 포함하기도 합니다. 이런 문제들은 서버리스 애플리케이션으로 간다고 해도 여전히 존재하고 이를 해결할 전략이 필요하죠. 어떤 면에서는 Ops서버리스 환경에서 좀 더 어려운 일이 될 수도 있습니다. 왜냐하면 모든 것들이 전부 새롭기 때문이죠.

다음으로 시스템 관리자가 여전히 필요하다면 서버리스를 위해서는 아웃소싱을 하면 그만입니다. 딱히 나쁘진 않아요 실제로 우린 여러번 아웃소싱을 해 왔으니까요. 하지만 구체적으로 당신이 무엇을 하려고 하는가에 따라 이건 좋을 수도 있고 나쁠 수도 있습니다. 어느 시점에서 당신은 시스템 관리자가 당신의 애플리케이션을 지원할 필요가 있다는 것을 알아야 할 지 모릅니다.

Charity Majors는 이와 관련해서 최근 있었던 서버리스 컨퍼런스에서 좋은 발표를 해 줬습니다. 저는 온라인에 이 발표가 올라오면 꼭 확인해 보기를 권장합니다. 그 전까지는 이 글이 글을 읽어보면 좋겠네요.

Stored Procedures as a Service

또다른 흥미로운 주제는 서버리스 FaaS가 Stored Procedures as a Service라는 겁니다. (이 글에서 사용한 것들을 포함해서) FaaS 펑션의 많은 예제들이 주로 데이터베이스에 접근하기 위한 코드들이기 때문이 아닐까 생각합니다. 만약에 겨우 이정도가 우리가 FaaS를 사용하는 이유라고 한다면 이 네이밍은 적당할 지도 모르겠군요. 하지만 이건 FaaS의 서브셋에 불과할 뿐더러 만약 이런 용도로만 사용한다면 뭐랄까 조금은 맞지 않습니다.

이것은 어찌 보면 Stored Procedure가 갖는 동일한 문제를 FaaS 역시도 가질 수 있다는 것을 고려해 볼 필요가 있습니다. Camille이 트윗에서 언급한 것과 같은 기술적 부채들도 포함해서 말이지요.

만약에 서버리스 서비스가 마치 Stored Procedure 처럼 변한다면 이건 곧바로 엄청난 기술적 부채가 될 거라는 걸 생각해 보자구.

Stored Procedure를 사용하는 것에서 오는 수많은 교훈들이 있습니다. 그것들은 FaaS에서 반드시 되돌아보고 적용이 가능할지 아닐지를 결정해야 할 것들이지요. Stored Procedure들은:

  1. 종종 벤더 종속적인 언어를 요구하거나, 적어도 벤더 종속적인 프레임워크 혹은 언어로 확장할 필요가 있습니다.
  2. 데이터베이스 콘텍스트 안에서 실행시켜야 하기 때문에 테스트가 어렵습니다.
  3. 일급 애플리케이션으로서 다루기 까다롭고 버전 관리도 힘듭니다.

이러한 제약사항들이 모두 Stored Procedure를 구현하는데 있어서 적용되는 것은 아닐 겁니다. 하지만 지금까지 제 경험상 수많은 문제들을 읽으켰던 것은 사실이예요. 그렇다면 이것을 FaaS에 어떻게 적용을 시킬 수 있는지 살펴봅시다.

1번 항목은 FaaS 구현에 있어서 큰 걸림돌은 아닙니다. 그냥 그런 부분들을 걷어내면 그만이죠.

2번 항목에서 우리는 코드만 쓰기 때문에, 단위 테스트는 다른 코드들과 마찬가지로 쉽습니다. 통합 테스트는 다른 (그리고 정당한) 문제예요. 이건 나중에 얘기해 봅시다.

3번 항목에서 다시금 FaaS 펑션은 코드일 뿐이기 때문에 버전 관리도 괜찮습니다. 하지만 애플리케이션 패키징 측면에서 봤을 때 아직 어떤 성숙한 패턴이 나오지는 않았어요. 앞서 언급했던 서버리스 프레임워크는 자체적으로 이런 패키징 형태를 제공합니다. AWS는 2016년 5월에 열렸던 서버리스 컨퍼런스에서 패키징 관련해서 Flourish라는 이름으로 작업중이라고 발표했습니다. 하지만 이건 뭐 나와 봐야 아는 거겠죠.

이 문서는 지속적으로 진화합니다. 저는 수시로 이 문서를 업데이트할 예정입니다. 그렇게 해서 좀 더 많은 서버리스 아키텍처와 관련한 장단점들을 포함한 주제들을 이 문서에 담길 희망합니다. 아마도 향후 일이년 이내에 좀 더 서버리스 관련 주제들이 발전하지 않을까 싶네요. 이 주제와 관련해서 우리가 어떻게 업데이트 하는지를 알고 싶다면 우리 사이트의 RSS 피드, 제 트위터 피드 또는 마틴 파울러의 트위터 피드를 주목해 주세요.


알림

이 글을 쓰는데 도움을 주신 분들께 감사 드립니다: Obie Fernandez, Martin Fowler, Paul Hammant, Badri Janakiraman, Kief Morris, Nat Pryce, Ben Rady.

이 새 기술에 적당히 반론도 해 주시고 격려도 해주신 Internet Media의 제 전 팀원들께 감사 드립니다: John Chapin, Pete Gieser, Sebastián Rojas and Philippe René.

마지막으로 이 주제와 관련해 여러 생각들을 피력해 주신 모든 분들, 특히 제가 언급한 분들께 감사 드립니다.

리비전

2016년 6월 17일: 서버리스가 아닌 것은? 섹션 추가 2016년 6월 16일: Functions as a Service 뒤집어 보기 섹션 추가 2016년 6월 15일: 첫번째 버전 발행 - 몇가지 예제들