A/B 테스트 간단하게 구현해보기

ABTest

이 글은 2024-03-14에 작성되었어요.

프롤로그


여러분은 A/B 테스트에 대해 알고 계시는가요? 사실 이미 비즈니스적으로 엄청 유명한 내용이기에 많은 분들이 알고 계실 것 같아요. 그럼에도 혹시 A/B 테스트가 무엇인지 잘 모르시는 분들을 위해서 간략하게 설명드리고 시작할게요.

A/B 테스트란 어느 서비스 사용자의 집단을 나누고, 집단마다 서로 다른 기능 또는 화면을 제공한 다음 어떤 집단이 높은 성과를 보이는지 테스트하는 작업

A/B 테스트는 아마존이나 쿠팡과 같은 기업에서도 이용하는 만큼 가설을 잘 세운다면 몰랐던 인사이트를 얻을 수도 있어요.

그렇다면 어떻게 가설을 세우는지도 궁금하실 테지만, 안타깝게도 이 글에서는 A/B 테스트가 왜 사용되는지, 가설은 어떻게 세우는지 등에 대한 내용을 다루지는 않을 예정이에요. 그래도 혹시나 궁금하신 분은 글 하단에 정보를 얻을 수 있는 링크를 제공할 테니 확인해 보시면 좋겠습니다.

필자는 이 글에서 A/B 테스트를 코드로 구현한다면 어떻게 간단하게 구현할 수 있을지 말씀드리려고 합니다. 구현 조건은 아래 세 조건을 고려하겠습니다.

  1. A, B 두 개의 집단만이 아닌 N 개의 집단을 넘나들며 테스트를 할 수 있도록 한다.
  2. 집단마다 비율을 유연하게 조절할 수 있도록 한다.
  3. 사용자는 ‘랜덤’한 집단에 배정받지만 언제 어디서나 같은 ‘랜덤’이어야 한다. (* pseudo-random)

유저 식별자


A/B 테스트를 구현하기 전에 가장 중요한 점은 ‘유저 식별자(Unique Key)’를 어떻게 정할 것인가’입니다. 유저 식별자는 중복이 없는 유일한 값이어야 합니다. 그러나 상황에 따라 유저를 정확하게 식별하는 것은 쉽지 않습니다.

왜냐하면 도메인에 따라 비로그인 상태로 서비스를 사용하는 경우가 있는데, 이 ‘비로그인’ 상태를 추적하는 것이 쉽지 않기 때문입니다. 심지어는 비로그인이면서 여러 기기를 사용한다면 더 추적하기가 힘들어집니다.

비로그인 상태에서도 추적해야 한다면 제가 아는 한 100% 유저를 식별하기는 어렵습니다. 그렇다면 ‘최대한’ 유저를 식별하기 위한 방법이 필요하겠네요. 물론 로그인 상태에서만 이용할 수 있는 서비스라면 식별하기가 쉽겠지만요.

일반적으로는 웹 또는 앱에서 다음과 같은 방법을 권장합니다.

  • 웹 또는 PC 환경에서는 Persistent Cookie(PCID)를 이용한다.
  • 앱에서는 앱 자체에서 생성되는 고윳값인 UUID 또는 모바일 운영체제가 만든 광고 ID인 ADID를 이용한다.

랜덤한 값을 알아내는 것은 알겠는데, 결국 어떤 알고리즘을 통해 사용자들의 집단을 나눌 수 있을까요?

랜덤한 값에 나머지를 연산하여 N 번 슬롯을 갖게 하고 필요한 만큼 나누어 집단을 형성하면 됩니다. 이해를 돕기 위해 아래 이미지를 가지고 왔습니다. 비로그인 상태에서도 추적해야 한다면 회원 번호를 랜덤한 값으로 사용한다고 생각하시면 됩니다.

Untitled.png

자바스크립트로 구현하기


필자는 자바스크립트 기반에서 기능을 구현하였고, 비로그인 상태도 추적할 수 있어야 했기에 자바스크립트의 내장 메소드인 crypto를 사용했습니다. crypto의 randomUUID 메소드를 통해 확실한 랜덤 UUID를 갖게 하고 이를 16진수로 변경한 뒤 나머지 값을 연산해 각 슬롯을 배정했습니다.

function getRandomHash() { return crypto.randomUUID() } function getRemainingNumberOfHash(hash, divisionNumber) { return (parseInt(hash, 16) % divisionNumber) + 1 }

‘Math.random으로 처음부터 1~N의 난수를 얻으면 되지 않냐?’ 하실 수 있는데, 앞서 말한 2번 조건인 ‘집단마다 비율을 유연하게 조절할 수 있도록 한다.’를 고려해야 합니다. 단순한 예시로 더 섬세하게 분포를 나누고 싶어 N의 범위를 늘려야 한다면, 기존 N까지 할당된 유저와 동일하게 비율을 유지할 수 없습니다.

발생할 수 있는 상황별 가이드라인


랜덤한 슬롯을 할당하는 것은 생각보다 쉽게 완성했습니다. 그러면 이제 해당 슬롯을 기반으로 집단을 나눠봅시다.

해당 가이드라인은 아래 레퍼런스로 등록된 ‘Hackle’에서 제공하는 가이드라인을 참고해 정리했습니다.

  1. 로그인 하지 않은 사용자의 경우
    1. UUID를 이용해 무작위 할당
  2. 로그인하지 않은 사용자가 활동하다 로그인하는 경우 (첫 로그인)
    1. UUID를 이용해 무작위 할당 한 값을 로그인 이후에도 그대로 할당 → 유저 데이터베이스에 저장
  3. 로그인 사용자가 여러 기기를 사용하는 경우
    1. 유저 데이터베이스에 저장된 UUID 값을 우선으로 할당
  4. 하나의 기기를 여러 사용자가 사용하는 경우
    1. 로그인 유저가 가진 UUID 값을 로그아웃 시에도 유지
    2. 새로운 유저로 로그인 시 해당 유저 UUID 값으로 변경, 로그아웃 시 유지
  5. 한 명의 사용자가 기기를 변경하고 로그인하는 경우
    1. 로그인 유저가 가진 UUID로 할당
    2. 다른 기기, 로그아웃 상태일 시 새로운 UUID 값으로 랜덤 할당
    3. 위 기기에서 로그인 시 로그인 유저가 가진 UUID로 재할당

만약, 비로그인을 고려하지 않아도 된다면 유저의 유니크 값으로 랜덤할당하는 경우만 고려하면 됩니다.

이후, 유저의 행동을 트래킹하는 것은 여러분이 원하는 방식으로 시도하시면 됩니다.

마무리


사내에서 A/B 테스트를 도입 후 매우 근소한 차이를 유지하며 분포가 잘 되었습니다. 또한 서비스에 정말 필요한 기능인지 아닌지를 구분하는 게 정말 쉬워졌습니다. 빠른 경우에는 일주일만으로도 결과에 대한 충분한 통계가 잡히기도 하더라고요. 혹시나 A/B 테스트를 도입하려는 분들에게 도움이 되었으면 좋겠습니다.

읽어주셔서 감사합니다.

Reference.


👉🏻 ab 테스트란? 비즈니스 사례를 통해 알아보는 ab 테스트

👉🏻 Pseudo-random

👉🏻 핵클 통합 식별자