Vite를 사용해 React 컴포넌트를 라이브러리로 패키징하면, dist 디렉토리에 style.css 파일이 생성되지만, 실제로 해당 컴포넌트를 사용하는 쪽에서 CSS가 적용되지 않는 문제가 발생할 수 있다. 이 글에서는 왜 이런 문제가 발생하는지, 그리고 어떻게 해결할 수 있는지를 실전 예제와 함께 자세히 살펴보자.
Vite로 React 컴포넌트를 라이브러리 형태로 빌드할 경우, vite.config.ts를 다음과 같이 설정하는 경우가 많다.
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
lib: {
entry: 'src/index.ts',
name: 'MyComponentLib',
fileName: 'my-component-lib',
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
},
},
},
});
// src/components/MyButton.tsx
import React from 'react';
import './MyButton.css';
export const MyButton = () => {
return <button className="my-button">Click me</button>;
};
/* src/components/MyButton.css */
.my-button {
padding: 10px 20px;
background-color: #007bff;
color: white;
}
빌드를 수행하면 다음과 같은 구조가 생성된다:
dist/
├── style.css ← 여기에 CSS는 존재한다
├── my-component-lib.es.js
├── my-component-lib.umd.js
하지만, 이 패키지를 외부 프로젝트에서 사용할 경우 다음과 같은 코드로 불러오게 된다:
import { MyButton } from 'my-component-lib';
export default function App() {
return <MyButton />;
}
결과는?
❌ 버튼은 HTML 구조는 보이지만 스타일이 적용되지 않는다.
이는 Vite의 라이브러리 모드(build.lib)가 CSS를 JS 번들에서 분리하기 때문이다. 라이브러리 모드에서는 Vite가 CSS 파일을 별도로 추출하고, 이를 JS 파일에 자동으로 포함하거나 주입하지 않는다.
이 디자인은 일반적으로 라이브러리 소비자가 스타일 적용 여부를 스스로 결정할 수 있도록 하기 위한 의도이다. 하지만 대부분의 사용자는 라이브러리를 사용할 때 CSS가 자동으로 적용되기를 기대하기 때문에, 실제 사용에서 불편함을 유발한다.
보다 강력하고 사용자 친화적인 방법은 CSS를 라이브러리 JS 파일 내부에 자동으로 주입해주는 방식이다. 이를 도와주는 플러그인이 vite-plugin-lib-inject-css이다.
npm install vite-plugin-lib-inject-css --save-dev
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import libInjectCss from 'vite-plugin-lib-inject-css';
export default defineConfig({
plugins: [react(), libInjectCss()],
build: {
lib: {
entry: 'src/index.ts',
name: 'MyComponentLib',
fileName: 'my-component-lib',
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
},
},
},
});
이렇게 설정하면 빌드된 JS 파일 내부에 다음과 같은 코드가 자동으로 삽입된다:
const style = document.createElement('style');
style.textContent = '...빌드된 CSS 내용...';
document.head.appendChild(style);
Vite의 라이브러리 빌드 모드에서는 기본적으로 CSS가 JS와 분리되어 출력되며, 자동으로 로드되지 않는다. 이를 방치하면 라이브러리를 사용하는 쪽에서 예상치 못한 스타일 누락 문제가 발생한다.
방법 | 장점 | 단점 |
---|---|---|
vite-plugin-lib-inject-css 사용 | 자동 스타일 적용, UX 향상 | 빌드 크기 소폭 증가 |
라이브러리를 보다 완성도 있게 만들고 싶다면, vite-plugin-lib-inject-css를 적용하여 개발자 경험을 개선하자.