npm 패키지 만들어야지! 했던 적이 있다. 그러나 다른 프로젝트하느라 바쁘다는 핑계로 미뤘는데, nextJS로 개인 플젝을 하다가 오 이건 라이브러리로 만들어도 되겠는데? 하는 간단한 컴포넌트가 있어서 이틀만에 후다닥 만들었다! 물론 rollup 은 초면이라 매-우 헤맸지만 배운 것도 정-말 많아서 쓰게된 글이다 ㅎㅎ
우선 내가 만든 라이브러리는 react-scroll-header-loading 이다. javascript 의 scroll event 를 기반으로 scroll 위치만큼 상단 로딩바를 움직이는 컴포넌트이다.

자세한건 여기 확인하면 된당 ㅎㅎ (많이 써주셨으면 좋겠다......)
cd npm-project
npm init
npm 정보를 설정하는 명령어를 입력하면 패키지명, 버전, 패키지 설명, git url, 작성자, license 를 설정한다. 입력한 데이터로 pakcage.json이 생성된다.
package name: (npm_install_test)
version: (1.0.0)
description:
git repository:
author:
license: (ISC)
npm login
NPM에 라이브러리를 배포하려면 로그인해야한다. 위의 명령어를 입력하면 OTP를 입력하라는 화면으로 이동하고 메일로 받은 OTP 번호를 입력하면 된다!
npm publish
위의 명령어를 입력하면 npmjs.com 에서 본인 계정 > packages 에 배포한 라이브러리를 확인할 수 있다!

라이브러리 배포를 위해 어떤 빌드도구를 사용할까 고민이 되었다. 그래서 가장 많이 사용하는 3가지 툴을 비교해보았다.
복잡한 애플리케이션 => Webpack 추천👍
라이브러리 or 패키지 => Rollup 추천👍
빠르게 개발해야한다 => ESBuild 추천👍
npm 라이브러리를 개발하는 나는 Rollup을 사용하기로 결정했다!
빌드를 위해 rollup을, ES5로 변환하기 위해 babel을 설치했다. 설치 스크립트는 다음과 같다.
// 최신 JavaScript 코드를 구형 브라우저나 환경에서도 동작하도록 변환
npm install --save-dev @babel/core
// 브라우저 호환성을 보장하기 위해 필요한 변환을 자동으로 설정
npm install --save-dev @babel/preset-env
// JSX와 기타 React 관련 최신 JavaScript 기능 변환
npm install --save-dev @babel/preset-react
// 드 크기 감소 및 폴리필 관리
npm install --save-dev @babel/plugin-transform-runtime
// Rollup 빌드 프로세스에서 Babel을 통합하여 ES6/7 코드를 변환
npm install --save-dev @rollup/plugin-babel
// Node.js 모듈이나 기존 CommonJS 모듈을 사용하는 프로젝트에서 Rollup을 사용하도록 처리하는 모듈
npm install --save-dev @rollup/plugin-commonjs
// Rollup이 Node.js 모듈을 해석하고 가져올 수 있도록 하는 플러그인
npm install --save-dev @rollup/plugin-node-resolve
// javaScript와 기타 자산을 효율적으로 번들링하는 모듈 번들러
npm install --save-dev rollup
// Peer dependencies를 외부 모듈로 처리하는 Rollup 플러그인
npm install --save-dev rollup-plugin-peer-deps-external
// Terser를 사용하여 JavaScript 코드를 최소화(minify)하는 Rollup 플러그인
npm install --save-dev rollup-plugin-terser
// // Node.js 모듈을 해석하고 가져오기 위한 플러그인
import resolve from '@rollup/plugin-node-resolve';
// CommonJS 모듈을 ES 모듈로 변환하기 위한 플러그인
import commonjs from '@rollup/plugin-commonjs';
// Babel을 Rollup과 통합하여 코드를 변환하기 위한 플러그인
import babel from '@rollup/plugin-babel';
// Peer dependencies를 외부 모듈로 처리하기 위한 플러그인
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
// Terser를 사용하여 코드를 최소화하기 위한 플러그인
import { terser } from 'rollup-plugin-terser';
export default {
input: './index.js', // 번들링을 시작할 파일 지정 : 번들을 생성할 입력 파일
// 출력 파일 설정
output: {
file: 'dist/index.esm.js', // 번들 파일이 저장될 경로
format: 'es', // 번들 파일의 모듈 형식 지정 : ES 모듈 형식으로 출력
sourcemap: true // 소스 맵 생성하여 디버깅을 쉽게 하도록 설정
//(소스 맵을 생성하여 디버깅 시 원본 소스 코드와 매핑)
},
// 외부 종속성 설정
external: ['react'], // 번들에 react 제외
plugins: [
peerDepsExternal(), // peerDependencies를 외부 모듈로 처리하여 번들 크기를 줄임
resolve(), // Node.js 모듈을 해석하고 가져오기 위한 플러그인
// Babel을 사용하여 코드 변환
babel({
exclude: 'node_modules/**', // node_modules 는 변환 대상 제외
babelHelpers: 'bundled', // Babel 헬퍼 함수를 번들에 포함
presets: ['@babel/preset-env', '@babel/preset-react'] // Babel 프리셋 설정
// @babel/preset-env는 최신 JavaScript 기능을 변환하고, @babel/preset-react는 JSX를 변환함
}),
// CommonJS 모듈 -> ES 모듈로 변환
commonjs(),
// JavaScript 코드 최소화
terser()
]
};
...
"scripts": {
// rollup.config.js 를 사용하여 빌드한다는 의미
"build": "rollup -c"
},
...
{
// Babel이 사용할 프리셋 설정
"presets": [
"@babel/preset-env", // 최신 JavaScript 기능을 변환하기 위한 프리셋
"@babel/preset-react" // JSX와 기타 React 관련 코드를 변환하기 위한 프리셋
],
// Babel이 사용할 플러그인 설정
"plugins": [
"transform-commonjs", // CommonJS 모듈을 변환하기 위한 플러그인
["@babel/plugin-transform-runtime", {
// Babel의 헬퍼 함수를 번들에 포함하지 않고, 별도로 모듈화하여 재사용 가능하게 함
"helpers": false,
// async/await 등의 기능을 변환하기 위해 regenerator를 사용하도록 설정
// ES6 이상의 비동기 기능을 ES5 환경에서 사용할 수 있게 해줌
"regenerator": true
}]
]
}
Babel이 JavaScript 코드를 변환할 때 공통적으로 필요한 기능들을 제공한다.
🔍 다른 객체로 확장하거나 병합할 때 사용하는 _extends
🔍 ES6 클래스 생성자를 변환할 때 사용하는 _classCallCheck
🔍 ES6 클래스의 정적 및 인스턴스 메서드를 정의할 때 사용하는 _createClass
🔍 부모 클래스와 자식 클래스 간의 상속 관계를 설정할 때 사용하는 _inherits
🔍 객체 디스트럭처링에서 사용하는 _objectWithoutProperties 가 있다.
Babel의 설정 파일로, Babel이 자바스크립트 코드를 변환할 때 사용할 설정을 지정한다. 이 파일은 프로젝트의 루트 디렉토리에 위치하며, JSON 형식으로 Babel 프리셋(presets)과 플러그인(plugins)을 정의한다. .babelrc를 사용하면 프로젝트에 필요한 Babel 설정을 쉽게 관리할 수 있다.
npm run build
위의 명령어를 통해 빌드를 하면 output에 정의한대로 dist 아래 빌드된 파일이 생성된다. 그러면 이제 테스트를 해보자!
npm 에 배포하기 전에 작성한 모듈을 로컬 환경에서 테스트할 수 있다.
개발이 완료된 프로젝트 경로에서 링크를 생성하여 다른 프로젝트에서 해당 패키지를 사용하면 된다.
npm link
개발이 완료된 프로젝트 경로에서 링크를 생성한다.
// npm link {패키지명}
npm link react-scroll-header-loading
이렇게하면 아주 간편하게 테스트를 할 수 있다!!
역시 삽질을 하면 배우는 게 많다. 이번 프로젝트를 하면서도 정-말 많이 배웠다. 그 내용을 간단하게 정리하려 한다.
JavaScript 모듈에서는 파일당 하나의 default export만을 지원한다. 따라서 만약 n개 이상의 default export가 필요하다면, 아래와 같은 방법으로 해결해야 한다.
1. 객체를 사용하여 여러 export를 내보내기
function ComponentA() {
// ComponentA code
}
function ComponentB() {
// ComponentB code
}
export default {
ComponentA,
ComponentB,
};
2. Named Export 사용하기
// src/myModule.js
export default function DefaultComponent() {
// DefaultComponent code
}
export function NamedComponentA() {
// NamedComponentA code
}
export function NamedComponentB() {
// NamedComponentB code
}
// src/useMyModule.js
import DefaultComponent, { NamedComponentA, NamedComponentB } from './myModule';
위의 오류를 모두 표현하자면 다음과 같다.
expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
나의 친구 chatGPT 에게 물어보니 React 컴포넌트를 사용하려할 때 발생한다했고, 나의 경우에는 import 와 export 가 불일치했기 때문에 문제가 되었다. named export 와 default export 중 하나만 사용을 해야하는데, 나는 둘다 사용하고 있어서 named export 로 통일해주었다.
Warning: React does not recognize the loadingBarTopColor prop on a DOM element.
위의 warning 은 prop이 HTML 표준이 아니라서 나는 경고 메시지였다. 그래서 컴포넌트 구조를 변경했고, 문제가 해결되었다!
const LoadingBar = ({ loadingBarTopColor = 'red' ... }) => {
const loadingBarStyle = {
// 여기서 loadingBarTopColor 사용
...
};
return <div style={loadingBarStyle} {...props} />;
}
진짜 정말 재밌는 프로젝트였다. 다운로드 수가 올라가는 것도 보이고, 내가 만든걸 누군가 쓴다라고 생각하니까 성취감이 컸다. 스스로 개발을 좋아하는가에 대한 물음을 던질 때가 많은데, 이번 경험을 통해 느꼈다. 나는 개발을 좋아하고, 계속해서 무언가를 만들고 싶다. 또 다른 걸 한번 만들어봐야징!!!!!
✔️ 혹시나 header loading bar 가 필요하다면 여기로 들어가서 한번씩 써봐주세요..!
❤️피드백도 대환영입니다❤️