---
# System prepended metadata

title: '컴포넌트 라이브러리 개발(React library 배포 with Typescript, circleci)'

---

# 컴포넌트 라이브러리 개발(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을 통해 본인의 라이브러리에 대한 디자인 가이드를 제작, 배포하는 과정까지 설명하겠습니다.
