6월 회고
서론
6월 1,2주차는 고민이 상당히 많았던 한 주이다.
더 많은 다양한 문제를 만나고 싶은데,,, 현재 프로젝트나 여러 상황이 갑자기 나에게 작게 느껴져서 온전히 집중하지 못했다. 이런 상황에도 매일 감사하려고 했음에도 불구하고 갈망이 있었던 것 같다.
하지만 6월 2주차 사업하는 친구, 개발자 선배님들과 커피챗을 하면서 느낀 것은 결국 "넌 고객의 문제를 해결해준 경험이 있어?"라는 질문에 대한 답변을 찾는 것이 중요하다는 것으로 수렴했다.
현재 다니고 있는 회사에서 더 일을 잘해야 한다는 것을 다시 느꼈다.
"나는 얼마나 고객을 신경썼는가..."
"나는 고객을 이해하기 위해 얼마나 노력했는가..."
회고해보며, 6월 3주차부터는 기술을 활용하여 문제를 해결하는 데 더 예민한 감각으로 나아가려고 했다.
이런 맥락으로 월간 레포트 기능을 제안하였고 개발하기 시작했고 이후 새로운 길이 열리기 시작했다.
"그러던 어느날 두 군데의 서류 합격을 받게 됐다." 어라??
6월 Action Point
- 월간 리포트 생성 및 저장 기능 구현하기
- 퓨랩 디자인 시스템 업무 프로세스 정착
- 객체 지향의 오해와 진실 읽고 생각 정리
- 단위 테스트 기술 책 읽고 생각 정리 -> 프론트엔드 가장 만만한 로직부터 단위 테스트 적용하자!
- Next.js 스터디를 통해 Insight 정리해서 공유하기 (생각없이 스터디 금지)
- 네트워크 공부를 통해 사고를 확장시켜보자
- XSS에 대해 학습 및 결과물 정리
- CSRF에 대해 학습 및 결과물 정리
- OAuth에 대해 깊이 학습 및 결과물 정리
계획하진 않았지만 해낸 것
- 더 기여할 수 있는 환경으로 이직
공부는 당장 필요하지 않다고 생각해서 우선순위를 미뤄뒀더니... 체크하지 못한 것들이 많다. 하지만 가장 치열하게 산 한 달이었다.
두 군데 최종 합격을 하고 느낀점은 정말 고객의 문제를 해결해보는 경험은 천하 무엇보다 귀하구나를 느꼈다. 이젠 미친 듯이 고객을 이해하는 데 집중하려고 한다. 결국 한 명이라도 고객은 고객이다.
본론
월간 리포트 기능 기획 및 개발
이게 무엇인가 싶을 것 같아 간단하게 불릿포인트로 당시 상황을 정리해보려고 한다.
우선 빠르게 만든 프로토타입부터 살펴보자.
왜 이 기능을 제안하고 구현하게 됐나
-
Problem
- 가상 자산 급등락으로 인해 고객 문의 폭주, 응대로 인해 동료들 잠을 자지 못하는 문제 발생!
-
Action
- 고객의 불만에 대해 선제 대응하는 방식으로 월간 리포트 기능 제안 (과거에 시도했다가 지속하지 못했던 기능)
- 하지만 고객이 많아, 일일이 월간 리포트 발행하는 것이 현실적으로 어렵다는 의견
- 그렇다면 대시보드 내에서 자동화 기능 제안 및 구현
- 하지만 고객이 많아, 일일이 월간 리포트 발행하는 것이 현실적으로 어렵다는 의견
- 고객의 불만에 대해 선제 대응하는 방식으로 월간 리포트 기능 제안 (과거에 시도했다가 지속하지 못했던 기능)
-
Result
- 월간 리포트 기능을 통해 리포트 생성 시간 480분 => 2분 (99.6% 감소)
- 결과적으로 고객 응대 빈도 전월 대비 평균 30건 => 12건 (60% 감소)
기능 기획
기획을 시작해보았다.
1. 월간 리포트를 작성하는 어떤 정보가 포함되어야 하는 거지?
우선 과거의 히스토리를 찾아보기 시작했고 과거에 월간 리포트 ppt를 동료에게 받았다. 그래서 동적으로 처리할 것들과 정적으로 처리할 것들을 분리하고 데이터를 정리하기 시작했다. 자세한 내용을 작성하긴 어렵지만 아주 간단하게 정리해보면, 우리 사내 활성 계좌는 꽤 많다. 우선 리포트는 기관과 1대1 매칭되는 것이 아니라 각 기관 아래에 있는 계좌들과 1대1 매핑되는 것을 발견했다.
하나의 계좌를 생성한 이후로 수익 그래프, 수익과 관련된 데이터를 보여줘야 한다. 그런데 이 데이터는? 어떻게 확보할 것인가... 대시보드 내에 흩뿌려져 있어서 프론트에서 조합을 해야 한다.
2. 어떻게 만들어야 사용할 때 편하고 즉시 동료들이 사용할 수 있을까?
가장 쉬워야 한다. 한눈에 파악되어야 한다.
음... 이게 가장 어려웠는데 우선 이 기능이 실제 문제를 해결하는 데 도움이 되는지 파악하기 위한 단계이기에 막 멋지게 만들 필요가 없었고 정말 도움이 되는지만 파악하면 됐다. 그래서 위와 같이 만들었다.
간단한 플로우는 다음과 같았다.
report Tab 클릭 --> 계좌 선택 -> export
우선 계좌를 선택해야 했고 그리고 export 할 수 있는 버튼이 필요하다고 생각했다.
Q. 그렇다면 export된 결과물은 어떤 포맷으로 export 되어야 하는지 고민이었다.
우선 PDF로 변환되도록 구현했다. 그렇게 구현하니 문제가 생각보다 복잡해졌다. pdf로 변환하도록 하니 완벽하게 구현해야 되는 것을 발견했다. 왜냐하면 수정하기가 어렵기 때문이었다. 그리고 pdf로 변환할 때 CSS가 반영이 안 되는 문제가 발생했다. 그래서 하루정도 고생했었다. 과감하게 다시 생각해보기 시작했다. 원하는 결과물은 pdf이지만 우선 데이터만 복사할 수 있도록 ppt 형식으로 export 되도록 할 수 있을까? 싶어서 시도해봤는데 우선 pptx 쉽게 변환할 수 있는 라이브러리를 찾았고 사용해보니 우선 이게 맞다는 생각이 들었다. 그리고 결과적으로 이게 더 유용했다.
구현하다 보니 내가 만드는 것은 월별 리포트라는 것임을 다시 자각했다... 그 말인 즉슨 특정 계좌의 원하는 월을 선택할 수 있어야 하고 해당 월의 데이터만 필터해서 그래프와 테이블로 표현해야 한다는 것이다. 어라... 조금씩 복잡해지기 시작했다.
그래서 플로우가 수정됐다.
report Tab 클릭 --> 계좌 선택 --> 월 선택 -> export
그런데 추가적으로 사용하는 입장에서는 눈으로 데이터가 맞는지 미리 확인하고 싶을 수 있을 것 같았다. 그래서 동료에게 물어보니 확인할 수 있으면 좋겠다는 피드백을 즉시 받을 수 있었다.
그래서 또 플로우가 추가됐다.
report Tab 클릭 --> 계좌 선택 --> 월 선택 -> 해당 리포트 내부 페이지에 렌더링 혹은 export
내가 생각했던 것은 이게 아닌데 생각보다 기능이 복잡해 보였다. 호언장담하게 1주일만에 결과를 보이겠다는 말이 거짓이 될 것 같다는 느낌이 들었다. 하지만 이게 있으면 동료에게 도움될 것 같아서 긴장은 됐지만 더 설렜다.
기능 개발
1. 그래서 구현은 어떻게 할 건데??
우선 그래프는 생각보다 금방됐다.
export const AumChartForReport = () => {
const { isMobile } = useDevice();
const { data: accountList } = useSuspenseQuery(AccountQueries.getAdminAndStaffAccountsQuery());
const uniqueStrategies = getUniqueFieldValues(accountList, 'strategy');
const { getFilteredAums } = useHistoricalAumWithStore();
const result = queryTotalEquityByDate(getFilteredAums());
const sortedList = result.sort((a, b) => a.timestamp - b.timestamp);
const { filteredData, timeRange, handleTimeRange } = useDurationFilter(
sortedList,
(item) => item.timestamp,
);
const { data: organizationList } = useSuspenseQuery(OrganizationQueries.getAdminOrgQuery());
const { filters, handleStrategy, handleOrganization } = useFilterByDomain();
return (
...
)
}
비즈니스 로직은 완벽하지 않지만 어느 정도 커스텀 훅으로 분리를 시도 했다. 그래서 해당 훅만 복사해서 새로운 View 컴포넌트를 만들어보니 바로 동작하는 것을 확인했다.
오호!!?
그리고 해당 그래프를 html2canvas
라는 라이브러리로 DOM을 이미지로 변환해서 ppt에 나타나도록 했다.
그럼 하단 테이블과 그에 맞는 데이터는?
생각보다 이 부분도 수월했다. 기존에 수익률 트래킹 기능을 구현하면서 구현했던 로직을 재활용할 수 있었다. 당시에는 수익률을 선택한 날짜 기준, 일, 월, 연도 별로 계산하는 로직을 다른 데서 사용할지 몰랐지만 당시 고민하면서 구현한 게 도움이 많이 되고 있다. 역시 함수의 인자는 3개 이하로 좁히고 내부에서도 한 가지 일만 하도록 하고 명석님의 클린 코더에서 나온 command와 query를 분리하여 함수를 만드는 게 핵심이었던 것 같다.
- command는 내부에서 상태를 변경하고 Return 값이 없는 함수
- query는 내부에서 상태를 변경하지 않고 Return 값을 갖는 함수
도메인 지식을 요구하는 로직이라 간단히 공유해보면,
const PerformanceSection = ({
filteredDailiesBySelectedMonth,
filteredDailiesFromInception,
}: {
filteredDailiesBySelectedMonth: Dashboard['dailies'];
filteredDailiesFromInception: Dashboard['dailies'];
}) => {
const earliestDailyFromInception = getEarliestTimestamp(filteredDailiesFromInception);
const earliestDailyFromMonth = getEarliestTimestamp(filteredDailiesBySelectedMonth);
const latestDaily = getLatestTimestamp(filteredDailiesFromInception);
const returnValue = calcReturnMonthAndYearToDate({
dailies: filteredDailiesBySelectedMonth,
selectedDate: dayjs.unix(latestDaily.updatedTimestamp).toDate(),
key: "month",
});
const mdd = calculateMaxDrawdown(filteredDailiesBySelectedMonth);
const inceptionMdd = calculateMaxDrawdown(filteredDailiesFromInception);
return (
...
)
}
해당 함수들은 다 계산 함수이다. 그래서 단위 테스트로 로직이 잘 동작하는지 검증하고 있고 그래서 안심하고 동료에게 수치는 로직대로 동작한다고 말할 수 있게 됐다.
이런 방식으로 재활용하니 생각보다 구현이 어렵지 않았다.
pptxgenjs를 활용해서 화면에 보이는 테이블이 피피티로 export할 때도 동일하게 나타나도록 했다.
4. 어떻게 개선하면 좋을까? (미래 동료에게 전달 예정)
우선 지금은 머리속에 있는 아이디어만 구현해놓은 상태이다.
먼저는 지금은 PPT로 export해서 이를 pdf로 복사 붙여넣기해서 고객에게 월별 리포트를 보내지만 아예 PDF로 나오도록 할 수 있을 것 같다. 하지만 생각보다 렌더링이 제대로 안 되는 문제가 발생할 수 있다. 이럴 경우는 서버에서 해당 기능을 구현해서 해결할 수 있을 것 같다. 가령 puppeteer를 사용하면 서버에서 Chromium을 활용하여 기능을 구현할 수 있을 것 같다. 그러면 더 정확하게 이미지나 DOM을 PDF로 바꿀 수 있지 않을까 생각해본다.
유저가 접근할 수 있는 페이지에 월별 리포트 자체를 보여줘도 참 좋을 것 같다고 생각한다.
지금은 웹이라 푸시 알림을 구현할 수 없다. PWA로 하면 가능은 하겠지만 고객들이 원하지 않음을 발견해서 그렇게는 하지 못했다. 그렇다면 간단한 앱을 만들어서 푸시 알림을 통해 리포트를 제공하는 방식도 어떨까 싶다. 이게 고객들이 원하는 것일까 고민해본다.
태어나서 첫 이직 무사히 Clear
24년 6월 13일에 퓨쳐리즘랩스라는 너무 감사한 회사를 만나 입사하게 됐다. 당시 DND, 개인 프로젝트 등 실무 경험이 없는 나를 믿어주고 기회를 준 회사다. 정말 힘들 때 계속 상고해보면서 감사를 잃지 않을 수 있을 것 같다.
그로부터 1년이 지난 지금 갑작스레 더 다양하게 기여할 수 있는 동시에 개인적으로 많은 성장을 할 수 있는 회사의 문이 열렸고 오퍼를 받게 됐다. 실은 이직의 이유 중 가장 큰 것은 더 많이 기여할 수 있는 환경이라는 것. 현재는 대시보드 프로젝트만 주로 기여하고 있어서 개인적으로 더 다양하고 어려운 프로젝트에 대한 갈망이 있었다. 그러던 와중 이직할 회사에는 플랫폼 회사로 기여할 수 있는 것들이 면접을 통해 들어만 봐도 5가지였다. 도저히 매력적이지 않을 수 없었다.
나에게도 지금 현 직장에도 도움이 되기 위해선 조금 더 성장에 초점을 맞춰서 선택해보려고 한다. 진심으로 감사했고 그 것들을 7월초에 잘 표현하고 마무리하려고 한다. 7월은 내 인생에서 가장 차분하고 즐거운 한 달이 될 것 같다. 기대해본다.
결론
이번 한 달간 일하며 여러 경험을 하며 개발에는 많은 시간을 사용하지 못했지만
느낀 것은 결국 기여 중심적 사고
가 중요함을 느꼈다.
집에서도 회사에서도 나에게도 스스로 기여하는 삶을 살아야겠다고 다짐해본다. 더 적극적으로 더 주도적으로 살아내야겠다.
7월에는 지난 1년간 했던 것들을 정리해보고 부족했던 것들을 복기하며 다음 스텝을 준비하는 시간을 가져보려고 한다. 인생에서 너무 귀한 시간일 것 같다. 부모님과 그간 못 뵀던 친척들 은사님들을 찾아뵐 예정이다.
모두 각자의 위치에서 파이팅
7월 Action Point
개발 관련
- 현재 개인적으로 진행하고 있는 카페 실시간 정보 조회 프로젝트 화면 구현
- 입사할 회사 기술 스택 활용해서 개인 프로젝트에 적용해보기 (Next.js, react, python, postgresql, Nest.js, zustand)
일상 관련
- 퓨랩 인수인계 및 마무리 지혜롭게 하기
- 1년 간 했던 것들 정리하여 경력 기술서에 정리하기
- 건강한 루틴으로 휴식하며 1kg 감량하기
- 부모님 모시고 생일에 즐거운 시간 보내기