지난 빅쿼리 파이프라인 구축기에 이은 작업인 통계 데이터 및 api 개발 회고.
들어가며
지난 회고에서 빅쿼리로 유저정보에 대한 데이터 ETL 파이프라인을 만들었었다. 이제 적재되는 데이터를 가지고 2차 가공을 해서 실제 회사내부 사람들에게 보여질 통계 데이터를 만들 차례이다. 이번엔 먼저 데이터베이스를 만들에 계산된 통계 데이터를 넣고, 그 테이블들을 조회해 백엔드와 프론트엔드를 통해 유저들에게 보여질 api를 만드는 작업까지 하게 되었다. 이번 작업은 어느정도 제 시간에 맞춰 끝낼 수 있을줄 알았는데 지난 번과는 또다른 시행착오들을 겪으며 또 스케줄이 늘어지게 되었다. 그래도 작년보단 비슷한 작업에서 훨씬 덜 헤맬 수 있어서 어느정도 발전했구나 느낄 수 있었다. 이번에도 기록을 남겨 어떤 작업을 했었는지 돌이켜 보려고 한다.
설계 및 개발
유저에게 보여지는 화면까지 나가야하는 작업이었기 때문에 기획 디자인 문서가 따로 존재했다. 기획문서를 살펴보면서 유즈케이스를 정리하면서 개발문서를 작성했다. 문제별로 정답률이나 학습시간 같은 것을 보여주는 것이 요구사항이었다. 제일 중요했던 것은 학년 별로 통계 정보를 확인할 수 있어야한다는 것이었는데, 이 부분의 데이터를 어떻게 쌓을 것인가에 대한 고민이 처음엔 많았다. 학년이나 문제의 선택지 개수 같은 것은 변동적이기 때문에 정해진 스키마로 관리 할 수 없어서 json 타입을 이용하기로 했다. 첫 설계는 테이블이 하나였기 때문에 목적에 맞는 값들만 계산해서 넣을 수 있도록 효율적이게 코드를 짰다. 하지만..
리팩토링
피할 수 없는 리팩토링. 개발이 완료 될때쯤 api 개발로 슬슬 넘어가게 되면서 뒤늦게 문제점들을 발견했다. sorting이 필요한데 이것을 어디에서 어떻게 처리 할 것인지, 한문제 안에 여러 문제가 존재하는 멀티문제, 원본 문제 하나가 다른 커리큘럼에도 들어갈 수도 있다는 점을 보완해야 했다. sorting은 우리가 order 순서를 보장할 정보를 갖고있지 않다는게 문제였기 때문에 결국 스키마를 수정해 다시 순서보장을 위한 order_id를 쌓고 offset과 limit을 받아 정렬하는 것으로 마무리 지었다. 멀티문제는 디자인적 요소도 있기 때문에 디자인/프론트엔드 팀과 회의를 통해 멀티문제여도 펼쳐서 하나의 문제로 보는 것이 맞다고 결론짓고, 그대로 펼쳐서 보내주기로 했다. 원본 문제가 다른 커리큘럼에 들어가는 부분은 다른 커리큘럼에 속하게 될 경우 풀이하는 학생도, 풀이 순서도 달라지기 때문에 통계치를 각각 따로 계산해서 넣어줘야 한다는 점이 문제가 되었다. 그래서 원본/커리큘럼 path를 따로 두고 계산 할 수 있도록 테이블을 아예 나눠서 관리하기로 했다.
이렇게 크게 세가지의 문제점을 리팩토링하며 고치게 되었다. 이 부분에서 기존 함수에 인자가 마구 추가되고, 어떻게든 만들기 위해 함수를 수정하게 되면서 가용성은 매우 떨어지고 엄청 난잡한 코드가 되어버렸다. 첫 설계부터 제대로 했어야 하는데 점점 클린코드에서 멀어지는 내 코드를 보며 마음이 너무 아팠다.. 하지만 기획이 바뀌는 경우는 굉장히 많기 때문에 꼼꼼한 설계도 중요하지만 알맞은 방법으로 리팩토링하는 것도 중요하다고 다시금 느꼈다.
Airflow
이번에도 역시나 에어플로우가 문제가 되었다. 여러 통계정보에 대한 dag을 동시에 돌리다 보니 연산량이 미친듯이 증가해 8기가 메모리가 부족해 자꾸만 뻗어버리는 것이다. 그래서 적용한 방법은, 일차적으로 기존에 (eks) 노드 그룹이 두개였는데 airflow worker가 이상한 곳에 붙어서 동작 하던 것을 노드그룹을 하나로 줄여버리고 그 노드그룹의 메모리 스펙을 16기가로 올리는 것이었다. eks 배포를 전임자가 했었기 때문에 어떤 식으로 나뉘어서 동작하던지 잘 파악하지 못하고 있었어서 이번 기회에 살펴보면서 정리하는 작업을 했다. 노드그룹 정리를 마치고 dag도 연산량이 많은 경우 순서를 적용해 동시에 실행되지 않고 하나를 끝마치면 돌 수 있도록 했다. 이렇게 두가지 방법을 적용하니 이제 쾌적하게 돌아가는 것을 확인 할 수 있었다!
API 개발
에어플로우를 통해 하루에 한번 통계정보를 적재 할 수 있도록 돌려놓은다음, api 개발에 들어가게 되었다. 다시 api 설계문서를 작성하고, 백엔드 팀과 회의를 통해 request&response 를 정의해나갔다. 콘텐츠 순서인지, 정답률 별 정렬인지와 offset limit을 받아 페이지 단위로 정렬해 정보를 보내 줄 수 있도록 스키마를 만들고 fastapi로 구현해 기존에 사용하던 eks 클러스터에 올렸다. ETL 작업은 워낙 복잡한 처리작업이 많았는데 api는 그보단 비교적 짧은 시간에 끝낼 수 있었다.
이번 작업에서는 확실히 저번보다 속도가 붙는 것을 느꼈고, 에어플로우도 한번 삽질하며 많은 에러를 마주했더니 덜 헤매며 작업 할 수 있었다. 경험치가 쌓여가는 기분도 들지만 한편으론 또 아직 멀었다는 것도 동시에 느끼고 있는 중이다. 특히 쿠버네티스는 한번 뭐가 안되기 시작하면 어디서 어떤 것이 문제인지 디버깅하는게 아직은 어렵기 때문에 막막하고 더 공부를 해야겠다고 느낀다.. Lens마저 없었으면 정말 힘들었을듯. 현재는 일차 개발 마무리를 하고 이제 이차작업이 남았다. 이차 작업을 마치고 또 다른 회고로 돌아와야겠다.
'데이터 엔지니어링' 카테고리의 다른 글
firebase + BigQuery 이벤트로그 쿼리 Tip (0) | 2023.06.19 |
---|---|
Airflow execution date와 실행시간에 대하여 (0) | 2023.05.10 |
Elastic Search & Logstash (0) | 2023.04.12 |
m1 mac에 docker로 Airflow 실행시키기 (0) | 2023.02.06 |
ETL 파이프라인 구축기 (0) | 2023.01.21 |