메일 발송에 필요한 데이터 수집

2024년 3월 13일 수요일

Today I Learend

날짜

2024년 3월 13일 수요일

내용

주간 성과 메일

약 2달 전에 각 스토어에게 주간 작성되거나 import된 리뷰 수에 대한 메일을 보내는 Task를 진행했었다. 이와 비슷하게, 새롭게 생긴 List Designer 기능의 성과를 담은 메일을 매 주 전송해야 한다. 필요한 데이터는 위젯의 클릭 수와 위젯 내 상품의 매출.

위젯의 클릭 수

데이터를 어떻게 저장할 것인지 잠깐 고민했다. 클릭 이벤트가 발생할 때마다 테이블에 레코드를 하나 씩 추가하는 방법이 있는데, 우리 서비스에서 방문자 수를 체크하는 방식이 이렇게 구현되어 있다. 다른 방법은, 각 위젯의 데이터 테이블에 필드를 하나 추가하는 것이다.

후자를 고민하게 된 이유는 클릭 수가 많아지면 데이터가 정말 많이 쌓이고, 이를 탐색하는게 성능에 영향을 끼치진 않을지 걱정이 되기 때문이었다. 전자를 선택하면, 위젯 데이터를 찾아 특정 필드에 +1만 해주면 된다. 관리하기도 편하고, 참조하기도 편할듯 했다. 다만, “일주일 간”의 데이터만 취급해야 한다는 것이 장애물이였다. 매 주 0으로 초기화해주면 되기야 하겠다만, 그것 또한 크론이 필요하니 마냥 성능상 우위에 있다고 보기도 힘들 듯 하다. 결국 테이블을 새로 만들고 클릭이 발생했다고 프론트에서 호출이 오면 데이터를 추가하는 방식으로 구현하기로 했다.

상품의 매출

위젯에 표시된 상품들 중 매출을 기준으로 상위 3개 품목을 추려내야 했다. 따라서

  1. 상품들 중 위젯에 사용된 상품을 고르고
  2. 해당 상품들의 주문수량과 가격을 곱해 매출을 계산하여
  3. 각 스토어 별로 상위 3개를 파악해야

했다.

Flow

로직의 흐름이 꽤 복잡했다. 발송할 메일은 스토어 별로 처리되야 하므로 크론 자체는 shop 서버에서 시작되야 했다. 하지만 위젯과 위젯의 클릭 수는 review 서버에 저장되어 있어서, 요청하고 받아오는 함수를 구현해야 했다. 매출을 계산하는 것은 특히 복잡했는데, 주문 상품에 대한 정보인 Lineitem이 shop 서버에 있는 반면 상품과 위젯은 review 서버에 데이터가 저장되기 때문이다. 다시 말해, 원하는 데이터는 shop 서버에 있지만 이 중 필요한 것을 골라내기 위한 정보를 review 서버에서 가져와야 했다.

흐름을 정리하면 다음과 같다.

  1. shop 서버에서 List Designer 기능을 사용하는 스토어들을 추려낸다.
  2. review 서버로 스토어들의 id를 보낸다.
  3. review 서버에선 각 스토어에 있는 위젯마다 클릭수를 종합하고 상위 3개를 결정한다.
  4. 이와 동시에, 각 스토어마다 위젯에 포함된 상품의 id를 취합한다.
  5. 클릭수가 높은 위젯 3개에 관한 데이터와 위젯에 포함된 상품의 id를 응답으로 보낸다.
  6. shop 서버는 응답에 포함된 상품 id로 매출을 계산하여 상위 3개를 결정한다.
  7. jinja2 템플릿을 이용해 이메일에 담을 HTML에 정보를 추가한다.

의 과정이 되겠다. 기존 lineitem 데이터에 있는 주문수량(quantity)과 가격(price)를 곱해주려다가 이전에 공부했던 hybrid_property가 생각나서 적용하기로 했다. 둘 다 가져와서 계산하는 것보단, 계산된 채로 상위 3개만 가져오는 것이 성능상 훨씬 좋기 떄문이다.

1
2
3
4
5
6
7
8
# 매출 계산
    @hybrid_property
    def sales(self):
        return self.quantity * self.price

    @sales.expression
    def sales(cls):
        return cls.quantity * cls.price

내일은 열심히 이메일 만들어야지..

회고

하루 종일 콧물과 재채기 폭풍이다.