NPM Package를 활용한 사내 공용 라이브러리와 컴포넌트 관리

함께 쓰는 기능을 NPM Package로 공유하기
- 가장 기본적이고 실천하기 쉬운 방법
- 작성한 함수나 클래스를 export 하면 바로 ES 모듈로 사용 가능
- 다양한 환경에서 사용하기 위해서는 Webpack이나 Rollup 등의 번들러를 활용해서 CommonJS, UMD등을 동시에 생성
함께 쓰는 기능을 NPM Package로 공유하기
/* dicom-anonymizer-js/index.js */
function Anonymizer() {}
Anonymizer.prototype.anonymize = function(fileBlob) {
return new Promise(function(resolve, reject) {
const reader = new window.FileReader()
reader.onload = function(file) {
// ...
};
export default Anonymizer;
/* dicom-anonymizer-js/package.json */
{
"name": "@lunit/dicom-anonymizer-js",
"version": "1.0.1",
"main": "./index.js",
}
함께 쓰는 기능을 NPM Package로 공유하기
# Publish
$ yarn publish
# .npmrc
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
# Install
$ export NPM_TOKEN="00000000-0000-0000-0000-000000000000"
$ yarn add @lunit/dicom-anonymizer-js
함께 쓰는 기능을 NPM Package로 공유하기
/* app/package.json */
{
"dependencies": {
"@lunit/dicom-anonymizer-js": "^1.0.0"
}
}
/* app/index.js */
import Anonymizer from '@lunit/dicom-anonymizer-js';
const anonymizer = new Anonymizer();
anonymizer.anonymize(dicomFile).then(anonymized => {
//...
});
UI 컴포넌트 작성하고 라이브러리로 묶기
- styled-components 등의 CSS-in-JS 라이브러리를 사용하는 것을 추천
- 개별 컴포넌트와 함께 Global Style도 포함해야 CSS Reset, Font Familly 등을 다루기가 편해진다
- 불러온 프로젝트에서 필요에 따라 확장(extend)해서 사용
- Storybook을 활용하면 개발도 쉽고 문서처럼 활용 가능
UI 컴포넌트 작성하고 라이브러리로 묶기
/* insight-react-components/Button.js */
import styled from 'styled-components'
import theme from '../theme'
const Button = styled.button`
background-color: ${props => props.theme.primary};
...
`
Button.defaultProps = {
theme
}
export default Button
/* insight-react-components/index.js */
export { default as Button } from './components/Button';
export { default as theme } from './theme';
// ...
export { GlobalStyle } from './global';
UI 컴포넌트 작성하고 라이브러리로 묶기
/* App.js */
import { theme, Button, GlobalStyle } from '@lunit/insight-react-components'
const DeleteButton = styled(Button)`
background-color: red;
`
const App = () => {
return (
<ThemeProvider theme={theme}>
<>
<GlobalStyle />
<div>
<Button>Action</Button>
<DeleteButton>Delete</DeleteButton>
</div>
</>
</ThemeProvider>
)
}
컴포넌트의 로직을 Hook으로 공유하기
- React에서 Hook을 사용하면 컴포넌트에서 공통된 로직을 쉽게 분리할 수 있다
- 기존에 사용했던 HoC나 render props보다 간편(특히 디버깅)
- 기본 Hook으로 먼저 작성한 뒤 Custom Hook으로 분리해보자
컴포넌트의 로직을 Hook으로 공유하기
/* src/useShortcut.js */
import { useEffect } from "react";
const useShortcut = ({ shortcut, onKeyDown }) => {
useEffect(() => {
const keyHandler = function(event) {
if (
event.key === shortcut &&
event.target.tagName !== "INPUT"
) {
onKeyDown();
}
};
document.addEventListener("keydown", keyHandler);
return () => {
document.removeEventListener("keydown", keyHandler);
};
}, [onKeyDown, shortcut]);
};
export default useShortcut;
Monorepo
- 패키지 여럿을 한 레포지터리에 묶어서 관리 가능
- 패키지 간 상호 의존성이 있을 경우 변경 이력을 추적 관리하기에 매우 유리
- Lerna, Bit, Rush등 여러 도구들이 있음
Yarn Workspace vs. Lerna
Yarn Workspace
- 빌드, 배포 등을 위한 명령어는 직접 작성
- Yarn을 사용해야만 함
Lerna
- 패키지 관리와 사용을 위한 다양한 명령어 지원
- NPM 뿐 아니라 Yarn Workspace와 함께 사용 가능
React ZeroConfig
- create-react-app 처럼 별도의 설정 없이 React 앱을 빌드 가능
- 하나의 레포에서 여러 앱과 패키지를 빌드, 배포 가능
- Typescript 지원
- SSR 지원
- Jest, Storybook 지원
$ tree src
src
├── __tests__
│ └── test.js
├── _packages
│ └── @lunit
│ ├── package1
│ ├── package1
│ └── package3
├── app1
├── app2
└── app3
ZeroConfig + Storybook

We're Hiring!
-
Frontend Engineer
-
Partner Engineer
-
Research Engineer
-
In-House Legal Counsel
원티드(wanted.co.kr)에서 루닛을 검색해주세요
NPM Package를 활용한 사내 공용 라이브러리와 컴포넌트 관리
By SangYeob Yu
NPM Package를 활용한 사내 공용 라이브러리와 컴포넌트 관리
- 787