ReactJS - 높은 순위 컴포넌트: 초보자 가이드

안녕하세요, 미래의 React 마법사 여러분! 오늘 우리는 ReactJS의 높은 순위 컴포넌트(Higher-Order Components, HOCs)의 세계로 흥미로운 여정을 떠납니다. 프로그래밍에 처음 도전하는 사람이라면 걱정하지 마세요 - 저는 친절한 안내자가 되어 step-by-step로 안내해 드릴게요. 이 튜토리얼의 끝을 맺을 때, 당신은 프로처럼 HOCs를 만들 수 있을 거예요!

ReactJS - Higher Order Components

높은 순위 컴포넌트는 무엇인가요?

들어가기 전에 높은 순위 컴포넌트가 무엇인지 이해해 보겠습니다. 상상해 보세요, 버거 가게에 가셨을 때. 기본 버거를 주문했지만, 치즈, 상추, 베이컨을 추가로 넣기로 결정합니다. 이러한 추가 과정은 React에서 HOCs가 하는 일과 비슷합니다!

React의 용어로, 높은 순위 컴포넌트는 컴포넌트를 입력받아 새로운 컴포넌트를 반환하는 함수로, 추가 기능을 제공합니다. 기존 컴포넌트의 핵심 성분을 변하지 않고 특별한 소스를 추가하는 것과 같은 것입니다.

다음은 간단한 비유입니다:

// 이것은 우리의 기본 버거입니다
const PlainBurger = () => <div>?</div>;

// 이것은 우리의 HOC로, 토핑을 추가하는 것과 같습니다
const addCheese = (Burger) => {
return () => (
<div>
<Burger />
<span>?</span>
</div>
);
};

// 이것은 치즈가 추가된 우리의 향상된 버거입니다!
const CheeseBurger = addCheese(PlainBurger);

이 예제에서, addCheese는 우리의 높은 순위 컴포넌트입니다. 그것은 PlainBurger를 받아와 치즈를 추가한 새로운 컴포넌트를 반환합니다!

높은 순위 컴포넌트를 어떻게 사용할까요?

이제 개념을 이해했으므로, 더 실질적인 상황에서 HOCs를 어떻게 사용할 수 있는지 보겠습니다. 예를 들어, 여러 컴포넌트가 API에서 데이터를 가져와야 할 때, 각 컴포넌트에 동일한 가져오기 로직을 작성하는 대신 HOC를 사용하여 이를 처리할 수 있습니다.

다음은 그 방법을 보여줍니다:

import React, { useState, useEffect } from 'react';

// 이것은 우리의 HOC입니다
function withDataFetching(WrappedComponent, dataSource) {
return function(props) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
fetch(dataSource)
.then(response => response.json())
.then(result => {
setData(result);
setLoading(false);
})
.catch(e => {
setError(e);
setLoading(false);
});
}, []);

if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;

return <WrappedComponent data={data} {...props} />;
}
}

// 이것은 가져온 데이터를 받을 간단한 컴포넌트입니다
function UserList({ data }) {
return (
<ul>
{data.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}

// 우리의 HOC를 사용하여 데이터 가져오기 기능을 가진 새로운 컴포넌트를 만듭니다
const UserListWithData = withDataFetching(UserList, 'https://api.example.com/users');

// 이제 우리의 앱에서 UserListWithData를 사용할 수 있습니다!
function App() {
return (
<div>
<h1>User List</h1>
<UserListWithData />
</div>
);
}

이를 간단히 설명하자면:

  1. 우리는 withDataFetching HOC를 정의합니다. 이 HOC는 두 개의 매개변수를 받습니다: 래핑할 컴포넌트(WrappedComponent)와 데이터를 가져올 URL(dataSource).

  2. withDataFetching 내부에서 새로운 기능 컴포넌트를 생성하고 반환합니다. 이 컴포넌트는 React hooks를 사용하여 상태와 측면 효과를 관리합니다.

  3. 우리는 useState를 사용하여 data, loading, error 상태를 관리합니다.

  4. 우리는 useEffect를 사용하여 컴포넌트가 마운트될 때 데이터를 가져옵니다. 데이터가 가져올 때마다 상태를 업데이트합니다.

  5. 상태에 따라 로딩 메시지, 오류 메시지, 또는 가져온 데이터를 가진 WrappedComponent를 렌더링합니다.

  6. 우리는 데이터를 받을 간단한 UserList 컴포넌트를 정의합니다.

  7. 우리는 HOC를 사용하여 데이터 가져오기 기능을 가진 새로운 컴포넌트 UserListWithData를 만듭니다.

  8. 마지막으로, 우리는 App 컴포넌트에서 UserListWithData를 사용합니다.

HOC 컴포넌트 적용

이제 HOC를 만들고 사용하는 방법을 배웠으므로, 일반적인 사용 사례와 좋은 관행을 살펴보겠습니다.

인증 HOC

HOC의 일반적인 사용 사례 중 하나는 인증을 처리하는 것입니다. 다음은 예제입니다:

function withAuth(WrappedComponent) {
return function(props) {
const [isAuthenticated, setIsAuthenticated] = useState(false);

useEffect(() => {
// 사용자가 인증되었는지 확인
const token = localStorage.getItem('token');
setIsAuthenticated(!!token);
}, []);

if (!isAuthenticated) {
return <Redirect to="/login" />;
}

return <WrappedComponent {...props} />;
}
}

// 사용
const ProtectedComponent = withAuth(SensitiveDataComponent);

이 HOC는 사용자가 인증되었는지 확인하기 전에 래핑된 컴포넌트를 렌더링합니다. 인증되지 않았다면 로그인 페이지로 리디렉션합니다.

로그 HOC

다른 유용한 응용은 컴포넌트에 로그를 추가하는 것입니다:

function withLogging(WrappedComponent) {
return function(props) {
useEffect(() => {
console.log(`Component ${WrappedComponent.name} mounted`);
return () => console.log(`Component ${WrappedComponent.name} unmounted`);
}, []);

return <WrappedComponent {...props} />;
}
}

// 사용
const LoggedComponent = withLogging(MyComponent);

이 HOC는 컴포넌트가 마운트되고 언마운트될 때 로그를 남김으로써 디버깅에 매우 유용할 수 있습니다.

최선의 관행과 고려사항

HOC를 사용할 때 다음 팁을 기억하세요:

  1. 원래 컴포넌트를 변하지 않게 하세요: 항상 원래 컴포넌트와 새로운 기능을 조합하세요.
  2. 관련이 없는 프로퍼티를 통과시키세요: HOC와 관련이 없는 프로퍼티를 반드시 통과시키세요.
  3. 최대한 조합할 수 있게 하세요: HOC는 다른 HOC와 조합될 수 있어야 합니다.
  4. 디스플레이 이름을 감싸서 디버깅을 용이하게 하세요: React.displayName를 사용하여 HOC에 명확한 이름을 부여하세요.

다음 표는 일반적인 HOC 패턴을 요약합니다:

패턴 설명 예제 사용 사례
Props Proxy 프로퍼티 조작 추가/수정 프로퍼티
Inheritance Inversion 컴포넌트 라이프사이클 확장 라이프사이클 메서드에 로그 추가
Render Highjacking 렌더 출력 제어 조건부 렌더링
State Abstraction 상태 관리 및 제공 데이터 가져오기 및 제공

기억해야 할 점은, 높은 순위 컴포넌트는 React 툴킷에서 강력한 도구이지만, 항상 최고의 솔루션은 아닙니다. Hooks가 도입된 이후로, HOC의 일부 사용 사례는 커스텀 Hooks로 더 간결하게 해결할 수 있습니다. HOC, Hooks 또는 다른 패턴을 사용할지는 애플리케이션의 특정 요구에 따라 결정하세요.

그럼 여러분, React의 높은 순위 컴포넌트 세계로 첫 걸음을 뗐습니다. 이 개념을 연습하고, 자신의 HOC를 실험해 보세요. 곧 마에스트로처럼 컴포넌트를 조합할 수 있을 거예요. 행복한 코딩을 기원합니다!

Credits: Image by storyset