Sunku

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
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