Backstageアプリリポジトリとプラグインの配線
한국어 원문으로 표시합니다.
목표
create-app 이 만들어 내는 Backstage 앱 저장소의 구조를 직접 세우고, 사내 플러그인을 하나 만들어 프런트엔드와 백엔드 양쪽에 배선합니다. 실습 파드는 인터넷이 막혀 있어 노드 의존성을 받을 수 없으므로 빌드는 하지 않고 구조와 배선만 다룹니다.
왜 중요한가
Backstage 를 쓴다는 것은 여러분 소유의 모노레포를 하나 갖는다는 뜻입니다. 그래서 "어느 파일을 고쳐야 하는가" 에 답하지 못하면 아무것도 커스터마이즈할 수 없고, 화면에서 찾을 수 있는 답도 없습니다. 특히 세 가지가 실무에서 반복해 사람을 막습니다. 첫째, package.json 의 역할 표시 하나가 그 패키지의 빌드 방식을 정합니다. 둘째, 새 백엔드 시스템에서는 플러그인과 모듈이 다른 것이고, 이름에 module 이 들어간 것은 짝이 되는 플러그인 없이는 아무 일도 하지 않습니다. 셋째, 엔티티 페이지에 탭만 붙이고 앱 라우트를 등록하지 않으면 탭은 보이는데 눌렀을 때 빈 화면이 뜨고 오류도 나오지 않습니다. 이 실습은 그 세 자리를 손으로 만들어 봅니다.
단계
/root/cba-app/package.json을 작성하세요 —private: true,workspaces.packages에packages/*와plugins/*두 개,scripts에dev·build:all·tsc·test:all네 개.build:all은backstage-cli repo build로 시작하는 명령,test:all은backstage-cli repo test로 시작하는 명령입니다./root/cba-app/packages/app/package.json을 작성하세요 —name: app,backstage.role: frontend,scripts.start는backstage-cli package start./root/cba-app/packages/backend/package.json도 작성하세요 —name: backend,backstage.role: backend,main은dist/로 시작하는 경로,scripts.start는 같은 명령입니다./root/cba-app/packages/backend/src/index.ts를 작성하세요 —@backstage/backend-defaults에서createBackend를 가져와 호출하고,backend.add(import('...'))를 정확히 일곱 번 씁니다. 등록할 패키지는@backstage/plugin-app-backend,@backstage/plugin-catalog-backend,@backstage/plugin-catalog-backend-module-github,@backstage/plugin-scaffolder-backend,@backstage/plugin-techdocs-backend,@backstage/plugin-auth-backend,@backstage/plugin-auth-backend-module-github-provider입니다. 마지막에backend.start()를 부르고,createRouter·PluginEnvironment·apiRouter같은 구 백엔드 방식의 흔적은 남기지 마세요./root/cba-app/plugins/oncall/package.json을 작성하세요 —name: @internal/plugin-oncall,backstage.role: frontend-plugin,sideEffects: false,dependencies에@backstage/core-plugin-api./root/cba-app/plugins/oncall-backend/package.json도 작성하세요 —name: @internal/plugin-oncall-backend,backstage.role: backend-plugin,main은dist/로 시작하는 경로,dependencies에@backstage/backend-plugin-api./root/cba-app/plugins/oncall/src/아래 세 파일을 작성하세요.routes.ts는createRouteRef로id: 'oncall'인rootRouteRef를 만들어 내보냅니다.plugin.ts는./routes에서 그 참조를 가져와createPlugin으로oncallPlugin을 만들고,createRoutableExtension으로OncallPage를 만들되mountPoint: rootRouteRef를 겁니다.plugin.ts안에서createRouteRef를 다시 부르지 마세요.index.ts는oncallPlugin과OncallPage두 개를 다시 내보냅니다./root/cba-app/packages/app/src/components/catalog/EntityPage.tsx를 작성하세요 —@internal/plugin-oncall에서OncallPage를 가져오고,isKind('component')조건 안에서EntityLayout.Route로path="/oncall"title="On-call"탭을 답니다./root/cba-app/packages/app/src/App.tsx도 작성하세요 — 같은 플러그인을 가져와path="/oncall"라우트에<OncallPage />를 element 로 겁니다./root/cba-app/packages.txt에packages/와plugins/아래 모든 패키지의 이름과 역할을이름=역할형식으로 한 줄에 하나씩, 중복 없이 정렬해 적으세요./root/cba-app/.github/workflows/ci.yaml을 작성하세요 —pull_request트리거,jobs.build.runs-on: ubuntu-latest,steps는 정확히 여섯 개입니다. 첫째는actions/checkout, 둘째는actions/setup-node, 그다음 네 개는 순서대로yarn install --immutable,yarn tsc,yarn build:all,yarn test:all을 run 으로 실행합니다.
참고
- 역할 값은
frontend,backend,frontend-plugin,backend-plugin네 가지를 씁니다. - 이름에
-module-이 들어간 백엔드 패키지는 짝이 되는 플러그인의 확장점에 끼우는 조각입니다. - 흔한 실수 1: 탭만 붙이고 앱 라우트를 빠뜨리는 것. 화면에 오류가 없어서 원인을 찾기 어렵습니다.
- 흔한 실수 2: 라우트 참조를
plugin.ts안에서 만드는 것. 순환 임포트를 막으려고 파일을 나눈 것이므로 의미가 사라집니다. - 흔한 실수 3: CI 에서
--immutable을 빼는 것. 잠금 파일이 조용히 바뀌면 어제 통과한 커밋이 오늘 다르게 빌드됩니다.
워크스페이스 루트
/root/cba-app/package.json 을 작성하세요 — private: true, workspaces.packages 에 packages/* 와 plugins/* 두 개, scripts 에 dev·build:all·tsc·test:all 네 개. build:all 은 backstage-cli repo build 로 시작하는 명령, test:all 은 backstage-cli repo test 로 시작하는 명령입니다.
루트 패키지는 배포하지 않습니다. 그리고 사내 플러그인을 레지스트리에 올리지 않고 쓰려면 워크스페이스 경로에 플러그인 디렉터리가 들어가야 합니다.
앱 두 개와 역할
/root/cba-app/packages/app/package.json 을 작성하세요 — name: app, backstage.role: frontend, scripts.start 는 backstage-cli package start. /root/cba-app/packages/backend/package.json 도 작성하세요 — name: backend, backstage.role: backend, main 은 dist/ 로 시작하는 경로, scripts.start 는 같은 명령입니다.
backstage-cli 는 package.json 의 역할 표시 하나를 보고 빌드 방식을 고릅니다. 백엔드 패키지의 진입점은 소스가 아니라 빌드 산출물을 가리켜야 합니다.
새 백엔드 시스템 배선
/root/cba-app/packages/backend/src/index.ts 를 작성하세요 — @backstage/backend-defaults 에서 createBackend 를 가져와 호출하고, backend.add(import('...')) 를 정확히 일곱 번 씁니다. 등록할 패키지는 @backstage/plugin-app-backend, @backstage/plugin-catalog-backend, @backstage/plugin-catalog-backend-module-github, @backstage/plugin-scaffolder-backend, @backstage/plugin-techdocs-backend, @backstage/plugin-auth-backend, @backstage/plugin-auth-backend-module-github-provider 입니다. 마지막에 backend.start() 를 부르고, createRouter·PluginEnvironment·apiRouter 같은 구 백엔드 방식의 흔적은 남기지 마세요.
새 백엔드 시스템은 라우터를 손으로 배선하지 않습니다. 그리고 이름에 module 이 들어간 것은 단독으로 동작하지 않으므로 짝이 되는 플러그인이 함께 등록되어 있어야 합니다.
사내 플러그인 패키지
/root/cba-app/plugins/oncall/package.json 을 작성하세요 — name: @internal/plugin-oncall, backstage.role: frontend-plugin, sideEffects: false, dependencies 에 @backstage/core-plugin-api. /root/cba-app/plugins/oncall-backend/package.json 도 작성하세요 — name: @internal/plugin-oncall-backend, backstage.role: backend-plugin, main 은 dist/ 로 시작하는 경로, dependencies 에 @backstage/backend-plugin-api.
사내 플러그인은 레지스트리에 올리지 않으므로 사내 스코프 이름을 씁니다. 프런트엔드 플러그인은 번들러가 쓰지 않는 코드를 떨어낼 수 있게 부수효과 없음을 선언합니다.
플러그인 소스 세 파일
/root/cba-app/plugins/oncall/src/ 아래 세 파일을 작성하세요. routes.ts 는 createRouteRef 로 id: 'oncall' 인 rootRouteRef 를 만들어 내보냅니다. plugin.ts 는 ./routes 에서 그 참조를 가져와 createPlugin 으로 oncallPlugin 을 만들고, createRoutableExtension 으로 OncallPage 를 만들되 mountPoint: rootRouteRef 를 겁니다. plugin.ts 안에서 createRouteRef 를 다시 부르지 마세요. index.ts 는 oncallPlugin 과 OncallPage 두 개를 다시 내보냅니다.
라우트 참조를 만드는 곳은 한 곳뿐이어야 합니다. 페이지 확장에는 그 참조를 마운트 지점으로 걸어 주세요.
엔티티 페이지 탭과 앱 라우트
/root/cba-app/packages/app/src/components/catalog/EntityPage.tsx 를 작성하세요 — @internal/plugin-oncall 에서 OncallPage 를 가져오고, isKind('component') 조건 안에서 EntityLayout.Route 로 path="/oncall" title="On-call" 탭을 답니다. /root/cba-app/packages/app/src/App.tsx 도 작성하세요 — 같은 플러그인을 가져와 path="/oncall" 라우트에 <OncallPage /> 를 element 로 겁니다.
탭을 붙이는 곳과 라우트를 등록하는 곳은 다른 파일입니다. 한쪽만 하면 화면에는 오류가 없는데 아무것도 안 나옵니다.
패키지 인벤토리
/root/cba-app/packages.txt 에 packages/ 와 plugins/ 아래 모든 패키지의 이름과 역할을 이름=역할 형식으로 한 줄에 하나씩, 중복 없이 정렬해 적으세요.
역할은 각 패키지가 스스로 선언한 값입니다. 손으로 적지 말고 파일에서 읽어 모으세요.
CI 게이트
/root/cba-app/.github/workflows/ci.yaml 을 작성하세요 — pull_request 트리거, jobs.build.runs-on: ubuntu-latest, steps 는 정확히 여섯 개입니다. 첫째는 actions/checkout, 둘째는 actions/setup-node, 그다음 네 개는 순서대로 yarn install --immutable, yarn tsc, yarn build:all, yarn test:all 을 run 으로 실행합니다.
합치기 전에 도는 게이트여야 하고, 순서는 설치 다음에 타입 검사입니다. 설치 단계에서 잠금 파일이 바뀔 수 있으면 게이트가 지키는 것이 없습니다.