전국 병의원을 대상으로 건강검진 예약·관리 솔루션을 제공하는 B2B 헬스케어 기업입니다.
기존 데스크톱 시스템을 React로 현대화하고 Electron으로 패키징해 데스크톱 앱으로 제공하는 프로젝트에 프론트엔드로 참여했습니다.
주 사용자는 병원 접수처 직원입니다. 이 사실이 제가 내린 판단 대부분의 기준이 됐습니다. 환자가 줄 서 있는 상황에서 화면이 1초 늦게 뜨면 그건 바로 대기 시간입니다.
Lighthouse 33~35 → 52 · LCP 12.1s → 4.8s · TBT 4,060ms → 460ms
수작업 1시간+ → 10분 · 불필요한 API 호출 30% 감소
9~10명 팀 · 진행 중이던 프로젝트에 중간 합류 · 커밋 400+건
초기 진입 시 LCP가 12.1초였습니다. Lighthouse 점수는 33~35점.
원인을 찾아보니 두 가지가 겹쳐 있었습니다.
첫째, 모든 페이지 컴포넌트가 정적 import였습니다. 접수 화면 하나 보려고 예약관리·검사관리·통계까지 전부 번들에 실려 왔습니다.
둘째, 라우팅이 조건부 JSX 나열이었습니다.
{v.id === MenuIdEnum.RSVN_MANAGE && <RsvnManage />}
{v.id === MenuIdEnum.EXAM_MANAGE && <ExamManage />}
// 메뉴 수만큼 계속
메뉴를 추가할 때마다 이 목록에 줄을 더해야 했습니다. 코드 스플리팅을 붙이기도 어려운 구조였고요.
① 심플 팩토리 패턴으로 전환
조건문 나열을 맵으로 바꿨습니다.
const PAGE_COMPONENTS: Record<number, React.ComponentType> = {
[MenuIdEnum.RSVN_MANAGE]: lazy(() => import("...")),
[MenuIdEnum.EXAM_MANAGE]: lazy(() => import("...")),
}
이제 메뉴 추가는 항목 하나 추가로 끝납니다. 그리고 값이 lazy()라서 코드 스플리팅이 자연스럽게 붙었습니다. 최적화를 하려고 구조를 바꾼 게 아니라, 구조를 바꾸니 최적화가 가능해졌습니다.