Mar 302016
 

 

모든 시스템은 문제가 생기기 마련이다

“사람은 누구나 실수를 하기 마련이다. (To err is human)”라는 말처럼 모든 시스템은 문제가 생기기 마련입니다. 사람이 만들었으니까… 특히 여러개의 단위 시스템들로 구성된 복합 시스템을 클라우드 상에서 운영한다면 통제할 수 없는 다양한 변수들이 당신을 괴롭힐 겁니다. 낮에도, 밤에도, 트래픽이 많을 때에도, 적을 때에도 문제는 항상 생깁니다.

Screen Shot 2016-03-30 at 9.05.59 AM

Nudge는 AWS 상에서 수십 대의 인스턴스로 구성된 어플리케이션 서버, 워커,  5가지 데이터베이스 (mySQL, redis, memcached, Couchbase, Elasticsearch 등) 클러스터 등을 운영하여 글로벌 기업 고객들에게 24/7 무중단 서비스를 제공하고 있습니다. 이 글에서는 시스템에 이상 징후가 발생했을 때 어떻게 효과적으로 대응할 것인가에 대한, 지난 4년간의 저희 나름대로의 해결책을 공유하고자 합니다.

 

먼저 용어부터 정의하고

  • Alert: 얼럿은 “시스템에 이상 징후가 있으니 확인해서 대응하라. “라는 알림으로 시스템 별로 설정합니다. 특정 프로세스에서는 이메일로, 모니터링 시스템에서는 alarm으로, 주기적으로 확인하는 heartbeat에서는 expired 등으로 발생됩니다.
  • On-Call 엔지니어: 특정 기간 (보통 12시간) 동안 시스템 alert를 1차적으로 확인하고 처리할 담당 엔지니어를 말하며 자신이 처리하기 힘든 이슈라면 해당 시스템의 담당 엔지니어에게 연락합니다.
  • On-Call 스케쥴: 누가 언제 On-Call 엔지니어로 근무할지를 정하는 일정을 말합니다.

 

가정

각 어플리케이션, 데이터베이스 등에서 모니터링해야 하는 metrics은 이미 정의가 되어 있고 어떤 모니터링 툴을 이용해서 어떤 경우에 어떤 alert를 발생시킬 것인가는 설정되어 있다고 가정하겠습니다. 해당 메트릭과 모니터링 툴에 대한 논의는 너무 광범위한 주제라서 이 글의 범위를 벗어난다고 생각합니다.  이 글에서는 Alert를 어떻게 분류하고 발생한 Alert를 누가 (On-Call) 어떤 프로세스에 따라 처리하는 것이 효과적인가에 대해서만 다루겠습니다.

 

내일 새벽에는 누가 일어날까?

Alert이 발생한 경우 누가 처리를 할 것인가를 정해야 합니다. 낮에 발생하면 큰 문제가 아니겠지만 밤이 문제죠. 24/7 운영을 한다면 제가 자는 시간에 서비스의 피크시간대가 있을 수 있겠죠. 24/7 시스템을 모니터링하고 운영하는 업무를 전담하는 시스템 엔지니어가 있다면 좋겠지만 대부분의 스타트업에서 그런 시스템 엔지니어를 채용하기란 쉽지 않습니다. 인원도 적어서 대개는 해당 시스템을 개발한 엔지니어가 직접 해당 이슈에 대응할 수 밖에 없습니다. 결국 한 사람에게 스트레스가 편중될 수 밖에 없고 장기간 지속되면 편하게 잠을 자기도 어렵습니다. 새벽에 alert이 발생해서 처리하고 다시 잠자리에 든 날은 하루종일 안좋은 컨디션으로 일을 하게 되고 심하면 하루를 완전히 날릴 수도 있습니다. 해당 시스템에 대응할 수 있는 사람이 여러 명인 경우에도 문제는 발생합니다. 모두의 마블 책임은 누구의 책임도 아니기 때문입니다. 결국에는 순번을 정해서 불침번을 서야 하는데 alert이 발생했을 때 대응할 수 있는 지식을 가지고 있지 못한 사람이 On-Call 담당자라면 ‘인간 자명종’으로 전락할 수 밖에 없습니다. 지식을 가진 사람에게 전화를 걸어 깨울 수 밖에 없습니다. -_- Alert이 발생해서 일어났더니 별일이 아니라고 한다면 그것 또한 팀에 큰 손실이 됩니다.

 

Alert & On-Call 정책

이런 비효율을 제거하기 위해 올바른 정책을 수립하고 그에 맞는 시스템을 도입해야 합니다. 저희는 1명에게 스트레스가 집중되는 문제, 심각한 alert이 발생했음에도 자꾸 놓치고 빠른 대응을 하지 못하는 것, 체계적인 기록과 관리가 안되는 문제 등이 있었습니다.

  • 일은 나눠야 한다. 시스템 전체에 대한 전문 지식을 가지고 있지 않아도 1차 대응을 할 수 있어야 한다.
  • 시스템 이슈의 심각도가 높을수록 빠른 대응이 필요하다.
  • On-Call 스케쥴을 통해 마음의 준비를 할 수 있어야 한다.
  • 공평해야 한다.
  • 나머지는 포기한다.

여기서 제일 중요한 정책은 맨 마지막 정책입니다. 모든 걸 다 하려고 하다가 아무것도 하지 못하고 계속 고민만 하는 상황을 끊어야 합니다.

그럼 위의 정책에 따라 alert를 분류하고 critical alert이 발생했을 때 어떻게 대응하고 처리할 것인가에 대해 살펴 보겠습니다.

 

자다가 일어나야 하는가?

Alert를 분류하는 방법은 생각보다 간단합니다. 제일 심각한 것부터 덜 심각한 순으로 분류하면 됩니다. 중요한 것을 처리하는 것이 가장 임팩트가 높기 때문에 심각한 것부터 정의해서 절차를 만들면 됩니다. 저희는 현재 3단계까지 분류해서 사용 중입니다.

여기서 가장 중요한 질문은 “자다가 일어나야 하는가?”입니다. (저희가 찾은 최고의 질문이었습니다.) 특정 상황이 발생했을 때 누군가가 일어나서 처리할 만한 문제이냐를 생각해 보면 됩니다. 이 경우는 심각한 상황이 이미 발생했거나 또는 일이 더 커지기 전에 누군가 일어나서 대응해야만 하는 상황 등을 의미합니다. 이런 상황에는 alert notification 시스템을 이용해서 당장 On-Call 엔지니어를 깨워서 대응하도록 해야 합니다. 아래는 critical alert의 예시입니다.

Critical (자다가 일어나야 한다.)
  • Fail-over가 일어난 경우
  • Database에 접속이 안되는 경우
  • Database 컨넥션이 일정 값 이하로 떨어진 경우
  • 특정 클러스터의 노드 중 AWS 특정 region (us-east-1a)에 위치한 노드가 3대 이상 문제가 발생해서 시스템 안정성에 문제가 발생한 경우

여기서 “아침에 일어나서 처리해도 되는가?”라는 질문에 ‘네’ 또는 ‘어느 정도는’이라고 답할 수 있는 이슈라면 Critical이 아닌 겁니다.  최대 8시간 정도 경과되더라도 시스템 운영에 큰 영향을 미치지 않는다라고 생각한다면 Severe로 변경했습니다. 엔지니어링팀의 근무 환경과 효율이 가장 중요하기 때문에 특정 시스템의 클러스터에 자꾸 문제가 발생하거나 바로 해결이 어려운 경우는 클러스터의 노드 수를 늘림으로써 critical alert을 severe alert으로 변경시켜 버리는 것도 하나의 방법입니다. 쉽게 말해 당분간 돈으로 해결하는거죠. 😉

Severe (아침에 일어나서 처리하면 된다. 하지만 꼭 처리해야 한다.)
  • Cluster의 일부 node가 죽었지만 QoS에 큰 영향은 없는 경우
  • CPU 사용률이 threshold를 넘은 경우
  • 특정 job이 죽어서 queue에 들어갔는데 복구에 실패했다.

그리고 그외 나머지는 ‘기타’ 버킷에 넣었습니다. 이 바구니에 담긴 이슈들은 On-Call 담당자가 아닌, 해당 시스템의 엔지니어가 확인하고 처리합니다.

기타 (아몰랑)
  • 특정 job이 죽었는데 queue에 들어가서 다시 처리했다.
  • 나.머.지.

저희도 처음에는 이런 분류를 하지 못해서 많이 애를 먹었지만 정리하고 보니 아주 간단한 질문에 대답하기만 하면 된다는 걸 깨달았습니다.

 

계란을 한바구니에 담지 말라

Alert를 잘 분류했더라도 모든 alert, warning들을 하나의 이메일 (예. engineering@abc.com)로 보내면 당연히 낮은 수준의 이메일들이 월등히 많기 때문에 이메일을 확인하는 데 있어 피로도가 증가하고 결국에는 둔감해지면서 무시하게 됩니다. 제목에 [Critical]로 표시하고 레이블로 빨간색을 달아봐야 소용 없습니다. 이메일 더미 속에 critical alert이 포함되어 있고 빨리 발견하고 대응하지 못한다면 시스템 장애는 심각한 수준으로 커질 수 있습니다. 어떤 경우에는 엔지니어링팀의 어느 누구도  이메일 확인을 하지 않아 장애 발생을 모르고 지나가는 일도 벌어질 수 있습니다.

따라서 alert 종류에 따라 다른 바구니 (notification 방법)를 사용하는 것이 좋습니다. 예를 들어 critical은 별도의 alert 알림 시스템을 사용하고, severe는 severe-alerts@abc.com로, 나머지는 warning-alerts@abc.com으로 보냅니다. 그런 다음 On-Call 엔지니어가 critical과 severe를 책임지고 처리하도록 하면 책임과 역할이 명확해 집니다. AWS CloudWatch의 경우 알람에 따라 어떤 것은 critical로 분류되어 있고 어떤 것은 severe로 분류되어 있습니다. 즉 특정 모니터링 툴에서 발생하는 alert들이 모두 동일한 수준이 될 필요는 없습니다.

이렇게 다른 바구니를 사용하면 alert 알림 시스템을 통해 전달된 alert는 자다가도 일어나서 처리해야 할 일이고 severe-alerts@abc.com으로 들어온 이메일은 업무 시간 중에 1순위로 처리해야 할 일 등으로 자연스럽게 인식되기 때문에 바구니 종류만으로도 업무 순서가 쉽게 파악이 됩니다.

 

내 너를 깨우리라.

Nudge는 critical alerts를 관리하기 위해 OpsGenie라는 alert 알림 시스템을 사용하고 있습니다. 예를 들어 critical alert이 발생하면 OpsGenie 시스템이 On-Call 엔지니어에게 스마트폰 푸시 알림, 이메일을 동시에 보내고 3분 안에 해당 엔지니어가 반응 (acknowledge)이 없으면 SMS를 보내고 1분 후에는 전화를 겁니다. 그래도 반응이 없으면 1분 후에 다음 스케쥴에 있는 On-Call에게 SMS를 보내고 전화를 겁니다. 즉 On-Call 엔지니어가 잠에서 깨지 않으면 5분 후에 다른 엔지니어를 깨우는 겁니다.On-Call 엔지니어는 민폐를 끼치지 않으려면 반드시 일어나야 합니다. -_- Policy 설정을 통해 알림의 순서와 시간 간격 등을 원하는대로 설정할 수 있습니다.

저희는 모든 critical alerts를 OpsGenie로 보내고 OpsGenie에 설정된 규칙에 따라 On-Call 엔지니어에게 알림을 보내도록 설정했습니다.  OpsGenie에서 제공하는 integration을 이용해서 AWS CloudWatch (CloudWatch에 설정된 critical alerts), email (어플리케이션 서버 또는 워커가 프로세싱 중 심각한 문제가 생긴 경우 발송하는 이메일), heartbeat (모든 시스템을 모니터링하는 observer 인스턴스에서 1분마다 각 시스템으로 보내는 테스트 스크립트 – i.e. ping, health check, db read/write test, etc – 의 결과) 등을 OpsGenie로 보내고 있습니다.

유사한 서비스로는 VictorOpsPagerDuty 등이 있으며 저희는 OpsGenie가 상대적으로 가격이 저렴하고 heartbeat+라는 기능을 제공해서 선택했습니다.

 

On-Call 스케쥴

On-Call 스케쥴은 팀의 구성인원에 따라 상황에 맞게 짜면 됩니다. 절대적 균등 배분보다는 서로의 상황을 이해하고 배려하는 것이 중요합니다. 누군가가 휴가를 갈 수도 있고 주말에는 시간이 안될 수도 있어서 가끔씩 일정을 조정한곤 합니다. 저희는 현재  3명의 엔지니어가 12시간마다 로테이션하고 있습니다.

 

Zombie-Proof

새벽 3시에 alert이 울려서 일어났는데 머리는 찌끈거리고 아무런 생각도 떠오르지 않는, 그런 날이 있습니다. 정말 좀비가 되면 이런 느낌이 아닐까 싶은 생각이 드는데 긴급 상황이니 일은 처리해야겠고 미칠 것 같습니다. 그러다 보면 실수를 하거나 잘못된 판단을 할 확률이 높아집니다. 특히 자기가 만든 시스템이 아닌 경우에는 위험성이 더 커집니다. 이런 상황을 개인의 책임으로 돌리거나 개개인의 능력으로 알아서 극복하도록 하는 것보다는 시스템적으로 해결하는 것이 낫습니다. 즉 해당 시스템에 대해 잘 모르더라도 기본적인 응급 처치를 할 수 있는 방법이 잘 정리되어 있다면 좀비도 따라 할 수 있겠죠?

따라서 Alert 발생시 대응 매뉴얼을 만들어야 합니다. 간략하게는 DevOps 대쉬보드 같은 문서 (또는 웹페이지)를 만들어서 필요한 정보를 한 곳에서 쉽게 확인할 수 있게 합니다. 접속해야 할 시스템의 IP, 로그를 보기 위해 입력해야 하는 명령어 등 반복적으로 사용하고 잘 변경되지 않는 정보라면 문서에 기록해 두는 것이 좋습니다. ‘잠깐만 찾아보면 되잖아’와 같은 의견은 깔끔하게 무시하고 무조건 기록해 둡시다. 긴급 상황에서 마음이 급해지면 평소에 쉽게 하던 일도 하기 어렵습니다. 추가적으로 각 시스템별 장애 유형과 해결책 등을 정리한 문서를 링크 걸어 두면 해당 내용을 따라하기만 해도 응급 처치를 할 수 있습니다. 약간의 노력과 준비가 있으면 엔지니어링팀의 누구나 On-Call 담당자가 될 수 있습니다.

Screen Shot 2016-03-28 at 5.28.33 PM

<구글독을 이용한 DevOps Dashboard 샘플>

 

On-Call 로그를 남겨라

Alert이 발생하면 반드시 On-Call 로그를 남겨서 기록해야 합니다. On-Call 로그 문서를 열고 양식에 따라 빈칸을 채우기만 하면 됩니다. 양식 아래에는 관련 로그 및 이미지 등을 첨부합니다. 다음 DevOps 미팅 (alert 발생한 날 또는 그 다음 날)에서 해당 케이스를 리뷰하고 개선하는 작업을 진행합니다. 저희는 월 단위로 구글독 문서를 생성하여 작성하고 있습니다.

Screen Shot 2016-03-28 at 4.26.52 PM

<구글독을 이용한 On-Call 로그 샘플>

 

이제 편안하게 자고 있어요

Alert 관리 정책을 수립하고 On-Call 시스템을 구축함으로서 여러가지 긍정적인 효과를 체감하고 있습니다.

  • 긴박한 alert를 놓치는 일이 없어져서 시스템 이슈에 대한 빠른 대응이 가능해졌다.
  • 마음 편하게 잘 수 있다. 문제가 생기면 깨워 줄 테니
  • 시스템 장애에 대한 스트레스 레벨이 낮아졌다. 매뉴얼에 따라 처리하면 된다는 믿음
  • 매뉴얼이 보다 자세해졌다.
  • 시간이 지나면서 모니터링이 더 타이트해 졌고 그 결과로 시스템 안정성이 개선되었다.
  • 엔지니어링팀 모두의 시스템 전반에 대한 이해도가 증가했다.
  • 한명의 엔지니어에게 일이 집중되는 현상이 사라졌다.

 

소회

시스템 장애는 일어나기 마련이니 alert이 발생하면 신속하게 대응해서 처리할 수 있다는 믿음을 가지는게 가장 중요한 일이라고 생각됩니다. 우리는 준비가 잘 되어 있다는 믿음, 내가 하지 못하면 내 동료가 도와줄 것이라는 신뢰 등을 바탕으로 마음의 평화를 찾아야 합니다. 스타트업은 단기전이 아니니까요.

막상 정리해서 쓰고 보니 간단해 보이는데 저희는 몇년이 걸려서 시행착오 끝에 배운 내용입니다. 짧게 쓰려다 보니 줄인 내용이 많아서 언제 한번 오프라인 세션을 통해서 공유를 해도 좋겠네요. 그리고 여러분께서 사용하고 있는 좋은 방법이 있다면 공유 부탁 드려요. 🙂

그리고 가장 중요한 것! 클라우드 상에서 24/7 무중단 비정형 데이터 시스템을 구현하고 운영하는 일에 관심이 있는 엔지니어라면 저희가 동료를 찾고 있으니 지금 바로 지원해 주세요. 고맙습니다.

Nov 192013
 

안녕하세요.

저희 AD fresca 팀은 지난 주 SK Planet에서 주최한 Tech Planet 2013에 참가하여 부스를 마련하였습니다. 이번 행사를 통해 많은 개발자 분들과 만나 저희 시스템을 소개해 드렸고 더불어 즐거운 대화를 나눌 수 있었습니다. (부스에 참여할 수 있도록 배려해 주신 SK Planet과 지디넷 코리아에 감사의 말씀을 드립니다.)

tech planet booth

 

이 글에서는 저희가 현재 사용하고 있는 시스템의 구조에 대해서 이야기해 보려고 합니다. (2013년 10월말 기준으로 월 6억건의 API call을 실시간으로 처리하고 있습니다.)

Tech Planet 2013 Booth slides.002

저희 서비스는 모바일 앱에 설치된 SDK를 이용하여 사용자 데이터를 수집하고 그에 따른 사용자 프로화일에 맞는 마케팅 캠페인을 실시간으로 매칭하고 분석하는 서비스입니다. 위 그림에서는 저희 서비스가 어떠한 과정을 통해 작동하는지를 설명하고 있습니다.

SDK Data Collection

저희 SDK는 모바일 앱에 설치되어 사용자 데이터를 수집하고 서버에 전송합니다. iOS, Android, Unity 등 다양한 플랫폼을 지원하며 손쉽게 적용이 가능합니다. 기본적으로 SDK가 수집하는 디바이스의 기본 정보 (예: 고유아이디,  사용언어, 앱 버전 등) 외에도 앱마다 설정할 수 있는 각종 커스텀 파라미터 (예: 레벨, 스테이지, 스코어 등)와 마케팅 이벤트 (예: 레벨업,  아이템 구매, 스토어페이지 방문 등) 등을 정의하여 데이터 분석 및 마케팅 캠페인 매칭에 이용하게 됩니다. 이와 더불어 사용자에게 전달된 메시지에 대한 사용자의 반응 (예: 배너 클릭, 앱 설치, 푸시 메시지 클릭 등)을 기록하여 서버에 전송합니다.

Data Processing

SDK를 통해 전송되는 데이터를 실시간으로 수집하고 분석하여 통계 데이터와 메타데이터를 생성합니다. 이를 바탕으로 해당 사용자의 프로화일에 맞는 캠페인을 실시간으로 매칭 (targeting)합니다. 또한 사용자의 캠페인 반응 데이터 또한 실시간으로 처리하여 통계 서비스를 제공합니다.

SDK Messaging

매칭된 마케팅 캠페인의 컨텐츠를 사용자에게 표시합니다. 저희 서비스는 앱 실행 중에 메시지를 전달하는 인-앱 메시징과 앱을 사용하지 않고 있을 때 메시지를 전달하는 푸쉬 메시징 등을 제공합니다. 인-앱 메시징에서는 interstrial 형태의 이미지, 텍스트 공지사항, iFrame, 그리고 직접 사이즈 설정이 가능한 커스텀 배너 등의 형태로 메시지 전달이 가능하며 푸쉬 메시징에서는 APNS (Apple Push Notification Service), GCM (Google Cloud Messaging) 등을 통해 텍스트 형태의 푸쉬 메시지를 전달할 수 있습니다. 모든 메시지는 여러 개의 언어로 생성이 가능하며 단말의 주언어 설정에 따라 사용자별로 맞는 언어로 메시지가 전송됩니다. (예. 일본어 사용자에게는 일본어 메시지가, 한국어 사용자에게는 한국어 메시지가 자동으로 전달됩니다.)

User Behaviour (Response)

타겟팅된 사용자가 자신에게 전달된 메시지에 반응해서 앱을 더 많이, 더 오래 사용하도록 하는 것이 저희 시스템의 목적입니다. 마케터가 의도하는 긍정적인 방향으로 사용자들의 행동 변화를 일으키도록 하는 것이 바로 Engagement 서비스의 목표입니다. (예. 관심이 떨어진 사용자가 다시 앱을 사용하도록, 한번도 아이템을 구입하지 않은 사용자가 아이템을 구매하도록)

 

Tech Planet 2013 Booth slides.003

저희 시스템은 아마존 웹 서비스 (AWS) 상에서 운영되고 있으며 전세계로부터 들어오는 트래픽을 처리하기 위하여 Cloud Front, Route 53, EC2 Auto Scaling 등 다양한 AWS의 기능들을 적극적으로 활용하고 있습니다. (저희 시스템에 AWS를 어떻게 활용하고 있는지에 대해서는 이후 포스트를 통해 공개할 예정입니다.)

우선 SDK에서 API 서버로 request를 보내면서 수집한 사용자 데이터를 전달합니다. API 서버에서 실시간으로 데이터를 처리, 저장하는 동시에 캠페인 매칭을 처리하고 적합한 캠페인이 존재하는 경우 해당 컨텐츠의 metadata를 SDK로 전송합니다. SDK는 전송 받은 metadata를 이용해서 CDN (Cloud Front)으로부터 컨텐츠를 내려받아 앱 사용자에게 표시합니다. 사용자가 화면에 표시된 메시지에 대해 반응을 보이면 SDK는 Tracking Server로 해당 데이터를 전달합니다.

각 서버가 데이터를 저장하는 과정에서 실시간으로 처리할 수 있는 데이터와 그렇지 못한 데이터를 구분합니다. 실시간 처리가 가능한 데이터는 바로 데이터베이스에 그렇지 못한 데이터는 Message Queue를 통해 Data Processing Server와 Worker 들에게 전달됩니다. 이후 해당 데이터들은 각 특성에 맞게 SQL DB, No SQL DB, Hadoop Cluster 등의 데이터베이스에 저장됩니다. (Big Query는 위 그림에 없으며 AWS가 아닌, Google Cloud 상의 서비스입니다.)

마케터는 웹브라우저를 통해서 직접 캠페인을 설계하고 수정하고 실행할 수 있으며 통계 데이터를 실시간으로 확인할 수 있습니다. Application Server는 각종 데이터베이스 및 캐시를 조회하여 마케터에게 원하는 정보를 실시간으로 표시합니다.

Tech Planet 2013 Booth slides.004

실시간 데이터 수집

SDK에서 올라오는 request 중 반드시 저장되어야 하는 트랜잭션 데이터는 MySQL에 저장하고 그 데이터를 기반으로 가공되는 데이터는 각 특성에 맞는 데이터베이스에 저장합니다. 장애상황을 대비하여 시스템 이중화, Message Queue 등을 운영하고 있습니다.

실시간 캠페인 매칭

최신의 데이터를 사용하여 사용자 프로화일에 맞는 캠페인을 실시간으로 매칭합니다. 다양한 캐시 및 NoSQL 데이터베이스를 이용하여 보다 빠른 캠페인 매칭이 가능하도록 구현되어 있습니다. 주어진 조건에 가장 최적화된 쿼리를 생성하기 위해 Dynamic Query Builder를 구현하여 사용하고 있으며 다차원 조건을 조회하기 위한 캐시를 생성하여 이용하기도 합니다.

실시간 통계

incremental counting이 필요한 데이터의 경우 Redis를 이용함으로써 Dashboard를 통해 실시간 통계를 제공합니다. 또한 통계를 위해 필요한 metadata를 캐싱해서 보관함으로써 실시간 통계를 제공할 수 있습니다. Redis 데이터의 정합성을 보장하기 위하여 주기적으로 배치 프로세스를 실행하여 정합성 검사 및 보정 작업을 진행합니다.

준-실시간 통계

실시간으로 분석을 제공할 필요가 없는 데이터들은 모두 주기적인 배치 프로세싱을 통해 처리하고 있습니다. MySQL 또는 Couchbase에 저장된 데이터를 이용하여 통계 데이터를 추출하고 있으며 Big Query를 이용하여 이벤트 로그 분석 시스템을 구현하였습니다. 이렇게 1차로 분석된 데이터를 바탕으로 2차 가공하기 위해, 또는 빠른 데이터 조회를 위해 No SQL 서버들을 이용하고 있습니다.

 

Tech Planet 2013 Booth slides.005

저희 시스템이 작은 양의 데이터를 처리한다면, 그리고 실시간으로 처리할 필요가 없다면 이렇게나 다양한 데이터베이스를 운영할 이유가 없습니다. 실제로 저희도 서비스 초기에는 MySQL과 memcached만으로 실시간 분석 및 매칭 서비스를 제공하는 것이 가능하였고, 운영 비용도 훨씬 적게 구축할 수 있었습니다. 하지만 월 6억 건의 이벤트 request를 처리하고 수천만 건의 사용자 프로화일 데이터를 처리해야 하는 상황에서는 다른 방법을 찾을 수 밖에 없었습니다. SDK의 request를 실시간으로 처리하기 위해 각 데이터 처리에 최적화된 데이터베이스들을 선택해야 했고 많은 검증 과정을 거쳐 그에 맞는 데이터베이스를 선정하여 실시간 데이터 프로세싱을 구현하게 되었습니다.

MySQL

저희 시스템의 가장 기본이 되는 데이터베이스로써 정적인 데이터 (앱, 캠페인, 콘텐츠 정보 등)를 저장하며 SDK의 request인 트랜잭션 로그를 저장하는 데 이용합니다. 반드시 저장 및 조회가 보장되어야 하는 데이터들에 한하여 MySQL을 이용하고 있습니다.

memcached

각 서버 간의 공유되어야 할 기본적인 캐시 데이터들을 저장합니다. 업데이트 빈도가 그리 높지 않은 데이터에 한하여 in-memory cache를 이용한 빠른 데이터 접근을 위해 사용합니다.

Redis

카운팅이 되어야 하는 모든 레코드를 저장하고 조회하는 데 이용합니다. 그 외에도 업데이트가 빈번히 일어나는 데이터는 Redis를 통해 캐시를 생성하여 이용합니다. 이밖에도 SortedSet 형태의 데이터를 효율적으로 저장, 업데이트하기 위해 redis를 이용하고 있습니다.

Couchbase

사용자 프로화일 및 조건별 세그먼트 저장을 위해 이용하며 주요 사용자 프로화일 분석이나 실시간 캠페인 매칭에도 이용하고 있습니다. 또한 별도의 1차 데이터 프로세싱의 결과값을 저장함으로써  2차적인 데이터 가공 및 빠른 조회가 가능합니다.

Big Query

수집되는 이벤트 로그를 통해 준-실시간 배치를 제공하기 위하여 사용합니다. 구글 클라우드 플랫폼을 활용하여 대용량 데이터를 편리하게 분석할 수 있습니다. 특정 주기마다 수집된 이벤트 로그를 등록하고 배치 프로세싱을 통해 데이터를 가공하여 그 결과를 다른 데이터베이스에 저장합니다.

이 글에서는 데이터의 특성을 기준으로 저희가 사용 중인 데이터베이스들을 정리하였지만, 데이터의 특성 이외에도 데이터가 어떠한 형태로 해당 서버에 저장되는지, 얼마나 최적화된 쿼리를 이용하는지 등 다른 많은 요소들이 데이터베이스의 성능에 크고 작은 영향을 끼치고 있습니다. 이러한 점들을 잘 고려하여 알맞은 데이터베이스를 선택하여 이용하는 것이 중요합니다. 그 과정에서 데이터를 다른 서버로, 다른 데이터베이스로 옮기는 마이그레이션 작업이 빈번하게 일어납니다. 그 날은 Sleepless in Seoul이 되겠죠.

 

마치며…

최근 국내외에서 데이터 처리 기반의 서비스들이 다수 나오면서 여러 팀들이 자신들의 경험을 공유해 주셨습니다. 저희도 이러한 포스팅들을 통해 많이 배워 가고 있으며 작지만 저희들의 경험과 생각도 함께 공유하고자 이 글을 쓰게 되었습니다. 아무쪼록 다른 분들에게도 도움이 되었으면 합니다.

어떤 시스템의 구조가 다른 목적을 가진 서비스에 100% 적합할 수는 없다고 생각합니다. 자신들이 만들고 있는 Product를 완벽히 이해하고 그에 가장 적합한 구조를 설계하고 구현해 나가는 것이 정답이 아닐까 합니다.

그런 의미에서 저희 팀은 다양한 시각에서 Product에 대해 고민하고 그에 맞는 시스템을 구축하기 위해 노력하고 있습니다. 최근 저희 트래픽이 급증하는 추세를 보이면서 이러한 고민도 점점 늘어나고 있는데요, 함께 고민하고 함께 문제를 해결해 나갈 엔지니어분들을 찾고 있으니 많은 관심을 부탁드립니다.

 Posted by at 5:30 PM
Nov 102013
 

최근에 지인분께서 저희 구인공고 포스팅을 공유해 주셨는데 그 글에 이런 코멘트가 달렸습니다.

Screen_Shot_2013-11-10_at_8.00.47_PM

 

 

코멘트하신 분 입장에서는 아마도 의아하셨을 것 같습니다.  Rails?? Backend??

다른 분들도 비슷한 의문을 가지실 것 같아서 그런 선택을 한 이유에 대해  적어 보려고 합니다.

 

웹서비스를 만드는 데 최적화된 Rails

잘 아시겠지만 스타트업은 6개월 이후를 보고 엔지니어링을 할 수 없습니다. (대개는 그렇습니다.) 우리가 지금 만드는 것이 내일도 가치가 있을지 확신이 없습니다. (있다면 그건 검증되지 않은 자기 확신이겠지요.) 그 가치는 고객의 판단에 의해 인정되고 그런 다음에야 우리는 그 다음 가치를 구현해 나갈 수 있습니다. 그래서 빠르게 구현하고 검증을 받는 것이 가장 중요한 일입니다. 그게 Lean Startup이 일을 하는 방법입니다.

저희는 3년 전 가장 빠른 웹서비스 구현을 위해 Ruby on Rails를 선택했습니다. 덕분에 빠르게 프로토타잎을 만들 수 있었고 중간에 Pivot 또한 빠르게 할 수 있었습니다. 1) RESTful 서비스로 모바일 SDK와 통신을 하고 2) Dashboard가 서비스 가치의 핵심 중 하나인 저희 서비스에서는 올바른 선택이었다고 생각합니다.

언젠가 저희도 Javascript 기반의 Front-end로 넘어간다면 Rails의 가치가 급격히 떨어지겠죠? 그렇게 만들어 주실 Front-end Engineer를 구하고 있습니다.

 

Rails의 성능과 한계

twitter는 Rails로 구현된 전세계에서 가장 큰 서비스였습니다. 그들도 처음 (2006년)에 Rails로 서비스를 시작해서 상당히 오랜 기간 동안 그 첫 선택을 유지해 왔습니다. 그러다 2010년부터 Scala로의 이전을 시작으로 2011년  Java로 이전 등을 통해 점진적으로 이전해 갔습니다. 2011년 3월 11일, 하루에 1.7억개의 트윗이 포스팅될 때에도 서비스의 상당부분은 Rails였습니다. InfoQ의 기사를 읽어 보시면 그들이 어떤 도전을 겪었고 왜 Rails에서 다른 언어, 프레임워크로 이전했는지를 확인하실 수 있습니다.

저희 AD fresca가 twitter가 겪었던 그 변화의 시점에 도달한 것 같지는 않습니다. 그렇다면 저희가 US$10M 펀딩을 받았겠죠?!?! 🙂

twitter가 그랬듯이 저희도 언젠가는 Scala로 넘어가고 언어도 Java로 변경해야만 하는 시기가 올 거라고 생각합니다. 하지만 현재 (한달에 6억개의 API call을 처리하는 지금은)로서는 많은 개발 자원을 투자해야 하는, 더 효율적인 언어/프레임워크 등으로의 이전하기보다는 클라우드 상에서 인스턴스 몇 대를 더 사는 게 더 저렴한 선택이라고 생각합니다. Again, 역시 저희 시스템을 새롭게 바꿔 주실 Back-end Engineer도 구하고 있습니다.

 

하나의 ORM

저희 시스템의 기술적, 비즈니스적 요구사항 중 하나가 ‘1) 데이터 모델을 지속적으로 빠르게 변경해야 하고 2)  하나의 데이터 모델을 여러개의 서로 다른 어플리케이션 서버 (다양한 API 서버, Dashboard, workers 등)에서 사용할 수 있어야 한다‘입니다. 즉 2개 이상의 ORM을 이용해서 데이터 모델을 관리하는 것은 저희 팀이 감당할 수 있는 수준을 넘어섭니다. (최소한 저희 크기의 조직에서는 그렇습니다.) 저희도 초기에 twitter가 Scala로 이전하는 것을 보고 고민을 많이 하다가 하나의 ORM이 훨씬 효율적이라고 판단해서 프로젝트를 드랍했던 적이 있습니다.

하나의 데이터 모델을 여러 어플리케이션에서 사용하기 위해서 저희는 데이터 모델에 대부분의 코딩을 하고 독립된 리파지토리에 별도로 저장, 관리합니다. 그리고 그 리파지토리를 git의 submodule 기능을 이용하여 모든 어플리케이션에서 공용으로 사용하고 있습니다.

 

Rails Forever!

저희는 빠르게 프로토타이핑을 하고 빠르게 서비스를 만드는 데 Ruby on Rails만한 언어-프레임워크 조합도 없다고 생각합니다. 아직은요. 물론 영원한 것은 아무 것도 없으니 Forever는 아닙니다. Rails, we still love you though. 😉

저희가 빨리 성장해서 멋진 기술을 써서 여러분들로부터 환호(!)를 받을 수 있는 날이 오기를 기대합니다.

 

Update: 알고보니 원래 코멘트를 해 주신 분께서는 한국에서 Backend와 Rails를 잘 아는 사람은 구하기 어렵겠다라는 의미로 하신 말씀이었다고 합니다. 저는 Rails 콤플렉스가 있나 봅니다. 흑흑흑. 🙂

Jul 292012
 

안녕하세요. 저는 AD fresca 팀에서 개발을 총괄하고 있는 강선구입니다.

최근 AD fresca의 SDK 업데이트가 있었는데요. 업데이트 내용과 관련하여 그동안의 에피소드를 잠깐 소개하려 합니다.

AD fresca는 초기부터 글로벌 서비스를 목적으로 설계 및 개발되고 있습니다. 그래서 글로벌 서비스 대응이 가능한 Amazon Web Service를 주로 사용하고 있는데요. 메인 서버는 미국에 있고 Amazon CloudFront를 통해 전세계 40여 개의 CDN Edge 서버를 이용합니다. 현재 이미 AD fresca의 광고 노출 국가가 100개국을 넘은 상태이고 앞으로도 계속 증가될 것으로 예상합니다. (글로벌하게 잘나가시는 저희 고객님들 덕분에 해외 트래픽 비중이 꽤 높은 편입니다!)

이런 상황 속에서….

서버 인프라 측면에서 많은 고민과 노력을 기울이고 있지만 아무래도 모든 국가에서 만족할만한 반응속도를 내는 게 쉽지는 않습니다. 특히나 불안정한 모바일 3G 네트워크을 통해 접속하는 경우가 많다 보니 더욱 힘든 게 사실입니다. 그래서 저희 개발팀에서는 1차적인 답으로 좀 더 부지런한 SDK를 만들어 보기로 했습니다. 🙂

최신 버전의 AD fresca SDK는 사용자에게 광고 노출 시 캐쉬를 이용해서 다음에 사용될 광고 데이터를 미리 더 받아옵니다. 그리고 이후 광고 노출 시 캐슁된 광고 데이터를 통해 빠르게 광고를 노출합니다. 물론 캐슁된 광고일지라도 별도의 Validation 절차를 거쳐서 저희 서비스의 강점인 Real-time Control을 보장해 드리고 있습니다. (절대로 불필요한 광고가 노출되지 않습니다!) 또한 SDK는 사용자 디바이스의 로컬 저장소를 캐쉬로 이용하지 않기 때문에 앱 사용자들에게는 아무런 영향이 없습니다.

저희 개발팀은 이렇게 계속해서 좀 더 부지런하고, 좀 더 똑똑해진 SDK를 만들어 나갈 예정입니다.

SDK가 부지런해 진다고 하더라도 저희가 반드시 지킬 약속들이 있습니다.

  1. 앱 사용자의 UX에 영향을 주지 않도록 하겠습니다. SDK를 탑재한 앱을 사용하시는 사용자분들도 저희의 소중한 고객입니다.
  2. 앱 퍼포먼스에 영향을 주지 않도록 하겠습니다. (항상 유의하고 있습니다.)
  3. 누구나 쉽게 적용하도록 만들겠습니다. (개발자 여러분을 귀찮게 해 드리지 않아요!)

앞으로도 저희 팀은 좋은 서비스를 뒷받침할 수 있도록 보다 좋은 SDK, 좋은 Back-end 서비스를 제공해 드리기 위해 항상 노력하겠습니다.

또한, 저희와 함께 글로벌 서비스를 경험하고 만들어나갈 엔지니어분들을 항상 모시고 있으니 언제라도 연락 주세요.

많은 관심 부탁 드립니다 ^^

 Posted by at 7:34 PM
Jul 252012
 

안녕하세요

오늘 SW 마에스트로 3기 멘티들을 대상으로 강의를 하고 왔습니다.

Software Startup을 경영하면서 엔지니어들이 흔히 잘못 생각하는 선택들에 대한 이야기를 모아봤습니다.


좋은 하루 되세요. 🙂

 

 Posted by at 11:25 AM