# 컴포넌트 라이브러리 개발(React library 배포 with Typescript, circleci)
이번 글에선 typescript로 개발된 리엑트 라이브러리 패키지를 circleci를 통해 자동배포하는 과정까지 설명할 예정입니다.
이전 글인 **컴포넌트 라이브러리 개발(디자인 시스템, npm 배포 기초까지)** 를 읽고 오시면 더 좋습니다.
[컴포넌트 라이브러리 개발(디자인 시스템, npm 배포 기초까지)](https://blog-seolim.vercel.app/article/4)
## 사전에...
### package.json
React component library를 개발하려면 먼저 react의 버저닝에 유의해야 합니다. react는 16.8 버전을 기준으로 hook의 사용이라는 큰 변화가 있었습니다. 따라서 개발하는 패키지를 최소 16.8 버전 이상의 환경에서 할 것을 권장합니다.
package.json에 peerDependencies를 아래와 같이 설정합니다.
```typescript
peerDependencies {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
}
```
위 디펜던시에따라 라이브러리를 사용하는 개발자는 16.8버전 이상의 react를 사용해야 정상적으로 동작합니다. 만약 17, 18을 설정하지 않으면 16버전에서만 동작하게됩니다.
그외 필요한 패키지를 설치하고 dependency 혹은 peerDependency에 추가합니다. `@seolim/react-ui` 는 개발용 package.json과 deploy용을 별도로 두고 개발합니다. devDependecies에 storybook등이 포함되어 있고 react를 굳이 dependecies로 설정할 이유가 없으므로(peerDependecies로인해 리엑트 없이는 사용 불가하므로) 아예 별도의 파일로 관리합니다.
```bash
- package.json ## 개발용 package.json
- package.deploy.json ## 배포용 package.json -> peerDependecies만 설정되어 있음
```
## 디렉토리 구조와 typescript 설정
```
├── .circleci
│ └── config.yml
├── component
│ ├── index.tsx
│ └── ...components...
├── package.json
├── package.deploy.json
├── tsconfig.json
└── ...
```
`@seolim/react-ui` 의 대략적인 디렉토리 구조는 위와 같습니다. .circleci 는 배포 자동화를 위한 config 설정이고, component 디렉토리는 개발한 컴포넌트 소스코드를 담은 디렉토리입니다.
js 패키지와 달리 ts 패키지를 배포하기 위해선 각 패키지에 대한 타입선언이 포함된 `d.ts` 파일이 포함되어야 합니다. `d.ts` 는 `@types/~~` 로 별도 배포하거나 패키지자체에 포함되어 배포합니다. `@seolim/react-ui` 는 빌드 타임에 `d.ts`를 포함되도록 빌드합니다. tsconfig.json을 아래와 같이 설정합니다.
```json
{
"compilerOptions": {
"outDir": "./dist",
"module": "commonjs",
"target": "es5",
"lib": ["es6", "dom", "es2016", "es2017"],
"jsx": "react",
"types": ["react", "@emotion/react/types/css-prop"],
"sourceMap": true,
"declaration": true,
"esModuleInterop": true,
"strictNullChecks": true,
"noImplicitAny": true,
"removeComments": true,
"typeRoots": ["index.d.ts", "node_modules/@types"]
},
"include": ["component"],
"exclude": ["node_modules", "dist"]
}
```
주요한 설정은 output을 dist 디렉토리에 설정하는 **outDir**, typescript를 commonjs로 트랜스파일링 하는 것에대한 **module**설정, 빌드 디렉토리(component)를 포함하는 **include** 설정이 있습니다. 그 외 설정에 대해선 아래 북마크를 참고하시면 좋습니다.
[tsconfig의 모든것](https://evan-moon.github.io/2021/08/22/tsconfig-compiler-options-modules/)
package.json에 build 명령어를 아래와 같이 설정합니다.
```json
"script": {
"clean": "rm -rf dist",
"build": "npm run clean && tsc && cp deploy.package.json dist/package.json",
}
```
빌드를 실행해보면 dist 파일을 생성하고 내부에 d.ts, sourcemap파일이 포함되어 생성됩니다. 예를 들어 아래와 같은 Button.tsx를 작성하고 index.tsx에서 export 후 빌드하게 되면 dist 디렉토리에 Button.d.ts, Button.js, Button.js.map이 생성된 것을 확인할 수 있습니다.
```typescript!
/** Button.tsx */
import React from 'react';
const Button = () => <button>커스텀</button>;
export default Button;
/** index.tsx */
export { default as Button } from './Button.tsx';
```
## circleci를 통한 자동 배포
빌드까지 완료되었기에 이제 배포단계만 남았습니다. 아래 커맨드를 실행합니다.
```bash
npm publish --access=public dist
```
이 과정을 circleci를 통해 자동화 해봅시다.
circleci는 자동 배포를 위한 컴퓨팅과 트리거를 제공하는 서비스로 프로젝트를 등록하는 방법은 생략하고 circleci의 설정 부분만 다루도록 하겠습니다. circleci를 등록하는 방법은 아래 공식 문서를 참고합시다.
[circleci quick start](https://circleci.com/docs/getting-started/)
config.yml 파일을 아래처럼 설정합니다.
```yaml
version: 2.1
defaults: &defaults
working_directory: ~/{reponame}/{your working directory}
docker:
- image: cimg/node:14.20.0
jobs:
react-publish:
<<: *defaults
steps:
- checkout:
path: ~/{reponame}
## 캐시 가져오기
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- v1-dependencies
- run:
name: install node_modules
command: npm install
## 캐시 저장하기
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ "package.json" }}
- run:
name: npm build
environment:
NODE_ENV: product
command: npm run build
- run:
name: authentication
command: npm set //registry.npmjs.org/:_authToken=$NPM_TOKEN
- run:
name: deploy
command: npm publish --access=public dist
workflows:
version: 2
build:
jobs:
## 동작 브랜치 설정
- react-publish:
filters:
branches:
only: master
```
주요 부분을 살펴보면 배포를 위한 **authentication**에서 npm login 과정을 token을 설정하여 처리하는 곳입니다.다. 자세한 내용은 아래 설명을 참고합시다.
[circleci deploy to npm registry](https://circleci.com/docs/deploy-to-npm-registry/?utm_source=google&utm_medium=sem&utm_campaign=sem-google-dg--japac-en-dsa-maxConv-auth-nb&utm_term=g_-_c__dsa_&utm_content=&gclid=Cj0KCQjw--2aBhD5ARIsALiRlwDYN45jN4KFjYR9-xDlFapdO4wXbgAYx7t58oNnfWYa_6HfAsUBYhwaAtr8EALw_wcB)
위 과정을 모두 등록하고 master 브랜치에 push하면 본인의 라이브러리가 배포되고 `npm install`을 통해 가져올 수 있습니다.
## 마무리
지금까지 컴포넌트 라이브러리를 직접 npm 배포와 자동화까지 살펴보았습니다. 다음엔 storybook을 통해 본인의 라이브러리에 대한 디자인 가이드를 제작, 배포하는 과정까지 설명하겠습니다.