← portfolio

모립 (morib)

2024 · React · TypeScript · Framer Motion · Tailwind · Electron

Saas 기반 생산성 웹 애플리케이션

사용자가 할일을 생성·관리하고, 할일을 선택한 뒤 타이머를 실행해 서로의 작업 집중 시간을 공유하는 생산성 도구입니다.

사용 기술 React, TypeScript, Framer Motion, MSW Tailwind CSS, Electron

1년 가까이 이어진 프로젝트로, UX 개선·유지보수를 진행했습니다. 번들 분석으로 초기 로딩 병목을 찾아 코드 스플리팅과 Preloading으로 풀어냈습니다. 서버 작업이 지연되는 동안에는 MSW 기반 API 모킹 환경을 구축해 클라이언트 작업을 멈추지 않고 진행했고, 랜딩페이지를 전담 제작해 Framer Motion 기반 스크롤 위치 추적 인터랙션도 구현했습니다. 타이머 provider 영역을 축소해 타이머 페이지 리렌더링 범위를 줄이는 등, 사용자 흐름에 직접 영향을 주는 레거시 코드도 우선적으로 정리했습니다.

코드 스플리팅과 onMouseEnter Preloading으로 초기 번들 경량화

문제 상황 React SPA 특성상 사용하지 않는 컴포넌트까지 초기에 한 번에 불러와 첫 화면 렌더링이 지연되고 있었습니다. 번들을 분석해보니 두 곳에서 초기 진입에 불필요한 용량이 함께 묶이고 있었습니다. - LoginPage의 Lottie 애니메이션: Login 페이지에서만 쓰이는 Lottie가 Home 번들에도 포함돼, 첫 화면 진입까지 무거운 의존성을 끌고 들어왔습니다. - HomePage의 Calendar(DatePicker) 컴포넌트: BoxCategoryModalAddCategory에서 카테고리를 추가할 때만 쓰이는데도, HomePage 진입 시점에 함께 로드되고 있었습니다. 해결 두 경우 모두 React.lazy로 분리하고 Suspense로 감싸 사용 시점에만 청크가 로드되도록 코드 스플리팅했습니다. 다만 lazy만 적용하면 사용자가 액션을 취한 순간에 로딩이 시작돼, 클릭하고 나서 화면이 뜨기까지 짧은 빈 시간이 생기는 문제가 있었습니다. 이를 막기 위해 onMouseEnter 시점에 다음에 쓸 청크를 미리 prefetch하는 Preloading을 함께 적용했습니다. - LoginPage: 로그인 버튼에 마우스가 올라오면 HomePage 청크를 prefetch해, 로그인 직후 라우트 전환이 지연 없이 이어지도록 처리했습니다. - Calendar: + 버튼과 날짜 토글에 마우스가 올라오면 Calendar 청크를 선반입하도록 하고, 두 컴포넌트가 공통으로 쓰는 로직은 usePreloadCalendar 훅으로 분리해 재사용성을 확보했습니다.

export const usePreloadCalendar = () => {
  const [isCalendarLoaded, setIsCalendarLoaded] = useState(false);

  const preloadCalendarComponent = useCallback(() => {
    if (!isCalendarLoaded) {
      import('@/shared/components/Calendar').then(() => {
        setIsCalendarLoaded(true);
      });
    }
  }, [isCalendarLoaded]);

  return { isCalendarLoaded, preloadCalendarComponent };
};

성과 Login·Home 페이지 초기 번들에서 무거운 의존성이 빠져 첫 화면 렌더링이 가벼워졌고, 사용자가 실제로 액션을 취하는 시점에는 prefetch가 이미 끝나 있어 클릭 → 표시 사이 지연 없이 자연스럽게 이어집니다.

MSW 기반 API 모킹 환경 구축으로 서버·클라이언트 작업 병렬화

문제 상황 서버 파트 작업이 지연되면서 클라이언트 측 페이지·UI 작업이 함께 멈춰 있었습니다. 응답 스펙은 정의돼 있었지만 실제 API 응답 없이는 데이터 흐름이 끊겨, 페이지 연동·로딩 처리·에러 케이스를 미리 검증할 수 없었습니다. 해결 MSW(Mock Service Worker)를 도입해 실제 네트워크 요청을 가로채는 모킹 환경을 구축했습니다. 페이지에서 사용되는 API 엔드포인트마다 핸들러와 응답 타입을 정의해 실제 API와 동일한 인터페이스로 동작하도록 만들었고, 페이지와 직접 연동해 서버 작업이 끝나기 전부터 데이터 흐름을 검증할 수 있게 했습니다. 트러블 슈팅 핸들러에서 request.body를 그대로 읽었더니 응답 값을 확인할 수 없는 이슈가 있었습니다. fetch 스타일의 Request 객체에서 bodyReadableStream 형태로 제공되어 RAW 상태에서는 JSON으로 바로 접근할 수 없었고, request.json() 메서드로 스트림을 파싱해 해결했습니다. 성과 서버 응답을 기다리지 않고 클라이언트 단독으로 페이지·로딩·에러 흐름을 작업할 수 있게 됐고, 실제 API 연결 시점에는 핸들러 인터페이스를 그대로 따라가면 돼서 통합 비용도 줄었습니다.