본문 바로가기
Next.js

React의 고차 컴포넌트(HOC)

by code2772 2024. 11. 10.

[ 목차 ]

    728x90
    반응형

    1. HOC(High Order Component)란?

    고차 컴포넌트(HOC)는 React에서 컴포넌트 로직을 재사용하기 위한 고급 기술입니다. 코드로 보면 다음과 같습니다:

    /**
     * 기본적인 HOC 구조
     *@paramWrappedComponent - 감싸질 컴포넌트
     *@returns 새로운 컴포넌트
     */
    const withSomething = (WrappedComponent) => {
        return class extends React.Component {
            render() {
    // 추가적인 props와 함께 컴포넌트 반환
                return <WrappedComponent {...this.props} extraProp="value" />;
            }
        }
    }

     

    2. HOC가 필요한 이유



    2.1 횡단 관심사(Cross-Cutting Concerns) 해결

    • 여러 컴포넌트에서 공통으로 필요한 기능 처리
    • 권한 검증, 데이터 로딩, 에러 처리 등

    2.2 코드 재사용성

    예시 코드:

    typescript
    Copy
    // 권한 검증 HOC
    const withAuth = (requiredPermission: string) => (WrappedComponent: React.ComponentType) => {
        return function AuthWrapper(props) {
            const permissions = useSelector(state => state.auth.permissions);
    
    // 권한 검증
            if (!permissions.includes(requiredPermission)) {
                return <AccessDenied />;
            }
    
    // 권한이 있는 경우 원래 컴포넌트 렌더링
            return <WrappedComponent {...props} />;
        };
    };
    
    // 사용 예시
    const SecurePage = withAuth('ADMIN')(UserManagementPage);
    
    

    3. HOC의 주요 사용 사례

    3.1 권한 관리

    typescript
    Copy
    /**
     * 권한 검증을 위한 HOC
     */
    const withAuth = (WrappedComponent, requiredPermission) => {
        return function WithAuthComponent(props) {
            const { permissions } = useAuth();
    
            useEffect(() => {
                if (!permissions.includes(requiredPermission)) {
                    router.push('/login');
                }
            }, [permissions]);
    
            return <WrappedComponent {...props} />;
        };
    };
    
    

    3.2 데이터 로딩 처리

    typescript
    Copy
    /**
     * 데이터 로딩 상태를 관리하는 HOC
     */
    const withLoader = (WrappedComponent) => {
        return function WithLoaderComponent(props) {
            const [loading, setLoading] = useState(true);
            const [data, setData] = useState(null);
    
            useEffect(() => {
                fetchData()
                    .then(result => {
                        setData(result);
                        setLoading(false);
                    });
            }, []);
    
            if (loading) return <LoadingSpinner />;
            return <WrappedComponent data={data} {...props} />;
        };
    };
    
    

    3.3 에러 처리

    typescript
    Copy
    /**
     * 에러 핸들링을 위한 HOC
     */
    const withErrorHandling = (WrappedComponent) => {
        return function WithErrorComponent(props) {
            const [error, setError] = useState(null);
    
            const handleError = (err) => {
                setError(err);
    // 에러 로깅, 사용자 알림 등
            };
    
            if (error) return <ErrorDisplay error={error} />;
            return <WrappedComponent onError={handleError} {...props} />;
        };
    };
    
    

     

    4. HOC 사용 시 주의사항

    4.1 렌더링 최적화

    typescript
    Copy
    // 잘못된 사용
    const Example = () => {
    // 매 렌더링마다 새로운 HOC 인스턴스 생성 - 안티패턴
        const EnhancedComponent = withAuth(MyComponent);
        return <EnhancedComponent />;
    };
    
    // 올바른 사용
    const EnhancedComponent = withAuth(MyComponent);
    const Example = () => {
        return <EnhancedComponent />;
    };
    
    

    4.2 Props 관리

    typescript
    Copy
    const withProps = (WrappedComponent) => {
        return function WithPropsComponent(props) {
    // props 전달 시 주의사항
            const newProps = {
                ...props,// 기존 props 유지
                extraProp: 'value'// 새로운 props 추가
            };
    
            return <WrappedComponent {...newProps} />;
        };
    };
    
    

    4.3 정적 메서드 복사

    typescript
    Copy
    function withAuth(WrappedComponent) {
        class WithAuth extends React.Component {/*...*/}
    
    // 정적 메서드 복사
        hoistNonReactStatics(WithAuth, WrappedComponent);
    
        return WithAuth;
    }
    
    

     

    5. 실제 사용 예시: 복합 HOC

    typescript
    Copy
    /**
     * 여러 HOC를 조합하여 사용
     */
    const enhance = compose(
        withAuth('ADMIN'),
        withLoader,
        withErrorHandling
    );
    
    // 사용
    const EnhancedComponent = enhance(BaseComponent);
    
    

     

    6. HOC vs Hooks

    6.1 HOC의 장점

    • 컴포넌트 로직의 명확한 분리
    • 기존 코드 수정 없이 기능 확장
    • 코드 재사용성 극대화

    6.2 Hooks와의 비교

    typescript
    Copy
    // HOC 방식
    const withUser = (WrappedComponent) => {
        return function WithUser(props) {
            const user = useSelector(state => state.user);
            return <WrappedComponent user={user} {...props} />;
        };
    };
    
    // Hook 방식
    const useUser = () => {
        return useSelector(state => state.user);
    };
    
    

     

    7. 결론

    HOC는 React 애플리케이션에서 컴포넌트 로직을 재사용하고 관심사를 분리하는 강력한 패턴입니다. 특히 권한 관리, 데이터 로딩, 에러 처리와 같은 횡단 관심사를 처리할 때 매우 유용합니다. 다만, Hooks의 등장으로 일부 사용 사례는 Hooks로 대체될 수 있으므로, 상황에 맞는 적절한 패턴을 선택하는 것이 중요합니다.

    반응형