본문 바로가기
WIKI 기술 지식 베이스

여러 위치에 확장 공유하기

원문 보기 위키 갱신

여러 위치에 확장 공유하기 (Sharing Extensions Across Multiple Locations)

일부 플러그인은 앱 전체의 여러 위치에서 재사용할 수 있는 확장성을 제공해야 할 수 있어요. 예를 들어 이 페이지에서 보여주는 패턴에서는 위젯을 기여해 여러 페이지에서 렌더링되도록 함으로써 플러그인을 확장 가능하게 만들 수 있어요. 이를 달성하려면 확장을 수집해 플러그인이나 앱 전체에서 사용할 수 있게 하는 Utility API를 사용하는 것이 권장 패턴이에요.

출처: 문서

본문

일부 플러그인은 앱 전체의 여러 위치에서 재사용할 수 있는 확장성을 제공해야 할 수 있어요. 예를 들어 이 페이지에서 보여주는 패턴에서는 위젯을 기여해 여러 페이지에서 렌더링되도록 함으로써 플러그인을 확장 가능하게 만들 수 있어요. 이를 달성하려면 확장을 수집해 플러그인이나 앱 전체에서 사용할 수 있게 하는 Utility API를 사용하는 것이 권장 패턴이에요.

개요 (Overview)

이 패턴은 Utility API와 확장 블루프린트를 결합해 다음을 수행해요.

  • 확장 데이터 유형과 API 인터페이스 정의

  • 확장을 만들기 위한 블루프린트 제공

  • 확장을 입력으로 수집하는 Utility API 확장 만들기

  • API를 통해 확장 소비하기

이 접근 방식은 프론트엔드 시스템과의 기본 통합을 제공하며, 확장을 구성 가능하게 만들거나 추가 확장 지점을 갖는 것 같은 기능을 추가로 활용할 수 있게 해줘요.

기본 패턴 (Basic Pattern)

다음 예시는 여러 페이지에서 표시할 수 있는 위젯을 사용해 이 패턴을 보여줘요. 하지만 이 패턴은 유연하며 다음을 수행해야 하는 많은 다른 시나리오에 적용할 수 있어요.

  • 같은 유형의 확장을 다른 페이지나 뷰 간에 공유

  • 서드파티 플러그인이 분리된 방식으로 확장을 기여할 수 있도록 허용

  • 여러 소스의 유사한 기능을 일관된 방식으로 집계

공유하는 기능 유형이 무엇이든 핵심 개념은 동일하게 유지돼요.

1. 확장 데이터 유형과 API 인터페이스 정의하기

먼저 플러그인의 -react 패키지(예: backstage-plugin-foo-react)에서 위젯 유형과 API 인터페이스를 정의해요.

in backstage-plugin-foo-react

import { createApiRef } from '@backstage/frontend-plugin-api';import { ComponentType } from 'react';export interface FooWidgetProps {  title: string;}// Define what data each widget provides, prefer using lazy loading for large pieces of functionality like componentsexport interface FooWidget {  title: string;  size: 'small' | 'medium' | 'large';  loader: () => Promise<ComponentType<FooWidgetProps>>;}// Define the API interfaceexport interface FooWidgetsApi {  getWidgets(): FooWidget[];}// Create the API referenceexport const fooWidgetsApiRef = createApiRef<FooWidgetsApi>({  id: 'plugin.foo.widgets',});

2. 확장을 만드는 블루프린트 제공하기

다음으로, 역시 -react 패키지(예: backstage-plugin-foo-react)에서 확장을 만드는 블루프린트를 만들어요. 블루프린트는 내부 데이터 참조를 만들고 dataRefs 속성을 통해 노출해요. 이 블루프린트는 다른 플러그인이 사용하도록 export될 거예요.

in backstage-plugin-foo-react

import {  createExtensionBlueprint,  createExtensionDataRef,  ExtensionBoundary,} from '@backstage/frontend-plugin-api';const fooWidgetDataRef = createExtensionDataRef<FooWidget>().with({  id: 'foo.widget',});export const FooWidgetBlueprint = createExtensionBlueprint({  kind: 'foo-widget',  // Attach extensions created with this blueprint to the API extension that will be created in the next step  attachTo: { id: 'api:foo/widgets', input: 'widgets' },  output: [fooWidgetDataRef],  *factory(params: FooWidget, { node }) {    yield fooWidgetDataRef({      title: params.title,      size: params.size,      loader: ExtensionBoundary.lazyComponent(node, params.loader),    });  },  dataRefs: {    widget: fooWidgetDataRef,  },});

3. 확장을 수집하는 Utility API 확장 만들기

기본 플러그인 패키지(예: backstage-plugin-foo)에서 위젯을 입력으로 수집하는 Utility API 확장을 만들어요. 이는 FooWidgetBlueprint.dataRefs.widget를 통해 블루프린트의 데이터 참조를 import한다는 점에 유의하세요.

in backstage-plugin-foo

import {  ApiBlueprint,  createExtensionInput,} from '@backstage/frontend-plugin-api';import {  FooWidgetBlueprint,  fooWidgetsApiRef,} from 'backstage-plugin-foo-react';export const FooWidgetsApiExtension = ApiBlueprint.makeWithOverrides({  name: 'widgets',  inputs: {    widgets: createExtensionInput([FooWidgetBlueprint.dataRefs.widget]),  },  factory(originalFactory, { inputs }) {    // Collect all widgets from the inputs and forward them to the API implementation    const widgets = inputs.widgets.map(w =>      w.get(FooWidgetBlueprint.dataRefs.widget),    );    return originalFactory(defineParams =>      defineParams({        api: fooWidgetsApiRef,        deps: {},        factory: () => ({          getWidgets: () => widgets,        }),      }),    );  },});

이제 다른 플러그인은 -react 패키지에서 블루프린트를 import하고 API가 수집할 위젯 확장을 만들 수 있어요.

in a consuming plugin

import { FooWidgetBlueprint } from 'backstage-plugin-foo-react';const barWidgetExtension = FooWidgetBlueprint.make({  name: 'bar',  params: {    title: 'Bar Widget',    size: 'small',    loader: () => import('./components/BarWidget').then(m => m.BarWidget),  },});const bazWidgetExtension = FooWidgetBlueprint.make({  name: 'baz',  params: {    title: 'Baz Widget',    size: 'medium',    loader: () => import('./components/BazWidget').then(m => m.BazWidget),  },});

4. API를 통해 확장 소비하기

이제 Utility API를 소비하는 사용 가능한 어떤 방법으로든 위젯을 소비할 수 있어요. 예를 들어 컴포넌트에서 위젯에 접근하는 방법은 다음과 같아요.

in backstage-plugin-foo

import { useApi } from '@backstage/frontend-plugin-api';import { fooWidgetsApiRef } from 'backstage-plugin-foo-react';import { Suspense, lazy } from 'react';export function FooPageContent() {  const widgetsApi = useApi(fooWidgetsApiRef);  const widgets = widgetsApi.getWidgets();  return; // load and render widgets ...}

Utility API 소비에 대한 자세한 내용은 Utility API 소비 페이지를 참고하세요.

더 알아보기 (Learn more)