이전장(플라워로드 시스템 아키텍처 - 도입편)에서 우리 플라워로드 Backend 시스템에서 사용되는 기술들에 대해서 간략하게 알아보았습니다. 여기서는 설명한 기술들을 이용해서 시스템이 어떻게 구성되어 있고, 어떤 플로우로 서비스를 제공하고 있는지 살펴볼 예정입니다.
플라워로드는 크게 사용자앱, 관리자앱, 스쿠터 세가지의 Frontend로 구분할 수 있습니다. Backend 시스템 내에서 각각의 Frontend에 따른 구분은 없고, 기본적으로 Backend의 computing system은 MSA를 따라 Lambda function들의 묶음으로 구성되어 있기 때문에 Frontend로 부터 요청되는 데이터 혹은 command에 따라서 사용되는(호출되는) Lambda function의 묶음이 결정됩니다.
위의 그림은 플라워로드의 전체 데이터, 사용자요청의 흐름을 보여주고 있습니다.
화살표의 색깔을 보고 따라가기만 해도 흐름에 대해서 파악 할 수 있기 때문에 크게 설명할 내용은 없을거라 생각이 되기 때문에 각각의 component만 간단하게 소개합니다.
AWS API Gateway에서 요청을 받아서 각 요청에 맞는 handler(Lambda)를 호출하는 역활을 합니다. URL에 대한 assign은 AWS Route53으로 구성되어 있고, 요청에 대한 인증은 AWS Cognito와 api key를 API의 특성에 맞게 사용하도록 설정되어 있습니다.
여기서 말하는 Handler는 모두 Lambda Function을 말합니다. MSA를 기반으로 설계를 했기 때문에 작은 단위의 service로 분류 한 후 Lambda로 구현했습니다. 이렇다보니 기능이 늘어남에 따라 Lambda의 숫자도 많아지고 Lambda의 call횟수도 기하급수적으로 늘어나고 있는걸 볼수 있습니다.
그나마 다행인것은 AWS Lambda의 요금을 보면 Call 횟수에 대한 요금 부담 보다는 상대적으로 Lambda가 실행되는 총 시간(computing time)에 대한 요금이 더 큰편입니다.(이건 저희 서비스의 경우입니다. 너무 작은 단위로 service를 구성하면 call 횟수에 따른 금액이 더 커질수도 있습니다.) 따라서, IO가 필요한 service들은 최대한 빠르게 완료 될수 있도록 구성 및 구현을 하거나 caching, 임시 저장소 등을 이용해서 lambda chaining 방식 혹은 step function 으로 처리해야 합니다.
여기서 사용된 Redis는 AWS ElastiCache의 Redis를 사용했습니다.
주로 스쿠터의 current data를 caching하는 역활을 하고 있습니다. 예를 들면 현재 좌표, 스쿠터의 주행 상태, 사용자의 점유 상태, 배터리 상태, 잠금 상태 등 앱에서 현재 위치 주변의 스쿠터 정보를 요청했을때 빠르게 데이터를 획득 및 전달 해주는 역활을 맡고 있습니다. 그리고, 아직 적용은 하지 않았지만 pub/sub 기능을 이용해서 스쿠터의 정보에 변경이 있으면 즉각적으로 시스템 혹은 앱에게 알려주는 기능도 적용예정에 있습니다.
사실 초기 설계시 Redis를 사용하게 된 이유는 따로 있었습니다. 당시 AWS aurora가 mysql 5.6 version 까지만 지원을 해서 좌표를 이용한 범위, 거리 검색이 되지 않았기 때문이였습니다. redis의 경우 중심좌표를 기준으로 특정 거리내의 좌표를 query할 수 있기 때문에 이를 이용해서 사용자 중심 반경 특정 범위 내의 스쿠터만 쉽게 조회가 가능했었습니다.
최근 NoSQL DB(mongoDB, dynamoDB등)도 많이 사용되고 있어서 설계 당시 조금 고민을 하기는 했습니다만, 역시 결제 기능이 있어서 transition을 지원하는 RDB의 사용을 선택했습니다.
초기 설계 당시 AWS의 serverless Aurora를 사용하려고 했으나 그 당시 seoul region에는 serverless가 서비스 되고 있지 않던 관계로 일반 서버 형태를 사용하게 되었습니다. mySql 5.6 버전을(당시 사용할 수 있는 최신 버전.....)사용했었고, 초기에는 main과(write 용) read replica 하나를 생성해서 사용했었고, 현재는 data analysis용으로 read replica를 하나더 생성해서 사용하고 있습니다.