CBA — Backstage 인증 어소시에이트 · 플러그인·인증·운영 · 이론
플러그인 구조와 운영 — 포털이 죽지 않게 하려면
한 줄 요약
Backstage 의 확장은 프론트엔드·백엔드 두 갈래 플러그인으로 이루어지고, 최근에는 새 백엔드 시스템(new backend system) 으로 플러그인 설치가 크게 단순해졌습니다. 그리고 운영에서 실제로 부딪히는 것은 화려한 기능이 아니라 인증·신원 동기화·카탈로그 처리 주기·데이터베이스 입니다.
왜 이게 필요했나
포털은 "설치하고 끝"이 되지 않습니다. 붙이는 시스템이 늘어날수록 세 가지가 문제가 됩니다.
1. 누가 누구인가 — 로그인한 사람이 카탈로그의 어느 User 엔티티이고 어느 Group 에 속하는가. 이게 맞지 않으면 "내 서비스" 목록이 비고, 소유권 기반 기능이 전부 무의미해집니다.
2. 정보가 얼마나 신선한가 — 카탈로그가 저장소를 언제 다시 읽는가. 너무 잦으면 API 한도에 걸리고, 너무 뜸하면 사람들이 포털을 불신합니다.
3. 무엇이 상태를 갖는가 — 포털은 무상태처럼 보이지만 카탈로그와 스캐폴더 작업 이력은 데이터베이스에 있습니다.
어떻게 동작하나
플러그인 두 갈래와 새 백엔드 시스템
| | 프론트엔드 플러그인 | 백엔드 플러그인 |
| --- | --- | --- |
| 형태 | React 컴포넌트 | Node.js 모듈 |
| 제공하는 것 | 라우트, 엔티티 페이지의 탭·카드, 홈 위젯 | HTTP 엔드포인트, 카탈로그 프로세서·엔티티 제공자, 스캐폴더 액션 |
| 자격증명 | 없어야 함 | 여기에 있음 |
예전 백엔드는 플러그인마다 라우터를 손으로 배선하고 의존성을 직접 넘겨야 했습니다. 새 백엔드 시스템 은 이를 뒤집어, 백엔드가 플러그인과 모듈(module) 을 등록만 하면 필요한 것(로거, 설정, 데이터베이스, 인증, 스케줄러 등)을 의존성 주입 으로 받게 했습니다. 결과적으로 설치가 "패키지 추가 + 한 줄 등록"으로 줄었고, 플러그인 사이의 확장점이 명확해졌습니다. CBA 에서 이 전환(구 백엔드 → 새 백엔드 시스템)을 묻습니다.
인증과 신원 동기화
두 가지를 구분해야 합니다.
- 인증(authentication) — 로그인. GitHub, Google, Okta, Microsoft, OIDC 같은 제공자를 붙입니다.
- 신원 결정(sign-in resolver) — 로그인한 사람을 카탈로그의 어느 User 엔티티에 매핑할 것인가. 이메일로 맞출지, 사용자명으로 맞출지, 없으면 만들지.
여기에 조직 데이터 수집 이 더해집니다. GitHub Org, LDAP, Microsoft Entra 같은 곳에서 사용자와 팀 목록을 주기적으로 읽어 User/Group 엔티티로 넣는 것입니다. 이게 되어 있어야 spec.owner: group:team-checkout 이 실제 사람 목록으로 연결됩니다.
가장 흔한 도입 실패가 여기서 납니다. 카탈로그에 Group 이 없는데 소유자로 참조하면 관계가 끊긴 엔티티가 되고, "내 서비스" 페이지가 비어 있으면 사용자는 두 번째 방문을 하지 않습니다. 소유권 그래프가 채워지기 전에는 포털을 공개하지 않는 편이 낫습니다.
Kubernetes 플러그인의 연결 고리
엔티티 페이지에서 워크로드를 보여 주는 방식이 시험에 나옵니다.
- 엔티티(카탈로그)에는 애너테이션
backstage.io/kubernetes-id: <값>을 답니다. - 클러스터의 워크로드에는 같은 값을 라벨
backstage.io/kubernetes-id: <값>으로 답니다. - 백엔드가 등록된 클러스터들에 그 라벨 셀렉터로 질의해 결과를 모아 프론트엔드에 돌려줍니다.
방향을 헷갈리기 쉽습니다 — 엔티티는 애너테이션, 워크로드는 라벨입니다. 라벨 대신 네임스페이스로 찾게 하는 backstage.io/kubernetes-namespace 애너테이션도 있습니다. 그리고 질의는 백엔드가 하므로 클러스터 자격증명은 서버에만 있습니다.
운영 — 처리 주기와 데이터베이스
카탈로그는 두 단계로 데이터를 만듭니다.
1. 엔티티 제공자(entity provider) — 어디에 무엇이 있는지 발견해 넣는다(예: GitHub 조직 스캔).
2. 프로세서(processor) — 그 원본 엔티티를 읽어 검증하고, 관계를 계산하고, 파생 엔티티를 만든다.
이 처리는 주기적으로 반복됩니다. 주기를 짧게 하면 최신성이 좋아지지만 SCM API 호출이 늘어 한도(rate limit)에 걸립니다. 대규모에서는 웹훅이나 이벤트로 즉시 갱신하고 주기 자체는 길게 두는 조합을 씁니다.
데이터베이스는 개발 편의를 위해 SQLite 인메모리로 시작할 수 있지만 재시작하면 전부 사라집니다. 운영에서는 PostgreSQL 이 사실상 표준이고, 카탈로그·스캐폴더 작업 이력·검색 색인이 여기 들어갑니다. 이 말은 포털이 무상태 애플리케이션이 아니며 백업과 복구 계획이 필요하다 는 뜻입니다.
그리고 잊기 쉬운 운영 항목이 업그레이드입니다. Backstage 는 활발히 변하고, 여러분의 앱은 여러분 소유의 코드 트리입니다. 몇 달 미루면 나중에 한꺼번에 올리는 비용이 급격히 커집니다. 정기적으로 조금씩 올리는 것이 유일하게 지속 가능한 방식입니다.
현장에서 만나는 모습
저자의 홈랩에는 CloudNativePG 로 PostgreSQL 18 을 2 인스턴스 스트리밍 복제로 돌린 검증 기록이 있습니다. 포털을 얹는다면 그 데이터베이스가 바로 카탈로그의 집이 됩니다. 그리고 이 클러스터의 가장 뼈아픈 교훈이 여기 그대로 적용됩니다 — 컨트롤 플레인 3 대로 etcd 쿼럼은 갖췄지만 controlPlaneEndpoint 가 첫 노드의 물리 IP 라, 그 노드가 죽으면 데이터는 살아 있는데 아무도 API 에 접속하지 못합니다. 데이터 가용성과 접근 가용성은 별개 입니다.
포털도 똑같습니다. 카탈로그 데이터베이스를 복제해 두어도 포털 앱이 뜨지 못하면 아무도 정보를 얻지 못합니다. 반대로 포털이 살아 있어도 카탈로그 처리 주기가 멈춰 있으면 화면의 정보가 조용히 낡습니다. 후자가 더 위험합니다 — 장애는 눈에 보이지만 낡은 데이터는 안 보이기 때문입니다.
또 하나. 이 클러스터에서 반복 확인된 "상태가 Ready 와 실제로 동작한다는 다른 명제" 는 포털 운영의 핵심 감각입니다. KubeVirt 는 모든 컴포넌트가 AllComponentsReady 였는데 VM 이 뜨지 않았습니다. 포털도 헬스 체크는 초록인데 카탈로그 프로세서가 조용히 실패하고 있을 수 있습니다. 그래서 처리 성공률과 마지막 갱신 시각을 지표로 봐야 합니다.
다음 퀴즈에서 확인할 것
이 모듈은 퀴즈로 마무리합니다. 앞 모듈 실습에서 만든 backstage.io/kubernetes-id 애너테이션(엔티티)과 라벨(워크로드)의 짝을 다시 확인해 보면, 플러그인이 실제로 무엇을 하는지가 눈에 들어옵니다.