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

사용법

원문 보기 위키 갱신

notifications 백엔드 플러그인은 알림을 만들고, 로그인한 사용자별로 알림을 나열하며, 매개변수를 기반으로 검색하는 API를 제공해요.

출처: 문서

본문

info

이 문서는 새 Backstage 앱에서 기본이 되는 새 프론트엔드 시스템을 위해 작성됐습니다. Backstage 앱이 여전히 옛 프론트엔드 시스템을 사용한다면, 대신 이 가이드의 옛 프론트엔드 시스템 버전을 읽으세요.

Notifications Backend

notifications 백엔드 플러그인은 알림을 만들고, 로그인한 사용자별로 알림을 나열하며, 매개변수를 기반으로 검색하는 API를 제공해요.

플러그인은 영속성을 위해 관계형 데이터베이스를 사용해요. 이 맥락에서 특정 사항은 도입되지 않아요.

processors를 위한 선택적 추가 모듈을 제외하면 app-config에 추가 구성이 필요 없어요.

Notifications Frontend

알림의 수신자는 카탈로그의 엔티티, 예를 들면 User나 Group 종류여야 해요.

그 외에는 프론트엔드 notifications 플러그인에 특정 구성이 필요 없어요.

NotificationsSidebarItem 컴포넌트를 프론트엔드의 활성 왼쪽 메뉴 항목으로 사용할 수 있어요. notifications 플러그인에는 아직 내장 내비게이션 항목이 없으므로, 커스텀 앱 모듈의 NavContentBlueprint를 통해 사이드바에 수동으로 추가해야 해요. 설정 지침은 Getting Started 가이드를 참고하세요.

사이드바 항목은 그 속성을 사용해 특정 요구에 맞게 커스터마이즈할 수 있어요.

사용법

새 알림은 백엔드 플러그인 또는 REST API를 통한 외부 서비스가 보낼 수 있어요.

Backend

기술적으로 가능한지와 무관하게, 백엔드 플러그인은 notifications REST API에 직접 접근하는 것을 피해야 해요. 대신 @backstage/plugin-notifications-node와 통합해 새 알림을 send(생성)해야 해요.

이 방식의 이유는 API 요청에서 인증의 전파, 그리고 향후 유지보수성과 하위 호환성의 개선을 포함해요.

import { notificationService } from '@backstage/plugin-notifications-node';export const myPlugin = createBackendPlugin({  pluginId: 'myPlugin',  register(env) {    env.registerInit({      deps: {        // ...        notificationService: notificationService,      },      async init({        // ...        notificationService,      }) {        httpRouter.use(          await createRouter({            // ...            notificationService,          }),        );      },    });  },});

새 알림을 발행하려면:

await notificationService.send({  recipients /* of the broadcast or entity type */,  payload /* actual message */,});

자세한 내용은 API 문서를 참고하세요.

외부 서비스

알림의 발신자가 Backstage 백엔드 플러그인일 때는 위에서 설명한 대로 @backstage/plugin-notifications-node를 통한 통합을 사용하는 것이 필수예요.

발신자가 Backstage 외부의 서비스라면, 인증이 제대로 구성되었다면 HTTP POST 요청을 API에 직접 보낼 수 있어요. 더 자세한 내용은 service-to-service auth 문서를 참고하세요. 가장 간단한 설정 옵션인 Static Tokens 섹션에 주목하세요.

브로드캐스트 알림을 만드는 예시 요청은 이렇게 생겼을 거예요.

curl -X POST https://[BACKSTAGE_BACKEND]/api/notifications -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_B...OKEN" -d '{"recipients":{"type":"broadcast"},"payload": {"title": "Title of broadcast message","link": "http://foo.com/bar","severity": "high","topic": "The topic"}}'

Scaffolder 템플릿

scaffolder 템플릿이 실행될 때 알림을 보내도록 @backstage/plugin-scaffolder-backend-module-notifications를 사용할 수 있어요. 모듈을 설치하려면 백엔드 플러그인에 추가하세요.

yarn workspace backend add @backstage/plugin-scaffolder-backend-module-notifications

그런 다음 모듈을 백엔드에 추가하세요.

const backend = createBackend();// ...backend.add(  import('@backstage/plugin-scaffolder-backend-module-notifications'),);

이제 템플릿에서 steps의 일부로 notification:send 액션을 사용할 수 있어요.

steps:  - id: notify    name: Notify    action: notification:send    input:      recipients: entity      entityRefs:        - component:default/backstage      title: 'Template executed'      info: 'Your template has been executed'      severity: 'info'      link: https://backstage.io

Signals

notifications와 signals의 함께 사용은 선택 사항이지만 일반적으로 사용자 경험과 성능을 향상시켜요.

알림이 생성되면, 구독한 리스너에게 알리기 위해 범용 메시지 버스에 새 신호가 발행돼요.

프론트엔드는 notifications 채널에서 이 공지를 받기 위해 영구 연결(WebSocket)을 유지해요. 업데이트되거나 생성된 알림의 구체적인 세부 사항은 성능상의 이유로 payload가 신호에 포함되는 새 알림을 제외하고, notifications API에 대한 요청으로 조회해야 해요.

프론트엔드 플러그인에서 notifications의 신호를 구독하려면:

import { useSignal } from '@backstage/plugin-signals-react';const { lastSignal } = useSignal<NotificationSignal>('notifications');React.useEffect(() => {  /* ... */}, [lastSignal, notificationsApi]);

자신의 플러그인에서 signals 사용하기

자신의 플러그인에서 signals를 사용해 백엔드에서 프론트엔드로 거의 실시간으로 데이터를 전달할 수 있어요.

자신의 프론트엔드 플러그인에서 signals를 사용하려면 @backstage/plugin-notifications-common에서 @backstage/plugin-signals-react의 useSignal 훅을 신호의 선택적 제네릭 타입과 함께 추가해야 해요.

// To use the same type of signal in the backend, this should be placed in a shared common packageexport type MySignalType = {  user: string;  data: string;  // ....};const { lastSignal } = useSignal<MySignalType>('my-plugin');useEffect(() => {  if (lastSignal) {    // Do something with the signal  }}, [lastSignal]);

백엔드 플러그인에서 신호를 보내려면 플러그인 또는 모듈에 signalsServiceRef를 종속성으로 추가해야 해요.

import { signalsServiceRef } from '@backstage/plugin-signals-node';export const myPlugin = createBackendPlugin({  pluginId: 'my',  register(env) {    env.registerInit({      deps: {        httpRouter: coreServices.httpRouter,        signals: signalsServiceRef,      },      async init({ httpRouter, signals }) {        httpRouter.use(          await createRouter({            signals,          }),        );      },    });  },});

서비스를 사용해 신호를 보내려면 publish 메서드를 사용할 수 있어요.

signals.publish<MySignalType>({ user: 'user', data: 'test' });

알림 소비하기

프론트엔드 플러그인에서 알림을 쿼리하는 가장 간단한 방법은 ID로 조회하는 거예요.

import { useApi } from '@backstage/core-plugin-api';import { notificationsApiRef } from '@backstage/plugin-notifications';const notificationsApi = useApi(notificationsApiRef);notificationsApi.getNotification(yourId);// or with connection to signals:notificationsApi.getNotification(lastSignal.notification_id);

Metadata 필드

metadata 필드는 프로세서가 사용하도록 설계된 자유 형식 객체예요.

잘 알려진 알림 Metadata 필드

아래는 프로세서들 사이에서 공통으로 사용되고 정의된 스키마가 있는 metadata 필드예요.

backstage.io/body.markdown

# Example:const payload = {  title: 'Entities Require Attention',  description: 'Entities: Service A, Service B',  metadata: {     'backstage.io/body.markdown': `        # Entities        - Service A        - System B     `  }}

이 metadata 필드의 값은 마크다운 형식의 알림 메시지여야 해요. 이렇게 하면 마크다운을 지원하는 프로세서에 추가 서식 옵션을 제공할 수 있어요.

사용법

아래는 커스텀 프로세서에서 backstage.io/body.markdown metadata 필드를 사용하는 예시예요.

알림을 보낼 때:

notificationService.send({  recipients: { type: 'entity', entityRef: 'group/default:team-a' },  payload: {    title: 'Notification',    description: 'Description',    metadata: {      'backstage.io/body.markdown': `        ### Notification        Description      `,    },  },});

프로세서에서 metadata 필드를 그에 따라 사용할 수 있어요.

async postProcess(notification: Notification): Promise<void> {  // We suggest you parse the metadata field with a schema, i.e. Zod  const parseResult = CustomProcessorMetadataSchema.safeParse(notification.payload.metadata ?? {});  const metadata = parseResult.success ? parseResult.data : {};  customNotificationSender.send({    to: getUsers(notification.recipients),    subject: notification.payload.title,    markdownText: metadata['backstage.io/body.markdown'] ?? notification.payload.description,  });}

더 알아보기 (Learn more)