그동안 회사에서 진행했던 이벤트 로그 설계 과정과 운영하면서 생긴 문제점을 개선하는 과정에 대해 정리하는 글이다.
이벤트 로그란?
이벤트 로그란 시스템이나 애플리케이션이 실행되는 동안 발생하는 다양한 이벤트를 기록하여 문제 해결, 운영 모니터링, 데이터 기반 의사결정에 활용하는 데이터를 의미한다.
시스템 로그 | 유저 이벤트 로그 |
• 주로 인프라와 서버 상태 기록
• 개발자나 운영자가 문제 발생시 이슈 파악하고 대응하도록 도움
• CPU, 메모리, 네트워크 등 상태 모니터링 & 디버깅
• ex) Datadog 같은 툴 | • 서비스 사용자 활동을 추적해 주요 지표 도출
• 서비스의 성과와 사용자의 행동 패턴을 분석하는데 사용
• 데이터 기반 의사결정 내리는데 활용 |
Firebase-BigQuery 기반 로그 수집
기존 시스템에 일부 이벤트 로그가 존재했었지만, 신규 시스템에서는 새롭게 로그 수집이 필요한 상황이었다. 당시 레거시에도 프론트에서 Firebase를 이용해 로그 수집을 하고 있어, 추가적인 러닝커브나 리소스 투입없이 작업이 가능해 이를 그대로 이용하기로 했다.
Firebase를 통해 이벤트 로그를 정의하면 BigQuery와 연동해 데이터를 자동으로 저장해줄 수 있다. BigQuery에서는 이런 이벤트 로그의 스키마를 자동으로 관리해주고, 쿼리를 통해서 실시간으로 쌓이는 로그에 접근해 원하는 데이터를 추출할 수 있어 유용하다. 또한 파티셔닝 같이 BigQuery에서 제공하는 기본기능을 활용 할 수도 있다.
첫 번째 접근: 모든 로그 수집 시도
처음에는 어떤 데이터가 중요할지 모른다는 이유로, 모든 기능에 대해 가능한 모든 이벤트를 기록하려는 시도를 했다. 당시에는 PM이나 데이터 분석가 role이 따로 없었고, 기능의 운영 상황을 세부적으로 파악할 수 있는 기반도 부족했기 때문에, 그냥 데이터팀에서 일단 가능한 모든 이벤트를 정의하고 프론트엔드에 구현요청을 전달하는 방식을 택했다.
일단 무작정 쌓기: 모든 사용자의 클릭, 페이지 이동 등 사용자 인터페이스에서 발생하는 모든 이벤트를 기록. 특정 지표를 위한 로그 설계보다 “어떻게든 수집해두면 나중에 도움이 될 것”이라는 어쩌보며 안일한 접근이다..
한가지 예시를 가져와서 보자. 아래는 video 화면의 세팅에서 발생하는 모든 버튼을 정의해놓은 부분이다. 일단 모든 버튼에 다는 것이 목표였기 때문에 뎁스를 고려하지 않고 전부 넣었다. 만약 속도 조절을 빠르게 하는 경우 or 느리게 하는 경우의 강의를 비교하고 싶었다면 빠른 배속 버튼과 느린 배속 버튼 두개로 나눠 정의할 수도 있고, 그렇게 되면 앞단의 세팅 버튼이나 스피드 버튼같은 경우는 굳이 같이 넣지 않아도 될 수 있다.
회원가입 창의 예시를 한가지 더 보면, 상단에 로그인 버튼과 하단의 로그인 버튼은 사용성이 상당히 애매해 사실상 1, 2도 나눠가면서까지 굳이 달 필요가 없는 정보이다. 또한 학교 재학중 체크 버튼 같은 경우도 어차피 데이터베이스에 들어가는 재학중 여부의 값으로 이 버튼의 로그를 통해 얻을 수 있는 정보는 거의 없는데 굳이 달려있는 상황이다.
결과: 데이터를 많이 수집했지만 불필요한 정보가 과도하게 쌓여 용량만 차지하게 되었다. 약 일년간 서비스 운영을 경험해보니 이게 옳지 않은 방식이란 것을 알았다. 향후 개선될 가능성이 큰 기능이나 거의 사용되지 않는 기능에 대한 로그는 굳이 남길 필요가 없었고, 명확한 목표와 시나리오 없이 모든 이벤트를 기록하는 것은 효과적이지 않았다. 나중에 유저 한명에 대해 트래킹할 때도 쓸데없는 정보가 너무 많아서 오히려 복잡성이 증가했다.
두 번째 접근: 협업을 통한 목적 중심의 이벤트 로그 설계
첫 번째 접근에서 배운 교훈을 바탕으로 약 일년만에 로그 이벤트를 재정비할 기회가 생겼다. 이번에는 데이터팀만이 이벤트 정의 작업을 진행하는 것이 아닌, 각 팀원과 필요한 데이터만을 명확히 정의하여 수집하는 방향으로 개선하게 되었다. 새 기능이 추가될 때마다 PM, 기획, 프론트엔드 개발자 등 각 팀원과 논의하여 기능별로 필요한 지표와 로그 이벤트를 확정하고나서, 실제 개발된 기능이 배포될 때 동시에 수집이 시작될 수 있도록 했다.
트래킹 플랜 작성 및 문서화
기존에도 이벤트 정의 내용을 문서화하여 가지고 있었지만 데이터팀과 프론트팀만 이를 보고 작업하며 소통하는 용도로만 사용했다. 이번에는 트래킹 플랜이라는 템플릿을 적용해 모든 팀에서 접근하여 유지보수 할 수 있도록 만들었다.
트래킹 플랜이란 기능별로 어떤 이벤트를 기록해야 할지, 각 이벤트의 목적과 수집 방식, 저장되는 속성 등을 템플릿화하여 적어두는 문서이다. 정해진 템플릿이 있는게 아니고 각 회사마다 조금씩 다르게 운영하고 있어 여러 템플릿을 참고해 우리 회사에 맞게 조정해 사용중이다. 기본적으로 포함되는 정보의 예시는 다음과 같다.
•
문서에 대한 가이드나 규칙
•
이벤트가 사용되는 도메인, 스크린의 이름
•
이벤트의 이름, 트리거(버튼, 슬라이드 등), 설명
•
이벤트의 파라미터(or 프로퍼티)
◦
파라미터의 타입
◦
파라미터의 설명
•
플랫폼(ios, android 등)
•
수집 시작 및 종료 시점, 최종 업데이트 일자
•
기획/개발/QA/배포 유무 등
트래킹 플랜 문서화의 효과
이렇게 문서화를 통해 서비스 기능과 로깅 작업이 확정되고 나서 개발 단계부터 릴리즈 이후 QA까지 모든 과정에서 문서를 참조해 소통 할 수 있다. 데이터팀과 운영팀이 같이 문서를 관리함으로 책임과 관리 포인트가 분산되어 로그 관리가 원활해졌고, 보다 일관된 기준으로 데이터를 검토하고 활용할 수 있었다. 책임 분산이 나온 이유는 사실 기능 개발이 항상 주 포커스이지 로깅은 메인 작업이 아니기 때문에 모두가 놓치기 쉽기 때문이다. 특히 데이터팀이 모든 기능의 로그에 대해 매번 파악하고 있을 수 없기에, 이 트래킹 플랜을 모두에게 공유하고 사전에 로그 정의를 하는 프로세스를 만듦으로 이전보다 놓치지 않고 좀 더 잘 챙겨 작업을 하게 되었다.
빅쿼리에서의 활용
이렇게 정의한 이벤트는 Firebase를 통해 BigQuery에 자동으로 저장된다. 앞서 말한 것같이 스키마를 자동으로 관리해줘서 별도의 설정이 필요 없다. 기본적인 스키마는 정해져 있고, event_params 라는 RECORD 필드에 key와 value를 나눠 우리가 정의한 로그의 파라미터 값이 nested 구조로 저장된다. 이 nested 구조는 어떤 값이 들어올지 모를때 확장성 측면에서는 좋지만, 조회하는 입장에서는 UNNEST를 통해 flatten을 해야 하기 때문에 쿼리가 복잡해진다는 단점도 있다.
이후 특정 기능에 대한 데이터가 필요할 때 데이터팀이 BigQuery에서 쿼리를 통해 데이터를 추출하거나, 필요에 따라 ETL 파이프라인을 통해 리대시나 메타베이스에서 시각화된 대시보드로 제공하여 각 팀이 데이터를 확인할 수 있도록 운영중이다.
개선해야 할 점
현재 로그 시스템은 각 기능별로 수집은 되고 있으나, BigQuery 접근성과 쿼리 비용이 높아 모든 팀이 자유롭게 데이터에 접근하는 데는 한계가 있다. 매번 데이터팀에게 AD HOC한 쿼리나 ETL을 요청하는 것도 비용이 적지 않기 때문에, 이 데이터베이스의 사용자의 접근성 자체를 강화할 필요가 있다. 여러 솔루션을 비교해본 결과 Clickhouse라는 컬럼 지향 데이터베이스에 이벤트 로그를 옮기는 방향으로 진행할 예정이다. 이에 대한 자세한 이야기는 다음 포스팅에서..


