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

프론트엔드 시스템 체인지로그

원문 보기 위키 갱신

프론트엔드 시스템 체인지로그 (Frontend System Changelog)

이 섹션은 프론트엔드 시스템 핵심 API의 다양한 버전에 대한 마이그레이션 가이드를 제공해요. 각 가이드는 특정 Backstage 릴리스에서 이루어진 변경 사항의 요약과 핵심 API 사용을 업데이트하는 방법을 제공해요.

출처: 문서

본문

소개 (Introduction)

이 섹션은 프론트엔드 시스템 핵심 API의 다양한 버전에 대한 마이그레이션 가이드를 제공해요. 각 가이드는 특정 Backstage 릴리스에서 이루어진 변경 사항의 요약과 핵심 API 사용을 업데이트하는 방법을 제공해요.

이 가이드는 이미 코드를 새 프론트엔드 시스템으로 마이그레이션했고, 최신 변경 사항에 맞춰 유지하려는 앱 및 플러그인 작성자를 위한 것이에요. 이 가이드는 이름이 바뀐 export처럼 deprecation 메시지로 설명할 수 있는 사소한 마이그레이션은 다루지 않아요.

1.50

확장 구성용 새 configSchema 옵션

createExtension과 createExtensionBlueprint의 config.schema 옵션은 이제 새 최상위 configSchema 옵션을 위해 폐기(deprecated)됐어요. 새 옵션은 factory 함수를 요구하는 대신 JSON Schema 지원이 있는 Standard Schema 호환 라이브러리의 직접 스키마 값을 받아요. createSchemaFromZod 헬퍼도 제거됐어요.

configSchema 옵션은 JSON Schema 지원이 있는 Standard Schema 인터페이스를 구현하는 스키마를 요구해요. 즉 zod v4(zod@^4.0.0)를 사용해야 해요. 참고로 zod v3 패키지의 zod/v4 하위 경로 export는 작동하지 않아요. Zod v4 API 표면을 노출하지만, 결과 스키마 객체가 configSchema가 요구하는 JSON Schema 변환을 지원하지 않기 때문이에요. 직접 zod v3 스키마도 새 configSchema 옵션에서는 지원되지 않아요. 이들은 폐기된 config.schema 콜백 형식을 통해서만 지원돼요.

예를 들어 이전에 이렇게 선언된 확장은:

createExtension({  // ...  config: {    schema: {      title: z => z.string().default('Hello'),      count: z => z.number().optional(),    },  },  factory({ config }) {    // ...  },});

이제 zod v4(zod@^4.0.0)를 사용해 이렇게 보여야 해요.

import { z } from 'zod';createExtension({  // ...  configSchema: {    title: z.string().default('Hello'),    count: z.number().optional(),  },  factory({ config }) {    // ...  },});

createExtensionBlueprint에도 동일하게 적용돼요.

import { z } from 'zod';const MyBlueprint = createExtensionBlueprint({  // ...  configSchema: {    title: z.string().default('Hello'),  },  factory(params, { config }) {    // ...  },});

그리고 makeWithOverrides를 통해 구성을 추가할 때도 동일해요.

import { z } from 'zod';MyBlueprint.makeWithOverrides({  configSchema: {    extra: z.string(),  },  factory(originalFactory, { config }) {    return originalFactory({      // ...    });  },});

configSchema 레코드의 각 필드는 factory 함수가 아닌 독립형 스키마 값이에요. 이는 구성 스키마 선언을 특정 zod 버전에서 분리하며, JSON Schema 지원이 있는 Standard Schema 인터페이스를 구현하는 모든 스키마 라이브러리를 사용할 수 있게 해줘요.

1.31

namespace 매개변수는 제거해야 함

모든 createExtension, createExtensionBlueprint 또는 .make()와 .makeWithOverrides() 메서드의 namespace 매개변수는 제거할 수 있어요. 이제 이것은 이미 그래야 했던 것처럼 plugin의 id로 기본 설정돼요.

createExtensionOverrides -> createFrontendModule

확장은 프론트엔드에 설치되려면 모듈로 감싸야 해요. 즉 createExtensionOverrides 함수를 createFrontendModule로 교체하고, pluginId 매개변수를 재정의 대상 pluginId로 설정해야 해요.

예를 들어:

import {  createPageExtension,  createExtensionOverrides,} from '@backstage/frontend-plugin-api';const customSearchPage = PageBlueprint.make({  namespace: 'search',  params: {    defaultPath: '/search',    loader: () =>      import('./CustomSearchPage').then(m => <m.CustomSearchPage />),  },});export default createExtensionOverrides({  extensions: [customSearchPage],});

이제 이렇게 보여야 해요.

import {  createPageExtension,  createFrontendModule,} from '@backstage/frontend-plugin-api';const customSearchPage = PageBlueprint.make({  params: {    defaultPath: '/search',    loader: () =>      import('./CustomSearchPage').then(m => <m.CustomSearchPage />),  },});export default createFrontendModule({  pluginId: 'search',  extensions: [customSearchPage],});

createApp 이동

createApp 함수가 새 @backstage/frontend-defaults 패키지로 이동했어요. @backstage/frontend-app-api의 이전 export는 이제 폐기되었으며 새 것으로 교체해야 해요.

"v1" 확장 지원 제거

1.30 릴리스 이전의 @backstage/frontend-plugin-api로 만든 확장은 createApp에서 더 이상 지원되지 않아요. 새 앱에서 확장을 사용하려면 @backstage/frontend-plugin-api 버전 0.7.0 이상으로 만들어야 해요.

ExtensionDefinition과 ExtensionBlueprint의 새 유형 매개변수

ExtensionDefinition과 ExtensionBlueprint의 유형 매개변수가 더 읽기 쉽고 진화하기 쉽도록 단일 객체 유형 매개변수를 사용하도록 업데이트됐어요.

기존 사용은 일반적으로 다음과 같이 업데이트할 수 있어요.

ExtensionDefinition<any> -> ExtensionDefinition ExtensionDefinition<any, any> -> ExtensionDefinition ExtensionDefinition<TConfig> -> ExtensionDefinition<{ config: TConfig }> ExtensionDefinition<TConfig, TConfigInput> -> ExtensionDefinition<{ config: TConfig, configInput: TConfigInput }>

매개변수를 추론해야 한다면 ExtensionDefinitionParameters와 ExtensionBlueprintParameters를 사용할 수 있어요. 예를 들어:

import {  ExtensionDefinition,  ExtensionDefinitionParameters,} from '@backstage/frontend-plugin-api';function myUtility<T extends ExtensionDefinitionParameters>(  ext: ExtensionDefinition<T>,): T['config'] {  // ...}

1.30

확장 입력과 출력 재작업

프론트엔드 시스템의 이전 버전에서는 확장 입력과 출력을 각 명명된 속성이 확장 factory에서 같은 이름으로 접근할 수 있는 데이터 조각에 해당하는 "데이터 맵"으로 정의했어요. 확장 재정의와 블루프린트를 더 잘 지원하고 혼동 위험을 줄이기 위해, 이 데이터 맵은 데이터 참조 배열로 교체됐어요.

예를 들어 이전에 이렇게 선언된 확장은:

createExtension({  name: 'example',  attachTo: { id: 'some-extension', input: 'content' },  inputs: {    header: createExtensionInput(      { element: coreExtensionData.reactElement },      {        optional: true,        singleton: true,      },    ),  },  output: { element: coreExtensionData.reactElement },  factory({ inputs }) {    return {      element: <ExtensionPage header={inputs.header?.output.element} />,    };  },});

이제 이렇게 보여요.

createExtension({  name: 'example',  attachTo: { id: 'some-extension', input: 'content' },  inputs: {    header: createExtensionInput([coreExtensionData.reactElement], {      optional: true,      singleton: true,    }),  },  output: [coreExtensionData.reactElement],  factory({ inputs }) {    return [      coreExtensionData.reactElement(        <ExtensionPage          header={inputs.header?.get(coreExtensionData.reactElement)}        />,      ),    ];  },});

inputs와 output 선언의 변경과 이를 factory에서 사용하는 방법에 주목하세요. inputs와 output 모두 이제 각 데이터 조각에 연결된 이름 없이 배열을 사용해 예상 데이터를 선언해요. 입력 객체의 get 메서드는 입력 데이터에 접근하는 데 사용되며, 해당 입력에 대해 선언된 데이터와 일치하는 데이터 참조를 받아요.

실질적으로 가장 큰 변경은 확장 factory가 데이터를 출력하는 방식이에요. 데이터 값이 있는 객체를 반환하는 대신 각 확장 데이터 참조를 사용해 값을 캡슐화하고 factory에서 이 캡슐화된 값의 모음을 반환해요.

확장 생성자 대신 블루프린트

특정 종류의 확장을 만들기 위해 createExtension을 함수로 감싼 "확장 생성자(extension creator)" 패턴이 확장 블루프린트로 교체됐어요. 확장 생성자는 구현하고 유지하기 어려웠으며, 블루프린트는 플러그인 빌더와 통합자 모두에게 훨씬 더 일관되고 강력한 API 표면을 제공해요. 예를 들어 createPageExtension은 PageBlueprint의 확장 생성자 동등물이었어요.

플러그인 또는 앱에서 확장 생성자의 모든 기존 사용을 해당하는 블루프린트로 교체하세요. 주어진 확장 생성자 create<Kind>Extension에 대해 블루프린트 동등물은 <Kind>Blueprint예요. 둘 사이에 API에 약간의 차이가 있을 수 있지만, 대부분 확장 생성자의 kind 특정 옵션을 블루프린트에 매개변수로 전달하기만 하면 돼요. 확장이 추가 입력이나 구성을 선언했다면 블루프린트의 .makeWithOverrides 메서드를 사용해야 한다는 점에 유의하세요.

플러그인이 확장 생성자를 export한다면, 이들을 블루프린트로 마이그레이션해야 해요.

확장 테스터 재작업

@backstage/frontend-test-utils 패키지의 createExtensionTester가 확장 테스트를 더 잘 지원하도록 재작업됐어요. 새 API는 새 .get(ref) 메서드를 사용해 확장 출력에 직접 접근할 수 있고, 새 .query(id/extension) 메서드를 통해 테스트된 모든 확장에 접근할 수 있어요.

테스트 앱에서 테스트 대상을 렌더링하는 데 사용되던 .render() 메서드는 폐기됐어요. 확장 테스터는 더 이상 전체 앱 트리를 구성하지 않고, 테스트 중인 확장에 대한 트리만 인스턴스화해요. 앱에서 출력하는 확장의 렌더링을 테스트하고 싶다면, 확장 테스터의 새 .reactElement() 메서드와 함께 renderInTestApp 유틸리티를 사용할 수 있어요: renderInTestApp(tester.reactElement()).

확장 데이터 참조 업데이트

확장 데이터 참조가 선언되는 방식이 ID의 유형 추론을 허용하도록 변경됐어요. 이를 위해 선언을 두 개의 별도 함수 호출로 분할해야 해요. 하나는 유형을 공급하고 다른 하나는 옵션을 추론하기 위한 것이에요. 예를 들어 이전에 이렇게 선언된 참조는:

export const myExtension = createExtensionDataRef<MyType>('my-plugin.my-data');

다음과 같이 업데이트해야 해요.

export const myExtension = createExtensionDataRef<MyType>().with({  id: 'my-plugin.my-data',});

더 알아보기 (Learn more)