Search Service in Serverless Architecture

kwonsejung
Vingle Tech Blog
Published in
9 min readJan 28, 2018

Search Service 는 제가 빙글에 입사하고 나서 처음으로 맡은 독립적인 서비스입니다. 그래서 유난히 애착이 가는 서비스인데요. 현재는 제가 만들었을 때보다 많은 것이 추가되었습니다. 오늘 포스팅에서는 제가 만들었을 당시의 Search Service 에 대해 적어보도록 하겠습니다.

빙글이란?

Search Service 를 설명하려면 빙글이 어떤 서비스인지를 미리 설명 드려야할 것 같은데요. 간단하게 말하면 빙글은 사람이 주인 기존의 SNS 와 다르게 관심사가 주가 되는 SNS 서비스 입니다. 자기가 관심 있는 것의 Contents 만 받아 볼 수 있는 것이죠. 아래 사진이 관심사 페이지를 들어가면 나오는 화면입니다. 현재는 카드밖에 없지만 나중엔 여러가지 추가되겠죠? ㅎㅎ

Interest Service

빙글에 대해서 알아보았으니 이제 빙글의 주가 되는 Interest Service 가 어떻게 돌아가는지 알아보겠습니다. 저희 서비스는 8월에 진행한 리뉴얼의 영향으로 인해 기존의 Monolithic Architecture 나 Microservice Architecture 의 구조랑 조금 다른 구조를 하고 있는데요.(자세한 내용은 https://medium.com/vingle-tech-blog/serverless-microservice-architecture%EC%97%90%EC%84%9C%EC%9D%98-inter-communication-caching-80a43c979121 참고) 아래처럼 client 에서는 기존 Monolithic Service 인 Rails 서버로 요청을 보내고 Rails 서버에서는 해당 요청을 SDK 를 사용해서 lambda 로 보내는 역할을 해줍니다. Rails 는 일종의 Gateway 역할입니다. 적어도 Interest Service 에서는 말이죠.

Interest service architecture

AWS Services

위에서 Interest Service 의 구조에 대해 설명드렸는데요. 아마 AWS 에 대해 잘 모르시는 사람들은 lambda 가 뭔지, dynamoDB 가 뭔지 잘 모르실거라고 생각됩니다. 부가설명이 본 포스팅 목적보다 더 길어지는 느낌이 없잖아 있지만 .. search service 에 대해 적기 전에 간단하게 search service 에서 사용하는 AWS service 들에 대해 알아보도록 하겠습니다.

  1. Lambda
Lambda

Lambda 입니다. 장점은 기존의 EC2와 달리 서버가 항상 띄워져 있지 않습니다. 그리고 사용한 만큼만 과금을 합니다. 또 사용량이 많아지면 자동으로 Auto Scaling 을 해줍니다. 그래서 서버가 터질 일이 거의 없죠. 허나 하나의 이벤트가 처리되는게 5분내로 처리되어야 합니다. 그 이상 걸리게 되면 Timeout이 나면서 Lambda가 죽게됩니다. 빙글의 모든 Microservice 들은 이 Lambda 를 이용하여 구성되어 있습니다.

2. DynamoDB

DynamoDB

AWS 의 NoSQL 서비스인 DynamoDB 입니다. 가장 큰 특징이라고 한다면 AutoScaling 을 제공을 합니다. DynamoDB 는 capacity 라는 것으로 DB 의 스펙을 관리하는데 DB의 read, write 량이 많아지거나 줄어들게 되면 알아서 조정을 해줍니다. 그리고 Streaming 기능을 지원해주는데요. DynamoDB 의 Record 가 생성, 변경, 삭제됨에 따라서 해당 이벤트를 Lambda 에서 처리할 수 있도록 해줍니다. 오늘 설명드릴 Search Service 에서도 이 Streaming 기능을 사용합니다.

그러면 실제로 Search service 는 어떻게 구현할까요? RDB 를 사용했더라면 LIKE 문을 이용해서 구현할 수 있을겁니다. 물론 RDB 의 LIKE 같은걸 DynamoDB 에서 제공을 해주긴 합니다. 허나 전체 Record 를 scan 하기 때문에 resource 낭비도 심하고 performance 또한 좋지 못합니다. 이런 점을 해결하기 위해 도입한게 CloudSearch 라는 AWS Service 입니다.

3. CloudSearch

CloudSearch

마찬가지로 사용량에 따라 자동으로 AutoScaling 해줍니다. 그리고 Serverless service 라서 ElasticSearch 와는 다르게 따로 관리가 필요 없습니다. 또한 Lambda 와 마찬가지로 사용(upload, read, storage)한 양에 따라서만 비용을 지불하면 됩니다.

Interest Search Service

자 이제 드디어 빙글의 관심사 검색 서비스에 대해 알아보도록 하겠습니다.

Interest Search Service Architecture

예전 구조를 보니까 뭔가 되게 초라해 보이네요. 구조는 이게 전부입니다. DynamoDB Streaming Callback 을 Lambda 로 연결하고 Lambda 에서는 해당 이벤트를 적절하게 처리해서 CloudSearch 에 적용시키는 역할을 합니다. 좀 더 자세하게 설명드리면 사용자가 새로운 관심사를 만들었습니다. 그럼 Rails 에서 앞쪽의 Interest Service Lambda 로 새로운 관심사를 생성하라는 요청을 보내겠죠? 그럼 Lambda 에서는 DynamoDB 에 Record 를 생성합니다. DynamoDB 에서는 생성되었다는 Event 를 뒤쪽의 Callback Lambda 로 넘기고 Callback Lambda 에서는 해당 Event 를 알아서 처리하는 거죠. Event 의 종류는 Streaming 에서 자동으로 분별해주지 않기 때문에 Lambda 에서 알아서 분별해야 합니다. 아래와 같이 말이죠.

DynamoDB Streaming Callback

마치며

애초에 포스팅에서 설명드리고 싶었던 내용들은 전부 설명을 드렸는데요. 그 외에 부가적으로 몇 가지 주의사항(?)을 적어보겠습니다.

  1. Callback 이 항상 옳은 것은 아니다.

당연한 소리일수도 있겠지만 Record 가 변경되고 해당 변경에 대해 뭔가를 처리해야된다고 해서 항상 Callback 을 사용하는 것이 맞지는 않습니다. 그 이유는 Callback 은 실시간으로 처리되지 않기 때문입니다. Streaming 은 Queue 에 처리되어야 하는 Event 정보를 담는데요. 해당 Queue 는 일정 시간이 지나거나 지정해둔 Queue 의 크기만큼 Event 가 쌓이지 않을 경우 Callback 으로 넘어가지 않습니다. 그래서 실시간성이 중요시 되는 기능이나 서비스에서는 DynamoDB Callback 사용은 피하는 것이 좋습니다.

2. Model Share In Different Service

하나의 Model 을 여러 서비스에서 사용하는 경우인데요. 저희 서비스로 예를 들면 User Service 에서 Interest Service 의 Model 을 필요로 하는 경우를 예로 들 수 있겠네요.

Model sharing

예전에는 전자와 같이 그냥 Model 에 바로 접근했습니다. 그래서 생긴 문제가 하나의 Model을 여러 곳에서 접근하게 돼서 Model 관리가 복잡해졌습니다. 이를 해결하기 위해 구조를 뒤와 같이 변경했습니다. Model 에 접근하는 Service 는 하나고 다른 Service 에서 해당 Model 을 사용할 일이 있을 경우에는 접근 가능한 Service 에 필요한 요청을 수행하긴 위한 기능을 구현하고 다른 Service 에서는 SDK 를 이용하여 그 기능을 요청합니다. 조금 번거롭긴 하지만 이렇게 함으로써 Model 을 여러 곳에서 관리하면서 생기는 Dependency 를 줄일 수 있었습니다.

3. Data Migration

Search Service 는 보통 기존의 Service 위에 붙이는 경우가 많습니다. 따라서 기존의 데이터들을 Migration 해줘야 하는데요. Migration 하는 과정에서 Service 에 문제가 생긴 경우가 있었습니다. 기존 데이터를 Migration 하기 위해서 전체 Record 를 scan 한 다음 데이터를 집어넣었는데요. Auto Scaling 을 믿고 따로 capacity 관리를 안한 상태에서 진행했습니다. 허나 scan 과정에서 Read Capacity 가 순간적으로 많은 양이 들어온 탓인지 장애가 나게 되었습니다. 물론 Auto Scaling 으로 알아서 Scaling 이 되면서 문제를 해결할 수 있었습니다만 Real time 으로 Scaling 이 되지 않는 만큼 순간적으로 들어오는 이벤트를 예측할 수 있다면 capacity 를 강제적으로 올려서 장애를 막는 것이 좋아보입니다.

DynamoDB Read capacity AutoScaling

이상으로 이번 포스팅을 모두 마치도록 하겠습니다~ 다음엔 더 좋은 내용으로 찾아 뵙겠습니다.

빙글에는 이런 문제를 함께 풀어갈 사람을 언제나 기다립니다.

--

--