본문 바로가기
WIKI 기술 지식 베이스

URL Readers

원문 보기 위키 갱신

플러그인은 사용자가 구성한 특정 통합과 통신해야 하는 경우가 있어요. 인기 있는 통합으로는 GitHub, BitBucket, GitLab 같은 버전 관리 시스템(VCS)이 있어요. 이 통합들은 app-config.yaml 파일의 integrations 섹션에 구성돼요.

출처: 문서

본문

플러그인은 사용자가 구성한 특정 통합과 통신해야 하는 경우가 있어요. 인기 있는 통합으로는 GitHub, BitBucket, GitLab 같은 버전 관리 시스템(VCS)이 있어요. 이 통합들은 app-config.yaml 파일의 integrations 섹션에 구성돼요.

이 URL reader들은 기본적으로 VCS 저장소에 저장될 수 있는 파일과 폴더에 대한 인증이 포함된 래퍼예요.

서비스 사용하기

다음 예시는 example 백엔드 플러그인에서 URL Reader 서비스를 가져와 GitHub 저장소에서 파일과 디렉터리를 읽는 방법을 보여줘요.

import {
  coreServices,
  createBackendPlugin,
} from '@backstage/backend-plugin-api';
import os from 'os';

createBackendPlugin({
  pluginId: 'example',
  register(env) {
    env.registerInit({
      deps: {
        urlReader: coreServices.urlReader,
      },
      async init({ urlReader }) {
        const buffer = await urlReader
          .read('https://github.com/backstage/backstage/blob/master/README.md')
          .then(r => r.buffer());
        const tmpDir = os.tmpdir();
        const directory = await urlReader
          .readTree(
            'https://github.com/backstage/backstage/tree/master/packages/backend',
          )
          .then(tree => tree.dir({ targetDir: tmpDir }));
      },
    });
  },
});

사용자 지정 URL reader 제공하기

내부적이거나 특수한 reader를 만들어 서비스 팩토리를 사용해 백엔드에 제공할 수도 있어요. 다음 예시는 사용자 지정 URL reader를 만들어 백엔드에 제공하는 방법을 보여줘요.

packages/backend/src/index.ts

import { createBackend } from '@backstage/backend-defaults';
import {
  ReaderFactory,
  urlReaderFactoriesServiceRef,
} from '@backstage/backend-defaults/urlReader';
import {
  createServiceFactory,
  UrlReaderService,
} from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';

class CustomUrlReader implements UrlReaderService {
  static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
    const reader = new CustomUrlReader(config);
    const predicate = (url: URL) => url.host === 'myCustomDomain';
    return [{ reader, predicate }];
  };

  constructor(private readonly config: Config) {}

  // implementations of read, readTree and search methods skipped for this example
}

const customReader = createServiceFactory({
  service: urlReaderFactoriesServiceRef,
  deps: {},
  async factory() {
    return CustomUrlReader.factory;
  },
});

const backend = createBackend();
// backend.add() of other plugins and modules excluded
backend.add(customReader);

URL Reader 작성하기

모든 URL Reader가 같은 방식으로 동작하도록 하고 싶어요. 그러므로 가능하면 UrlReaderService 인터페이스의 모든 메서드를 구현해야 해요. 하지만 그중 하나만 구현하는 것으로 시작하고 나머지는 이슈로 만들어도 괜찮아요.

사용 사례가 다른 사용자에게도 유익하다면 새 URL Reader를 오픈 소스로 만들 수도 있어요. 자체 패키지로 만들거나 URL Reader의 default 팩토리 메서드를 업데이트해서 만들 수 있어요. 새 핵심 URL Reader 구현을 시작하기 전에 사용 사례를 논의하고 피드백을 받기 위해 Backstage 저장소에 이슈를 만드는 것을 권장해요.

URL Reader를 작성하기 위한 몇 가지 일반 지침은 다음과 같아요.

readUrl

readUrl 메서드는 사용자 친화적인 URL을 기대해요. 사람이 브라우저에서 프로바이더를 탐색할 때 자연스럽게 복사할 수 있는 것 같은 URL이에요.

  • ✅ 유효한 URL: https://github.com/backstage/backstage/blob/master/ADOPTERS.md
  • ❌ 유효하지 않은 URL: https://raw.githubusercontent.com/backstage/backstage/master/ADOPTERS.md
  • ❌ 유효하지 않은 URL: https://github.com/backstage/backstage/ADOPTERS.md

readUrl은 URL을 받으면 사용자 친화적인 URL을 프로바이더의 API를 요청하는 데 쓸 수 있는 API URL로 변환해요.

그런 다음 readUrl은 프로바이더 API에 인증된 요청을 하고, 파일 내용과(프로바이더가 지원한다면) ETag가 담긴 응답을 반환해요.

readTree

readTree 메서드도 read와 비슷하게 사용자 친화적인 URL을 기대하지만, URL은 트리를 가리켜야 해요(저장소의 루트나 하위 디렉터리가 될 수 있음).

  • ✅ 유효한 URL: https://github.com/backstage/backstage
  • ✅ 유효한 URL: https://github.com/backstage/backstage/blob/master
  • ✅ 유효한 URL: https://github.com/backstage/backstage/blob/master/docs

프로바이더의 API 문서를 사용해 zip이나 tarball을 다운로드하는 데 쓸 수 있는 API 엔드포인트를 찾아보세요. 전체 트리(예: 저장소)를 다운로드하고, 사용자가 하위 트리만 기대한다면 그 안에서 필터링할 수 있어요. 하지만 일부 API는 경로를 받아 다운로드된 아카이브에서 하위 트리만 반환할 만큼 똑똑해요.

search 메서드는 URL의 glob 패턴을 기대하고, 쿼리와 일치하는 파일 목록을 반환해요.

  • ✅ 유효한 URL: https://github.com/backstage/backstage/blob/master/**/catalog-info.yaml
  • ✅ 유효한 URL: https://github.com/backstage/backstage/blob/master/**/*.md
  • ✅ 유효한 URL: https://github.com/backstage/backstage/blob/master/*/package.json
  • ✅ 유효한 URL: https://github.com/backstage/backstage/blob/master/README

여기서 readTree의 핵심 로직을 사용해 트리 안의 모든 파일을 추출하고 url의 패턴과 일치하는 파일을 반환할 수 있어요.

캐싱

위의 모든 메서드는 ETag 기반 캐싱을 지원해요. 메서드가 ETag 없이 호출되면 응답에 리소스의 ETag가 포함돼요(프로바이더가 반환한 ETag를 그대로 전달하는 것이 이상적). 메서드가 ETag와 함께 호출되면 먼저 ETag를 비교하고, 리소스가 수정되지 않은 경우 NotModifiedError를 반환해요. 이 방식은 실제 ETag와 If-None-Match HTTP 헤더와 매우 유사해요.

더 알아보기 (Learn more)