본문 바로가기
클라우드/Backstage

내 맘대로 구성하는 Backstage 엔터티 페이지! 조건부 탭(Conditional Tab) 구현 가이드 🛠️

by gasbugs 2025. 12. 25.

안녕하세요, 플랫폼 엔지니어 여러분! 👋 Backstage를 운영하다 보면 이런 고민이 생깁니다.

 

"우리 팀은 Kubernetes를 쓰는 서비스만 K8s 탭을 보여주고 싶은데..."

"자바 프로젝트에만 SonarQube 탭을 노출할 수 없을까?"

 

Backstage는 EntityLayout.Route와 'Filter Functions'를 결합하여 이 문제를 아주 우아하게 해결합니다. 지금부터 그 방법을 상세히 파헤쳐 보겠습니다!


1. 기본 개념: EntityLayout.Route와 if 프롭 🧩

Backstage 엔터티 페이지의 각 탭은 EntityLayout.Route 컴포넌트로 정의됩니다. 이 컴포넌트에는 if라는 아주 특별한 프롭(Prop)이 있습니다.

  • 동작 원리: if 프롭에 전달된 함수가 true를 반환하면 탭이 렌더링되고, false를 반환하면 탭이 아예 나타나지 않습니다.
  • 입력 값: 이 함수는 현재 페이지의 Entity 객체를 인자로 받아 메타데이터를 검사합니다.

2. 자주 사용하는 필터 함수들 🛠️

Backstage는 @backstage/plugin-catalog-react 패키지를 통해 자주 쓰이는 필터용 유틸리티 함수들을 제공합니다.

① 특정 종류(Kind)에 따라 보여주기

TypeScript

import { isEntityKind } from '@backstage/plugin-catalog-react';

<EntityLayout.Route if={isEntityKind('component')} path="/docs" title="Docs">
  <EntityTechdocsContent />
</EntityLayout.Route>

② 어노테이션(Annotation) 존재 여부에 따라 보여주기 (가장 많이 사용!)

특정 플러그인 설정이 catalog-info.yaml에 있을 때만 탭을 보여주고 싶을 때 사용합니다.

TypeScript

import { isAnnotationNonEmpty } from '@backstage/plugin-catalog-react';

<EntityLayout.Route 
  if={isAnnotationNonEmpty('backstage.io/kubernetes-id')} 
  path="/kubernetes" 
  title="Kubernetes"
>
  <EntityKubernetesContent />
</EntityLayout.Route>

③ 컴포넌트 타입(Type)에 따라 보여주기

서비스인지, 라이브러리인지, 웹사이트인지에 따라 구분합니다.

TypeScript

import { isComponentType } from '@backstage/plugin-catalog-react';

<EntityLayout.Route if={isComponentType('service')} path="/api" title="API">
  <EntityApiDefinitionCard />
</EntityLayout.Route>

3. 고수들의 비법: 커스텀 필터 만들기 💡

제공되는 함수만으로는 부족할 때가 있죠? 직접 필터 함수를 만들 수도 있습니다. 예를 들어, 특정 태그(tag)가 포함된 경우에만 탭을 보여주고 싶다면 다음과 같이 작성합니다.

TypeScript

const isJavaProject = (entity: Entity) => 
  entity.metadata.tags?.includes('java') ?? false;

// ... EntityPage.tsx 내부
<EntityLayout.Route if={isJavaProject} path="/jvm-metrics" title="JVM Metrics">
  <MyCustomJvmComponent />
</EntityLayout.Route>

4. 여러 조건을 조합하고 싶을 때: isAnd 🤝

두 가지 이상의 조건이 모두 충족되어야 할 때는 isAnd 함수를 사용합니다.

TypeScript

import { isAnd, isEntityKind, isAnnotationNonEmpty } from '@backstage/plugin-catalog-react';

const myCondition = isAnd([
  isEntityKind('component'),
  isAnnotationNonEmpty('my-plugin/id')
]);

<EntityLayout.Route if={myCondition} path="/my-plugin" title="My Plugin">
  <MyPluginContent />
</EntityLayout.Route>

5. 실무 적용 꿀팁: 쾌적한 UX 만들기 ✨

  1. 불필요한 노이즈 제거: 데이터가 없는 탭은 빈 화면을 보여주는 대신, 위와 같이 if 문으로 탭 자체를 숨기는 것이 사용자 경험(UX) 측면에서 훨씬 좋습니다.
  2. 기본값 설정: 필수적인 정보(Overview, CI/CD 등)는 조건 없이 항상 노출하여 일관성을 유지하세요.
  3. 카탈로그 가이드 제공: 탭이 보이지 않아 당황하는 사용자들을 위해, "이 탭을 보려면 catalog-info.yaml에 어떤 어노테이션을 추가해야 하는지" 안내하는 가이드를 사내 위키에 작성해 두는 것이 좋습니다. 📚

🏁 마무리하며

EntityLayout.Route의 if 프롭은 Backstage 엔터티 페이지를 단순한 대시보드에서 "엔터티 맞춤형 인텔리전트 포털"로 진화시키는 핵심 도구입니다. 이제 여러분의 서비스 성격에 꼭 맞는 최적화된 화면을 구성해 보세요!