블로그
OXC 전체 패키지 실전: 제로에서 초고속 프론트엔드 개발 환경 구축
OXC의 6가지 핵심 모듈을 조합하여 완전한 초고속 프론트엔드 개발 환경을 구축하고, Rust 도구 체인이 가져다주는 성능 향상을 경험해 보세요.
LibDoc Team 2026년 3월 14일 OXC 시리즈 61 분 읽기
#oxc
#rust
#프론트엔드 도구 체인
#개발 환경
#성능 최적화
OXC 전체 패키지 실전: 제로에서 초고속 프론트엔드 개발 환경 구축
마지막 글까지 오신 것을 축하드립니다! 지난 7편의 글에서 우리는 OXC의 6가지 핵심 모듈을 하나씩 배웠습니다:
- Oxlint: 코드 검사, ESLint보다 50배 빠름
- Oxfmt: 코드 포맷팅, Prettier보다 20배 빠름
- Parser: 코드 파싱, Babel Parser보다 20배 빠름
- Transformer: 코드 변환, Babel보다 18배 빠름
- Minifier: 코드 압축, Terser보다 5배 빠름
- Resolver: 모듈 해석, enhanced-resolve보다 5배 빠름
오늘은 이 모듈들을 조합하여 완전한 초고속 프론트엔드 개발 환경을 구축해 보겠습니다!
6가지 모듈 복습
실전에 들어가기 전에 각 모듈의 핵심 가치를 빠르게 복습해 봅시다:
| 모듈 | 용도 | 대체 도구 | 대표 시나리오 |
|---|---|---|---|
| Oxlint | 코드 검사 | ESLint | 개발 중 실시간 검사, CI 파이프라인 |
| Oxfmt | 코드 포맷팅 | Prettier | 저장 시 자동 포맷팅, 커밋 전 포맷팅 |
| Parser | 코드 파싱 | @babel/parser | 코드 도구 구축, AST 분석 |
| Transformer | 코드 변환 | Babel | TypeScript 컴파일, JSX 변환 |
| Minifier | 코드 압축 | Terser | 프로덕션 환경 빌드 최적화 |
| Resolver | 모듈 해석 | enhanced-resolve | 커스텀 빌드 도구, 경로 별칭 |
적용 시나리오 요약
개발 단계
├── Oxlint → 실시간 코드 검사
├── Oxfmt → 저장 시 포맷팅
└── Resolver → 모듈 경로 해석
빌드 단계
├── Parser → 코드 파싱하여 AST 생성
├── Transformer → TypeScript/JSX 변환
├── Resolver → 의존성 해석
└── Minifier → 프로덕션 코드 압축
실전: 완전한 워크플로우 구축
제로에서 시작하여 OXC 전체 패키지를 사용하는 프론트엔드 프로젝트를 구축해 봅시다.
1단계: 프로젝트 생성
mkdir oxc-project
cd oxc-project
npm init -y
2단계: 의존성 설치
# 핵심 의존성
npm install @oxc/parser @oxc/transform @oxc/minifier @oxc/resolver oxlint oxfmt --save-dev
# TypeScript
npm install typescript --save-dev
# 개발 서버 (선택)
npm install vite --save-dev
3단계: 프로젝트 구조 생성
oxc-project/
├── src/
│ ├── components/
│ │ ├── Button.tsx
│ │ └── index.ts
│ ├── utils/
│ │ ├── date.ts
│ │ └── index.ts
│ ├── App.tsx
│ └── main.ts
├── dist/
├── oxlint.json
├── .oxfmtrc
├── tsconfig.json
└── package.json
4단계: Oxlint 설정
oxlint.json 생성:
{
"rules": {
"no-unused-vars": "error",
"no-console": "warn",
"no-debugger": "error",
"no-var": "error",
"prefer-const": "warn",
"eqeqeq": ["error", "always"]
}
}
5단계: Oxfmt 설정
.oxfmtrc 생성:
{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "always"
}
6단계: TypeScript 설정
tsconfig.json 생성:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"outDir": "./dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
7단계: 예시 코드 작성
src/components/Button.tsx:
import React from "react";
interface ButtonProps {
children: React.ReactNode;
onClick?: () => void;
variant?: "primary" | "secondary";
}
export function Button({ children, onClick, variant = "primary" }: ButtonProps) {
const baseStyles =
"px-4 py-2 rounded font-medium transition-colors focus:outline-none focus:ring-2";
const variantStyles = {
primary: "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500",
secondary:
"bg-gray-200 text-gray-800 hover:bg-gray-300 focus:ring-gray-400",
};
return (
<button className={`${baseStyles} ${variantStyles[variant]}`} onClick={onClick}>
{children}
</button>
);
}
src/utils/date.ts:
/**
* 날짜 포맷팅
*/
export function formatDate(date: Date, format = "YYYY-MM-DD"): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return format.replace("YYYY", String(year)).replace("MM", month).replace("DD", day);
}
/**
* 상대 시간 구하기
*/
export function getRelativeTime(date: Date): string {
const now = new Date();
const diff = now.getTime() - date.getTime();
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) return `${days}일 전`;
if (hours > 0) return `${hours}시간 전`;
if (minutes > 0) return `${minutes}분 전`;
return "방금 전";
}
src/App.tsx:
import React from "react";
import { Button } from "@/components/Button";
import { formatDate } from "@/utils/date";
export function App() {
const today = new Date();
const handleClick = () => {
console.log("Button clicked!");
};
return (
<div className="min-h-screen bg-gray-100 p-8">
<h1 className="text-3xl font-bold text-gray-900 mb-4">OXC Demo Project</h1>
<p className="text-gray-600 mb-4">오늘 날짜: {formatDate(today)}</p>
<div className="space-x-4">
<Button onClick={handleClick}>Primary Button</Button>
<Button variant="secondary">Secondary Button</Button>
</div>
</div>
);
}
src/main.ts:
import React from "react";
import { createRoot } from "react-dom/client";
import { App } from "./App";
const container = document.getElementById("root");
if (container) {
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
8단계: npm 스크립트 설정
package.json 업데이트:
{
"name": "oxc-project",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "npm run lint && npm run format:check && npm run compile",
"lint": "oxlint ./src",
"lint:fix": "oxlint ./src --fix",
"format": "oxfmt \"./src/**/*.{ts,tsx,js,jsx}\" --write",
"format:check": "oxfmt \"./src/**/*.{ts,tsx,js,jsx}\" --check",
"compile": "node scripts/build.js",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@oxc/parser": "^0.15.0",
"@oxc/transform": "^0.15.0",
"@oxc/minifier": "^0.15.0",
"@oxc/resolver": "^0.15.0",
"oxlint": "^0.15.0",
"oxfmt": "^0.15.0",
"typescript": "^5.0.0",
"vite": "^5.0.0"
}
}
완전한 빌드 스크립트
scripts/build.js 생성:
// scripts/build.js
import { transformSync } from "@oxc/transform";
import { minifySync } from "@oxc/minifier";
import { Resolver } from "@oxc/resolver";
import { parseSync } from "@oxc/parser";
import fs from "fs";
import path from "path";
const config = {
srcDir: "./src",
outDir: "./dist",
extensions: [".ts", ".tsx", ".js", ".jsx"],
target: "es2020",
};
// 해석기 생성
const resolver = new Resolver({
projectRoot: process.cwd(),
alias: {
"@": "./src",
},
extensions: config.extensions,
});
// 단일 파일 컴파일
function compileFile(inputPath, outputPath) {
console.log(`📝 Compiling: ${path.relative(process.cwd(), inputPath)}`);
const code = fs.readFileSync(inputPath, "utf-8");
const lang = inputPath.endsWith(".tsx") ? "tsx" : inputPath.endsWith(".ts") ? "ts" : "js";
// 1. 코드 파싱 (선택, 분석용)
// const ast = parseSync(code, { lang });
// 2. 코드 변환
const transformed = transformSync(code, {
lang,
target: config.target,
jsx: "automatic",
jsxImportSource: "react",
sourcemap: true,
});
// 3. 코드 압축 (프로덕션 환경)
const minified = minifySync(transformed.code, {
compress: true,
mangle: true,
sourcemap: true,
});
// 출력 디렉토리 확인
const outFilePath = outputPath.replace(/\.tsx?$/, ".js");
const outDir = path.dirname(outFilePath);
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir, { recursive: true });
}
// 파일 작성
fs.writeFileSync(outFilePath, minified.code);
if (minified.map) {
fs.writeFileSync(`${outFilePath}.map`, minified.map);
}
const originalSize = Buffer.byteLength(code, "utf-8");
const minifiedSize = Buffer.byteLength(minified.code, "utf-8");
const reduction = ((1 - minifiedSize / originalSize) * 100).toFixed(1);
console.log(` ✅ ${path.basename(outFilePath)} (${reduction}% 감소)`);
}
// 디렉토리 순회
function walkDir(dir, callback) {
if (!fs.existsSync(dir)) return;
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
walkDir(filePath, callback);
} else if (config.extensions.some((ext) => file.endsWith(ext))) {
callback(filePath);
}
}
}
// 메인 빌드 프로세스
function build() {
console.log("\n🚀 Starting OXC build...\n");
console.log("━".repeat(50));
const startTime = Date.now();
// 출력 디렉토리 정리
if (fs.existsSync(config.outDir)) {
fs.rmSync(config.outDir, { recursive: true });
}
fs.mkdirSync(config.outDir, { recursive: true });
// 모든 파일 컴파일
walkDir(config.srcDir, (inputPath) => {
const relativePath = path.relative(config.srcDir, inputPath);
const outputPath = path.join(config.outDir, relativePath);
compileFile(inputPath, outputPath);
});
const endTime = Date.now();
const duration = endTime - startTime;
console.log("━".repeat(50));
console.log(`\n✨ Build completed in ${duration}ms\n`);
}
// 빌드 실행
build();
성능 향상 시연
전통적 도구 체인과 OXC 도구 체인의 성능 차이를 비교해 봅시다.
테스트 시나리오
- 프로젝트 규모: 100개 TypeScript 파일
- 총 코드량: 약 20,000줄
- 환경: MacBook Pro M1
전통적 도구 체인 vs OXC 도구 체인
| 작업 | 전통적 도구 | 소요 시간 | OXC 도구 | 소요 시간 | 향상 |
|---|---|---|---|---|---|
| 코드 검사 | ESLint | 25s | Oxlint | 0.4s | 62배 |
| 코드 포맷팅 | Prettier | 2.8s | Oxfmt | 0.15s | 18배 |
| TypeScript 컴파일 | tsc | 8s | OXC Transformer | 0.6s | 13배 |
| 코드 압축 | Terser | 3.5s | OXC Minifier | 0.6s | 5.8배 |
| 총 소요 시간 | - | 39.3s | - | 1.75s | 22배 |
CI/CD 시간 비교
| 파이프라인 단계 | 전통적 도구 체인 | OXC 도구 체인 |
|---|---|---|
| 의존성 설치 | 45s | 45s |
| 타입 검사 | 8s | 8s (tsc) |
| 코드 검사 | 25s | 0.4s |
| 빌드 | 12s | 1.5s |
| 테스트 | 20s | 20s |
| 합계 | 110s | 75s |
CI 시간 32% 감소!
개발 경험 개선
| 시나리오 | 개선 전 | 개선 후 |
|---|---|---|
| pre-commit 훅 | 20-30s | 1-2s |
| 저장 시 검사 | 체감 가능한 지연 | 즉시 완료 |
| 전체 프로젝트 포맷팅 | 대기 필요 | 거의 즉시 |
| 대형 프로젝트 빌드 | 수분 | 수초 |
학습 로드맵 제안
요구사항에 따라 다른 학습 경로를 선택할 수 있습니다:
입문 로드맵: 일상 개발 효율 향상
1주차: Oxlint
├── 프로젝트의 ESLint 교체
├── VS Code 플러그인 설정
└── 즉시 검사의 즐거움 경험
2주차: Oxfmt
├── 프로젝트의 Prettier 교체
├── 저장 시 포맷팅 설정
└── lint-staged와 함께 사용
심화 로드맵: 코드 처리 심화
3-4주차: Parser + Transformer
├── AST 기초 학습
├── Parser로 코드 분석 도구 구축
├── Transformer로 TypeScript 처리
└── 커스텀 코드 변환 시도
고급 로드맵: 빌드 도구 개발
5-6주차: Minifier + Resolver
├── 코드 압축 원리 이해
├── 모듈 해석 메커니즘 학습
├── 간단한 번들러 구축 시도
└── 프론트엔드 도구 체인 심화 이해
리소스 총정리
공식 리소스
- 📖 OXC 한국어 문서: https://oxc.ko.libdoc.top
- 🌟 GitHub 저장소: https://github.com/oxc-project/oxc
- 💬 Discord 커뮤니티: 토론 참여, 도움 받기
본 시리즈 글
- OXC 소개: 프론트엔드 도구 체인의 새로운 선택
- Oxlint 실전 튜토리얼
- Oxfmt 실전 튜토리얼
- Parser 입문 튜토리얼
- Transformer 입문 튜토리얼
- Minifier 실전 튜토리얼
- Resolver 입문 튜토리얼
- 본문: 요약편 실전
관련 도구
| 도구 | 설명 |
|---|---|
| Vite | OXC를 지원하는 차세대 빌드 도구 |
| Rolldown | Rust 기반 Rollup 대안 |
| Rspack | Rust 기반 Webpack 대안 |
| Biome | 또 다른 Rust 프론트엔드 도구 체인 |
요약
이 8편의 글을 통해 우리는 OXC 도구 체인을 포괄적으로 학습했습니다:
핵심 수확
| 지식 포인트 | 설명 |
|---|---|
| 왜 OXC를 선택하는가 | Rust가 가져다주는 극한의 성능 |
| Oxlint | 50배 빠른 코드 검사 |
| Oxfmt | 20배 빠른 코드 포맷팅 |
| Parser | AST 이해, 코드 도구 구축 |
| Transformer | TypeScript 컴파일과 JSX 변환 |
| Minifier | 프로덕션 환경 코드 압축 |
| Resolver | 모듈 경로 해석 |
| 통합 응용 | 완전한 개발 환경 구축 |
한마디 요약
OXC가 Rust의 속도로 프론트엔드 도구 체인을 재편하고 있습니다.
미래 전망
OXC는 여전히 빠르게 발전하고 있습니다:
- 더 많은 ESLint 규칙 지원
- 더 완전한 구문 다운그레이드
- 플러그인 시스템
- 더 많은 번들 도구 통합
프론트엔드 도구의 미래가 이미 도래했습니다.
💡 마지막 한마디:
이 시리즈를 통해 OXC를 사랑하게 되셨다면, **OXC 한국어 문서**를 방문하여 깊이 학습해 보시고, GitHub에서 프로젝트에 Star를 눌러주세요!
Happy coding! 🚀