[ 원티드 프리온보딩 ] MadUp - 매체별 기간 내 광고 효율 분석
💪 Study 참여/원티드 프리온보딩 백엔드

[ 원티드 프리온보딩 ] MadUp - 매체별 기간 내 광고 효율 분석

반응형


지난 4월 26일부터 원티드 프리온 보딩 백엔드 코스에 운 좋게 참여할 수 있게 되었다.
아래의 링크에서 더 자세한 설명을 보실 수 있습니다!

 

프리온보딩 백엔드 코스 | 원티드

프리온보딩 코스는 참가기업의 실전 과제를 팀 단위의 동료 학습으로 케이스스터디하여 빠른 역량 향상과 취업을 목표로 하고 있습니다. 선발 과제를 제출할 수 있는 백엔드 개발 전공자, 주니

www.wanted.co.kr


커리큘럼을 간단하게 소개하자면, 멘토님 한분과 참여자들이 있으며 멘토님께서 첫날 팀을 정해주셨다.
팀을 나눈 기준으로는 제출한 선발 과제를 기반으로 하여 팀을 나누셨다고 하셨으며, 나는 A팀에 배정되었다.
다른 팀은 4명이 팀인데.. 우리는 왜 3명이에요!
아무튼 이렇게 첫 시간에 팀을 정해주시고 기본적으로 안내와 팀별 의사소통 툴은 Discord를 사용했다.
디스코드는 게임용 음성채팅인 줄 알았지만 이렇게도 사용할 수 있구나를 깨닫게 되었다.


멘토님께서 공지사항들을 전달해주시는 채팅방이 있고, 프로젝트 과정 진행 중 발생한 이슈에 대해서 공유하는 이슈 방, 그리고 각 팀별로 자유롭게 의사소통하는 공간의 채팅방이 있었다.
그리고 디스코드를 사용하는 가장 큰 이유는 간편하게 음성 채팅방이 있는데 이를 통해서 팀원들 간에 회의나 의견 공유들을 채팅보다 더 쉽게 할 수 있었다.
보통 구글 미팅 아니면 줌을 사용하는데 되게 간편했다고 개인적으로 생각했다.
우선 어색한 분위기에서 이야기를 주고받았던 것 같았다. 각자의 개발 경험을 공유하고 어떤 방식으로 공부를 진행해 왔는지 등등 우선 팀 분위기가 절대 어색하면 어떤 일을 진행하더라도 힘들 것 같다고 생각했기 때문에 막 말을 던졌던 것 같았다.
그 뒤로 팀장을 선발하는 과정에서 운 좋게? 팀장이 되었다.


학부 시절에 캡스톤 프로젝트를 진행하면서 사용했던 전략이나 공유 문서를 정하고 기타 등등..
앞으로 미워도 한팀이기 때문에 내가 책임감을 가지고 이끌어야겠다고 생각이 들었고, 한 편으로는 Django에 대해서 아직 아는 게 많지 않아서 Django를 베이스로 작업하는 데 있어서 문제가 생기면 어쩔까 걱정이 들기도 했다.
아무튼 이제 초반 이야기는 각설하고, 첫 번째 프로젝트에 대해서 기록을 남기려고 한다.
아래는 실제 내가 참여한 과정의 Github Organization을 링크해 두어야 겠다.

 

2nd-wanted-pre-onboarding-team-A

원티드 프리온보딩 2기. 2nd-wanted-pre-onboarding-team-A has 4 repositories available. Follow their code on GitHub.

github.com

 

첫 번째 프로젝트 - Madup

우리 팀이 마주한 프로젝트는 매드 업에 대한 기술 과제였다.
주어진 문제나 관련 데이터들은 자세하게 설명하지는 않고 내가 이 프로젝트에 대해서 기여한 부분이나, 느꼈던 점을 위주로 작성해보려고 한다.
보통 팀이 꾸려지고 프로젝트를 시작하려고 준비단계에 들어간다면 바로 코딩에 들어가는 것이 아니다.
문제에 대한 각자의 생각과 분석이 가장 먼저 진행되어야 한다.
이번 프로젝트에 대한 요구사항이 무엇인지, 어떻게 해결해 나아가야 할 지에 대한 이해가 필수적이기 때문이다.
따라서 각자 시간을 가지고 분석하는 시간을 갖고, 공유하는 시간을 순서대로 가졌다.
그러면서 자연스럽게 주어진 데이터를 어떻게 모델링하여 DB에 적재할 지에 대한 논의도 이어졌던 것 같다.
이 과정에서 좀 시간이 걸렸던 것 같았다.


나는 주어진 데이터를 보면서 join이 된 결과에 대한 table이라고 생각이 들었고, DB 과정 시간에 배운 정규화 내용이 떠올라서 최대한 RDB 특성상 중복된 데이터가 최소화시키는 것에 초점을 두었는데 생각보다 이 과정에서 이야기를 나누면서 하다 보니 고려해야 할 점이 계속해서 늘어나거나 다시 원점으로 돌아오는 경우가 있었던 것 같았다.
이렇게 모델링에 신경을 쓴 이유는 Django에서 마이그레이션이 중간에 꼬인다면 굉장히 골치 아프다고 생각했기 때문이다.
경험해보니 모델링에 정답은 없는 것 같았다. 멘토님의 세션 피드백 내용 중에서 모델링은 초기 단계에서 너무 타이트하게 하지 말라는 말씀이 있어서 메모해 두었다.


설계 시에 시작부터 인덱스를 매기고 시작하지는 않는다고 하셨었고, 필요시에 추가하거나 수정하는 작업을 진행한다고 하셨다.
아무튼 피드백 내용은 나중에 더 적어보기로 하고,
이후 주요 기능은 광고와 광고주의 CRUD api와 핵심 api인 기간에 따른 광고 효율을 분석하는 api를 작성하는 것이었다.
우리 팀은 Django View를 사용해서 로직을 작성했다. 실제 내부 로직을 작성하였기 때문에 추후 GenericView, APIView 등 DRF로 구현할 때 이해를 더 잘하도록 하기 위해서 작성하였다.
이 부분에서는 내가 기여한 부분이 없었고 팀원들이 작성한 코드에 대해서 리뷰를 해주는 역할을 중심적으로 했던 것 같았다.
굳이 사용하지 않는 app들을 import 시키지 않도록, 예외 처리를 하는 부분과 응답하는 부분에서 좀 더 명확하게 JSON 응답을 주도록 수정하였다.
또, 광고 효율을 계산하는 공식들을 살펴보면,


위와 같은데 모두 나눗셈 연산이 들어간다. 보통 이렇게 나눗셈 연산을 한다면 분모가 0인 경우 ZeroDivisionError가 발생하기 마련이다.
초반에는 생각하지 못했지만 이후 분모 데이터가 0인 값들이 존재한다는 것을 알게 되었고 처리를 해주었다.

analysis_datas = {
    'ctr': 0 if total['total_impression'] == 0 else round(total['total_click'] * 100 / total['total_impression'], 2),
    'roas': 0 if total['total_cost'] == 0 else round(total['total_cv'] * 100 / total['total_cost'], 2),
    'cpc': 0 if total['total_click'] == 0 else round(total['total_cost'] * 100 / total['total_click'], 2),
    'cvr': 0 if total['total_click'] == 0 else round(total['total_conversion'] * 100 / total['total_click'], 2),
    'cpa': 0 if total['total_conversion'] == 0 else round(total['total_cost'] * 100 / total['total_conversion'], 2),
}

위와 같이 Python의 삼항 연산자를 사용해서 처리를 해주었다.
지금 와서 생각해보니 중복이 많고 그렇게 가독성이 있는 것 같지는 않았다.
멘토님께서 주신 더 좋은 방법으로는 utils라는 폴더를 하나 생성해주어, safe_divide 하는 함수를 정의해두어 처리하는 방법도 고려할 수 있겠다고 말씀해주셨다.
추후 적용하여 수정해보도록 해야겠다!

다음으로는 시간이 많이 걸렸던? 부분에 대해서 기록을 남겨보려고 한다.
이제 얼추 핵심 기능과 CRUD 할 수 있는 api, 자주 조회되는 항목에는 index를 걸어두는 등의 작업을 하고 난 뒤,
우리가 작성한 광고 효율을 계산하는 api에 대한 테스트 코드를 작성하는 부분을 진행해 보았다.
Django에는 app을 생성할 때 생성한 app 폴더 내에 test.py라는 파일이 자동적으로 생성된다.
이 파일에서 테스트 로직을 작성할 수 있다.


실제 Test용 DB를 사용하여 진행할 수도 있었지만 시간상 불가능하였고, 임의로 테스트 코드 내에서 DB의 사용할 데이터를 몇 개만 가져와서 진행하도록 하는 로직을 작성하였다.
이 부분에서 계속해서 테스트가 통과되지 않는 것이다..
분명 확인하였을 때 2022년 1월 1일과 2022년 1월 2일 데이터만 존재하는 것을 확인하였고,
api 테스트 툴인 insomnia로 출력된 결과를 테스트 코드 예상 결괏값으로 설정 해준 뒤, 테스트를 돌리면 통과되지 않았다는 것이다.. 😂
이때는 몰랐었다.. 소문자와 대문자의 중요성을..
우선 손으로 직접 계산해 보았다. 그랬더니 api tool의 결과와 달랐던 것이다. 그러면 우리의 로직이 잘못되었던 것인가? 아니다..
직접 우리 팀원 중 한 명이 디버깅을 찍어본 결과 날짜를 2개만 가져오는 게 아니라 4개의 날짜에 대한 데이터를 가져오는 것이었다.
엥 도대체 왜?! 이유에 대해서 머리를 맞대고 생각해보았다..
우선 가장 먼저 생각했던 부분은 처음에 모델링할 때 date 부분을 DateTimeField를 사용했었다. 이 부분에서 잘못되었나? 싶어서 DateField로 다시 마이그레이션을 진행해보았지만 결과는 같았다.
참고로 Django의 DateTimeField와 DateField의 차이에 대해 자세한 내용은 아래 링크

 

Django DateTimeField and DateField in detail with Examples | JAFOOR'S BLOG

In this article, I will explain how you should handle date and time in Django models using DateField and DatetimeField in detail with examples.

www.jafoor.com


아무튼 말하고 싶었던 부분인 이게 아니라..
바로 이 부분이었던 것이다.

# Before
date_format = '%Y.%M.%d'

# After
date_format = '%Y.%m.%d'
date = datetime.strptime(date, date_format)

우리가 csv파일을 DB에 적재하는 업로더 파일 중 일부분인데 처음에 일자 입력에 대한 format을 % M 형식으로 받아왔던 것이다..
여기서 % M과 % m에 대한 차이는 어마어마했다. 바로 "분"을 의미하느냐, "월"을 의미하느냐가 달랐던 것이다.
그니까 애초에 우리가 2022-01-01이라는 데이터를 DB에 적재할 때 2022년 1분 1일에 대한 데이터를 적재하고 있었던 것이다..
그래서 결괏값이 다르게 나왔던 것이었다. 결국 테스트 코드에서 출력되는 결과가 맞았던 것이다.
모든 % M 부분을 % m으로 수정하고 다시 적재.. 후 테스트 코드를 돌려보니 통과가 되었다 😆
정말 상상하지도 못했던 부분에서 우리가 원하는 결과가 다르게 나오니 살짝 멘탈이 흔들렸지만 역시 팀원들과 함께 고민해보니까 생각보다 오래 걸리지는 않았다.


만약 혼자서 이러한 문제를 해결했더라면 정말 오래걸리지 않았을까 싶다...
아무튼 이렇게 1주 차에 진행했던 프로젝트의 이슈들과 느꼈던 점을 간략하게나마 기록해보았다.
아직 과정이 마무리되진 않았지만 최선을 다해서 마무리하고 차근차근 정리해보려고 한다.
마지막으로는 멘토님께 피드백 받은 내용이다.

 

A팀 Feedback

💡 Good!

  • 업무를 명확히 구분 하였고, 툴을 이용해 시각적으로 진행을 잘 보여줌.
  • 코드 좋고, django views 로 실제 내부 로직을 구현하였기에 추후 이해에 도움 많이 되실듯.
  • Validator 및 친절한 예외처리(단순 개발 넘어 고려했다는게 보이기에).

☝ Tips!

  • DRF를 적용하여 사용 가능함을 보여주자.(이미 하고계시네요.)
  • 개발 관련 업무들을 Git 로직과 연동하자.(doing 은 Feature 개발중, git merge 할때 상태 Done 으로)
  • 진행 중 에는 실제 진행중인 업무를. (다른 개발자와 협업할때, 내가 안하고 있는건 그분들이 하실수 있게 손에서 놓아둬야함.)
반응형