개발/React

[중급반] Step 2-3. 컴포넌트 아키텍처 패턴 (결합도 낮추기)

ophelisis 2025. 12. 15. 14:00
반응형

React 애플리케이션의 복잡도가 증가할수록 컴포넌트 파일 하나가 비즈니스 로직, 상태 관리, UI 렌더링을 모두 처리하게 되어 유지보수와 테스트가 매우 어려워집니다. 중급 개발자는 이러한 문제를 해결하기 위해 컴포넌트 간의 **결합도(Coupling)**를 낮추고 재사용성을 높이는 아키텍처 패턴을 숙지해야 합니다.

이 섹션에서는 가장 널리 쓰이는 두 가지 아키텍처 패턴과 로직 분리 전략을 다룹니다.


1. 🖼️ Presentational & Container Pattern (P&C 패턴)

P&C 패턴은 Dan Abramov가 처음 제안한 방식으로, 컴포넌트의 역할을 **'데이터 및 로직'**과 **'순수 UI'**로 명확하게 분리합니다.

구분 Container (컨테이너) 컴포넌트 Presentational (프레젠테이셔널) 컴포넌트
별칭 Smart (똑똑한) 컴포넌트 Dumb (멍청한) 컴포넌트
주요 역할 데이터와 로직 담당. API 호출, Redux/Context 상태 구독 및 변경, 비즈니스 로직 처리. UI 렌더링 담당. 오직 Props로 받은 데이터를 화면에 보여주는 역할만 수행.
React 요소 클래스 또는 함수형 컴포넌트 (Hook 사용) 함수형 컴포넌트 (Hook 미사용 또는 매우 제한적인 UI Hook만 사용)
테스트 용이성 로직 분리로 단위 테스트 용이. Props에 따른 UI 변화 테스트 용이.

1-1. P&C 패턴의 장점

  1. 관심사 분리 (SoC): 데이터 흐름과 UI 표현이 분리되어 컴포넌트가 담당하는 역할이 명확해집니다.
  2. 재사용성: Presentational 컴포넌트는 어떤 데이터를 받든 동일한 UI를 보여주기 때문에, 여러 Container에서 재사용하기 쉽습니다.
  3. 유지보수: 로직 수정은 Container에서, 디자인 수정은 Presentational에서만 하면 되므로 유지보수가 효율적입니다.

2. 🎣 Custom Hooks을 이용한 로직 분리

현대의 함수형 컴포넌트 중심 React 환경에서 P&C 패턴의 Container 역할은 점점 Custom Hooks로 대체되고 있습니다. Custom Hook은 컴포넌트의 복잡한 로직을 완전히 외부로 분리하는 가장 효율적인 방법입니다.

2-1. Custom Hook의 역할

Custom Hook은 useState, useEffect 등의 내장 Hook을 조합하여 특정 비즈니스 로직 또는 상태 관리 로직을 캡슐화하는 함수입니다.

  • 예시: 로그인 폼의 모든 유효성 검사, 제출 로직, 에러 상태 관리를 하나의 useFormValidation() Hook으로 분리.
  • 컴포넌트 경량화: 컴포넌트 파일은 Hook을 호출하고 UI를 렌더링하는 역할만 남게 되어 가볍고 가독성이 높아집니다.

2-2. HOC (Higher-Order Component)와의 비교

과거에는 Custom Hook 대신 HOC를 사용하여 로직을 재사용했습니다.

  • Custom Hook: 로직만 분리하고 Props 충돌 위험이 없음 (Hooks의 유연성).
  • HOC: 컴포넌트 자체를 감싸서 로직을 주입하며, Props 충돌이나 Wrapper Hell 같은 구조적 복잡성을 유발할 수 있습니다.

결론: 재사용 가능한 로직을 분리할 때는 HOC보다 Custom Hook을 사용하는 것이 현대 React의 표준이자 모범 사례입니다.

3. 🎯 결합도 최소화를 위한 설계 원칙

견고한 아키텍처를 위해 컴포넌트를 설계할 때 다음 원칙을 따릅니다.

  • 원칙 1: 단일 책임 원칙 (SRP, Single Responsibility Principle): 각 컴포넌트(또는 Hook)는 하나의 명확한 책임만 가져야 합니다. (예: TodoList는 목록을 보여주는 책임만, useTodoLogic은 목록을 관리하는 책임만)
  • 원칙 2: 상태의 위치 (State Colocation): 상태를 공유하는 컴포넌트 트리에서 가장 가까운 공통 부모에 상태를 위치시키세요. 전역 상태 관리(Redux, Recoil)는 정말 필요한 경우에만 사용하고, 가능하다면 지역 상태(Local State)로 유지하는 것이 좋습니다.
  • 원칙 3: 'Props 깊숙이 넘기기' 방지: Prop Drilling(Props를 여러 단계의 자식에게 전달하는 행위)이 심해지면, Context API나 전역 상태 관리 솔루션(RTK, Zustand)을 도입하여 중간 컴포넌트의 결합도를 낮춰야 합니다.

🛠️ 2-3 실습 미션 (Challenge)

  1. P&C 패턴 적용: 기존에 하나의 컴포넌트에 로직과 UI가 모두 있던 UserList 컴포넌트를 UserListContainer (데이터 페칭, 필터링 로직 담당)와 UserListItem (Props를 받아 UI만 렌더링 담당)으로 분리하세요.
  2. Custom Hook 구현: 사용자 정의 훅 **useScrollFetch**를 구현하여, 페이지 하단에 도달했을 때 다음 데이터를 자동으로 불러오는 무한 스크롤 로직을 캡슐화하세요. 이를 UserListContainer에 적용합니다.
반응형