What I Learn Today

Start Date : 2022/02/07 ~

Learn/Company

[TIL #20] CRM 속성 추가하기 (본격적인 업무 시작!)

HannaDev 2022. 3. 19. 00:49

본격적인 업무 시작 ! 지금까지는 연습용 Mission 에 가까운 API 조사나 작은 함수 작성에 한해 업무? 실습?을 진행했는데요. 어제 본격적으로 CRM (Braze, Amplitude) 속성 추가 작업 문서를 전달받아 오늘부터 코드 설계를 열심히 하고 있습니다.

체감상 일주일간 그저 대기 상태로 공부만 하고 있던 것 같은데... 정신없지만 본격적으로 저만의 업무가 생기니 의욕이 다시 생기네요! 기본적인 CRM add/send daily batch 코드는 차장님이 작업 후 넘겨주셨고, 해당 코드를 분석하면서 속성 추가 시 어떻게 코드를 더해 가야 할 지 고민하고 있는데요. 회사 내부 DB 구조를 전반적으로 파악해야되는 부분들이 많아서 생각보다 더 복잡하네요. =͟͟͞͞(꒪ᗜ꒪ ‧̣̥̇)

오늘은 실질 코드작업은 2시간 정도 하고 요구사항 분석 및 DB 파악, 흐름도 구상, 코드 구조 설계에 대부분의 시간을 보낸 것 같습니다. 그런데 확실히 내부 DB 구조가.... 음.... 레거시가 많긴 하네요 ㅋㅋㅋ 매우 복잡합니다.

어찌되었든 오늘 TIL 에서는 현재 작업 스타일을 기록해보고 개선점을 파악해보면 좋을 것 같아서 'How' 에 맞춰 기록해보려고 합니다. 약간은 코드 분석 및 노트 정리에 시간을 너무 과투자하고 있는 것 같아서 확인해 볼 필요가 있을 것 같아요! (마감 기한이 제시되진 않아서 조금 여유를 부리고 있지 않나.... 하는 반성이 들었습니다.)


▶ 현재 작업 순서 복기

 

ⓧ CRM add/send batch 코드 분석 (흐름 파악, 노트 정리)

① 요구사항 정리 (추가 필요 속성 리스트업)

② 속성 별 접근 필요한 DB 테이블 파악

③ DB 접근 흐름도 드로잉

④ 효율적인 DB 테이블 접근 방식 고민

⑤ 총 20개의 속성 -> DB 접근 고려해 세 파트로 분할

⑥ A 파트 (쉬운 부분) - add batch 부터 접근

⑦ Test 환경 조성 - 원본 코드 Copy 후 Test 수월하게 코드 수정

⑧ Loop (속성 추가 -> 디버깅)

⑨ 리팩토링 고민 -> 주말에 책 보면서 고민해봐야 할 듯 (인프런 강의도 들어보자)

ㄴ 현재 이런 상태


▶ CRM add/send batch 코드 분석 (흐름 파악, 노트 정리)

코드 분석 시, 현재 가장 중요하게 짚고 넘어가는 것은 '큰 그림' - 전체적인 흐름과 주요 역할, 목적입니다.
성향 자체가 나무를 초월해 나뭇잎부터 보는 경향이 심해서 (›´ω`‹ ) 항상 숲부터 보려고 노력 중입니다.
최근에 '실용주의 사고와 학습' 책을 완독을 했는데 전문가일수록 숲을 먼저 본다고 하네요!
실질적으로 코드 작성보다 설계에 많은 시간이 소요되는 만큼 기둥부터 파악하는 게 중요한 것 같아요.

1. 큰 틀에서 코드 흐름 파악 (접근 DB 파악)

 

2. 시작점 함수 세부 흐름 파악 (= 가장 복잡도 높은 함수)

 

2. 궁금점 수집 -> 질문

항상 생각하는 건데 어디서든 질문을 만들어내는 능력 (=호기심) 이 정말 중요한 것 같아요.

맨날 '그럴 수 있지~' 를 외치고 다니는데 작년부터는 '그럴 수 있지~' 라는 생각을 '왜 why?' 로 변환시키고 있습니다! (질문 많은 분들 항상 신기하고 부럽습니다 (๑>ᴗ<๑))


요구사항 정리 (추가 필요 속성 리스트업) + DB 테이블 파악

~혹시 모르니까 모자이크~

노트 필기하거나 문서 만드는 작업을 개인적으로 좋아하는데요!
회사 들어가면서 느낀 점은.... 남의 문서는 알아보기 힘들<<<
아무래도 회사 시스템 흐름도는 복잡하다보니 문서도 같이 복잡해지는걸까요...?
엑셀로는 도저히 알아볼 수가 없어서 (ㅋㅋㅋ) 개발자에게 필요한 내용만 발췌해서 쉽게 변환했습니다.
화면 앞에 펼쳐두고 제 3의 모니터처럼 사용하니 한결 작업하기 편하더라구요!

속성 별 DB 흐름도를 구상하고 현재 접근 DB, 추가로 접근 필요한 DB 를 나열해 어떻게 하면 효율적으로 DB 에 적게 접근하면서 속성을 가져올 수 있을지 고민 중에 있습니다. _〆(。。)

▶ DB 접근 고려해 세 파트로 분할 - 쉬운 부분부터 접근

  • 추가되어야 하는 속성 '총 20개'

 

① A 파트 (난이도 下) : 8개
ㄴ member, membership, coupon 등 주요 DB 접근 필요 / 단순 조회

 

② B 파트 (난이도 中) : 11개
ㄴ daily 유저 재생 기록 DB 접근 필요 / count 쿼리 등 약간의 계산 필요

 

ⓒ C 파트 (난이도 ??) : 1개
ㄴ 해당 속성이 무엇을 뜻하는지, 어느 DB 테이블에 접근해야하는지 모르겠음 / 계산은 필요할 듯...??

 

<분할 정복 알고리즘>
분할 정복 (Divide and Conquer) 은 여러 알고리즘의 기본이 되는 해결방법으로, 기본적으로는 엄청나게 크고 방대한 문제를 조금씩 조금씩 나눠가면서 용이하게 풀 수 있는 문제 단위로 나눈 다음 그것들을 다시 합쳐서 해결하자는 개념에서 출발하였다.

알고리즘이나 코딩할 때마다 생각하는 거지만 어렵게 생각할수록 더 어려워지더라구요!
그래서 최대한 작업을 쪼개고 쉬운 것부터 처리하는 방식을 취하고 있습니다.
저는 보통 이런 방식으로 분할하는 것부터 시작하는데 다른 분들은 어떠실지 궁금하네요 *☸⛵☸*

+TMI 로 어제까지만 해도 3일 정도 걸리지 않을까 산정했는데 오늘해보니까 4-5일은 걸릴 것 같네요. |ω´・;;;)

+ 신입은 일정 산정할 때 생각나는 일정의 2배를 곱하라는 공식이 많이 들어맞는 것 같습니다...ㅎㅎ

 


Test 환경 조성 - 원본 코드 Copy 후 Test 수월하게 코드 수정

  • 일단 'A 파트' add batch 부분부터 수정해보기로 결정
DB 흐름 구상 및 작업 분할 완료 -> 코딩 시작
▷ 테이블에 속성부터 추가해야되나? - 내 마음대로 추가해도 되나 - 차장님께 질문 - (~~~) - 일단 테이블 저장 전 단계까지로 분리해서 수정해보자
▷ 그러면 따로 class 를 만들어서 저장해서 print, debug 해봐야겠다.
class TestCrmSource:

    id = None
    """
    	생략
    """

    # [3/18] 새롭게 추가되는 속성 테스트 중
    user_b2b_ㄱ = None
    user_b2b_ㄴ = None
    user_b2b_ㄷ = None

    user_coupon_ㄱ = None
    user_coupon_ㄴ = None

    user_ㄱ = None
    user_ㄴ = None

    user_age_range = None

    # [3/18] 4개 항목 (12개 속성) 은 추가 예정

    def __init__(self, **kwargs):
    	""" 생성자 """
        self.__dict__.update(kwargs)

    def get_info_keys(self) -> dict:
        """
            출력하고 싶은 key 를 두 종류로 분할해 반환
        """
        basic_key_list = ['A', 'B', 'C', 'D',
                          'E', 'F', 'G', 'H',
                          'I', 'J']
        new_key_list = ['user_b2b_ㄱ', 'user_b2b_ㄴ', 'user_b2b_ㄷ',
                        'user_coupon_ㄱ', 'user_coupon_ㄴ', 'user_ㄱ',
                        'user_ㄴ', 'user_age_range']

        return {'basic_keys': basic_key_list, 'new_keys': new_key_list}
▷ 원본에 바로 수정? ㄴㄴ -> copy 한 테스트용 파일을 만들어서 수정 -> 그럼 수정한 코드 부분에는 주석 # Test-Code 로 표기해놓자 (이게 옳은 방식은 아닌 것 같은데... 일단 고!)
▷ 막상 속성 추가하니 개발 서버 crm_source 테이블에는 b2b 멤버가 없어서 None 만 나옴 -> 테스트 코드가 정상적인 상태인지 확인 불가 -> 그럼 taget_user id 를 가져오는 함수 대신 test_user id 를 가져오는 함수를 만들어서 테스트하자 (해당 함수에서는 b2b 멤버 5명 정도의 id 임의로 가져오기)
def _get_test_user_ids(self):
        with transaction_scope(True) as read_session:
            self.r_session = read_session

            b2b_member_list = self.r_session.query(B2bㅁㅁㅁ.member_id).filter(
            ).order_by(
                desc(B2bㅁㅁㅁ.created_at)
            ).limit(5).all()

            all_test_user_ids = [b2b_member_info.member_id for b2b_member_info in b2b_member_list]

            if all_test_user_ids.__contains__(0):
                all_test_user_ids.remove(0)

            return all_test_user_ids
▷ 추가적으로 run (=main 에 해당) 함수, 마지막 crm_source 데이터 리스트를 만드는 함수 일부 수정하여 속성 추가 및 테스트 진행 (ex. print 추가하여 분석하기 쉽게 테이블 속성 순서대로 예쁘게 출력하기)
▷ 'A파트' 4개/8개 (50%) 속성 추가 - But 예외 케이스 핸들링 추가 작업 필요

▷ 퇴근~~ 주말에 리팩토링 공부 필요
Insight : 디버깅은 소중하다 ✨

리팩토링 고민 (추가 공부 필요)

  • 코드가 점점 길어진다 -> 분리 필요 -> 어떻게 분리할 것인가
  • 현재 테스트 방식, 올바른 방법인가 -> 살짝 dirty 한 느낌이 들고 있다
  • DB 접근 -> 흐름도 체크해서 효율성 높일 수 있는지 확인 필요
일단 주요 안건은 이렇게 3가지. 실무 관련 인프런 강의도 구입해놓은 만큼 주말에 공부하자~~ (To. 미래의 나 / 진짜 해야됨 진짜 해야됨)

작성하면서 느낀 건데, 학부 때 하던 고민은 똑같이 하고 있는 느낌이다.

뭔가 더 좋은 방법이 있을 것 같은데...! 하면서 일단 마감 맞춰서 급하게 뚝딱뚝딱 하는 느낌 (Noooo)

이제는 진짜 현업에서 일하고 있는 만큼 실무적인 고민, 공부를 진행하자.

현재 리팩토링 관점이 나에게 부족한 것 같다. 공부 필요~~