Files
2nd/00_Raw/프론트엔드 리팩토링 및 코드 유지보수.md
T

77 lines
12 KiB
Markdown

# [[프론트엔드 리팩토링 및 코드 유지보수]]
## 📌 Brief 시 Summary
프론트엔드 리팩토링 및 코드 유지보수는 애플리케이션의 기존 동작을 그대로 유지하면서 코드의 구조, 가독성, 확장성을 개선하는 지속적인 소프트웨어 공학 과정입니다 [1, 2]. 프로젝트가 성장함에 따라 얽혀있는 비즈니스 로직과 UI를 분리하고, 파일 유형이 아닌 도메인 또는 기능(Feature) 단위로 구조를 재편하여 아키텍처의 붕괴를 막는 것이 핵심입니다 [1, 3, 4]. 또한, SOLID나 DRY, KISS와 같은 설계 원칙을 적용하고, 자동화된 린팅(Linting)과 엄격한 Git 거버넌스를 통해 다수의 개발자가 협업하는 환경에서도 기술 부채를 최소화하고 안정적인 시스템을 유지하는 것을 목표로 합니다 [1, 5, 6].
## 📖 Core Content
* **리팩토링의 준비와 테스트 의존성**
* 레거시나 다른 사람이 작성한 React 코드베이스를 리팩토링하기 전에는 반드시 유닛 테스트나 UI 테스트를 먼저 작성하여 기존 기능이 깨지지 않도록 보장해야 합니다 [2].
* Storybook과 연동되는 시각적 회귀 테스트(Visual Regression Testing) 도구(예: Happo, Chromatic)를 활용하면, 리팩토링 과정에서 발생하는 의도치 않은 UI 레이아웃 변경이나 접근성 오류를 자동으로 식별할 수 있습니다 [7].
* 완전히 코드를 갈아엎는 재작성(Rewrite)보다는 한 번에 알림 기능이나 체크아웃 흐름 등 작은 스토어 단위로 기술을 교체하는 '점진적 마이그레이션(Incremental Migration)' 전략이 필수적입니다 [1].
* **아키텍처 및 폴더 구조의 현대화**
* 컴포넌트, 훅, 스타일 등을 단순히 기술적 파일 유형(Type-based)으로 묶는 폴더 구조는 프로젝트 규모가 커지면 유지보수를 극도로 어렵게 만듭니다 [1, 4].
* 2025년 기준 모범 사례는 코드를 기능(Feature) 단위로 묶는 것입니다. 특정 기능 내에 해당 기능만의 컴포넌트, API, 훅 등을 위치시켜 높은 응집도를 확보합니다 [1, 4].
* 더 나아가 **Feature-Sliced Design (FSD)** 같은 아키텍처론을 도입하여, 코드를 app, pages, widgets, features, entities, shared 계층으로 나누고, 상위 계층이 하위 계층에만 의존하게 하는 '단방향 의존성' 및 '단일 진입점(Public API)' 규칙을 강제하여 결합도를 낮출 수 있습니다 [1, 3].
* **코드 품질 및 설계 원칙(SOLID, DRY, KISS) 적용**
* **단일 책임 원칙(SRP):** 300줄이 넘어가는 등 너무 많은 역할을 하는 대형 컴포넌트는 상태 관리, 데이터 페칭, 렌더링 역할을 분리하여 더 작고 집중된 컴포넌트로 리팩토링해야 합니다 [1, 6].
* **로직의 추출과 재사용:** 반복되는 코드를 없애는 'DRY(Don't Repeat Yourself)' 원칙에 따라, 얽혀있는 복잡한 비즈니스 로직과 폼 처리 로직 등을 '커스텀 훅(Custom Hooks)'으로 분리해 리팩토링의 기본 단위로 삼습니다 [1, 6].
* 클래스형 컴포넌트 환경이라면 함수형 컴포넌트와 훅 기반으로 마이그레이션하고, 불필요한 `useEffect`를 제거하며, 타입스크립트(TypeScript)를 도입해 타입 안정성을 확보해야 합니다 [2]. 클라이언트 상태와 서버 상태를 분리해, 서버 데이터는 TanStack Query와 같은 전용 도구를 사용해 관리하는 것이 좋습니다 [1, 2].
* **유지보수를 위한 거버넌스와 표준화**
* React 컴포넌트 파일 이름은 PascalCase, 일반 유틸리티나 훅은 camelCase, 폴더명은 운영체제 간 충돌을 막기 위해 kebab-case를 사용하는 등 일관된 네이밍 컨벤션을 확립해야 합니다 [1, 8].
* 팀 단위 유지보수를 위해 ESLint, Prettier, Husky를 조합하여 커밋이나 병합 전에 아키텍처 경계 위반(예: feature가 다른 feature를 임포트하는 행위)이나 코드 포맷팅을 자동으로 검사하고 수정해야 합니다 [1].
* Git 브랜칭 시 짧은 생명주기를 가진 기능 브랜치(Feature Branch)를 운영하고, 'Conventional Commits' 규칙에 따라 의미 있는 커밋 메시지를 작성하며, 단일 책임에 맞는 작은 PR(Pull Request)을 생성하는 것이 핵심 유지보수 프랙티스입니다 [1, 5, 9].
## ⚖️ Trade-offs & Caveats
* **추상화와 복잡성의 충돌 (DRY vs KISS):** 중복 코드를 줄이기 위해(DRY) 무리하게 재사용 가능한 추상화를 만들면, 오히려 코드를 이해하기 어려워져 KISS(Keep It Simple, Stupid) 원칙을 위배하게 됩니다. 소스 코드 패턴이 최소 3번 반복될 때까지 기다렸다가 추상화하는 것이 섣부른 최적화로 인한 부작용을 막는 방법입니다 [1, 6].
* **아키텍처 오버헤드:** Feature-Sliced Design(FSD)과 같이 엄격하게 분리된 계층 구조는 대규모 앱의 유지보수성에 탁월하지만, 소규모 프로젝트나 초보자에게는 폴더와 파일이 불필요하게 쪼개지고 개념적 오버헤드를 발생시켜 과도한 설계(Overkill)가 될 수 있습니다 [3, 4].
* **상태 관리 리팩토링의 반대 급부:** Context API에서 시작한 상태를 대규모 앱의 성능(리렌더링) 문제로 인해 Zustand나 Redux로 마이그레이션할 때 트레이드오프가 존재합니다. Zustand는 유연하지만 팀원마다 비동기 처리 패턴이 파편화될 위험이 있으며, Redux는 일관된 구조를 제공하지만 보일러플레이트(Boilerplate) 코드가 폭발적으로 증가하여 개발 속도를 저하시킬 수 있습니다 [10].
* **전면 재작성의 위험성:** 유지보수가 어려운 코드를 마주했을 때 전체 코드를 한 번에 재작성(Rewrite)하려는 시도는 실패할 확률이 매우 높습니다. 리팩토링은 비즈니스 기능 개발을 멈추지 않은 상태에서, 컴포넌트 및 스토어를 하나씩 '점진적(Incremental)'으로 수정해야만 리스크를 최소화할 수 있습니다 [1].
## 🔗 Knowledge Connections
### Related Concepts
#### [관계 유형 A (아키텍처/기반 기술)]
- [[Feature-Sliced Design (FSD)]]
- 연결 이유: 대규모 프론트엔드 프로젝트의 코드를 리팩토링할 때 기술 부채를 줄이기 위해 채택하는 최신 폴더 및 아키텍처 방법론입니다 [1, 3].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 앱을 레이어(app, pages, widgets, features, entities, shared)로 엄격히 나누고 단방향 의존성을 강제하여 코드 결합도를 낮추는 원리를 배울 수 있습니다.
- [[SOLID 원칙]]
- 연결 이유: 리팩토링 시 컴포넌트와 모듈을 어떻게 나누고 구성할지 결정하는 가장 기초적인 소프트웨어 엔지니어링 철학입니다 [1, 6].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 단일 책임 원칙(SRP)을 통해 비대해진 컴포넌트를 분할하고, 개방-폐쇄 원칙(OCP)을 통해 기존 코드를 건드리지 않고 컴포넌트를 확장하는 방법을 이해할 수 있습니다.
#### [관계 유형 B (구현/활용 도구)]
- [[커스텀 훅 (Custom Hooks)]]
- 연결 이유: React 리팩토링에서 비즈니스 로직과 UI를 분리하고, DRY 원칙을 실현하는 가장 기본적인 단위이자 도구입니다 [1, 6].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 컴포넌트 내부에 산재한 상태 관리와 부수 효과(`useEffect`)를 어떻게 응집도 높은 독립적인 함수로 분리할 수 있는지 파악할 수 있습니다.
- [[점진적 마이그레이션 (Incremental Migration)]]
- 연결 이유: 레거시 코드베이스를 개선할 때 시스템을 중단시키거나 위험한 '전체 재작성'을 피하기 위해 반드시 채택해야 하는 전략입니다 [1].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 알림이나 단순 상태 같은 작은 모듈부터 시작해 점진적으로 상태 관리 도구나 아키텍처를 교체해 나가는 구체적인 전환 절차를 이해할 수 있습니다.
- [[시각적 회귀 테스트 (Visual Regression Testing)]]
- 연결 이유: 대규모 코드 구조를 변경하는 리팩토링 시, 기존 UI가 의도치 않게 깨지는 것을 방지하는 핵심 안전망입니다 [7].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: Storybook과 통합된 도구(예: Happo, Chromatic)를 통해 DOM 구조뿐만 아니라 실제 브라우저 렌더링 픽셀 차이를 감지하는 메커니즘을 배울 수 있습니다.
### Deeper Research Questions
- DRY 원칙과 KISS 원칙이 상충하는 상황에서, 프론트엔드 개발자가 리팩토링 시 추상화의 적절한 시점(예: Rule of Three)을 결정하는 구체적인 실무적 기준은 무엇인가?
- 대규모 React 애플리케이션에서 Context API로 구축된 기존 상태 관리를 Zustand나 Redux로 점진적 마이그레이션(Incremental Migration)할 때 직면하는 기술적 장애물과 단계별 해결 전략은 무엇인가?
- Feature-Sliced Design (FSD)을 도입하여 리팩토링할 때, 여러 기능(Feature)에서 공통으로 필요한 로직이 'Shared' 계층에 지나치게 비대해지는 문제를 어떻게 방지하고 조율할 수 있는가?
- 레거시 React 코드베이스에 존재하는 다수의 불필요한 `useEffect`와 파편화된 서버 상태를 TanStack Query와 같은 도구로 리팩토링할 때, 기존 유닛 테스트 코드의 전략은 어떻게 수정되어야 하는가?
- 다수의 프론트엔드 팀이 협업하는 환경에서 ESLint, Prettier, Husky를 활용해 FSD의 아키텍처 경계(단방향 의존성 등)와 네이밍 컨벤션을 자동화 및 강제하는 최적의 CI/CD 거버넌스 구성 방식은 무엇인가?
### Practical Application Contexts
- **Implementation:** 비대해진 React 컴포넌트를 마주했을 때 단일 책임 원칙(SRP)을 적용하여, UI 렌더링 로직은 그대로 두고 복잡한 상태 업데이트나 API 페칭 로직을 커스텀 훅으로 분리하는 리팩토링을 즉시 수행합니다 [1, 6].
- **System Design:** 프로젝트 구조가 점점 혼란스러워지는 것을 막기 위해, 초기부터 파일 유형(components, hooks) 기반의 폴더 분류를 지양하고, Feature-Sliced Design(FSD)과 같은 도메인/기능 중심의 폴더 구조를 시스템의 뼈대로 설계합니다 [1, 3, 4].
- **Operation / Maintenance:** 유지보수 과정에서 버그 픽스와 리팩토링 코드가 섞이지 않도록, 짧은 생명주기의 기능 브랜치를 사용하고 Conventional Commits를 도입하여 유지보수 이력(History)의 가독성을 높입니다 [5].
- **Learning Path:** 리액트를 처음 배운 후, 단순히 코드를 작동하게 만드는 것을 넘어, 작성한 코드를 유닛 테스트(Unit Test)로 검증한 뒤 DRY, KISS, YAGNI 원칙에 따라 군더더기를 없애는 안전한 리팩토링 사이클을 훈련합니다 [2, 6].
- **My Project Relevance:** 타인이 작성한 또는 오래된 레거시 코드를 인계받았을 때, 코드를 전면 재작성하지 않고 Storybook 등으로 시각적 테스트 안전망을 구축한 뒤 [7], 불필요한 상태 및 Effect를 점진적으로 정돈해 나가는 [2] 구체적인 가이드라인으로 활용할 수 있습니다.
### Adjacent Topics
- [[프론트엔드 성능 최적화 (Frontend Performance Optimization)]]
- 확장 방향: 리팩토링을 통해 코드의 가독성을 높이는 것을 넘어, 메모리 누수를 해결하거나(Chrome DevTools 활용), 불필요한 리렌더링 요소(React.memo, useCallback 오남용 등)를 찾아내어 애플리케이션의 런타임 성능을 개선하는 기법으로 학습을 확장합니다.
- [[Git 브랜칭 및 협업 전략 (Git Branching & Workflow)]]
- 확장 방향: 리팩토링과 새로운 기능 개발이 동시에 일어나는 팀 환경에서, 코드 충돌을 최소화하고 리뷰 효율을 높이기 위한 Trunk-based Development, GitHub Flow 등 실무적 협업 워크플로우로 이해를 넓힙니다.
---
*Last updated: 2026-04-30*