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

백엔드 기능 로더

원문 보기 위키 갱신

백엔드 기능 로더는 Backstage 백엔드에서 기능을 프로그래밍 방식으로 선택하고 설치하는 데 사용돼요.

출처: 문서

본문

백엔드 기능 로더는 Backstage 백엔드에서 기능을 프로그래밍 방식으로 선택하고 설치하는 데 사용돼요. 정적 구성에 따라 기능을 활성화하거나 비활성화하고, 런타임에 기능을 동적으로 로드하거나, 시스템의 상태에 따라 기능을 조건부로 로드하는 것과 같은 광범위한 사용 사례를 처리할 수 있어요.

기능 로더는 @backstage/backend-plugin-api가 내보내는 createBackendFeatureLoader 함수로 정의해요. loader 함수와 서비스 의존성을 선언하기 위한 선택적 deps 객체를 받아요. 플러그인과 모듈과 달리 기능 로더는 루트 범위 서비스에만 의존하도록 제한되지만, 예를 들어 루트 config와 루트 logger 서비스에는 여전히 접근할 수 있어요.

loader 함수는 여러 방식으로 정의할 수 있으며, 주요 요구 사항은 어떤 형태로든 BackendFeature 목록을 반환하는 것이에요. 백엔드 기능은 backend.add(...)에 전달할 수 있는 종류의 객체로, 예를 들어 서비스 팩토리, 플러그인, 모듈, 또는 다른 기능 로더가 있어요. loader 함수는 동기식이거나 비동기식일 수 있으며, 더 복잡한 로직을 허용하기 위해 제너레이터 함수로 정의할 수도 있어요.

예시

다음은 기능 로더를 사용할 수 있는 몇 가지 예시예요:

단순 기능 목록

기능 로더는 설치할 기능 목록을 단순히 반환할 수 있어요:

export default createBackendFeatureLoader({  loader() {    return [      import('@backstage/plugin-search-backend'),      import('@backstage/plugin-search-backend-module-catalog'),      import('@backstage/plugin-search-backend-module-explore'),      import('@backstage/plugin-search-backend-module-techdocs'),    ];  },});

커스텀 기능 모음을 캡슐화할 수도 있어요:

export default createBackendFeatureLoader({  // Async loader is fine too  async loader() {    return [      createBackendPlugin({        ...      }),      createBackendModule({        ...      }),    ]  },});

조건부 로딩

기능 로더는 config 서비스 같은 루트 범위 서비스에 접근할 수 있어요. 이는 구성에 따른 기능의 조건부 로딩을 허용해요. 이 용도로는 제너레이터 함수를 사용하는 것이 편리할 때가 많아요:

export default createBackendFeatureLoader({  deps: {    config: coreServices.rootConfig,  },  // The `*` in front of the function name makes it a generator function  *loader({ config }) {    // Example of a custom config flag to enable search    if (config.getOptionalString('customFeatureToggle.search')) {      yield import('@backstage/plugin-search-backend');      yield import('@backstage/plugin-search-backend-module-catalog');      yield import('@backstage/plugin-search-backend-module-explore');      yield import('@backstage/plugin-search-backend-module-techdocs');    }  },});

서비스 팩토리 재정의

기능 로더가 등록한 서비스 팩토리는 backend.add로 직접 추가한 것보다 우선순위가 낮아요. 이렇게 하면 더 많은 수의 서비스 구현에 기능 로더를 사용하면서도 개별 서비스는 여전히 재정의할 수 있어요.

서로 다른 기능 로더나 서비스 팩토리가 추가되는 순서는 중요하지 않아요. 기능 로더 사이에도 우선순위가 없어서, 두 개의 서로 다른 기능 로더가 같은 서비스에 팩토리를 추가하면 백엔드는 시작에 실패해요.

const backend = createBackend();backend.add(  createBackendFeatureLoader({    async *loader() {      yield import('./commonDiscoveryService'); // discovery service      yield import('./commonRootLoggerService'); // root logger service    },  }),);backend.add(import('./myDiscoveryService')); // discovery service

위 예시의 결과는 백엔드가 discovery 서비스 구현으로 ./myDiscoveryService를 사용해 시작되고, ./commonDiscoveryService는 무시되는 것이에요. ./commonRootLoggerService는 여전히 사용돼요.

동적 로직

기능 로더는 비동기일 수도 있고, 예를 들어 외부 소스에서 데이터를 가져와 어떤 기능을 로드할지 결정할 수 있어요:

export default createBackendFeatureLoader({  // The `async *` in front of the function name makes it an async generator function.  async *loader() {    const localMetadata = await readMetadataFromDisk();    if (localMetadata.enableSearch) {      yield import('@backstage/plugin-search-backend');      yield import('@backstage/plugin-search-backend-module-catalog');      const remoteMetadata = await fetchMetadata();      if (remoteMetadata.enableExplore) {        yield import('@backstage/plugin-search-backend-module-explore');      }      if (remoteMetadata.enableTechDocs) {        yield import('@backstage/plugin-search-backend-module-techdocs');      }    }  },});

더 알아보기 (Learn more)