BLOG
블로그 콘텐츠의 내용 및 의견은 AWS SUMMIT 2021의 세션을 리뷰한 내용입니다.
이번 포스팅에서는 AWS Lambda를 활용한 서버리스 애플리케이션을 구성할 때 발생할 수 있는 문제 사항 및 고려 사항과 모범 아키텍처 패턴에 대해서 알아보겠습니다.
AWS Lambda를 활용한 서버리스 애플리케이션
가장 일반적인 서버리스 아키텍처는 아래 그림과 같이 클라이언트의 요청을 API G/W가 받고 이러한 요청 처리는 Lambda가 로직 수행하며, Database는 Amazon RDS를 활용하는 형태입니다. 이와 같은 단순한 아키텍처는 트래픽이 많지 않은 환경에서는 아무런 문제없이 동작할 수 있지만, 만약 많은 트래픽이 발생하고 처리해야 하는 요청이 많아진다면 문제가 발생할 수 있습니다.
Lambda에서 예상되는 문제 사항
- DB 부하가 쿼리 성능 저하에와 Lambda 실행 시간에 영향
- Lambda는 스케일 아웃 방식으로 확장되기 때문에 DB Connection 관리 문제 발생 가능
- Lambda 실행 시간이 길수록 비용 증가하며, API G/W 타임 아웃(29초) 발생 가능
- Lambda 타임(15분) 아웃 발생 가능
- Lambda 버스트 스로틀링으로 인한 API G/W 오류 발생 가능
Lambda 최적화 방안
무거운 Lambda 함수의 최적화
위의 좌측 코드를 살펴보면 하나의 람다함수가 Function1, Function2 함수를 각각 실행한 후에 결과를 기다리고 있고, 3번째 함수를 다음에 실행하는 것을 볼 수 있습니다. 이러한 방법은 모듈화가 되어 있지 않기 때문에 효율적인 방법이라고 볼 수 없습니다. 이를 오른쪽과 같이 Step Function을 활용하면 하나의 모롤리스 코드를 모듈화하여서 재사용이 높도록 구성할 수 있습니다.
코딩 문제에 의한 성능 저하 및 스로틀링 발생
좌측에 보시는 것처럼 DB 자격증명 정보를 가져오고 DB와 커넥션을 맺는 부분이 핸들러 내부에 있다고 한다면, 람다가 웜 스타트 상태라 하더라도 모든 요청을 처리할 때 새로 DB 자격증명 정보를 가져오고 새로 DB와 커넥션을 맺게 되면서 지연이 발생됩니다. 또한, 우측에 API 스로틀링이라고 표현해 둔 것처럼 만약 AWS에 다른 서비스로 API를 호출한다면 과도한 호출이 이루어져서 API 스로틀링 역시 발생할 수 있습니다. 이러한 문제를 피하기 위해서는 실행 컨텍스트를 재 사용하도록 람다 함수를 개발해야 합니다. 앞서 예를 들었던 DB 자격증명 정보를 읽고 DB 커넥션을 맺는 부분을 최초 1회 수행한 뒤에 커넥션을 유지하면 더 효과적으로 람다를 실행할 수 있습니다. 이러한 부분은 Lambda 핸들러 외부에 선언해 주시는 것이 더 유리합니다.
DB 커넥션 오버헤드 발생
Lambda함수에서 AWS RDS를 사용하고, Lambda가 스케일 아웃 시 DB 커넥션 오버헤드가 극심한 대규모 부하 상황에서 DB커넥션 Pool 관리 기능을 제공할 수 있는 Amazon RDS Proxy 서비스를 사용할 수 있습니다. RDS Proxy는 어플리케이션과 RDS 사이에 놓이게 되는 Proxy 서비스로, 완전 관리형으로 제공되는 고가용성 DB Proxy 서비스입니다.
Lambda 모범 아키텍처 패턴
우선 운영적인 측면에서는 모니터링이 가장 중요하며, Cloud Watch를 통한 로그인과 X-Ray를 서비스 맵을 통해 전체 서버리스 애플리케이션 상태를 파악하는 것이 중요합니다. 안정성 측면에서는 RPS를 고려해서 Lambda의 Provisioned Concurrency를 구성하는 것이 중요합니다. 이를 통해 스로틀링을 방지함으로써 애플리케이션의 안정성을 향상 시킬 수 있습니다. DB 자격증명 정보는 Lambda 자체의 코드를 포함하는 것 보다는 AWS Secrets Manager에 저장해서 사용하는 것이 보안적으로 더욱 안전합니다. RDS 연결에 경우는 RDS Rroxy를 사용하는 것이 보다 효과적이고, 앞서 말씀드렸듯이 Step Function, 코드 최적화를 통해 성능 최적화가 가능합니다. Cloud Watch의 Lambda Insights를 사용하시면 함수를 모니터링하고 최적의 메모리를 할당할 지표를 제공 받을 수 있으며, 이를 통해 1m/s 결제 기간 이점을 최대한 얻으므로 비용도 최적화가 가능합니다.
추가적인 모범 사례
실행 컨텍스트를 최소화해서 사용 하는 것은 성능과 굉장히 직결되는 문제입니다. 큰 메모리를 할당하면 함수의 실행시간을 단축시킬 수 있지만, 전체 비용은 람다함수의 크기와 실행시간이 복합적으로 작용한다는 점을 고려하여 최적의 메모리를 할당하는 것이 중요합니다. 추가적인 가이드는 아래와 같습니다.
- 코드 패키지 사이즈 최소화
- Lambda Handler와 Core Logic 분리
- 실행 컨텍스트 재사용 적극 활용
- Environment Variable 적극 활용
- 자바의 경우 .java 파일들을 별도의 /lib 디렉토리 배치
- Max Memory Used 사이즈는 Lambda Function 실행에 충분할 만큼 할당
- 반드시 필요한 경우에만 Lambda를 VPC에 배치
- CloudWatch Custom Metrics을 통해 Lambda에 필요한 지표 기록
- X-Ray를 이용해 Lambda함수 트레이스
마무리하며
서비스 개발을 위해서 물리적인 하드웨어에 대한 계획, 구매, 구성에 대한 시간 비용, 인프라 비용, 모든 기회비용까지 생각한다면 Lambda와 같은 서비스는 스타트업과 같은 기업에게는 매력적인 AWS 서비스입니다. 요즘 많은 IT업체들이 그렇겠지만 인력난으로 개발자 선발이 매우 어렵고, 많지 않은 개발 인력으로 서비스 개발시 Lambda와 같은 기능들을 사용한다면 제한된 개발 인력과 시간을 절약하여 서비스 개발 공수를 절약할 수 있을 것입니다. 개발자분이시라면 앞으로 다양한 AWS Serverless 서비스들에 대해서 더 많은 관심을 갖고 많은 프로젝트에 적용해 보는 것도 흥미로운 도전이 될 수 있을 것입니다.
발표자료URL:https://www.slideshare.net/awskorea/optimal-serverless-applications-to-handle-heavy-traffic
*해당 블로그는 메가존클라우드 임직원이 AWS SUMMIT 2021 “대용량 트래픽을 처리하는 최적의 서버리스 애플리케이션”” 세션을 보고 작성한 글로 발표 자료 및 자세한 내용은 위의 URL에서 확인하실 수 있습니다. 세션을 보고 작성한 글로 발표 자료 및 자세한 내용은 위의 URL에서 확인하실 수 있습니다.