002 - 둘러보기
yarn new --select frontend-plugin --option pluginId=todo --option owner= 가 생성한 코드를 하나씩 살펴볼게요.
플러그인 정의
plugins/todo/src/plugin.tsx를 열어 보세요. 이것이 플러그인의 진입점이에요.
import {
createFrontendPlugin,
PageBlueprint,
} from '@backstage/frontend-plugin-api';
import { rootRouteRef } from './routes';
export const page = PageBlueprint.make({
params: {
path: '/todo',
routeRef: rootRouteRef,
loader: () => import('./components/TodoPage').then(m => <m.TodoPage />),
},
});
export const todoPlugin = createFrontendPlugin({
pluginId: 'todo',
extensions: [page],
routes: {
root: rootRouteRef,
},
});
createFrontendPlugin은 플러그인을 Backstage에 등록해요.PageBlueprint.make는 페이지 확장을 정의해요. 앱에서TodoPage컴포넌트를 지연 로드(lazy-load)하는 라우트죠.rootRouteRef는 다른 플러그인이 여러분의 플러그인 페이지로 링크할 때 쓰는 라우트 참조예요.
출처: 문서
본문
TodoPage 컴포넌트
plugins/todo/src/components/TodoPage/TodoPage.tsx를 열어 보세요. 이 컴포넌트는 백엔드에서 데이터를 가져와 렌더링해요.
const { value: todos, loading, error } = useTodos();
useTodos 훅은 Backstage의 fetchApiRef 를 사용해 plugin://todo/todos를 요청해요.
fetchApiRef는 브라우저fetch를 감싸고, 인증 자격 증명을 자동으로 주입하며,plugin://URL 스킴을 올바른 백엔드 플러그인 엔드포인트(예:http://localhost:7007/api/todo/todos)로 해석해요.
백엔드가 실행 중이 아니면 페이지는 예시 데이터로 폴백해서, 플러그인이 기본 상태에서도 올바르게 렌더링되도록 해요.
TodoList 컴포넌트
plugins/todo/src/components/TodoList/TodoList.tsx를 열어 보세요. 이것은 TODO 목록을 props로 받아 @backstage/ui의 Table로 렌더링하는 프레젠테이셔널 컴포넌트예요.
TodoItem 타입은 백엔드 플러그인이 반환하는 형태와 일치해요.
export type TodoItem = {
title: string;
id: string;
createdBy: string;
createdAt: string;
};
페이지 구조 이해하기
스캐폴딩된 플러그인은 @backstage/ui와 @backstage/core-components의 컴포넌트를 사용해 모든 Backstage 플러그인에서 일관된 모양과 느낌을 갖도록 해요.
- 페이지의 상단 바는 보통 페이지 컴포넌트 안의 커스텀
Header가 아니라, 주변의PageLayout(기본 앱에서 흔히PluginHeader)이 제공해요. Container는 페이지의 주요 콘텐츠 영역이에요(@backstage/ui에서 제공).Table은 열(column) 설정으로 데이터 테이블을 렌더링해요(@backstage/ui에서 제공).Progress는 로딩 표시기를 보여줘요(@backstage/core-components에서 제공).
플러그인을 Backstage의 나머지와 시각적으로 일관되게 유지하는 것은 중요해요. 어떤 플러그인과 상호작용하든 사용자가 편안함을 느껴야 하거든요.