9.2 KiB
9.2 KiB
Clean Code and SOLID Principles
📌 Brief Summary
Clean Code와 SOLID 원칙은 소프트웨어 개발에서 유지보수성, 가독성, 확장성을 높이기 위해 사용되는 핵심 설계 원칙이다 [1]. SOLID는 SRP, OCP, LSP, ISP, DIP의 5가지 원칙으로 구성되어 명확하고 잘 조직된 소프트웨어 구조를 안내하며, 객체 지향뿐만 아니라 React의 함수형 컴포넌트에도 유효하게 적용된다 [1, 2]. 더불어 DRY, KISS, YAGNI와 같은 Clean Code 원칙들은 불필요한 코드 중복과 복잡성을 줄여, 코드를 단순하고 예측 가능하며 테스트하기 쉽게 만들어준다 [3, 4].
📖 Core Content
SOLID 원칙의 React 적용
- 단일 책임 원칙 (SRP - Single Responsibility Principle): 컴포넌트나 커스텀 훅은 변경되어야 할 이유가 단 하나여야 한다 [5]. 컴포넌트가 너무 많은 역할을 수행하거나 크기가 300줄을 넘어갈 경우, UI 컴포넌트(예: UserProfile, UserPosts)나 커스텀 훅으로 비즈니스 로직을 분리해야 한다 [2, 5].
- 개방-폐쇄 원칙 (OCP - Open/Closed Principle): 기존 코드를 수정하지 않고도 새로운 기능을 추가할 수 있어야 한다 [6]. React에서는 컴포넌트 합성(Composition),
childrenprop, 혹은 렌더 프롭스(render-props)를 활용하여 기존 컴포넌트를 건드리지 않고 기능을 확장할 수 있다 [2, 7, 8]. - 리스코프 치환 원칙 (LSP - Liskov Substitution Principle): 하위 타입은 상위 타입을 무리 없이 대체할 수 있어야 한다 [6]. 현대 React는 클래스 상속을 거의 사용하지 않지만, 서브 컴포넌트가 기본 컴포넌트의 자리를 매끄럽게 대체할 수 있도록 설계하는 방식으로 이 원칙을 적용한다 [2, 8].
- 인터페이스 분리 원칙 (ISP - Interface Segregation Principle): 컴포넌트는 사용하지 않는 props에 의존해서는 안 된다 [2, 7]. 거대한 객체를 통째로 props로 넘기기보다는, 해당 컴포넌트가 실제로 사용하는 명확하고 작은 단위의 데이터만 전달해야 한다 [7, 8].
- 의존성 역전 원칙 (DIP - Dependency Inversion Principle): 구체적인 구현(Concretions)이 아닌 추상화에 의존해야 한다 [2]. 컴포넌트 간 직접적인 결합을 피하고, props나 Context를 통해 의존성을 주입받아 사용한다 [2, 8].
추가적인 Clean Code 원칙
- DRY (Don't Repeat Yourself): 동일한 코드를 두 번 작성하지 않고 재사용 가능한 로직을 커스텀 훅이나 고차 컴포넌트(HOC)로 추출한다 [4, 9]. 단, 성급한 추상화를 피하기 위해 패턴이 최소 세 번 이상 반복될 때 추출하는 것이 권장된다 [10].
- KISS (Keep It Simple, Stupid): 복잡성보다 단순성을 최우선으로 해야 한다 [4]. 컴포넌트와 함수를 '단순하고 바보같이(simple and dumb)' 유지하며, 불필요한 조기 최적화를 피해야 한다 [9, 11].
- YAGNI (You Aren't Gonna Need It): 미래에 사용될지도 모른다는 이유로 기능을 미리 구현하지 않는다 [4, 12]. 현재 컴포넌트나 요구사항에 반드시 필요한 기능만 구현하여 유지보수해야 할 죽은 코드(dead code)를 방지한다 [9, 13].
⚖️ Trade-offs & Caveats
- SOLID 도입의 복잡성: SOLID 원칙을 도입하면 코드가 고도로 체계화되고 유지보수성이 향상되지만, 초기 설계 단계에서는 구조가 지나치게 복잡하게 느껴질 수 있다 [14].
- DRY 원칙과 과도한 추상화: 코드의 중복을 줄여주지만, 무분별하게 적용할 경우 지나치게 복잡한 추상화(overly complex abstractions)를 초래하여 코드를 이해하기 더 어렵게 만들 수 있다 [10, 14].
- KISS 원칙의 지나친 단순화: 디버깅을 쉽게 하고 직관적인 코드를 만들 수 있으나, 때로는 복잡한 비즈니스 요구사항에 대한 해결책을 너무 단순화(oversimplify)할 위험이 존재한다 [14].
- YAGNI와 확장성 간과: 낭비되는 노력을 줄이고 기민하게 대응할 수 있도록 돕지만, 현재에만 너무 집중한 나머지 미래의 확장성(future scalability)을 간과할 가능성이 있다 [14].
- Clean Code 유지를 위한 규율: 읽고 유지보수하기 쉬운 코드를 작성하려면 팀 전체의 지속적인 노력과 강력한 규율(discipline)이 요구된다 [14].
🔗 Knowledge Connections
Related Concepts
[소프트웨어 엔지니어링 아키텍처 원칙]
- Feature-Sliced Design
- 연결 이유: 코드를 기술적인 파일 단위가 아니라 비즈니스 기능(Feature)이나 도메인 중심으로 분리하여 SRP(단일 책임 원칙) 및 관심사 분리를 아키텍처 수준에서 실현한다 [15-17].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 거대한 프론트엔드 프로젝트에서 하위 레이어만 참조할 수 있도록 의존성을 제어(DIP와 유사)하여, 독립적인 코드 모듈화를 구축하는 방법을 배울 수 있다 [16, 17].
[React 구현 패턴 및 기술]
- Custom Hooks
- 연결 이유: React에서 DRY 원칙을 실현하고 비즈니스 로직을 UI와 분리하여 SRP를 충족시키는 가장 효과적인 리팩토링 단위이자 도구이다 [10, 18].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 데이터 페칭, 폼(Form) 처리 등의 복잡한 논리를 커스텀 훅으로 분리함으로써 컴포넌트를 단순하게(KISS) 유지하는 패턴을 이해할 수 있다 [9].
- Component Composition
- 연결 이유: OCP(개방-폐쇄 원칙)를 React에서 구현하기 위한 핵심 패턴으로, 기존 컴포넌트의 내부 코드를 수정하지 않고
children을 통해 새로운 기능을 조합 및 확장할 수 있게 해준다 [7, 8]. - 이 개념을 통해 더 깊게 이해할 수 있는 부분: React 환경에서 상속 없이 합성만을 사용하여 유연하고 재사용 가능한 UI 구조를 어떻게 설계하는지 파악할 수 있다.
- 연결 이유: OCP(개방-폐쇄 원칙)를 React에서 구현하기 위한 핵심 패턴으로, 기존 컴포넌트의 내부 코드를 수정하지 않고
Deeper Research Questions
- React의 함수형 프로그래밍 패러다임에서 클래스 상속을 전제로 한 LSP(리스코프 치환 원칙)는 컴포넌트 설계 시 구체적으로 어떻게 재해석되고 적용되어야 하는가?
- DRY 원칙을 지키기 위해 공통 로직을 추상화할 때, 지나친 추상화를 경계하는 KISS 원칙과 충돌한다면 이를 조율하기 위한 실무적인 기준(예: Rule of three) 외에 어떤 척도가 있는가?
- ISP(인터페이스 분리 원칙)를 위배하여 거대한 Props 객체를 하위 컴포넌트로 전달할 때 발생하는 불필요한 리렌더링 문제를 React 최적화 기법으로 어떻게 극복할 수 있는가?
- Feature-Sliced Design(FSD)과 같이 계층과 규칙이 엄격한 아키텍처를 도입할 때, YAGNI 원칙을 함께 적용하여 오버엔지니어링을 피하는 방법은 무엇인가?
- SRP를 준수하기 위해 300줄 이상의 React 컴포넌트를 다수의 작은 컴포넌트로 분리할 때 발생하는 Props 드릴링(Prop Drilling) 문제를 아키텍처 측면에서 어떻게 효율적으로 해결할 수 있는가?
Practical Application Contexts
- Implementation: 300줄이 넘는 비대해진 React 컴포넌트를 리팩토링할 때, 상태 관리나 API 호출 로직은 커스텀 훅으로, 독립적인 UI 요소는 개별 컴포넌트로 쪼개어 SRP와 Clean Code를 실현한다 [5, 18].
- System Design: 소프트웨어 설계 초기 단계에서는 당장 필요하지 않은 미래 기능까지 포함하지 않고(YAGNI), 대신 새로운 요구사항이 생겼을 때 쉽게 덧붙일 수 있도록 컴포넌트 합성을 활용한 OCP 구조를 설계한다 [7, 9].
- Operation / Maintenance: ESLint 및 Prettier와 같은 도구와 Husky를 연동하여 CI/CD 파이프라인에서 코드가 커밋되기 전 Clean Code 규칙과 파일 명명 규칙이 자동 준수되도록 강제한다 [19].
- Learning Path: 처음 React를 배울 때는 KISS 원칙에 입각한 단순한 컴포넌트 작성을 연습하고, 점차 DRY를 위한 커스텀 훅 분리를 거쳐 SOLID 원칙이 결합된 대규모 아키텍처 설계로 학습을 확장한다.
- My Project Relevance: 현재 작업 중인 코드베이스에서 사용되지 않는 방대한 객체 속성이 props로 전달되고 있지 않은지 점검하여(ISP 적용), 코드 결합도를 낮추고 유지보수성을 극대화하는 리팩토링 작업에 즉시 적용할 수 있다.
Adjacent Topics
- State Management Architecture
- 확장 방향: 컴포넌트 레벨에서의 책임 분리를 넘어, Context API, Zustand, Redux 등 전역 상태 관리 라이브러리를 활용할 때 각 도메인의 상태와 비즈니스 로직을 어떻게 분리(SRP)하고 의존성을 관리할지 탐구한다.
- Frontend Performance Optimization
- 확장 방향: Clean Code와 모듈 분리(예: 코드 스플리팅, 지연 로딩)가 React 컴포넌트의 불필요한 렌더링을 방지하고 프론트엔드 성능(Core Web Vitals)을 어떻게 향상시키는지 연계하여 조사한다.
Last updated: 2026-04-30