프론트엔드에서 사용하기 좋은 Design Pattern - Higher Order Component Pattern

Kychann·2025년 4월 29일
post-thumbnail

🛠 Higher-Order Component (HOC) Pattern

개념

  • 컴포넌트를 입력받아서 새로운 컴포넌트를 반환하는 함수
  • 즉, (Component) => NewComponent 형태로 기존 컴포넌트에 기능을 추가하거나 수정해서 새로운 컴포넌트를 만든다.

📦 HOC는 컴포넌트를 감싸서 기능을 덧붙이는 패턴


왜 사용할까?

  • 공통 로직 재사용
    - 인증 처리, 로딩 처리, 권한 체크 같은 것을 여러 컴포넌트에 공통 적용하고 싶을 때
  • 관심사 분리
    - 기존 컴포넌트는 자신의 책임만 다하고, 부가 기능은 따로 추가
  • 코드 중복 제거
    - 비슷한 기능이 필요한 여러 컴포넌트를 효율적으로 관리 가능

기본 사용 예시

➡️ 예를 들어, “로딩 처리” 기능을 추가하는 HOC를 만들자

// withLoading.js
import React from "react";

function withLoading(Component) {
  return function WrappedComponent({ isLoading, ...props }) {
    if (isLoading) {
      return <div>Loading...</div>;
    }
    return <Component {...props} />;
  };
}

export default withLoading;

➡️ 사용하는 쪽

// 원본 컴포넌트
function UserList({ users }) {
  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

// HOC 적용
import withLoading from "./withLoading";

const UserListWithLoading = withLoading(UserList);

// 사용
<UserListWithLoading isLoading={true} users={[]} />

설명

  • withLoading이 UserList를 감쌌다.
  • isLoading이 true면 로딩 메시지가 나오고, false면 실제 리스트를 렌더링한다.

구조

원본 컴포넌트:   UserList (props 받아서 리스트 그림)

HOC: withLoading(UserList)
 └─ (isLoading 검사)
 └─ 로딩 중이면 Loading 출력
 └─ 아니면 UserList(props) 호출

HOC 작성 시 주의할 점

  1. Props 전달
    • 원본 컴포넌트에 props를 잘 전달해야 한다.
    • {...props} spread 필수!
  2. displayName 설정
    • 디버깅할 때 보기 편하게 HOC 이름 설정하는 것도 좋다.
    WrappedComponent.displayName = `WithLoading(${Component.displayName || Component.name || "Component"})`;
  3. Rerendering 최적화
  • HOC가 리렌더링을 유발할 수 있으니 React.memo나 최적화도 고려해야 한다.

요즘은 복잡한 HOC 대신 Custom Hook 쓰는 겨우가 많지만,
권한 인증, 라우팅 제어 등은 여전히 HOC 패턴으로 구현하는 경우도 꽤 많다.

profile
컴포넌트는 재사용, 감성은 1회용

0개의 댓글