고차 컴포넌트 (HOC)는 컴포넌트 로직을 재사용하기 위한 reac의 고급 기술이다. 컴포넌트를 가져와 새 컴포넌트를 반환하는 일종의 함수이다. HOC는 리엑트의 일부가 아니며, 리엑트의 구성적 특성에서 나오는 패턴이다.
우리는 이미 고차 컴포넌트를 이전 포스트에서 한번 목격한 적 있다. 바로 React.memo()
이다. 메모이제이션할 컴포넌트를 memo()함수로 감싸 export해주었었다.
export default memo(MyComponent);
컴포넌트는 props를 UI로 변환하는 반면에, 고차 컴포넌트는 컴포넌트를 새로운 컴포넌트로 변환한다. 이렇게 반환된 컴포넌트는 원래 컴포넌트의 기능을 보강하거나 수정하여 사용할 수 있다.
HOC는 규모가 큰 애플리케이션에서, 특정 state를 정의하고, 특정 시점에 setState()
를 호출하는 패턴이 반복적으로 이루어진다고 가정하면, 이 로직을 한 곳에서 정의하고 많은 컴포넌트에서 로직을 공유할 수 있게 하는 추상화가 필요하다. custom hook보다 더 한단계 진화한 기능이라고 볼 수 있다.
어떤 페이지를 접속할 때, 만약 데이터를 서버로부터 받아오는 페이지라면 이에 필요한 로딩 UI가 있을 수 있다. 만약 이 로딩 UI가, 모든 페이지에서 사용되는 동일한 UI라면 이는 HOC를 사용하기 좋은 예시가 될 수 있다. 다음과 같이 로딩 컴포넌트를 리턴하는 HOC 예시를 작성해보았다.
const withLoading = (Component: FC ): FC => {
const WithLoadingComponent: FC = (props: Attributes) => {
const [isLoading, setIsLoading] = useState<boolean>(true);
useEffect(() => {
const timer = setTimeout(() => {
setIsLoading(false);
}, 2000);
return () => {
clearTimeout(timer);
}
}, []);
return isLoading ? (<div>is Loading...</div>) : <Component {...props}/>;
};
return WithLoadingComponent;
};
export default withLoading;
컴포넌트를 인자로 받아 공통으로 사용할 로딩 컴포넌트를 반환하는 HOC이다.
로딩 중일 때는 <div>is Loading...</div>
이 화면에 표시되며, 로딩이 끝났을 때는
인자로 넣은 <Component {...props}/>
가 출력될 것이다. 이 <Component />
에는 로딩이 끝난 후의 보여줄 데이터 컴포넌트를 넣으면 된다.
이후, HOC를 통해 다음과 같이 간단하게 작성할 수 있다.
const UserInput: FC = () => {
return (
<input type='text' defaultValue={'this is default input box!'}/>
);
};
export default withLoading(UserInput);
앞으로 사용하는 <UserInput />
컴포넌트는 withLoading()
의 기능이 입혀진 체 작동될 것이다.
이제 앞으로 사용할 모든 로딩과 관련된 컴포넌트는 withLoading()
과 함께 리턴을 하면 된다.
사용한 결과는 아래와 같다.
프로토타입 수정 금지
주의할 점으로, HOC 내부에서 컴포넌트의 프로토타입을 수정하지 않도록 하는 것이다.
HOC는 변경 대신에 입력 컴포넌트를 컨테이너 컴포넌트로 감싸서 조합을 사용해야 한다.
컴포넌트로 취급
HOC는 다른 컴포넌트들과 마찬가지로 Reaect Developer Tools에 컴포넌트로 표시된다.
HOC는 다른 일반적인 컴포넌트들과 구분을 위해 디스플레이 네임을 부여하는 경우도 있다.
리렌더링 성능
HOC로 래핑된 컴포넌트가 불필요하게 많은 리렌더링을 유발할 수 있다. HOC의 반환 결과가 항상 새로운 컴포넌트 인스턴스인 경우, 이로 인해 컴포넌트가 불필요하게 리렌더링되는 문제가 발생할 수 있다.
컴포넌트 구조의 복잡성
HOC를 남용하면 컴포넌트 구조가 복잡해질 수 있다. HOC를 여러 개 중첩해서 사용하거나, 많은 HOC를 사용하면 컴포넌트 트리를 이해하기 어려워질 수 있기에 HOC를 사용할 때는 가독성을 유지하도록 노력해야한다.