Skip to content

필사 모드: Backstage로 IDP 구축하기 1 — 소프트웨어 카탈로그가 전부다

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며 — 왜 지금 IDP인가

마이크로서비스가 50개를 넘어가는 순간부터 조직에는 공통된 질문이 쏟아지기 시작합니다. "이 서비스 담당 팀이 어디죠?", "결제 API 스펙 문서는 어디 있나요?", "이 DB를 쓰는 서비스가 뭐가 있죠?", "신규 입사자가 우리 시스템 전체를 파악하려면 누구한테 물어봐야 하나요?" 이런 질문에 답하는 비용이 곧 조직의 인지 부하(cognitive load)이고, 이 부하를 시스템적으로 줄이는 것이 플랫폼 엔지니어링의 핵심 과제입니다.

내부 개발자 포털(Internal Developer Portal, IDP)은 이 문제에 대한 업계의 답입니다. 그리고 그 사실상의 표준이 Spotify가 2020년 오픈소스로 공개하고 CNCF에 기증한 Backstage입니다. Backstage는 CNCF 샌드박스(2020년)와 인큐베이팅(2022년) 단계를 거치며 성숙해 왔고, 공개된 어답터 목록 기준으로 수천 개 조직이 도입한, CNCF에서 가장 활발한 프로젝트 중 하나입니다. Gartner와 Puppet의 플랫폼 엔지니어링 보고서들도 "대규모 엔지니어링 조직의 대다수가 2026년까지 내부 플랫폼 팀을 운영하게 될 것"이라는 방향성을 일관되게 제시해 왔습니다.

이 시리즈는 Backstage로 IDP를 구축하는 과정을 3편에 걸쳐 다룹니다. 1편인 이 글의 주제는 단 하나, 소프트웨어 카탈로그입니다. 결론부터 말씀드리면 이렇습니다. **카탈로그가 비어 있는 Backstage는 아무것도 아닙니다.** Scaffolder도, TechDocs도, Kubernetes 플러그인도 전부 카탈로그의 엔터티에 매달려 동작합니다. 카탈로그 설계가 IDP 프로젝트의 성패를 가릅니다.

IDP에서 Backstage의 위치

먼저 용어를 정리하겠습니다. IDP라는 약어는 두 가지로 쓰입니다.

| 용어 | 의미 | 초점 |

| --- | --- | --- |

| Internal Developer Platform | 셀프서비스 인프라 플랫폼 전체 | 프로비저닝, 골든 패스, 환경 관리 |

| Internal Developer Portal | 플랫폼의 단일 진입점 UI | 카탈로그, 문서, 셀프서비스 UI |

Backstage는 엄밀히는 후자, 즉 포털 프레임워크입니다. 인프라를 직접 프로비저닝하는 엔진이 아니라, 조직의 모든 소프트웨어 자산과 도구를 하나의 화면으로 모으는 프레임워크입니다. 핵심 구성 요소는 네 가지입니다.

+---------------------------------------------------------------+

| Backstage (포털 프레임워크) |

| |

| +----------------+ +----------------+ +-----------------+ |

| | Software | | Scaffolder | | TechDocs | |

| | Catalog | | (골든 패스) | | (docs-as-code) | |

| | (이 글의 주제) | | [2편] | | [3편] | |

| +-------+--------+ +-------+--------+ +--------+--------+ |

| | | | |

| +-------v-------------------v--------------------v--------+ |

| | 플러그인 생태계 (K8s, ArgoCD, ...) | |

| +----------------------------------------------------------+ |

+---------------------------------------------------------------+

카탈로그는 나머지 모든 기능의 데이터 기반입니다. Scaffolder가 새 서비스를 만들면 카탈로그에 등록하고, TechDocs는 카탈로그 엔터티에 문서를 연결하며, Kubernetes 플러그인은 카탈로그의 어노테이션을 보고 어떤 워크로드를 보여줄지 결정합니다.

카탈로그 데이터 모델 — 여섯 가지 핵심 Kind

Backstage 카탈로그는 엔터티(entity)의 그래프입니다. 모든 엔터티는 `apiVersion`, `kind`, `metadata`, `spec`을 가진 YAML 문서로 표현되며, Kubernetes 리소스 모델에서 의도적으로 영감을 받았습니다. 핵심 Kind는 다음과 같습니다.

| Kind | 설명 | 예시 |

| --- | --- | --- |

| Component | 코드로 만들어진 소프트웨어 단위 | 백엔드 서비스, 웹앱, 라이브러리 |

| API | 컴포넌트가 제공/소비하는 인터페이스 | OpenAPI, gRPC, GraphQL, AsyncAPI |

| Resource | 컴포넌트가 의존하는 인프라 | RDS, S3 버킷, Kafka 토픽 |

| System | 함께 하나의 기능을 이루는 묶음 | 결제 시스템, 검색 시스템 |

| Domain | 시스템들을 묶는 비즈니스 영역 | 커머스, 정산, 회원 |

| Group / User | 소유권의 주체 | 팀, 파트, 개인 |

이들이 관계로 연결되어 그래프를 이룹니다.

+------------------+

| Domain | 예: payments-domain

| (비즈니스 영역) |

+--------^---------+

| partOf

+--------+---------+

| System | 예: payment-system

+--------^---------+

| partOf

+--------------------+--------------------+

| | |

+-------+--------+ +------+---------+ +------+--------+

| Component | | Component | | Component |

| payment-api | | payment-worker | | payment-web |

+---+-------+----+ +-------+--------+ +---------------+

| | |

| | providesApi | consumesApi

| v v

| +--+----------------+--+

| | API | 예: payment-v1 (OpenAPI)

| +----------------------+

| dependsOn

v

+---+------------+ +-----------------+

| Resource | | Group |

| payment-db | | team-payments |

+----------------+ +--------^--------+

| ownedBy (모든 엔터티에서)

관계는 양방향으로 자동 생성됩니다. Component가 `providesApis`를 선언하면 API 쪽에는 `apiProvidedBy` 역방향 관계가 만들어집니다. 이 그래프 덕분에 "payment-db를 쓰는 서비스 전부"나 "team-payments가 소유한 모든 자산" 같은 질의가 클릭 한 번으로 가능해집니다.

catalog-info.yaml 실전 작성

각 저장소 루트에 `catalog-info.yaml` 파일을 두는 것이 표준 관행입니다. 실전 예제를 세 가지 보겠습니다.

백엔드 서비스 (Component + 제공 API)

apiVersion: backstage.io/v1alpha1

kind: Component

metadata:

name: payment-api

title: Payment API Server

description: 결제 승인/취소를 처리하는 핵심 백엔드 서비스

annotations:

github.com/project-slug: acme-corp/payment-api

backstage.io/techdocs-ref: dir:.

backstage.io/kubernetes-id: payment-api

pagerduty.com/integration-key: PD-INTEGRATION-KEY

sonarqube.org/project-key: acme_payment-api

tags:

- java

- spring-boot

- payments

links:

- url: https://grafana.acme.io/d/payment-api

title: Grafana Dashboard

icon: dashboard

spec:

type: service

lifecycle: production

owner: group:default/team-payments

system: payment-system

providesApis:

- payment-v1

dependsOn:

- resource:payment-db

- resource:payment-events-topic

주목할 점은 `annotations`입니다. 카탈로그 자체는 이 값을 해석하지 않지만, 각 플러그인이 자신의 어노테이션을 읽어 동작합니다. `backstage.io/kubernetes-id`가 있어야 Kubernetes 탭이 뜨고, `pagerduty.com/integration-key`가 있어야 온콜 정보가 나옵니다. 어노테이션이 곧 플러그인 활성 스위치입니다.

API 엔터티 (OpenAPI 스펙 연결)

apiVersion: backstage.io/v1alpha1

kind: API

metadata:

name: payment-v1

title: Payment API v1

description: 결제 승인, 취소, 조회 REST API

spec:

type: openapi

lifecycle: production

owner: group:default/team-payments

system: payment-system

definition:

$text: ./openapi/payment-v1.yaml

`definition`에 OpenAPI 문서를 연결하면 Backstage가 API 정의 탭에서 Swagger UI를 렌더링합니다. 위 예제의 text 로더 지시자는 상대 경로 파일을 읽어오며, URL도 지정할 수 있습니다. gRPC라면 `type: grpc`에 proto 파일을, 이벤트 기반이라면 `type: asyncapi`를 사용합니다.

인프라 리소스와 시스템/도메인

apiVersion: backstage.io/v1alpha1

kind: Resource

metadata:

name: payment-db

description: 결제 원장 PostgreSQL (AWS RDS)

annotations:

amazonaws.com/arn: arn:aws:rds:ap-northeast-2:111122223333:db:payment-db

spec:

type: database

owner: group:default/team-payments

system: payment-system

apiVersion: backstage.io/v1alpha1

kind: System

metadata:

name: payment-system

description: 결제 승인부터 정산까지 담당하는 시스템

spec:

owner: group:default/team-payments

domain: commerce

apiVersion: backstage.io/v1alpha1

kind: Domain

metadata:

name: commerce

description: 커머스 비즈니스 도메인

spec:

owner: group:default/commerce-tribe

하나의 파일에 `---` 구분자로 여러 엔터티를 선언할 수 있습니다. System과 Domain은 보통 별도의 거버넌스 저장소(예: `acme-corp/software-catalog`)에 모아 관리하는 편이 운영상 깔끔합니다.

디스커버리 — 수동 등록은 확장되지 않는다

엔터티를 UI에서 하나씩 등록하는 방식은 저장소가 30개만 넘어가도 무너집니다. 카탈로그를 채우는 메커니즘을 이해하려면 두 가지 개념을 구분해야 합니다.

| 개념 | 역할 | 예시 |

| --- | --- | --- |

| Entity Provider | 외부 소스에서 엔터티를 카탈로그에 주입 | GitHub 디스커버리, LDAP, 정적 파일 |

| Processor | 주입된 엔터티를 검증/보강/관계 생성 | 스키마 검증, 관계 빌드, CODEOWNERS 해석 |

GitHub Org LDAP/AD 정적 locations

| | |

v v v

+-----+------------------+--------------------+-----+

| Entity Providers (주입 계층) |

+--------------------------+-------------------------+

v

+--------------------------+-------------------------+

| Processing Loop: 검증 -> 변환 -> 관계 생성 -> 저장 |

| (Processors가 단계별로 개입) |

+--------------------------+-------------------------+

v

+---------+---------+

| PostgreSQL (DB) |

+---------+---------+

v

+---------+---------+

| Catalog REST API |

+-------------------+

GitHub 조직 전체를 자동 스캔하는 디스커버리 설정은 다음과 같습니다.

app-config.yaml

catalog:

providers:

github:

acmeProvider:

organization: 'acme-corp'

catalogPath: '/catalog-info.yaml'

filters:

branch: 'main'

repository: '.*' # 정규식으로 대상 저장소 필터링

topic:

include: ['backstage-managed']

schedule:

frequency: { minutes: 30 }

timeout: { minutes: 3 }

이 설정 하나로 "main 브랜치에 catalog-info.yaml이 있고 backstage-managed 토픽이 붙은 모든 저장소"가 30분 주기로 자동 동기화됩니다. 백엔드에는 해당 모듈을 등록해야 합니다.

// packages/backend/src/index.ts

backend.add(import('@backstage/plugin-catalog-backend-module-github/alpha'));

조직 구조(Group/User)는 GitHub Teams를 그대로 가져오는 org 디스커버리를 쓰면 됩니다.

catalog:

providers:

githubOrg:

- id: acme-github-org

githubUrl: https://github.com

orgs: ['acme-corp']

schedule:

frequency: { hours: 1 }

timeout: { minutes: 15 }

소유권 모델 — 모든 엔터티에는 주인이 있어야 한다

카탈로그의 가장 중요한 불변 조건은 "owner 없는 엔터티는 없다"입니다. 소유권의 주체는 Group과 User 엔터티입니다.

apiVersion: backstage.io/v1alpha1

kind: Group

metadata:

name: team-payments

description: 결제 플랫폼 팀

spec:

type: team

profile:

displayName: Payments Team

email: team-payments@acme.io

parent: commerce-tribe

children: []

apiVersion: backstage.io/v1alpha1

kind: User

metadata:

name: youngju.kim

spec:

profile:

displayName: Youngju Kim

email: youngju.kim@acme.io

memberOf:

- team-payments

Group은 `parent`/`children`으로 조직 트리를 이룹니다. 트라이브-스쿼드 구조든 본부-팀 구조든 그대로 표현할 수 있고, 이 트리는 소유권 집계(하위 팀의 자산을 상위 조직 뷰에서 합산)에 활용됩니다.

owner 지정을 깜빡한 저장소를 위해 CODEOWNERS 연동도 가능합니다. 카탈로그 백엔드의 `CodeOwnersProcessor`를 활성화하면, `spec.owner`가 비어 있는 엔터티에 대해 저장소의 CODEOWNERS 파일을 읽어 소유 팀을 추론합니다. 다만 이는 보조 수단으로만 쓰고, 명시적 owner 선언을 원칙으로 삼는 것을 권장합니다. CODEOWNERS는 "코드 리뷰 책임"이고 카탈로그 owner는 "운영 책임"이라 의미가 미묘하게 다르기 때문입니다.

메타데이터 거버넌스 — 어노테이션 정책과 린트

카탈로그가 커질수록 메타데이터 품질이 곧 카탈로그의 신뢰도가 됩니다. 거버넌스 장치를 처음부터 심어두는 것이 좋습니다.

**1) 필수 메타데이터 정책을 문서로 선언합니다.** 예를 들어 이런 식입니다.

| 필드/어노테이션 | 필수 여부 | 비고 |

| --- | --- | --- |

| spec.owner | 필수 | 그룹만 허용, 개인 금지 |

| spec.lifecycle | 필수 | experimental, production, deprecated 중 택일 |

| description | 필수 | 한 문장 이상 |

| github.com/project-slug | 필수 | 소스 연결 |

| backstage.io/techdocs-ref | 권장 | 문서화 대상 서비스는 필수 |

| pagerduty.com/integration-key | 권장 | production 서비스는 필수 |

**2) CI에서 catalog-info.yaml을 린트합니다.** 엔터티 검증 도구를 PR 파이프라인에 넣으면 잘못된 파일이 머지되기 전에 걸러집니다.

.github/workflows/catalog-lint.yaml

name: catalog-lint

on:

pull_request:

paths:

- 'catalog-info.yaml'

jobs:

validate:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

- name: Validate catalog entity

run: npx @roadiehq/backstage-entity-validator validate catalog-info.yaml

**3) 커스텀 프로세서로 조직 정책을 강제합니다.** 예를 들어 "production 라이프사이클인데 PagerDuty 어노테이션이 없으면 검증 에러"를 코드로 만들 수 있습니다.

// 조직 정책 검증 프로세서 골격

export class RequiredAnnotationsProcessor implements CatalogProcessor {

getProcessorName(): string {

return 'RequiredAnnotationsProcessor';

}

async validateEntityKind(entity: Entity): Promise<boolean> {

if (entity.kind === 'Component' && entity.spec?.lifecycle === 'production') {

const annotations = entity.metadata.annotations ?? {};

if (!annotations['pagerduty.com/integration-key']) {

throw new Error(

`production component ${entity.metadata.name} requires pagerduty annotation`,

);

}

}

return false; // 다른 프로세서가 계속 처리하도록

}

}

프로덕션 배포 구성

로컬 데모는 SQLite로 충분하지만 프로덕션은 반드시 PostgreSQL을 사용해야 합니다. 핵심 app-config은 다음과 같습니다.

app-config.production.yaml

app:

baseUrl: https://backstage.acme.io

backend:

baseUrl: https://backstage.acme.io

listen:

port: 7007

database:

client: pg

connection:

host: ${POSTGRES_HOST}

port: ${POSTGRES_PORT}

user: ${POSTGRES_USER}

password: ${POSTGRES_PASSWORD}

ssl:

rejectUnauthorized: true

cache:

store: memory

integrations:

github:

- host: github.com

apps:

- $include: github-app-credentials.yaml

catalog:

rules:

- allow: [Component, API, Resource, System, Domain, Group, User, Location]

GitHub 연동은 개인 토큰(PAT)보다 GitHub App 방식을 권장합니다. 레이트 리밋이 설치 단위로 분리되고, 권한 범위를 세밀하게 제어할 수 있으며, 사람 계정에 종속되지 않기 때문입니다.

Kubernetes 배포 매니페스트의 골격은 다음과 같습니다.

apiVersion: apps/v1

kind: Deployment

metadata:

name: backstage

namespace: backstage

spec:

replicas: 2

selector:

matchLabels:

app: backstage

template:

metadata:

labels:

app: backstage

spec:

containers:

- name: backstage

image: ghcr.io/acme-corp/backstage:1.0.3

ports:

- containerPort: 7007

envFrom:

- secretRef:

name: backstage-secrets

readinessProbe:

httpGet:

path: /healthcheck

port: 7007

resources:

requests:

cpu: 500m

memory: 1Gi

limits:

memory: 2Gi

apiVersion: v1

kind: Service

metadata:

name: backstage

namespace: backstage

spec:

selector:

app: backstage

ports:

- port: 80

targetPort: 7007

레플리카를 2 이상으로 두는 경우, 엔터티 프로바이더의 스케줄 작업이 중복 실행되지 않도록 Backstage가 DB 기반 코디네이션을 사용한다는 점도 알아두면 좋습니다. 별도 리더 선출 설정 없이 동작합니다.

인증 연동 — GitHub 로그인과 OIDC

사내 포털이므로 인증은 필수입니다. 가장 간단한 GitHub OAuth 구성입니다.

auth:

environment: production

providers:

github:

production:

clientId: ${AUTH_GITHUB_CLIENT_ID}

clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}

signIn:

resolvers:

- resolver: usernameMatchingUserEntityName

sign-in resolver는 "외부 IdP의 신원"을 "카탈로그의 User 엔터티"에 매핑하는 규칙입니다. 즉 로그인하려면 카탈로그에 해당 User 엔터티가 존재해야 합니다. org 디스커버리로 User를 자동 주입해 두면 자연스럽게 해결됩니다. Okta, Keycloak, Azure AD 같은 사내 IdP가 있다면 OIDC 프로바이더를 사용합니다.

auth:

environment: production

providers:

oidc:

production:

metadataUrl: https://keycloak.acme.io/realms/acme/.well-known/openid-configuration

clientId: ${AUTH_OIDC_CLIENT_ID}

clientSecret: ${AUTH_OIDC_CLIENT_SECRET}

prompt: auto

signIn:

resolvers:

- resolver: emailMatchingUserEntityProfileEmail

백엔드에는 인증 모듈 추가가 필요합니다.

backend.add(import('@backstage/plugin-auth-backend'));

backend.add(import('@backstage/plugin-auth-backend-module-github-provider'));

// 또는 OIDC 모듈

backend.add(import('@backstage/plugin-auth-backend-module-oidc-provider'));

카탈로그가 만드는 가치 — 세 가지 장면

추상적인 효용 대신 구체적 장면으로 정리해 보겠습니다.

**장면 1: 새벽 2시 장애 온콜 찾기.** 주문 서비스에서 결제 API 타임아웃 알림이 옵니다. 카탈로그에서 payment-api를 열면 owner 팀, PagerDuty 온콜 담당자, Grafana 대시보드 링크, 최근 배포 이력이 한 화면에 있습니다. 슬랙에서 "이거 누구 담당이죠?"를 외치며 20분을 태우는 일이 사라집니다.

**장면 2: 의존성 추적과 변경 영향 분석.** payment-db의 PostgreSQL 메이저 버전 업그레이드를 계획합니다. 카탈로그의 dependsOn 역방향 그래프를 조회하면 이 DB에 의존하는 컴포넌트 전체와 각각의 소유 팀이 즉시 나옵니다. 공지 대상 선정이 1분 만에 끝납니다.

**장면 3: 신규 입사자 온보딩.** 입사 첫 주에 도메인 → 시스템 → 컴포넌트 계층을 따라 내려가며 조직의 소프트웨어 지형도를 혼자서 파악할 수 있습니다. "전체 그림을 아는 시니어의 머릿속"이 시스템으로 외재화된 상태이기 때문입니다.

도입 전략 — 파일럿 팀과 채우기 자동화

카탈로그 도입에서 가장 어려운 것은 기술이 아니라 채택입니다. 검증된 전략은 다음과 같습니다.

1. **파일럿 팀 1~2개로 시작합니다.** 전사 빅뱅은 거의 항상 실패합니다. 협조적이고 서비스 수가 적당한 팀을 골라 catalog-info.yaml 작성, 온보딩 과정의 마찰을 직접 관찰하고 템플릿화합니다.

2. **초기 채우기는 자동화합니다.** 저장소 목록을 스크립트로 순회하며 기본 catalog-info.yaml을 일괄 PR로 생성하는 방식이 효과적입니다. 언어/프레임워크는 저장소 내용에서 추론하고, owner는 CODEOWNERS나 커밋 이력에서 후보를 뽑아 PR 본문에 제안하면 각 팀은 "리뷰하고 머지"만 하면 됩니다.

3. **카탈로그를 다른 프로세스에 연결해 강제력을 만듭니다.** 예를 들어 "프로덕션 배포 파이프라인은 카탈로그에 등록된 서비스만 허용" 같은 정책이 생기면 카탈로그 등록은 선택이 아니라 배포의 전제 조건이 됩니다.

4. **첫 90일 안에 가시적인 효용을 하나 만드세요.** 온콜 정보 통합이든 API 문서 모음이든, "포털 덕에 시간이 줄었다"는 경험이 한 번 생겨야 자발적 채택이 시작됩니다.

실패 패턴 — 이렇게 하면 망한다

**빈 카탈로그 증후군.** Backstage를 설치하고 데모 엔터티 몇 개만 등록한 채 "팀들이 알아서 등록하겠지"라고 방치하는 패턴입니다. 텅 빈 포털에 들어온 개발자는 다시 오지 않습니다. 디스커버리 자동화와 초기 일괄 채우기 없이 시작하면 안 됩니다.

**수동 관리 부패.** 등록은 했지만 갱신이 수동인 경우, 메타데이터는 6개월 안에 현실과 어긋나기 시작합니다. 카탈로그 정보가 한 번이라도 틀린 것으로 판명되면(엉뚱한 팀에 장애 문의가 가는 순간) 신뢰는 급락합니다. 해법은 단방향 원칙입니다. 진실의 원천(source of truth)을 Git 저장소의 catalog-info.yaml로 고정하고, UI 수동 등록을 최소화하며, 조직도 같은 데이터는 IdP/HR 시스템에서 자동 동기화합니다.

**소유권 인플레이션.** owner를 "platform-team" 하나로 몰아넣거나 퇴사자 개인으로 지정해 두는 패턴입니다. owner는 반드시 실재하는 팀 그룹이어야 하고, 조직 개편 시 그룹 엔터티 갱신이 프로세스에 포함되어야 합니다.

**과잉 모델링.** 첫날부터 Domain/System/Component/API/Resource 전 계층을 완벽하게 설계하려는 시도입니다. Component와 Group만으로 시작해서, 필요가 생길 때 System과 Domain을 추가하는 점진 접근이 현실적입니다.

체크리스트

도입 단계에서 다음 항목을 점검하세요.

- [ ] PostgreSQL 기반 프로덕션 구성 (SQLite 금지)

- [ ] GitHub App 기반 인테그레이션 (PAT 지양)

- [ ] GitHub 디스커버리 + org(Group/User) 디스커버리 활성화

- [ ] 인증(GitHub OAuth 또는 OIDC)과 sign-in resolver 구성

- [ ] catalog rules로 허용 Kind 명시

- [ ] 필수 메타데이터 정책 문서화 (owner, lifecycle, description, 핵심 어노테이션)

- [ ] PR 파이프라인에 catalog-info.yaml 린트 추가

- [ ] 기존 저장소 일괄 등록 자동화 스크립트 실행

- [ ] 파일럿 팀 선정과 피드백 루프 구성

- [ ] owner는 항상 그룹, 조직 개편 반영 프로세스 정의

- [ ] 첫 90일 가시적 효용 목표 설정 (예: 온콜 정보 통합)

마치며

이번 글에서는 Backstage IDP의 토대인 소프트웨어 카탈로그를 다뤘습니다. 엔터티 모델과 관계 그래프, catalog-info.yaml 작성, 디스커버리 자동화, 소유권과 거버넌스, 프로덕션 배포까지가 1편의 범위였습니다. 핵심 메시지는 하나입니다. 카탈로그는 기능이 아니라 기반이며, 자동으로 채워지고 자동으로 갱신되도록 설계해야만 살아남습니다.

다음 2편에서는 카탈로그 위에서 동작하는 Scaffolder, 즉 골든 패스를 코드로 만드는 소프트웨어 템플릿을 다룹니다. 새 서비스를 5분 만에, 조직 표준이 전부 내장된 상태로 만들어내는 메커니즘입니다.

참고 자료

- [Backstage 공식 문서](https://backstage.io/docs/overview/what-is-backstage)

- [Backstage Software Catalog 문서](https://backstage.io/docs/features/software-catalog/)

- [Backstage System Model (엔터티 모델)](https://backstage.io/docs/features/software-catalog/system-model)

- [Descriptor Format (catalog-info.yaml 스펙)](https://backstage.io/docs/features/software-catalog/descriptor-format)

- [Well-known Annotations 목록](https://backstage.io/docs/features/software-catalog/well-known-annotations)

- [GitHub Discovery 설정 가이드](https://backstage.io/docs/integrations/github/discovery)

- [Backstage 인증 가이드](https://backstage.io/docs/auth/)

- [CNCF Backstage 프로젝트 페이지](https://www.cncf.io/projects/backstage/)

- [Backstage GitHub 저장소](https://github.com/backstage/backstage)

- [Spotify Backstage 공식 사이트](https://backstage.spotify.com/)

현재 단락 (1/392)

마이크로서비스가 50개를 넘어가는 순간부터 조직에는 공통된 질문이 쏟아지기 시작합니다. "이 서비스 담당 팀이 어디죠?", "결제 API 스펙 문서는 어디 있나요?", "이 DB를...

작성 글자: 0원문 글자: 13,370작성 단락: 0/392