뒤로
Hyeonmin
Hyeonmin ·

Braze To Kakaomoment 구축 회고

Braze를 사용해본 분들은 잘 아시겠지만 Webhook을 사용하면 거의 모든 마케팅 채널에서 메시지를 보낼 수 있습니다. 근데 국내에서 자주 활용하지만 불가능한 채널이 하나 있는데 바로 카카오 플러스친구입니다.

친구톡과 달리 플친은 오로지 카카오모먼트 내에서만 발송이 가능한데요, 이건 카카오모먼트의 정책인걸로 보여서 앞으로도 계속 그럴 것 같습니다. 현재 플친 발송용 오디언스를 다른 곳에서 생성해서 Import 시키려면 csv 파일 업로드 또는 모먼트 API를 활용해 업로드하는 방법 밖엔 없습니다.

그래서 Braze에서 세그먼트를 생성하고 플친으로 발송하려면 생성한 세그먼트의 유저 데이터를 내려받아 모먼트 업로드용 csv 파일 형식에 맞게 가공해서 업로드 해줘야하는 번거로움이 있는데요. 이러한 활동의 특성 상 빈번하게 이뤄져야 최신의 오디언스를 유지할 수 있을텐데, 그러기엔 바쁜 마케터 분들의 리소스가 꽤 들어갑니다.

다행히 Braze도 API를 제공하고 카카오모먼트도 API를 활용할 수 있는 상황이라 두 개를 잘 연결하면 자동화할 수 있었습니다. 현재 카카오모먼트 API는 아래처럼 신청을 받고 있네요.

할줄 아는게 React, Python, 그리고 AWS Lambda, API Gateway, S3, Amplify 조합이다 보니 이 구조에 맞춰 구축해보기로 했습니다.

Backend

1) Braze API

Braze가 제공하는 다양한 API 중에서 특정 세그먼트에 속한 유저들의 데이터를 내려받을 수 있는 건 아래 API입니다.

url thumbnail

POST: User Profile Export by Segment

This article outlines details about the Users by Segment Braze endpoint.

https://www.braze.com/docs/api/endpoints/export/user_data/post_users_segment/

Braze에서 플친 발송용 오디언스로 활용 가능한(마케팅 수신 동의 등이 완료된, 모먼트에 업로드할 ID가 있는) 세그먼트를 만들고 해당 세그먼트 ID와 가져올 값들을 API로 설정해 호출하면, 지정한 S3 버킷으로 알아서 파일을 넣어주도록 설정할 수 있습니다. 근데 이 부분이 애로 사항인 것이.. Braze는 총 몇 개의 압축 파일을 넣어줄지를 미리 친절하게 알려주지 않다보니 버킷에 더 이상 파일 추가가 되지 않으면 export가 다 끝났구나 하고 판단할 수 밖에 없습니다. 문서를 아무리 뒤져봐도 다른 방법은 없는 것 같아요.

2) 업로드용 CSV 파일 만들기

내려받은 gzip 파일 수백 개를 압축 해제 후 데이터를 읽어들여 정제 후 업로드용 csv 파일로 만들어야 했습니다. AWS Lambda 위에서 실행해야하다보니 무엇보다 실행 시간을 15분 내로 관리하는게 관건이었습니다. 이 부분에서도 또 삽질이 많았습니다.

  • zip 보다 gzip 이 용량도 적고 압축 해제도 훨씬 빠르다
  • 로컬에서 Python으로 동시에 빠르게 작업할 수 있는 멀티프로세싱이란게 있어서 적용해보니 빨랐으나, Lambda에서는 Python 멀티프로세싱을 지원하지 않는다
  • Python으로 파일을 읽어와 쓰고 기록하는 작업을 병렬로 빠르게 할 수 있는 방법이 뭔지는 잘 모르겠다... 결과적으로 asyncio를 활용하는걸로 짰지만 실행 시간이 대폭 줄지는 않는 듯하다

압축해제 + 데이터 정제 + csv 파일 S3 저장 작업을 하나의 Lambda 함수에서 하면 15분 시간 제약에 걸릴 것 같았습니다. 그래서 gzip 파일 압축해제 + 데이터 정제 + parquet 파일을 S3에 저장하는 함수와 S3에 저장된 parquet 파일을 csv로 변환하여 다시 S3에 저장하는 함수로 나눴습니다.

모먼트에 csv 파일로 올릴 때 하나의 고객파일/친구그룹 파일 당 총 200MB, 최대 10개 이하의 csv 파일을 한꺼번에 올릴 수 있어서 하나의 csv 파일을 19~20MB 정도로 생성되도록 했습니다. 광고 ID 혹은 카카오 UID만 들어간 csv 파일인 경우 약 54만개가 19~20MB 정도였네요.

3) 모먼트에 업로드

모먼트 API로 고객파일(광고 ID) 업로드, 친구그룹 파일(카카오 UID) 업로드를 호출할 수 있는데요. Multipart File 업로드에서 한참 헤맸는데 구글링하다보니 저처럼 헤매는 사람들이 꽤 많아보였습니다. Python에서 requests 모듈로 Multipart File 업로드 시,

  • files 파라미터에 업로드 파일 정보 및 데이터를 담기 때문에 header에서 content-type을 multipart/form-data를 명시하지 않아야 제대로 작동
  • 신규 고객파일/친구그룹 파일의 이름, 기존 고객파일 수정하는 경우 기존 고객파일 ID 등을 requests 모듈의 data 파라미터의 dict 형태로 넣어줌

수많은 삽질 끝에 아무튼 여러 파일을 읽어와 한꺼번에 올릴 수 있게 구현했습니다.

모먼트 API를 호출할 때 넣어줘야 하는 값 중 리프레시 토큰이 있는데 이 60일 짜리 리프레시 토큰을 미리 발급받아 환경변수로 넣어줬습니다. 리프레시 토큰 발급은 카카오 로그인 API 문서에서 설명해주고 있는데 이 부분만 따로떼서 발급받을 수 있는 웹페이지를 미리 만들어 놨었습니다.

4) API 생성 & Lambda layer 관련

만들어둔 Lambda 함수들을 FE에서 호출할 수 있도록 API로 만들어줬습니다. FE에서 활용하기 쉬우려면 어떻게 API에서 리턴해주는 좋을지 경험치가 잘 없다보니 API Gateway와 React 웹페이지를 왔다갔다하며 수정했습니다. 처음부터 이런 모델링을 잘 해놓는게 참 중요하겠구나... 싶었어요.

Lambda에서 제공하지 않는 모듈들은 layer로 따로 넣어줘야 하는데 추가로 넣어준 모듈이 datetime, requests 정도였던 것 같습니다. boto3, asyncio, gzip, itertools 등은 Lambda에 기본 내장되어 있는 것 같고, 용량 큰 pandas는 기본으로 layer를 제공해줘서 선택해서 쓸 수 있습니다.

Frontend

1) React + Tailwind CSS + MUI

미약하지만 그나마 익혀놓은게 위 조합 정도라 활용해보았고, 결과적으로는 MUI 컴포넌트들을 그대로 쓰다보니 Tailwind CSS는 거의 사용하지 않게되었네요. 커스터마이징 하고 싶은 부분들이 있으나 CSS를 잘 몰라 MUI에서 기본 제공하는 CSS를 수정하기가 어려운 상황입니다. Tailwind CSS를 수정해도 안 먹고 MUI sx 파라미터를 수정해도 안 먹는 부분들이 있네요. ㅠ.ㅠ

분명히 React는 여러 컴포넌트로 나눠 조합하면서 써야 맞을텐데... 아직 props 이동을 자유롭게 할 줄 몰라서 재사용되는 컴포넌트를 보기 좋게 분리해내지는 못했습니다. 완성된 페이지는 요청하기, 진행 중 작업 확인하기, 완료된 작업 확인하기 세 개로 구성된 아주 간단(만들기는 간단하지 않던데..)한 페이지 입니다.

요청하기 페이지에서는 Braze 세그먼트 리스트를 불러와 그 중에서 선택할 수 있고, 광고 ID 혹은 카카오 UID를 선택 후 모먼트의 고객파일 혹은 친구그룹 파일 리스트를 불러온 뒤 신규로 생성할지 기존 파일을 수정할지 선택할 수 있도록 했습니다. 선택 사항을 확인한 뒤 요청하면 진행 중 리스트에서 확인할 수 있고, 작업이 완료되면 완료 리스트로 넘어가는 구조입니다.

별도의 DB를 쓰지 않고 S3에 진행 중, 완료 폴더를 각각 마련해서 각 Lambda 함수 실행이 완료될때마다 json 형태의 로그 파일을 남기도록 했고, 진행 중 및 완료 페이지에서는 주기적으로 해당 위치의 json 파일을 스캔해 불러오는 식입니다.

2) AWS Amplify

제 입장에서 가장 간단하게 배포할 수 있는 방법이었습니다. github에 올려두고 main 브랜치가 커밋될 때마다 자동 배포 되도록 할 수 있습니다.

그 외 디테일들

  • csv보단 parquet가, zip보단 gzip이 용량도 적고 빠름
  • Lambda 함수들
  • 약 210만의 Braze 세그먼트 기준 gzip 파일을 541개 내려받게되는데 export가 모두 완료되었는지 체크하는 로직에 시간이 들긴하지만 모두 포함해서 최대 85MB 메모리 사용, 9.2분 소요
  • 내려받은 541개 gzip 파일을 읽어와 압축해제하고 정제하고 parquet 파일로 저장하는 작업에는 최대 414MB 메모리 사용, 7분 정도 소요
  • parquet 파일을 csv로 변환하는 함수는 최대 234MB 메모리 사용, 2.6초 소요
  • 준비된 csv 파일들을 모먼트로 업로드하는 함수는 최대 105MB 메모리 사용, 11.6초 소요
  • 카카오모먼트
  • 고객파일/친구그룹 파일이 각각 50개로 제한, 현재 업로드가 가능한 상태인지, 신규 파일명이 현재 존재하는 파일명은 아닌지, 파일명 규칙에는 맞는지 체크 필요
  • 고객파일은 기존 파일 수정하는 API가 있지만, 친구그룹 파일은 수정 API 없음. 그래서 수정하고자 하는 기존 친구그룹 파일을 삭제하고 동일한 이름으로 새로 만들어주는 로직으로 대체

마치며

시작은 내부 CRM팀의 요청으로 구축하였으나, 국내에서 Braze를 사용하는 곳이라면 마찬가지로 필요로 하지 않을까? 싶어 나름 회고도 할겸 상세하게 공유해봤습니다. Braze를 사용 중이고, 카카오모먼트 API를 활용할 수 있다면 AWS 프리티어 계정에서 저처럼 구글링과 YouTube로 코딩을 배운 비개발자도 가능한 수준입니다.

이걸 SaaS 형태로 오픈하여 사용할 수 있게하면 어떨까 싶은데 그만큼 니즈가 있을지, 그리고 유저 데이터를 export 하는 부분이 있다보니 실제로 쓸까? 싶긴 합니다. 그래도 이걸 시작으로 마이크로 SaaS를 만들어보고 싶긴해서.. 조만간 간단한 랜딩 페이지 만들어 한번 올려볼까 싶어요.

9

댓글

로그인 후 댓글을 남길 수 있습니다.

Hyeonmin
Hyeonmin

오 레이스트 다운님! 댓글 감사합니다. 힘이 되고 의욕이 생기네요! 일단 만들어봐야겠습니다.