구글 옵티마이즈 사용해 클라이언트 독립적 A/B테스트 구성하기

dante Yoon·2021년 10월 13일
1
post-thumbnail

안녕하세요, 단테입니다. 

오늘은 비단 개발자 뿐만 아닌, 마케터 및 기획자 분들도 관심을 가질만한 주제에 대해 글을 써보려고 합니다. 
A/B 테스트는 UX 라이팅, 버튼 배치, 페이지 전환 플로우등 제품을 개발하면서 마주하게 되는 여러 갈림길에서 A안이 B안보다 좋을 것이다라는 추측을 가설에서만 그치지 않고 검증까지 할 수 있게 도와주는 종합 대조 실험(controlled experiment) 방법입니다.

얼핏 A/B테스트라는 단어 자체만 보자면 A,B군을 잘 나누기만 하면 모든 일이 일사천리로 해결될 것 같지만, 작은 규모의 테스트라고 할지라도 유저에게 보여지기까지 정말 많은 단계의 세분화된 의사결정을 해야합니다.

가설 설계

제품이 주로 어떻게 사용자에게 소개되어지는지에 따라, 이 페이지의 최종 목표가 많은 유저에게 도달하는 것인지, 아니면 실제 서비스 구매까지 이어지는지에 따라 A,B의 후보가 크게 달라집니다.
서비스 홍보가 목표라면, 한 유저 세션당 얼마나 많은 페이지를 방문했는지, 또는 페이지 잔류 기간을 늘리는기 위한 가설들을 세워볼 것입니다. 실제로 제안해 볼만한 가설의 예를 들면 아래와 같습니다.

  A군: 스크롤 위치와 상관 없이 홍보페이지로 갈 수 있는 플로팅 버튼을 통해 홍보페이지 진입을 유도
  B군: 페이지 진입 시 스크롤 움직임을 감지하기 시작한 후 일정 범위를 넘으면 팝업을 띄워 홍보페이지 진입을 유도

반면 서비스 판매가 목표라면, 테스트 대상이 되는 가설들은 판매 유도를 더 잘하는 방법들이 후보군으로 자리잡게 될 것입니다.

  A군: 특정 행동을 한 유저에게 추천 상품 구매를 유도하는 배너를 띄움
  B군: 오후 6시 이후로 접속한 유저에게 식료품 관련 묶음 상품 구매를 유도하는 광고를 띄움

위의 가설들을 읽으며 나는 더 괜찮은 가설을 만들 수 있을 것 같은데? 라는 생각이 들지 않으신가요?
이런 가설 설정에는 정말 수 많은 아이디어가 후보군으로 자리잡을 수 있을 뿐 아니라, 해당 후보군들이 현재 설계하고자 하는 테스트의 의도와 부합하고 유효한 결과를 낼 수 있는지에 대해 많은 사람들의 의견을 수렴하고 검증해봐야 합니다.

이에 더해서, 새로운 아이디어들이 현재 사이트 설계상 구현 가능한지, 기존 사이트 정책 중 위반하는 것은 없는지 면밀하게 점검해 보아야 합니다.

테스트 환경 설계

여기까지 읽으신 분들은 팀 내에서 하나의 테스트를 설계하는데 있어, 많은 논의와 대화가 수반되어야 한다는 제 의견에 어느정도 공감하실 것 같습니다.

오랜 시간 동안 회의를 통해 의사결정을 거친 후 여러 후보들 중 A/B 군이 결정되었습니다. 이제 개발자가 작업해야할 차례입니다. 키보드에 손을 올리고 뚝딱뚝딱 만들어 내기만 하면 우리 모두가 행복한 미래를 그려나갈 수 있을까요? 불행하게도 그렇게 간단하지는 않습니다. 주어진 요구사항을 어떻게 구현할 수 있는지 고민해봐야 합니다.

먼저 두 테스트 그룹을 어떻게 나눌 것인가에 대한 문제가 있습니다. 랜덤으로 50:50으로 나눈다고 쉽게 생각해볼 수 있겠네요. 그럼 다음의 문제는 어떻게 해결해야 할까요?
나도 모르는 사이에 테스트에 참여하게 된 유저가 페이지를 리프레쉬를 하거나 다른 컴퓨터를 이용해 웹 사이트를 방문했을때 매번 다른 UI가 노출되면 많이 당황스럽지 않을까요? 어떻게 해야 이런 상황들을 미연에 방지할 수 있을까요?

보다 쉬운 방법으로 이 문제를 해결하기 위해서 여러분은 백엔드 서버의 도움을 받고자 합니다. 서버는 내부적인 로직으로 사이트에 접속하는 유저가 어떤 유저인지 데이터베이스를 통해서든, 이미 구축해둔 캐시서버를 통해서든 파악할 수 있는 정보가 있다면, 클라이언트에서는 이번에 접속한 유저가 어느 테스트 군에 속하는지 백엔드 서버에서 제공하는 API를 통해 해당 정보를 참조할 수 있는 것이지요.

위에서 말한 것과 같은 테스트 환경을 구축하기 위해서는 프론트엔드 개발자와 백엔드 개발자의 협업이 필요로 합니다. 각자가 로컬 환경에서 개발을 완료한 후 테스트 서버에 해당 작업을 배포해 서로 요구사항에 잘못 이해하고 잘못 구현한 부분은 없는지 확인하는 것입니다. 이런 소통은 일대일로만 이뤄지지 않습니다. 예상치 못한 클라이언트/서버 쪽 이슈로 프로젝트와 관련된 다른 동료에게 요청을 해야하는 경우도 생길 수 있습니다. 개발자가 하나의 업무만 맡은 것이 아니라면 서로의 작업이 완료될때까지 나의 작업은 블로킹 될 수도 있습니다. 이런 상황과 빈번하게 마주한다면 프로젝트 진행도는 정말 더디게 움직일 것입니다.

아, 이거 실제 쌓인 정보를 살펴보는 시간보다 하나의 테스트를 설계하는데 시간이 더 많이 드는데? 배보다 배꼽이 너무 큰데?

개발자가 아니더라도 완성된 가설들만 가지고 있다면 손쉽게 테스트 환경을 구축할 수 있고,
프론트엔드 개발자의 경우 테스트에 필요한 추가적인 API를 요청할 필요 없이 자체적으로 개발을 완료할 수 있게 도와주는 A/B테스트 솔루션이 있습니다.

구글 옵티마이즈 구조

구글 옵티마이즈는 A/B 테스트, 다변수 테스트, 리디렉션 테스트를 제공합니다. 구글의 다른 솔루션과도 기본적으로 통합되며 대표적으로 사이트 방문자 행동을 분석하는데 많이 사용하는 구글 애날리틱스와도 궁합이 잘 맞습니다. 구글 애날리틱스에서 미리 설정한 목표 설정을 그대로 옵티마이즈에 적용할 수도 있으며, 옵티마이즈를 통해 획득한 지표들을 내 계정에 연결되어있는 애널리틱스 보기 중 어느 보기와 연결할지에 대한 선택지도 제공합니다.

옵티마이즈는 다음과 같이 계정 - 컨테이너 - 테스트라는 이름들로 이뤄진 계층구조를 가지고 있습니다.

계정

옵티마이즈에 접속해 있는 내 아이디가 아니라, 독립적인 옵티마이즈 설정을 적용하여 사용할 수 있는 계정을 의미합니다.

하나의 계정에는 여러 컨테이너가 속해있습니다.
위 사진의 컨테이너 ID 를 보면 각 컨테이너에 고유 아이디가 부여되어 있는데, 이게 뭘까요? 다음에 알아보겠습니다.

현재 각 계정에는 Dante 유저만 접근 가능하지만, 다른 유저 에게도 특정 계정의 수정 및 조회 권한을 부여할 수 있습니다.

컨테이너

각 컨테이너를 누르면 테스트 목록이 담긴 페이지가 나옵니다.
각 테스트는 실행, 실험초안, 종료됨 세 가지의 상태를 가질 수 있습니다.

실행

현재 제품에 적용되어 돌아가고 있는 테스트입니다. 세션은 테스트 시작일로 부터 몇 명의 세션에 테스트가 적용되었는지를 나타내며, 활성 사용자는 현재 몇 명에게 테스트가 적용되었는지를 실시간으로 알려줍니다.
이미 배포된 테스트는 수정을 하지 않는 것을 옵티마이즈에서 권장하고 있습니다.

실험 초안

아직 배포가 되지 않은 테스트입니다. 사실상 실행, 실험 초안, 종료됨 세 개중 유일하게 테스트 환경을 수정할 수 있는 상태입니다.

종료됨

종료된 테스트입니다. 옵티마이즈는 최대 90일동안 테스트를 수행할 수 있습니다. 그 이전에 수동으로 테스트를 종료시키거나 유효기간이 지난 테스트는 종료됨 상태로 변경됩니다.

위 사진에서 테스트 환경 복사로 빨간색 화살표로 표시한 부분이 있습니다. 이미 종료된 테스트 중 동일한 테스트를 다시한번 돌려보거나, 비슷한 환경으로 테스트를 수행하기 원할때 기존 테스트를 복사할 수 있는데 생산성 향상에 도움을 주는 기능입니다.
복사된 테스트는 실험 초안 상태에 추가됩니다.

실험 설정

이제부터 테스트 대신 실험이라는 단어를 사용하겠습니다.
앞서 보여드린 컨테이너 페이지에서 새로운 실험을 생성하면 상세 설정을 할 수 있는 페이지로 들어갈 수 있습니다.
총 5가지의 과정을 거친 후 실험 배포가 가능합니다.

  • 대안 생성
  • 타겟팅 규칙 추가
  • 애날리틱스에 연결 및 목표 설정
  • 최적화 도구 설치 점검 및 활성화 이벤트 설정
  • 시작

각 과정을 자세히 살펴보겠습니다.

대안 생성

변이 추가

변이추가 버튼을 통해 실험에서 서로 비교할 대안들을 만들 수 있습니다. 각 대안에 가중치를 설정할 수 있는데, 이 가중치를 통해 전체 실험 참가자를 동일한 비율로 각 대안에 적용시킬지, 아니면 특정 비율로 적용시킬지를 소숫점 한자리까지 세부적으로 설정할 수 있습니다.

편집기 페이지

편집기 페이지는 비주얼 편집기가 실행될 페이지 url를 설정합니다.
비주얼 편집기는 통해 웹 개발자가 아니더라도 각 대안에서 사용자에게 노출될 UI를 간편하게 수정할 수 있도록 도와주는 툴인데요, 이 툴을 이용해서 특정 컴포넌트의 css를 수정할 수도 있고, 대안에서 실행될 script를 작성할 수도 있습니다.

미리보기를 누르면 어떤 디바이스에서 미리 보기를 할 것인지 설정할 수 있고, 미리보기 공유를 누르면 해당 대안으로 설정된 페이지를 배포하기 전 팀원들에게 공유해서 미리 피드백을 받아볼 수도 있습니다.

미리보기 공유를 받은 팀원들은 해당 링크에 접속했을 때 다음과 같은 안내페이지를 보게 됩니다.

타겟팅 규칙 추가

현재 설계하고 있는 실험을 어느 페이지에 적용하고 노출시킬 것인지에 대한 조건을 설정할 수 있습니다.
https://test.example.com 주소로 시작하는 모든 페이지들을 대상으로 실험을 적용시키길 원하기에, 다음과 같이 조건URL 포함으로 설정했습니다.

애날리틱스에 연결 및 목표 설정

구글 애날리틱스와 연동합니다. 옵티마이즈를 통해 쌓이는 지표는 애날리틱스를 통해서도 조회할 수 있습니다.
2021년 10월 현재 구글 옵티마이즈는 GA4를 지원하지 않습니다. 아마 내년에 지원하지 않을까 개인적으로 예상해봅니다.

기본 목표는 옵티마이즈 배포 이후 실험이 적용된 세션 대비 전환율을 계산하기 위해 설정합니다. 이 목표는 구글애나리틱스에 설정한 목표를 그대로 재활용할 수 있습니다.

최적화 도구 설치 점검 및 활성화 이벤트 설정


앞서 컨테이너에 고유 아이디가 부여되는 것을 확인했었는데요, A/B테스트를 실행시키고 싶은 페이지에 이 고유아이디를 이용해 먼저 옵티마이즈를 설치해야 합니다. 내가 만든 실험은 내가 소유하고 있는 페이지에서만 실행되어야겠죠? 이 설치 과정을 거쳤다는 것은 해당 페이지에 대한 소유권을 가지고 있음을 의미합니다.

위 사진에서 최적화 도구 설치 행에 있는 설치 확인 버튼을 통해 내 페이지에 옵티마이즈가 잘 설치되어 있는지 확인해볼 수 있습니다. 최적화 도구 설치가 확인되지 않았다면 옵티마이즈의 안내에 따라 최적화 도구를 설치해야 합니다. 설치방법
1. 페이지 내부에 직접 스크립트 태그를 배치하거나
2. 구글 태그 매니저(이하 GTM)을 이용할 수 있습니다.

오류 아래 경고 섹션에 비표준 깜박임 방지 스니펫 안내가 있습니다. 깜박임 방지 스니펫은 옵티마이즈 실행할 때, 화면이 깜빡깜빡 거려 UX를 해칠 수 있는 상황을 예방해주는 역할을 합니다. 깜박임 방지 스니펫이 설치되어있지 않아도 실험을 배포할 수 있으나, 가급적 안내에 따라 개발자에게 깜박임 방지 스니펫 스크립트 설치를 부탁하는 것이 좋습니다.

다음 사진은 GTM을 이용해서 옵티마이즈를 설치할때의 GTM 설정 모습입니다. 개발자의 도움을 받지 않아도 되며, 수동으로 잘못된 위치에 태그를 주입했을때 생길 부작용을 걱정하지 않아도 됩니다. 웹사이트 배포를 추가적으로 하지 않아도 된다는 장점도 있습니다. 옵티마이즈 설치 과정은 컨테이너 마다 한번씩 해주면 됩니다. 만약 실험 A 종료 이후 다른 새로운 실험 B를 만들 때 A,B가 같은 컨테이너에 속해있다면 이 설치 과정은 생략해도 됩니다.

트래픽 할당 및 활성화 이벤트 설정

실험 설정 초기에 만든 대안의 가중치 설정이 현 실험에 참가하는 사람들을 어떤 비율로 각 대안에 나눌지를 결정하는 거였다면, 트래픽 할당은 사이트에 접속하는 유저 중 이 실험에 참여하는 유저의 비율을 결정합니다.
기본 설정은 100%이며, 이는 사이트 방문자는 모두 실험의 영향을 받게하겠다는 의미입니다.

활성화 이벤트는 옵티마이즈를 실행시키기 위한 필요조건이자 실험이 시작되는 시점을 정하는 역할을 합니다. 옵션이페이지 로드 시로 기본 설정되어지기 때문에 이 부분을 따로 수동 설정하지 않아도 실험을 구동시키는데는 문제가 없습니다.

옵션을 맞춤 이벤트 시로 선택하는 경우는 실험 시작 시점을 실험 설계자가 원하는데로 설정하고 싶을때 입니다. 이 부분은 개발자 분들이 좀 더 주의 깊게 살펴보시면 좋을 것 같은데요,
앞서 보여드린 비주얼 편집기를 이용해 특정 대안의 경우, 자바 스크립트를 삽입해 원하는 동작을 하도록 유도해야 하는 경우가 생길 수 있습니다. 예를 들면 특정 대안이 실행됨에 따라 로컬스토리지에 특정 토큰을 삽입해야 하는 경우를 이야기 해보겠습니다.

만약 사이트 내부에 있는 코드를 사용해서 이 로컬스토리지를 조회하는 시점옵티마이즈에 의해 스크립트에 토큰이 생성되는 시점보다 앞선다면, 해당 대안은 성공적으로 실제 환경에서 제공되어질 수 없을 것입니다.
따라서 옵티마이즈에 의해 각 대안환경에서 실행될 스크립트 태그의 발동 시점을 세밀하게 조정하고 싶은 경우, 맞춤 이벤트를 사용하면 됩니다.

예를 들어 브라우저 스토리지 중 로컬스토리지를 사용한다고 한다면, 비주얼 편집기에 설정해 둔 로컬스토리지 조회 시간은 브라우저 렌더링 과정 중 윈도우 객체에 접근 가능한 시점 이후이어야 하며, 토큰 조회 시점이 내가 수동으로 설정한 활성화 이벤트의 주입 시점 이후가 됨을 보다 명확하게 보장받고 싶다면 이 맞춤 이벤트가 해결방안이 될 수 있습니다.

맞춤 이벤트를 이용해 활성화 이벤트를 작동시키는 방법은 두 가지가 있으며 첫번째는 GTM을 이용한 방법입니다.
이 방법은 기본적인 스크립트 문법만 알고 있다면 개발자가 아니더라도 사용할 수 있다는 장점이 있습니다.

두 번째 방법은 앱(사이트)를 구성하는 코드 단에서 window.dataLayer 객체를 통해 직접 맞춤 이벤트를 삽입해주는 것입니다.
옵티마이즈가 정상적으로 설치된 환경이라면 window.dataLayer객체를 통해맞춤 이벤트를 넣어줄 수 있습니다.
사용방법은 간단합니다 . 사전에 실험 환경에서 설정한 맞춤 이벤트를 다음과 같이 dataLayer에 넣어주면 됩니다.

  function gtag(){
    window.dataLayer.push(arguments)
  }
  const activationEvent ="activate_eventCode"
  useEffect(() => {
    gtag("event", activationEvent);
  },[])

위와 같이 프로그래밍을 통해 맞춤 이벤트를 삽입가능한 것을 다양한 상황에서 응용할 수 있는데요, 하단의 예제 코드와 같이 특정 실험이 실행되었을 때의 콜백함수를 설정할 수 있습니다. 콜백함수를 사용한다면 스크립트 삽입만을 위해서 비주얼 편집기를 사용하지 않아도 되는 것이며, 브라우저 스토리지를 사용하지 않고 컴포넌트 내부 상태를 이용해 UI 변경을 해줄 수 있습니다.

콜백함수는 gtag 함수의 두번째 인자로 optimize.callback인자를 넣어 줌으로 인해 등록시킬 수 있으며 이때 콜백으로 넘기는 함수의 인자 값으로 대안, 실험아이디, 컨테이너 아이디를 조회할 수 있습니다.

  gtag("event", "optimize.callback", {
    name,
    callback: ( variant, experimentId, containerId, ) => {
       switch(variant){
         case "0":
             ...
         case "1":
             ...
         default:
             ...
        }
    }
  });

지금까지 실험에 필요한 모든 설정을 마쳤습니다. 이제 실제로 배포 전에 내가 설정한 대안이 잘 동작하는지 한번 확인해보겠습니다. 대안 설정 섹션으로 이동해서 미리보기 버튼 클릭하면 볼 수 있는 디버그 메뉴는, 앞서 살펴본 활성화 이벤트를 포함해 내가 옵티마이즈 설치 및 환경 세팅을 잘 했는지 확인할 수 있게 해줍니다. 오른쪽에 있는 수정 버튼과의 차이점은 다음과 같습니다.

  • 수정은 내가 옵티마이즈 설정을 잘 했다는 과정하에 대안을 수정할 수 있게 도와주는 메뉴이며,

  • 디버그는 옵티마이즈 설정에 잘못된 부분이 있다면 해당 대안을 실행시키지 못한 이유에 대해 설명해줍니다.

    다음은 디버그 모드에 들어온 모습입니다. 하단에 옵티마이즈 디버그 창이 뜨며,
    This experience was applied.를 통해 설정에 문제가 없음을 알 수 있습니다.
    여기까지 확인을 했다면 실제 배포시 실험이 정상 동작할 것을 기대할 수 있습니다.

    배포 및 정상동작 확인

    완성된 실험 세팅을 배포하겠습니다.
    옵티마이즈 설정 페이지 최상단에 실험 기간을 설정할 수 있는데요, 기간은 최대 90일로 설정할 수 있습니다.
    시작버튼을 누르면 실험이 배포됩니다.

    배포이 적용되기까지는 어느정도의 시간이 걸릴 수 있습니다.
    크롬 브라우저를 기준으로 실험 대상 페이지에 접속해서 개발자도구를 열고 application 탭에 들어갑니다.
    옵티마이즈는 유저가 다시 창을 닫고 다시 접속하더라도 쿠키를 이용해서 항상 동일한 대안을 만나도록 합니다.
    _gaexp 쿠키가 옵티마이즈 관련 정보를 가지고 있습니다. 이 쿠키가 가지고 있는 값의 가장 마지막 숫자를 보고 현재 어느 대안이 해당 페이지에 적용되었는지 확인할 수 있습니다. 숫자1의 경우 추가한 대안 중 첫번째가 적용된 것입니다.

    배포 이후에는 현재 몇 명이 테스트에 참여하고 있는지, 현재까지 누적된 세션값과 전환율을 포함해서 함께 보여줍니다. 옵티마이즈 실험 페이지에만 들어오면 현재 실험 진행상황에 대해 한눈에 확인할 수 있는 것입니다.

    마치며

    하나의 A/B테스트를 위해서는 실험을 통해 궁극적으로 증명 하고자하는 목표 설정 및 여러 가설들을 설정하는 아이디어 회의가 필요합니다.
    이러한 논리적 설계를 통해 그리고자 하는 그림을 명확하게 설정하더라도 실제 사람들에게 그림이 선보여지기 전까지 기술적 설계를 어떻게 할 것인가에 대한 고민이 이어집니다.
    그림이 완성되더라도 예상과 다르게 붓칠을 잘못한 부분은 없는지 검증까지 거쳐야 하죠.

    기획 - 아이디어 설계 - 기술 설계 - 구현 - 소프트웨어 테스트

    옵티마이즈는 하나의 A/B테스트를 설계함에 있어 존재했던 이러한 복잡한 사이클을 보다 간편하게 줄여줍니다. 혼자 일하고 수정할 수 있는 부분은 충분히 혼자 가능하게 도와주는 것입니다. 개발자가 없이도 A/B테스트를 만들 수 있게, 클라이언트 개발자 혼자서도 유저 분류를 할 수 있게 도와줍니다.

    기술은 현재를 살고 있는 사람들이 보다 편하게 본인의 생활을 영위할 수 있게 도와주는 좋은 친구입니다.
    나의 시간 뿐만 아니라 팀 전체가 소비하는 시간까지 줄여주는 기술이 있다면 한번쯤 배워서 적용해보고 싶지 않으신가요? 단순 구현 뿐 아니라 하나의 피처를 만드는 과정에서 더 나아질 수 있는 부분은 없을지 고민해보고 시도해보고 개선하는 것은 훌륭한 엔지니어가 되는 지름길이라고 생각합니다. 꼭 프로그래밍 언어를 사용하지 않더라도 누군가 만들어둔 툴을 잘 사용할줄 안다면, 특정 영역의 문제를 해결하는 엔지니어가 될 수 있습니다. 애초에 엔지니어는 제한된 재화를 이용해 주어진 문제를 해결하는 사람을 가르키는 말이니까요.

    이 글을 끝까지 읽어주신 여러분도 주변 동료들과 크고 작은 도움을 주고 받으며 앞에 놓인 문제들을 원활하게 해결 하셨으면 좋겠습니다. 긴 글 읽어주셔서 감사합니다.

profile
성장을 향한 작은 몸부림의 흔적들

0개의 댓글