프로젝트 배경

기존 컴포넌트 구조는 props drilling, 불필요한 리렌더링, 낮은 재사용성 등의 문제를 겪고 있었습니다. 성능 최적화와 유지보수성 향상을 위해 전면적인 아키텍처 개선이 필요했습니다.

AS-IS

장점

  • 단순한 데이터 흐름

고려할 점

  • Props drilling 5개 이상
  • 불필요한 리렌더링
  • 낮은 재사용성
  • 컴포넌트 비대화

TO-BE

장점

  • 전역 상태 직접 구독
  • 컴포넌트 분리로 재사용성 확보
  • 렌더링 최적화

고려할 점

  • 전역 상태 의존성 증가

주요 구현 내용

1. 컴포넌트 분리 및 추출

Summary 컴포넌트에서 ClusterRow를 106줄 추출하여 단일 책임 원칙을 적용했습니다. 클러스터 행 렌더링 로직을 독립화하고 재사용 가능한 컴포넌트로 설계했습니다. CommitItem 컴포넌트도 104줄을 분리하여 커밋 아이템 렌더링 로직을 캡슐화했고, Props 인터페이스를 명확히 하여 테스트 용이성을 향상시켰습니다.

Summary (리팩토링 후)
  • ClusterRow (106줄 추출)
    • CommitItem (104줄 추출)
  • VerticalClusterList
    • ClusterGraph (전역 상태 구독)

2. Props Drilling 제거

전역 상태를 직접 구독하는 방식으로 전환했습니다. ClusterGraph에서 filteredData props를 제거하고(7줄 추가, 11줄 삭제), Detail 컴포넌트를 전역 상태로 마이그레이션했습니다(5줄 추가, 6줄 삭제). 중간 컴포넌트에서의 불필요한 props 전달을 제거하여 컴포넌트 간 결합도를 감소시켰습니다.

3. 불필요한 리렌더링 방지

클러스터 선택 상태를 분리하여(117줄 추가, 62줄 삭제) 상태 변경 시 영향 범위를 최소화했습니다. React.memo와 useMemo를 활용하여 렌더링 성능을 대폭 개선했습니다. 계산 로직도 최적화하여 clusterSizes props를 제거하고 컴포넌트 내부에서 직접 계산하도록 변경했으며(9줄 추가, 17줄 삭제), isExpanded 계산을 ClusterRow 내부로 이동시켰습니다(2줄 추가, 4줄 삭제).

4. Props 구조 개선

isExpanded 기반 구조로 전환하여 clusterId/selectedClusterIds props를 isExpanded로 대체했습니다(4줄 추가, 6줄 삭제). 컴포넌트 인터페이스가 단순해졌고, 의도가 명확한 props 네이밍으로 가독성이 향상되었습니다.

5. 네이밍 일관성 개선

selectedClusterId를 selectedClusterIds로 일관성을 확보했고(7줄 수정), getClusterIds를 getSelectedClusterIds로 명확화하여(5줄 수정) 코드 가독성과 이해도를 향상시켰습니다.

  1. 컴포넌트 분리
  2. Props Drilling 제거
  3. 리렌더링 방지
  4. 인터페이스 단순화

기술적 성과

⚡

성능

불필요한 리렌더링 제거

🧩

유지보수성

컴포넌트 분리로 이해도 증가

♻️

재사용성

독립 컴포넌트로 활용 범위 확대

🧪

테스트 용이성

작은 단위로 테스트 작성 용이

사용 기술

  • TypeScript
  • React (Hooks, Context API)
  • 전역 상태 관리
  • React 성능 최적화 (React.memo, useMemo, useCallback)
  • 컴포넌트 설계 패턴

측정 가능한 결과

리팩토링 규모
항목비교값 (줄/개)
컴포넌트 분리210210 줄/개
Props Drilling 제거55 줄/개
총 리팩토링300300 줄/개

총 300줄 이상의 컴포넌트 분리 및 리팩토링을 수행했습니다. Props drilling을 5개 이상 제거하여 컴포넌트 재사용성이 향상되었고, 불필요한 리렌더링이 감소하여 렌더링 성능이 개선되었습니다. 전반적으로 코드 복잡도가 낮아져 유지보수가 용이해졌습니다.