회사에서 코드 중복을 작성을 피하고 공통 이슈 대응을 용이하게 하기 위해 프론트엔드 공통 코드 라이브러리를 만들게 되었습니다. 가이드 문서를 만드는 과정과 검색기능을 제공하기 위해 algolia를 사용하며 겪은 시행착오를 기록하였습니다.
Docusaurus
저희는 토스 슬래시 라이브러리처럼 문서화를 하고 싶었고 github 저장소를 들여다본 결과 Docusaurus를 사용한다는 것을 알게되었습니다.
문서 작성하기
토스는 공통코드에 대한 설명을 코드가 작성된 폴더에서 markdown으로 함께 작성합니다. 저희도 개발 편의성과 이해도를 높이기 위해 같은 방식을 사용했습니다.
Docusaurus 세팅 및 스크립트 추가
저희는 모노레포를 사용하고 있으므로 프로젝트 내에 docusaraus라는 패키지를 추가해주었습니다. 공식문서에서 나온대로 Docusaurus를 세팅해줍니다.
npx create-docusaurus@latest docs classic
이후 토스의 generate-docs-from-md.ts 스크립트를 참고하여 docs 폴더로 md 파일을 복사해주는 스크립트를 작성해줍니다. (프로젝트에 맞게 변형하셔야 할거에요)
이제 빌드 전에 해당 스크립트를 실행하도록 package.json
을 수정해주면 끝! 입니다
Algolia
검색 기능 추가
문서는 성공적으로 띄웠으나 사용편의를 위해 검색 기능이 추가되면 좋겠다는 생각이 들었습니다. 토스를 보니 algolia라는 서비스를 사용중이었습니다. algolia는 빠르고 정확한 검색 서비스를 제공하는 SaaS 플랫폼으로 대용량 데이터에서도 빠른 검색이 가능하게 해줍니다.
Docusaurus의 공식 문서에도 algolia 사용법에 대한 설명이 나올만큼 편리하게 사용할 수 있을 것 같아 algolia를 선택하게 되었습니다. (간단히 적용할 수 있을 것 같았지만 조금 헤맸습니다 아래에서 다룰게요 하하)
아래에서 더 자세한 적용법을 말씀드리기 전에 어떤 과정이 필요한지 간략히 설명드리겠습니다.
1.algolia 공식 홈페이지에서 가입을 해줍니다.
2.가입후 app을 생성한 뒤 네가지 항목(write api key, read api key, application id, algolia index name)을 확인합니다.
3. 문서 인덱싱 (write api key 사용)
4. Algolia를 지원하는 라이브러리(docsearch/react)로 검색 기능 연동(read api key 사용)
여기서 문서 인덱싱 부분의 구현이 프로젝트의 성격에 따라 달라지는데요. 여기서는 private repo를 중점적으로 다루도록 하겠습니다.
public repo는 토스 config 파일을 참고하시기 바랍니다.
트러블슈팅
private repo에서의 문서 인덱싱
algolia 사용을 위해서는 문서를 인덱싱하여 서버에 저장해주는 과정이 필요한데 이 부분이 좀 까다로웠습니다. 토스는 public한 repo라서 algolia가 문서를 마음껏 가져다 읽을 수 있었지만 저희 프로젝트는 private하게 관리되고 있었기 때문입니다.
따라서 직접 문서 색인을 위한 코드를 작성해주어야 했습니다. 저는 index-docs-to-algolia.ts
라는 스크립트를 작성했고 Docusaurus를 통해 빌드된 html에서 원하는 부분을 뽑아 객체로 만들고 algolia 서버에 저장해주었습니다.
- 추가설치가 필요한 모듈: algoliasearch와 dotenv
//index-docs-to-algolia.ts
import { algoliasearch } from 'algoliasearch';
import 'dotenv/config';
const client = algoliasearch(
process.env.ALGOLIA_APP_ID,
process.env.ALGOLIA_WRITE_API_KEY,
);
const indexName = process.env.ALGOLIA_INDEX_NAME;
//생략
export async function IndexDocsToAlgolia() {
try {
//저는 인덱싱때마다 모든 객체를 replace하도록 했는데 디테일한 조건문을 넣어 save 메소드를 사용한다면 더 좋을 것 같습니다.
await client.replaceAllObjects({
indexName,
objects,
});
console.log('문서가 성공적으로 인덱싱되었습니다.');
} catch (err) {
console.error('인덱싱 중 오류 발생:', err);
}
}
아래는 저장되어야 할 object 데이터의 형식입니다.
{
objectID: "고유한 objectID",
url: '검색 결과를 누르면 이동할 경로',
type: "content | lv0 | lv1 등등의 값이 들어갈 수 있음",
hierarchy: { lv0: '내용' },
content: '내용' | undefined,
...
};
여기서 type과 hierarchy가 중요한데 이해를 돕기 위해 토스 문서 검색결과를 한번 더 보여드리겠습니다.
type은 safeArea, safeScrollTo 같은 큰 제목이 될 컨텐츠를 정해주는 역할을 합니다.
네트워크 탭으로 검색결과를 확인해보면 type이 lv1이고 lv1에 연결되어있는 컨텐츠인 safeArea가 화면에 나타나고 있음을 알 수 있습니다.
만약 `type: "content"`로 지정한다면 아래 네모 박스와 같이 결과가 나타나게 됩니다.
처음엔 원하는 형태로 검색결과가 나오도록 각 필드를 어떻게 적용해줘야 할지 몰라 혼란을 겪었습니다. 하지만 이런 규칙을 알고나니 무리없이 적용할 수 있었습니다.
(회사 코드를 블로그에 작성해도 되는지 몰라 코드가 없습니다. 혹시 질문이 있으시면 댓글 달아주시면 설명드리겠습니다)
docusaraus와 algolia의 불완전한 연동 (docsearch/react 사용으로 해결)
Docusaurus의 공식 문서를 보면 config 파일을 이용하여 간단히 algolia를 연동하는 방법이 나와있습니다. 하지만 적용을 해도 이상하게 검색 기능이 동작하지 않았습니다. 그래서 docsearch/react
라는 라이브러리를 통해 AlgoliaSearch라는 컴포넌트를 만들었습니다.
import '@docsearch/css';
import { DocSearch } from '@docsearch/react';
import useDocusaurusContext from '@docusaurus/core/lib/client/exports/useDocusaurusContext';
export default function AlgoliaSearch() {
const {
siteConfig: { customFields },
} = useDocusaurusContext();
//여기서는 Docusaurus에서 제공해주는 customFields를 통해 환경변수를 받아왔습니다.
return (
<DocSearch
appId={customFields?.algoliaAppId}
// app을 생성할 때 받아온 read api key
apiKey={customFields?.algoliaSearchApiKey}
indexName={customFields?.algoliaIndexName}
/>
);
}
문제는 Docusaurus의 docusaraus.config.js
로 제어할 수 있는 부분이 정해져있다보니 AlgoliaSearch라는 리액트 컴포넌트를 Docusaurus에서 생성해주는 헤더에 넣을 방법이 없었습니다.
다행히 공식문서를 뒤져본결과 Docusaurus에서 헤더나 여러 컴포넌트들을 커스텀하게 해주는 swizzle 기능을 제공해준다는 것을 알게 되었습니다.
yarn swizzle @docusaurus/theme-classic SearchBar
위 명령어를 입력하고 여러 cli 질문들에 대답을 하고 나면 src/theme/SearchBar
라는 파일을 생성해주는데 그곳에 AlgoliaSearch 컴포넌트를 집어넣으면 됩니다 :)
import AlgoliaSearch from '@site/src/components/AlgoliaSearch';
export default function SearchBarWrapper(): JSX.Element {
return <AlgoliaSearch />;
}
'트러블슈팅' 카테고리의 다른 글
github packages로 private하게 패키지 배포하기 (+다운로드 방법) (2) | 2024.10.29 |
---|---|
웹에서 FCM push 알림 기능 구현하기 (0) | 2024.10.28 |
맥에서 vs code로 스프링 프로젝트 띄우기-2 (0) | 2020.05.09 |
맥에서 vs code로 스프링 프로젝트 띄우기-1 (0) | 2020.05.09 |