ワンクリックで
bundling-compiler
tsup/Vite/Turbopack 번들러 선택 기준, React Compiler, Tree Shaking, 코드 스플리팅 패턴
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
tsup/Vite/Turbopack 번들러 선택 기준, React Compiler, Tree Shaking, 코드 스플리팅 패턴
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Spring Security 5.5.x + jjwt 0.10.7 레거시 JWT 인증 - WebSecurityConfigurerAdapter, OncePerRequestFilter, javax.servlet 환경
Spring Boot 3.x + Spring Security 6.x + jjwt 0.12.x 기반 모던 JWT 인증 패턴. SecurityFilterChain Bean, 람다 DSL, jakarta.servlet, Virtual Threads 적용
Unity 6 LTS 2D 모바일 게임용 uGUI 시스템 전문 스킬. Canvas/RectTransform/TextMeshPro, 모바일 UI 패턴(팝업·무한 스크롤·광고·IAP), 성능 최적화, UI Toolkit과의 선택 기준 포함.
아크라시아(akrasia, 자제력 없음) 학술 논쟁의 핵심 구도와 주요 연구자·문헌을 빠르게 파악할 수 있는 도메인 지식 스킬. 도덕윤리교육 전공 대학원생(석/박사)이 학위논문·KCI 투고·세미나 준비 시 고대–현대–한국 학계–도덕심리학 흐름을 한 번에 짚도록 구성. <example>사용자: "아리스토텔레스의 propeteia와 astheneia 구분을 인용하려는데 출처를 알려줘"</example> <example>사용자: "데이비슨이 의지박약을 어떻게 가능하다고 봤는지 핵심 논증을 정리해줘"</example> <example>사용자: "한국 도덕교육 학계에서 아크라시아 다룬 논문 있어?"</example>
아리스토텔레스 『니코마코스 윤리학』에서 akrasia(자제력없음)와 akolasia(무절제)의 5축 차이를 정밀하게 정리한 학위논문 자료 스킬. NE VII.4 1147b20-1148b14, VII.8 1150b29-1151a28, III.10-12 1117b23-1119b18 절별 분해와 표준 학자 해석(Bostock, Broadie-Rowe, Pakaluk, Hursthouse, Charles 등)을 포함. 도덕교육 적용을 위한 두 상태 차이의 함의 및 한국어 번역어 처리 권장안 제공. <example>사용자: "akrates와 akolastos를 prohairesis 측면에서 어떻게 구분해야 하나요?"</example> <example>사용자: "NE VII.4의 ἁπλῶς akrasia가 akolasia와 어떻게 갈라지는지 절별 분해해주세요"</example> <example>사용자: "Hursthouse의 연속체 모델을 도덕교육 적용 절에서 어떻게 활용할 수 있나요?"</example>
한국 위기 대응 자원(자살·자해·정신건강·여성·청소년·노인·다문화) 핫라인과 앱·챗봇 안전 가드 응답 패턴 종합. 꿈 해몽·정신건강 앱 등 자가 진단/감정 콘텐츠 도메인에서 위험 신호 포착 시 안전한 자원 안내 문구를 작성할 때 참조. <example>사용자: "꿈 해몽 앱에 위기 안내 문구를 어떻게 넣을까?"</example> <example>사용자: "한국에서 자살예방 핫라인 번호가 어떻게 바뀌었지?"</example> <example>사용자: "정신건강 챗봇 안전 가드 응답 템플릿을 짜줘"</example>
| name | bundling-compiler |
| description | tsup/Vite/Turbopack 번들러 선택 기준, React Compiler, Tree Shaking, 코드 스플리팅 패턴 |
| disable-model-invocation | true |
소스: https://tsup.egoist.dev | https://vitejs.dev | https://nextjs.org/docs | https://react.dev/learn/react-compiler 검증일: 2026-06-20
프로젝트 타입?
├─ 라이브러리 (npm 배포용)
│ └─ 단순 TS/JS → tsup (추천)
│
└─ 애플리케이션
├─ Next.js → Turbopack (내장, 기본값)
└─ SPA/기타 → Vite
| 도구 | 용도 | Dev 속도 | 설정 복잡도 |
|---|---|---|---|
| tsup | 라이브러리 빌드 | - | ⭐ 매우 간단 |
| Vite | SPA 앱 | ⭐⭐⭐ 빠름 | ⭐⭐ |
| Turbopack | Next.js 앱 | ⭐⭐⭐⭐ 매우 빠름 | ⭐⭐ (내장) |
// tsup.config.ts
import { defineConfig } from 'tsup'
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'], // ESM + CommonJS 동시 빌드
dts: true, // TypeScript 선언 파일 생성
clean: true, // 빌드 전 dist/ 정리
sourcemap: true,
splitting: false, // 라이브러리는 대개 false
treeshake: true,
})
export default defineConfig({
entry: {
index: 'src/index.ts',
utils: 'src/utils/index.ts',
types: 'src/types/index.ts',
},
format: ['esm', 'cjs'],
dts: true,
outExtension({ format }) {
return { js: format === 'esm' ? '.mjs' : '.cjs' }
},
})
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./utils": {
"types": "./dist/utils.d.ts",
"import": "./dist/utils.mjs",
"require": "./dist/utils.cjs"
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"sideEffects": false
}
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import path from 'path'
export default defineConfig({
plugins: [react()],
resolve: {
alias: { '@': path.resolve(__dirname, './src') }
},
build: {
outDir: 'dist',
sourcemap: true,
},
server: {
port: 3000,
}
})
export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
name: 'MyLibrary',
formats: ['es', 'cjs'],
fileName: (format) => `my-library.${format}.js`
},
rollupOptions: {
external: ['react', 'react-dom'], // peer deps 제외
output: {
globals: { react: 'React', 'react-dom': 'ReactDOM' }
}
}
}
})
// next.config.js - Next.js 16+에서는 기본값
/** @type {import('next').NextConfig} */
const nextConfig = {}
export default nextConfig
// Next.js 15: CLI 플래그로 활성화 (next dev --turbopack)
// Next.js 16+: 기본값. 커스터마이징만 turbopack 키 사용
const nextConfig = {
turbopack: {
// resolveAlias, rules 등 커스터마이징 시에만 설정
},
}
| 항목 | Webpack | Turbopack |
|---|---|---|
| 언어 | JavaScript | Rust |
| Dev 시작 | 느림 | 매우 빠름 |
| HMR | 느림 | 거의 즉각 |
| 플러그인 호환 | 전체 | 제한적 (재구현 필요) |
| 프로덕션 빌드 | 안정 | Next.js 16에서 안정화 (기본값) |
Turbopack 제약: 일부 Webpack 플러그인 미지원 → 대안 확인 필요
v1.0 안정화: 2025년 10월 | 출처: https://react.dev/learn/react-compiler
// Next.js 15+ (reactCompiler는 top-level 옵션, experimental 아님)
const nextConfig = {
reactCompiler: true,
}
// Vite (@vitejs/plugin-react v5 이하)
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
react({
babel: {
plugins: ['babel-plugin-react-compiler'],
},
}),
],
})
// Vite 8+ (@vitejs/plugin-react v6 — babel 옵션 제거됨, @rolldown/plugin-babel 사용)
import react, { reactCompilerPreset } from '@vitejs/plugin-react'
import babel from '@rolldown/plugin-babel'
export default defineConfig({
plugins: [react(), babel(reactCompilerPreset())],
})
// ❌ React Compiler 없이: 수동 최적화 필요
const sortedItems = useMemo(
() => items.sort((a, b) => a.name.localeCompare(b.name)),
[items]
)
const handleClick = useCallback(() => onSelect(id), [onSelect, id])
const MemoizedComponent = memo(MyComponent)
// ✅ React Compiler 활성화 시: 자동 처리됨 (수동 최적화 제거 가능)
const sortedItems = items.sort((a, b) => a.name.localeCompare(b.name))
const handleClick = () => onSelect(id)
// memo 제거 가능
// ❌ Rules of React 위반 시 컴파일러가 해당 컴포넌트 최적화 건너뜀
function BadComponent() {
// 조건부 Hook 호출 (규칙 위반)
if (someCondition) {
const [state, setState] = useState(0) // ❌
}
}
// ✅ 올바른 패턴 (컴파일러가 최적화 가능)
function GoodComponent({ condition }: { condition: boolean }) {
const [state, setState] = useState(0)
return condition ? <div>{state}</div> : null
}
// next.config.js
import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin'
const withVanillaExtract = createVanillaExtractPlugin()
export default withVanillaExtract({
// 다른 Next.js 설정
})
// styles.css.ts
import { style, styleVariants } from '@vanilla-extract/css'
export const base = style({
display: 'flex',
padding: '12px',
})
export const variants = styleVariants({
primary: { backgroundColor: 'blue', color: 'white' },
secondary: { backgroundColor: 'gray', color: 'black' },
})
// 컴포넌트에서 사용
import { base, variants } from './styles.css'
function Button({ variant = 'primary' }: { variant: keyof typeof variants }) {
return <button className={`${base} ${variants[variant]}`}>Click</button>
}
특징: 빌드 타임에 static CSS 생성 → 런타임 오버헤드 없음
주의:
@vanilla-extract/css의 webpack 플러그인은 현재 Turbopack에서 미지원. Turbopack 기반 Next.js 환경에서는 사용 불가.
// package.json: 부수 효과 없음을 번들러에 알림
{
"sideEffects": false
}
// CSS가 있는 경우
{
"sideEffects": ["**/*.css", "./src/polyfills.ts"]
}
// ✅ ESM: Tree Shaking 가능
export function add(a: number, b: number) { return a + b }
export function subtract(a: number, b: number) { return a - b }
// 사용 측에서 add만 import → subtract는 번들에서 제거됨
import { add } from '@myorg/utils'
// ❌ CJS: Tree Shaking 불가
module.exports = { add, subtract }
// → 전체가 번들에 포함됨
// ❌ 배럴 파일이 tree shaking을 방해하는 경우
// index.ts
export * from './heavy-module' // side effect가 있으면 전체 포함
// ✅ named export 명시
export { HeavyComponent } from './heavy-module'
// 또는 직접 경로로 import
import { HeavyComponent } from '@myorg/ui/heavy-module'
import { lazy, Suspense } from 'react'
// 라우트 기반 스플리팅
const Dashboard = lazy(() => import('./pages/Dashboard'))
const Settings = lazy(() => import('./pages/Settings'))
function App() {
return (
<Suspense fallback={<PageSkeleton />}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
)
}
import dynamic from 'next/dynamic'
// SSR 비활성화 (브라우저 전용 컴포넌트)
const Chart = dynamic(() => import('../components/Chart'), {
ssr: false,
loading: () => <ChartSkeleton />,
})
// 조건부 로드
const PDFViewer = dynamic(() => import('../components/PDFViewer'))
라우트 단위 스플리팅: 필수 (페이지별 독립 청크)
컴포넌트 단위 스플리팅: 선택적 (무거운 컴포넌트만)
라이브러리 단위 스플리팅: 자동 (번들러가 처리)
❌ 피해야 할 것: 너무 잘게 쪼개기 (HTTP 요청 오버헤드)
✅ 기준: 30KB 이상인 컴포넌트 또는 특정 조건에서만 사용하는 컴포넌트