>웹 프론트엔드 >JS 튜토리얼 >깔끔한 React 컴포넌트 통신을 위한 이벤트 중심 아키텍처

깔끔한 React 컴포넌트 통신을 위한 이벤트 중심 아키텍처

Barbara Streisand
Barbara Streisand원래의
2024-12-06 15:26:13341검색

React 애플리케이션에서 소품 드릴링과 콜백 체인이 끝없이 얽히는 것에 지치셨나요? 깊게 중첩된 구성 요소 간의 상태 및 통신을 관리하는 것이 스파게티 코드와 씨름하는 것처럼 느껴지나요?

이벤트 기반 아키텍처를 사용하면 구성 요소 상호 작용을 단순화하고 복잡성을 줄이며 앱의 유지 관리를 더욱 쉽게 만들 수 있습니다. 이 글에서는 사용자 정의 useEvent 후크를 사용하여 구성 요소를 분리하고 React 앱 전반의 통신을 개선하는 방법을 보여 드리겠습니다.

자세한 내용을 안내해 드리고, 시작해 보겠습니다.


문제: Props 드릴링 및 콜백 체인

최신 애플리케이션 개발에서는 구성 요소 간의 상태 및 통신 관리가 금방 번거로워질 수 있습니다. 이는 데이터가 여러 수준의 중첩된 구성 요소를 통해 전달되어야 하는 props 드릴링콜백 체인과 관련된 시나리오에서 특히 그렇습니다. 유지 관리하거나 디버그하세요.

이러한 과제는 종종 긴밀하게 결합된 구성 요소를 생성하고, 유연성을 감소시키며, 애플리케이션을 통해 데이터가 흐르는 방식을 추적하려는 개발자의 인지 부하를 증가시킵니다. 더 나은 접근 방식이 없으면 이러한 복잡성으로 인해 개발 속도가 크게 느려지고 깨지기 쉬운 코드베이스가 발생할 수 있습니다.

전통적인 흐름: Props Down, Callbacks Up

일반적인 React 애플리케이션에서 상위 구성 요소는 props를 하위 요소에 전달하고 하위 구성 요소는 콜백을 트리거하여 상위 요소와 다시 통신합니다. 이는 얕은 구성 요소 트리에서는 잘 작동하지만 계층 구조가 깊어지면 상황이 복잡해지기 시작합니다.

Props 드릴링: 데이터는 가장 깊은 구성 요소에만 필요한 경우에도 여러 수준의 구성 요소를 통해 수동으로 전달되어야 합니다.

콜백 체인: 마찬가지로 하위 구성 요소는 이벤트 핸들러를 트리 위로 전달하여 긴밀하게 결합되고 유지 관리하기 어려운 구조를 만들어야 합니다.

일반적인 문제: 콜백 복잡성

이 시나리오를 예로 들면 다음과 같습니다.

  • 부모는 자녀 A에게 소품을 전달합니다.
  • 여기에서 props는 GrandChildren A/B로 드릴다운되고 최종적으로는 SubChildren N
  • 으로 드릴다운됩니다.
  • SubChildren N이 부모에게 이벤트를 알려야 하는 경우 각 중간 구성 요소를 통해 다시 이동하는 콜백이 트리거됩니다.

애플리케이션이 커짐에 따라 이 설정을 관리하기가 더 어려워집니다. 중간 구성 요소는 종종 중개자, 전달 소품 및 콜백 역할을 하여 코드를 부풀리고 유지 관리 가능성을 떨어뜨립니다.

Event-Driven Architecture for Clean React Component Communication

props 드릴링을 해결하기 위해 우리는 글로벌 상태 관리 라이브러리(예: Zustand)와 같은 솔루션을 사용하여 데이터 공유를 간소화하는 경우가 많습니다. 그런데 콜백 관리는 어떻게 하나요?

여기서 이벤트 중심 접근 방식이 판도를 바꿀 수 있습니다. 구성 요소를 분리하고 이벤트를 사용하여 상호 작용을 처리함으로써 콜백 관리를 크게 단순화할 수 있습니다. 이 접근 방식이 어떻게 작동하는지 살펴보겠습니다.


해결책: 이벤트 기반 접근 방식 도입

Event-Driven Architecture for Clean React Component Communication

트리 위로 통신하기 위해 직접 콜백에 의존하는 대신 이벤트 중심 아키텍처가 구성 요소를 분리하고 통신을 중앙 집중화합니다. 작동 방식은 다음과 같습니다.

이벤트 발송

SubChildren N이 이벤트(예: onMyEvent)를 트리거할 때 상위에서 콜백을 직접 호출하지 않습니다.
대신 중앙 집중식 이벤트 핸들러가 처리하는 이벤트를 전달합니다.

중앙 집중식 처리

이벤트 핸들러는 전달된 이벤트를 수신하여 처리합니다.
상위 요소(또는 관심 있는 다른 구성 요소)에게 알리거나 필요에 따라 추가 작업을 실행할 수 있습니다.

소품은 아래쪽으로 유지됩니다.

Prop은 여전히 ​​계층 구조로 전달되어 구성 요소가 작동하는 데 필요한 데이터를 수신하도록 합니다.

이 문제는 zustand, redux와 같은 중앙 집중식 상태 관리 도구를 사용하여 해결할 수 있지만 이 기사에서는 다루지 않습니다.


구현

그런데 이 아키텍처를 어떻게 구현하나요?

useEvent 후크

useEvent라는 사용자 정의 후크를 만들어 보겠습니다. 이 후크는 이벤트 구독을 처리하고 대상 이벤트를 트리거하는 전달 함수를 반환하는 역할을 담당합니다.

typescript를 사용하고 있으므로 사용자 정의 이벤트를 생성하려면 창 이벤트 인터페이스를 확장해야 합니다.

interface AppEvent<PayloadType = unknown> extends Event {
  detail: PayloadType;
}

export const useEvent = <PayloadType = unknown>(
  eventName: keyof CustomWindowEventMap,
  callback?: Dispatch<PayloadType> | VoidFunction
) => {
  ...
};

이렇게 하면 맞춤 이벤트 맵을 정의하고 맞춤 매개변수를 전달할 수 있습니다.

interface AppEvent<PayloadType = unknown> extends Event {
  detail: PayloadType;
}

export interface CustomWindowEventMap extends WindowEventMap {
  /* Custom Event */
  onMyEvent: AppEvent<string>; // an event with a string payload
}

export const useEvent = <PayloadType = unknown>(
  eventName: keyof CustomWindowEventMap,
  callback?: Dispatch<PayloadType> | VoidFunction
) => {
  ...
};

이제 필요한 인터페이스를 정의했으니 최종 후크 코드를 살펴보겠습니다

import { useCallback, useEffect, type Dispatch } from "react";

interface AppEvent<PayloadType = unknown> extends Event {
  detail: PayloadType;
}

export interface CustomWindowEventMap extends WindowEventMap {
  /* Custom Event */
  onMyEvent: AppEvent<string>;
}

export const useEvent = <PayloadType = unknown>(
  eventName: keyof CustomWindowEventMap,
  callback?: Dispatch<PayloadType> | VoidFunction
) => {
  useEffect(() => {
    if (!callback) {
      return;
    }

    const listener = ((event: AppEvent<PayloadType>) => {
      callback(event.detail); // Use `event.detail` for custom payloads
    }) as EventListener;

    window.addEventListener(eventName, listener);
    return () => {
      window.removeEventListener(eventName, listener);
    };
  }, [callback, eventName]);

  const dispatch = useCallback(
    (detail: PayloadType) => {
      const event = new CustomEvent(eventName, { detail });
      window.dispatchEvent(event);
    },
    [eventName]
  );

  // Return a function to dispatch the event
  return { dispatch };
};

useEvent 후크는 사용자 정의 창 이벤트를 구독하고 전달하기 위한 사용자 정의 React 후크입니다. 이를 통해 사용자 정의 이벤트를 수신하고 특정 페이로드로 트리거할 수 있습니다.

우리가 여기서 하고 있는 일은 매우 간단합니다. 표준 이벤트 관리 시스템을 사용하고 맞춤 이벤트를 수용하기 위해 이를 확장하는 것입니다.

매개변수:

  • eventName(문자열): 수신할 이벤트의 이름입니다.
  • 콜백(선택): 이벤트가 발생했을 때 호출하는 함수로, 페이로드를 인자로 받습니다.

특징:

  • 이벤트 리스너: 지정된 이벤트를 수신하고 이벤트 세부정보(사용자 정의 페이로드)와 함께 제공된 콜백을 호출합니다.
  • 이벤트 전달: 후크는 사용자 정의 페이로드로 이벤트를 트리거하는 전달 기능을 제공합니다.

예:

interface AppEvent<PayloadType = unknown> extends Event {
  detail: PayloadType;
}

export const useEvent = <PayloadType = unknown>(
  eventName: keyof CustomWindowEventMap,
  callback?: Dispatch<PayloadType> | VoidFunction
) => {
  ...
};

좋아요. 그런데 어쩌죠

실제 사례?

이 StackBlitz를 확인하세요(로드되지 않으면 여기에서 확인하세요)

이 간단한 예는 useEvent 후크의 목적을 보여줍니다. 기본적으로 본문의 버튼은 사이드바, 머리글 및 바닥글 구성 요소에서 가로채서 그에 따라 업데이트되는 이벤트를 전달합니다.

이를 통해 많은 구성요소에 콜백을 전파할 필요 없이 원인/결과 반응을 정의할 수 있습니다.


useEvent의 실제 사용 사례

useEvent 후크를 사용하여 통신을 단순화하고 React 애플리케이션의 구성 요소를 분리할 수 있는 실제 사용 사례는 다음과 같습니다.


1. 알림 시스템

알림 시스템에는 글로벌 커뮤니케이션이 필요한 경우가 많습니다.

  • 시나리오:

    • API 호출이 성공하면 앱 전체에 "성공" 알림이 표시되어야 합니다.
    • 헤더의 '알림 배지'와 같은 구성요소도 업데이트해야 합니다.
  • 해결책: useEvent 후크를 사용하여 알림 세부정보와 함께 onNotification 이벤트를 전달합니다. 알림 배너 및 헤더와 같은 구성 요소는 이 이벤트를 수신하고 독립적으로 업데이트할 수 있습니다.

2. 테마 전환

사용자가 테마(예: 밝은 모드/어두운 모드)를 전환하면 여러 구성 요소가 응답해야 할 수도 있습니다.

  • 시나리오:

    • ThemeToggle 구성 요소는 사용자 정의 onThemeChange 이벤트를 전달합니다.
    • 사이드바 및 헤더와 같은 구성요소는 이 이벤트를 수신하고 그에 따라 스타일을 업데이트합니다.
  • 이점: 전체 구성 요소 트리에서 props를 통해 테마 상태나 콜백 함수를 전달할 필요가 없습니다.

3. 글로벌 키 바인딩

초안을 저장하려면 "Ctrl S"를 누르고 모달을 닫으려면 "Escape"를 누르는 등 전역 단축키를 구현하세요.

  • 시나리오:
    • 전역 keydown 리스너는 누른 키 세부정보와 함께 onShortcutPressed 이벤트를 전달합니다.
    • 모달 구성요소 또는 기타 UI 요소는 주요 이벤트를 전달하기 위해 상위 구성요소에 의존하지 않고 특정 단축키에 응답합니다.

4. 실시간 업데이트

채팅 앱이나 라이브 대시보드와 같은 애플리케이션에는 실시간 업데이트에 반응하기 위해 여러 구성 요소가 필요합니다.

  • 시나리오:
    • WebSocket 연결은 새 데이터가 도착하면 onNewMessage 또는 onDataUpdate 이벤트를 전달합니다.
    • 채팅창, 알림, 읽지 않은 메시지 카운터 등의 구성요소는 독립적으로 업데이트를 처리할 수 있습니다.

5. 구성 요소 간 양식 유효성 검사

섹션이 여러 개인 복잡한 양식의 경우 유효성 검사 이벤트를 중앙 집중화할 수 있습니다.

  • 시나리오:
    • 사용자가 필드를 작성할 때 양식 구성 요소는 onFormValidate 이벤트를 전달합니다.
    • 요약 구성 요소는 이러한 이벤트를 수신하여 양식 논리와 긴밀하게 결합하지 않고 유효성 검사 오류를 표시합니다.

6. 분석 추적

사용자 상호작용(예: 버튼 클릭, 탐색 이벤트)을 추적하여 분석 서비스로 보냅니다.

  • 시나리오:
    • 관련 세부정보(예: 클릭한 버튼의 라벨)와 함께 onUserInteraction 이벤트를 전달합니다.
    • 중앙 분석 핸들러는 이러한 이벤트를 수신하여 분석 API로 보냅니다.

7. 협업 도구

공유 화이트보드나 문서 편집기와 같은 공동 작업 도구의 경우 이벤트를 통해 다중 사용자 상호 작용을 관리할 수 있습니다.

  • 시나리오:
    • 사용자가 개체를 그리거나 입력하거나 이동할 때마다 onUserAction 이벤트를 전달합니다.
    • 다른 클라이언트와 UI 구성 요소는 이러한 이벤트를 수신하여 실시간 변경 사항을 반영합니다.

이러한 시나리오에서 useEvent 후크를 활용하면 깊게 중첩된 prop이나 콜백 체인에 의존하지 않고도 유지 관리 및 확장이 가능한 모듈식 애플리케이션을 만들 수 있습니다.


결론

이벤트는 복잡성을 줄이고 모듈성을 개선하여 React 애플리케이션을 구축하는 방식을 변화시킬 수 있습니다. 작게 시작하세요. 분리된 통신을 통해 이점을 얻을 수 있는 앱의 몇 가지 구성 요소를 식별하고 useEvent 후크를 구현하세요.

이러한 접근 방식을 사용하면 코드를 단순화할 뿐만 아니라 향후 유지 관리 및 확장도 더 쉽게 할 수 있습니다.

이벤트를 사용하는 이유는 무엇인가요?
불필요한 종속성이나 복잡한 콜백 체인을 도입하지 않고 애플리케이션의 다른 곳에서 발생한 일에 구성 요소가 반응해야 할 때 이벤트가 빛납니다. 이 접근 방식은 인지 부하를 줄이고 구성 요소를 긴밀하게 결합하는 함정을 방지합니다.

나의 추천
구성 요소 간 통신을 위해 이벤트를 사용합니다. 하나의 구성 요소가 구성 요소 트리에서의 위치에 관계없이 작업이나 상태 변경에 대해 다른 구성 요소에 알려야 하는 경우입니다.
특히 밀접하게 관련되거나 직접 연결된 구성 요소의 경우 구성 요소 간 통신에 이벤트를 사용하지 마세요. 이러한 시나리오에서는 props, state 또는 context와 같은 React의 내장 메커니즘을 활용하세요.

균형잡힌 접근
이벤트는 강력하지만 과도하게 사용하면 혼란을 초래할 수 있습니다. 느슨하게 연결된 구성 요소 간의 통신을 단순화하기 위해 신중하게 사용하되 로컬 상호 작용 관리를 위한 React의 표준 도구를 대체하지 마십시오.

위 내용은 깔끔한 React 컴포넌트 통신을 위한 이벤트 중심 아키텍처의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.