TechDocs Addons
이 문서는 이전 프런트엔드 시스템을 기준으로 작성됐어요.
출처: 문서
본문
info
이 문서는 이전 프런트엔드 시스템을 위해 작성됐어요. 새 프런트엔드 시스템을 사용 중이라면 별도의 문서를 읽는 것이 좋아요.
개념(Concepts)
TechDocs는 조직 전체의 기술 문서를 게시·보기·발견하기 위한 중앙 집중식 플랫폼이에요. 탄탄한 기반이죠! 그런데 문서에 대한 더 높은 차원의 요구 문제를 스스로 해결하지는 못해요. 문서 문화를 어떻게 만들고 강화할까? 기술 문서의 품질에 대한 신뢰를 어떻게 구축할까?
TechDocs Addons는 이러한 더 높은 차원의 요구 중 일부를 해결하기 위해 TechDocs 경험을 커스터마이즈할 수 있는 메커니즘이에요.
Addons
Addon은 그저 react 컴포넌트예요. 다른 어떤 react 컴포넌트처럼, 일반적인 Backstage나 네이티브 훅, API, 컴포넌트를 사용해 데이터를 가져오고 렌더링할 수 있어요. Props로 그 동작을 구성할 수도 있어요(적절한 경우에).
장소(Locations)
Addon은 렌더링될 location을 선언해요. 대부분의 location은 TechDocs UI의 물리적 공간을 나타내요.
-
Header: 제목과 같은 줄에, 헤더를 오른쪽부터 채우는 Addon용. -
Subheader: 헤더 아래이지만 모든 콘텐츠 위에 놓이는 Addon용. TechDocs 표시를 위한 도구/설정에 좋은 장소예요. -
Settings: 이 Addon들은 설정 메뉴 목록에 추가되는 항목으로, 예를 들어 접근성 옵션처럼 읽는 사람의 경험을 커스터마이즈할 수 있게 설계된 것들이에요. -
PrimarySidebar: 콘텐츠 왼쪽, 내비게이션 위. -
SecondarySidebar: 콘텐츠 오른쪽, 목차 위. -
Content: 문서 자체의 정적으로 생성된 콘텐츠를 보강하는 Addon을 위한 특수 장소. -
Component: 제안됐지만 아직 구현되지 않은 가상의 location으로, 일반적인 유형의 Addon을 단순화하는 것을 목표로 해요.
Addon 레지스트리
Addon의 설치와 구성은 Backstage 앱의 프런트엔드 안에서 이뤄져요. Addon은 플러그인에서 임포트되어 <TechDocsAddons>라는 레지스트리 컴포넌트 아래에 추가돼요. 이 레지스트리는 TechDocs Reader 페이지와 Entity 문서 페이지 양쪽에 대해 구성할 수 있어요.
Addon은 등록된 순서대로 렌더링돼요.
Addon 설치 및 사용
Addon을 사용하려면 @backstage/plugin-techdocs-module-addons-contrib 패키지를 앱에 추가해야 해요. 프로젝트 루트에서 yarn --cwd packages/app add @backstage/plugin-techdocs-module-addons-contrib 명령을 실행하면 돼요.
Addon은 다른 Backstage 플러그인의 확장과 거의 같은 방식으로 설치·구성할 수 있어요. App.tsx에서 TechDocs Reader 페이지를 나타내는 route 아래의 확장 레지스트리 컴포넌트(<TechDocsAddons>) 아래에 추가하면 돼요.
// packages/app/src/App.tsx
import { TechDocsReaderPage } from '@backstage/plugin-techdocs';
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
// ...
<Route path="/docs/:namespace/:kind/:name/*" element={<TechDocsReaderPage />}>
<TechDocsAddons>
<ReportIssue />
{/* Other addons can be added here. */}
</TechDocsAddons>
</Route>;
커스텀 TechDocs reader 페이지를 사용한다면 설정이 아주 비슷할 거예요. 예시는 다음과 같아요.
<Route path="/docs/:namespace/:kind/:name/*" element={<TechDocsReaderPage />}>
<TechDocsAddons>
<ReportIssue />
{/* Other addons can be added here. */}
</TechDocsAddons>
{techDocsPage} // This is your custom TechDocs reader page
</Route>
엔티티 페이지의 문서 탭에서 Addon을 구성하는 과정도 아주 비슷해요. <TechDocsAddons> 레지스트리를 <Route> 아래가 아니라 <EntityTechdocsContent />의 자식으로 추가해요.
// packages/app/src/components/catalog/EntityPage.tsx
import { EntityLayout } from '@backstage/plugin-catalog';
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
// ...
<EntityLayout.Route path="/docs" title="Docs">
<EntityTechdocsContent>
<TechDocsAddons>
<ReportIssue />
{/* Other addons can be added here. */}
</TechDocsAddons>
</EntityTechdocsContent>
</EntityLayout.Route>;
엔티티 페이지에서는 Catalog 플러그인이 페이지 헤더를 담당하기 때문에, location이 Header인 TechDocs Addons는 렌더링되지 않는다는 점을 알아두세요.
사용 가능한 Addons
Addon은 원칙적으로 어떤 플러그인이든 제공할 수 있어요! 사용 가능한 Addon을 더 쉽게 발견할 수 있도록 여기에 목록을 정리했어요.
| Addon | Package/Plugin | Description |
| <ExpandableNavigation /> | @backstage/plugin-techdocs-module-addons-contrib | TechDocs 사용자가 TechDocs의 전체 주요 내비게이션을 펼치거나 접을 수 있게 하고, 문서 사이트 사이에서 사용자가 선호하는 상태를 유지함 |
| <ReportIssue /> | @backstage/plugin-techdocs-module-addons-contrib | TechDocs 사용자가 TechDocs 페이지의 텍스트 일부를 선택하고 문서를 담고 있는 저장소에 대해 이슈를 열 수 있게 하며, 구성 가능한 템플릿에 따라 선택된 텍스트로 이슈 설명을 채움 |
| <TextSize /> | @backstage/plugin-techdocs-module-addons-contrib | 이 TechDocs addon은 사용자가 문서 페이지의 텍스트 크기를 커스터마이즈할 수 있게 해 주고, 슬라이더나 버튼으로 글꼴 크기를 얼마나 늘리거나 줄일지 선택할 수 있음. 글꼴 크기의 기본값은 100%이고, 이 설정은 변경될 때마다 브라우저의 로컬 저장소에 보관됨 |
| <LightBox /> | @backstage/plugin-techdocs-module-addons-contrib | 이 TechDocs addon은 사용자가 문서 페이지의 이미지를 라이트박스로 열 수 있게 해 주고, 한 페이지에 여러 장이 있으면 이미지 사이를 탐색할 수 있음. 라이트박스 이미지의 크기는 문서 페이지의 이미지 크기와 같음. 확대 아이콘을 클릭하면 이미지가 화면에 맞게 확대됨(background-size: contain과 유사) |
기여할 Addon이 있나요? 위에 행을 추가해 주세요!
Addon 만들기
가장 단순한 Addon은 TechDocs 사이트 내 특정 위치에 렌더링되는 평범한 react 컴포넌트예요. 그런 react 컴포넌트를 Addon으로 패키징하려면 다음 단계를 따르세요.
-
플러그인에서 다른 컴포넌트처럼 컴포넌트를 작성하기
-
플러그인에서 컴포넌트를 만들고 제공(provide)하고 내보내기
// plugins/your-plugin/src/plugin.ts
import {
createTechDocsAddonExtension,
TechDocsAddonLocations,
} from '@backstage/plugin-techdocs-react';
import { CatGifComponent, CatGifComponentProps } from './addons';
// ...
// You must "provide" your Addon, just like any extension, via your plugin.
export const CatGif = yourPlugin.provide(
// This function "creates" the Addon given a component and location. If your
// component can be configured via props, pass the prop type here too.
createTechDocsAddonExtension<CatGifComponentProps>({
name: 'CatGif',
location: TechDocsAddonLocations.Header,
component: CatGifComponent,
}),
);
Content location의 Addons
"지역에 컴포넌트 렌더링" 사용 사례를 넘어, Addon이 TechDocs 사이트의 DOM에 접근하고 조작하는 것도 가능해요. 예를 들어 클라이언트 측 다이어그램 라이브러리를 로드하고 인스턴스화하거나, 요소를 동적으로 로드된 콘텐츠로 교체하는 데 쓰일 수 있어요.
이런 유형의 Addon도 여전히 react 컴포넌트로 표현되지만, 렌더링할 react 요소를 반환하는 대신 부수 효과(side-effect, 예: useEffect)로 DOM을 업데이트해요. DOM 접근은 Addon 프레임워크가 제공하는 유틸리티 훅으로 가능해요.
// plugins/your-plugin/src/addons/MakeAllImagesCatGifs.tsx
import { useEffect } from 'react';
import { useShadowRootElements } from '@backstage/plugin-techdocs-react';
// This is a normal react component; in order to make it an Addon, you would
// still create and provide it via your plugin as described above. The only
// difference is that you'd set `location` to `TechDocsAddonLocations.Content`.
export const MakeAllImagesCatGifsAddon = () => {
// This hook can be used to get references to specific elements. If you need
// access to the whole shadow DOM, use the underlying useShadowRoot()
// hook instead.
const images = useShadowRootElements<HTMLImageElement>(['img']);
useEffect(() => {
images.forEach(img => {
if (img.src !== 'https://example.com/cat.gif') {
img.src = 'https://example.com/cat.gif';
}
});
}, [images]);
// Nothing to render directly, so we can just return null.
return null;
};
Addon 테스트하기
플러그인에 @backstage/plugin-techdocs-addons-test-utils를 devDependency로 설치하면 그런 Addon을 더 쉽게 테스트할 수 있는 유틸리티를 쓸 수 있어요.
위 Addon에 대한 테스트는 다음과 같은 모습일 수 있어요.
// plugins/your-plugin/src/addons/MakeAllImagesCatGifs.test.tsx
import { TechDocsAddonTester } from '@backstage/plugin-techdocs-addons-test-utils';
// Note: import your actual addon (the one provided by your plugin).
import { MakeAllImagesCatGifs } from '../plugin.ts';
describe('MakeAllImagesCatGifs', () => {
it('replaces img srcs with cat gif', async () => {
const { getByTestId } = await TechDocsAddonTester.buildAddonsInTechDocs([
<MakeAllImagesCatGifs />,
])
.withDom(<img data-testid="fixture" src="http://example.com/dog.jpg" />)
.renderWithEffects();
expect(getByTestId('fixture')).toHaveAttribute(
'src',
'https://example.com/cat.gif',
);
});
});