최근에 마음이 급해서 우선 돌아가는 코드를 짜려다 보니 최소한의 설계도, 코드품질도 없이 급급하게 코드를 짜곤 했는데요. 주말을 맞이하여 리팩토링을 해보았습니다.
데이터 시각화를 위한 차트의 경우에는 특정 조건별 데이터를 뽑아내야 합니다.
ex (a)특정기간별 매출 (b)상품종류별 매출 (c)신고종류별 횟수
오늘은 특정기간, 상품종류에 따라 데이터를 보여주는 코드를 리팩토링하며 배운점들을 적어보고자 합니다.
차트는 시간에 따른 데이터가 들어가다보니 결국 데이터는 배열형태로 들어가야 합니다. 그렇다면 특정 기간별 데이터는 어떻게 뽑아내는것이 좋을까요?
const batch1breakstart = moment('2019/07/20').diff(moment('2019/04/14'), 'days')
const batch1breakend = moment('2019/09/16').diff(moment('2019/04/14'), 'days')
const batch2start = moment('2019/07/18').diff(moment('2019/04/14'), 'days')
const batch3start = moment('2019/11/11').diff(moment('2019/04/14'), 'days')
const copedReportsWithBrokenByDayBatch1 = reportsWithBrokenByDayBatch1.slice()
const copedReportsWithBrokenByDayBatch2 = reportsWithBrokenByDayBatch2.slice()
const copedReportsWithBrokenByDayBatch3 = reportsWithBrokenByDayBatch3.slice()
copedReportsWithBrokenByDayBatch1.splice(batch1breakstart, batch1breakend - batch1breakstart - 1)
copedReportsWithBrokenByDayBatch2.splice(0, batch2start)
copedReportsWithBrokenByDayBatch3.splice(0, batch3start)
그러나 splice의 인자인 시작일과 끝일을 맞춰주는것도 어렵고, slice로 복사한것을 splice로 자르는 이런 난잡한 과정이 찜찜했습니다. 중간의 시작일과 끝일도 하드코딩이 되어있구요.
생각해보면 배열의 원소를 객체로 만들고 시간을 key값으로 가지고 있으면 필터하기가 훨씬 더 쉬운것같아서 데이터형식을 변경해주었습니다.
const BATCH_1_BREAK_START = '2019-MM-AB'
const BATCH_1_BREAK_END = '2019-MM-CD'
const BATCH_2_START = '2019-MM-EF'
const BATCH_3_START = '2019-MM-GH'
const filteredReportsWithBrokenByDayBatch1 = reportsWithBrokenByDayBatch1.filter(s => !moment(s.reportAt).isBetween(BATCH_1_BREAK_START, BATCH_1_BREAK_END))
const filteredReportsWithBrokenByDayBatch2 = reportsWithBrokenByDayBatch2.filter(s => moment(s.reportAt).isSameOrAfter(BATCH_2_START))
const filteredReportsWithBrokenByDayBatch3 = reportsWithBrokenByDayBatch3.filter(s => moment(s.reportAt).isSameOrAfter(BATCH_3_START))
진짜 왜 splice를 처음에 사용했을까요? 1분만 멈춰서 생각해볼걸 그랬어요.
특정 상품별 데이터를 보여주는 코드는 원래 상품종류가 N가지라고 했을때 N개의 배열이 하드코딩이 되어있었습니다. 그런데, 상품의 종류가 늘어날때마다 새로운 배열을 만들고 다시 차트에 추가하는 해야한다면요?
단기적으로 마음이 편할 수 있지만 그것이 장기적으로 손해인것은 확실한것같습니다.
그래서 우선, 하드코딩된 데이터들을 일괄 처리할 수 있는 방법에서부터
리팩토링을 시작해보았습니다.
아래의 코드는 차트의 시간축을 구하는 로직입니다.
기존의 코드는 이렇게 하드코딩이 되어있었는데요.
const dayLabelsBatch1 = props.dayAxis.filter(time => !time.isBetween(BATCH_1_BREAK_START, BATCH_1_BREAK_END)).map(formatWithDOW)
const dayLabelsBatch2 = props.dayAxis.filter(time => time.isSameOrAfter(BATCH_2_START)).map(formatWithDOW)
const dayLabelsBatch3 = props.dayAxis.filter(time => time.isSameOrAfter(BATCH_3_START)).map(formatWithDOW)
아래와 같이 idx별로 validTimeFilter를 리턴하는 함수를 만들고, idx별로 다르게 실행하도록 하였습니다.
const validTimeFilterByBatch = (idx) => (time) => {
let condition
switch (idx + 1) {
case 1:
condition = !time.isBetween(BATCH_1_BREAK_START, BATCH_1_BREAK_END)
break
case 2:
condition = time.isSameOrAfter(BATCH_2_START)
break
case 3:
condition = time.isSameOrAfter(BATCH_3_START)
break
}
return condition
}
const dayLabelsByBatch = Array(BATCH_AMOUNT).fill({}).map((el, idx) => props.dayAxis.filter(time => validTimeFilterByBatch(idx)(time)).map(formatWithDOW))
validTimeFilter는 dayLabelsByBatch 뿐만아니라 시간에따른 필터가 필요한 부분에서는 계속 사용할 수 있게되었네요!