React vs ExtJS vs VanillaFront
프론트엔드 개발 도구를 검토할 때 자주 저울에 오르는 이름 React와 글로벌 엔터프라이즈 UI Framework인 ExtJs입니다. 여기에 VanillaFront를 같이 비교해봅니다. 세 도구는 성격이 다르고 각자 잘 맞는 자리가 있습니다. 이 글에서는 항목별 특성과 실제 코드를 함께 비교합니다.
한눈에 요약
| 구분 | React | ExtJs | VanillaFront |
| 성격 | UI 렌더링 라이브러리 | 통합 프레임워크 | 통합 프레임워크 |
| 클래스 시스템 | 함수·클래스 컴포넌트 | 자체 클래스 시스템 | 표준 ES6 class |
| 모듈 시스템 | ES6 import + 번들러 | 자체 모듈 시스템 | ES6 import (No-Build) |
| 그리드·차트·다이어그램 | 별도 라이브러리 조합 | 내장 | 내장 |
| 상태 관리 | 라이브러리 조합 | 자체 Store 시스템 | DataManager + 컴포넌트 상태 |
| 컴포넌트 격리 | 라이브러리별 상이 | 전역 CSS 클래스 | Shadow DOM 격리 |
| 빌드 도구 | 번들러 필요 | 전용 도구 | 불필요 (브라우저 직접) |
| AI 워크플로우 통합 | 별도 도구 | 별도 도구 | VSCode Extension 내장 |
| 학습 곡선 | JSX + hooks + 조합 라이브러리 | 자체 클래스·Store 개념 | 표준 ES6 + config 트리 |
1. 라이브러리 vs 프레임워크
React는 UI를 렌더링하는 라이브러리입니다. 라우팅·상태 관리·폼·그리드·스타일은 프로젝트별로 라이브러리를 선택해 조합합니다.
ExtJS는 그리드·차트·폼·트리·다이어그램·레이아웃이 한 패키지에 담긴 통합 프레임워크입니다. 통일된 API와 벤더 지원이 특징입니다.
VanillaFront는 통합 프레임워크 방향을 따릅니다. 200개 이상의 컴포넌트가 한 패키지로 제공되어 조합 결정 없이 화면 구성이 가능합니다.
2. 컴포넌트 정의 방식
React
function CustomerList() {
const [customers, setCustomers] = useState([]);
useEffect(() => {
fetch('/api/customers').then(r => r.json()).then(setCustomers);
}, []);
return <Grid data={customers} />;
}
함수 컴포넌트 + hooks. 렌더 함수 안에서 상태·부수효과·마크업을 다룹니다.
ExtJS
Ext.define('MyApp.view.CustomerList', {
extend: 'Ext.grid.Panel',
xtype: 'customer-list',
initComponent: function() {
this.callParent();
}
});
자체 클래스 시스템을 통해 컴포넌트를 정의합니다.
VanillaFront
import Va from '../../lib/va.js';
export default class CustomerList extends Va.View {
constructor(){ super(arguments); }
mounted(){ this.onSearch(); }
onSearch(){ /* ... */ }
config(){
return {
tagName: 'grid',
columns: [
{ key: 'name', title: '이름' }
]
};
}
}
Va.registerView('/view/customer/CustomerList', CustomerList);
표준 ES6 class + 선언적 config 트리. 자바스크립트 표준 문법 위에서 IDE 지원을 그대로 활용할 수 있습니다.
3. 코드로 보는 차이 — 기본 화면
버튼을 누르면 인사말이 바뀌는 단순한 화면입니다.
React
import { useState } from 'react';
function Hello() {
const [greeting, setGreeting] = useState('Hello, World!');
return (
<div>
<h1>{greeting}</h1>
<button onClick={() => setGreeting('Hello, VanillaFront!')}>
Change
</button>
</div>
);
}
export default Hello;
ExtJS
Ext.define('MyApp.view.Hello', {
extend: 'Ext.panel.Panel',
xtype: 'hello-panel',
items: [
{
xtype: 'displayfield',
itemId: 'greeting',
value: 'Hello, World!'
},
{
xtype: 'button',
text: 'Change',
handler: function() {
this.up('panel')
.down('#greeting')
.setValue('Hello, VanillaFront!');
}
}
]
});
VanillaFront
import Va from '../../lib/va.js';
export default class Hello extends Va.View {
constructor(){ super(arguments); }
onChange(){
this.getRef('greeting').setValue('Hello, VanillaFront!');
}
config(){
return {
tagName: 'div',
layout: 'ds-flex fd-column ai-start gap-s',
tags: [
{
tagName: 'displayField',
ref: 'greeting',
value: 'Hello, World!'
},
{
tagName: 'button',
text: 'Change',
appearance: 'primary',
onClick: 'onChange'
}
]
};
}
}
Va.registerView('/view/hello/Hello', Hello);
같은 화면, 다른 표현 방식
- React는 렌더 함수 안에 상태·마크업이 함께 있고, 상태 변경은 useState 훅으로 관리합니다.
- ExtJS는 config로 선언하되 이벤트 핸들러가 인라인 함수로 들어가고, 컴포넌트 접근은 up(), down() 체인으로 탐색합니다.
- VanillaFront는 config가 순수 데이터 트리이고, 핸들러는 클래스 메서드로 분리되며, 참조는 ref 이름으로 직접 접근합니다.
4. 코드로 보는 차이 — 그리드 셀 편집
이름과 지역을 표시하고 셀을 클릭해 편집할 수 있는 그리드입니다.
React (엔터프라이즈 그리드 라이브러리 조합 예시)
import { useState } from 'react';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
function EditableGrid() {
const [rowData, setRowData] = useState([
{ name: '홍길동', region: '서울' },
{ name: '김철수', region: '부산' }
]);
const columnDefs = [
{ field: 'name', headerName: '이름', editable: true },
{ field: 'region', headerName: '지역', editable: true }
];
const onCellValueChanged = (e) => {
console.log('변경:', e.data);
};
return (
<div className="ag-theme-alpine" style={{ height: 400, width: 600 }}>
<AgGridReact
rowData={rowData}
columnDefs={columnDefs}
onCellValueChanged={onCellValueChanged}
/>
</div>
);
}
export default EditableGrid;
ExtJS
Ext.define('MyApp.view.EditableGrid', {
extend: 'Ext.grid.Panel',
plugins: 'cellediting',
store: {
fields: ['name', 'region'],
data: [
{ name: '홍길동', region: '서울' },
{ name: '김철수', region: '부산' }
]
},
columns: [
{ text: '이름', dataIndex: 'name', editor: 'textfield' },
{ text: '지역', dataIndex: 'region', editor: 'textfield' }
],
listeners: {
edit: function(editor, e) {
console.log('변경:', e.record.data);
}
}
});
VanillaFront
import Va from '../../lib/va.js';
export default class EditableGrid extends Va.View {
constructor(){ super(arguments); }
mounted(){
this.getRef('refGrid').setData([
{ name: '홍길동', region: '서울' },
{ name: '김철수', region: '부산' }
]);
}
config(){
return {
tagName: 'article',
layout: 'ds-flex fd-column ai-stretch gap-s',
tags: [{
ref: 'refGrid',
tagName: 'grid',
style: { height: '400px', width: '600px' },
columns: [
{
key: 'name',
title: '이름',
flashTag: { tagName: 'input' }
},{
key: 'region',
title: '지역',
flashTag: { tagName: 'input' }
}]
}]
};
}
}
Va.registerView('/view/grid/EditableGrid', EditableGrid);
세 접근의 차이
- React는 별도 그리드 라이브러리 (AG Grid, Handsontable 등) 를 선택해 컴포넌트로 임포트하고 props로 설정합니다. CSS 임포트, 테마 클래스 지정 등 세팅 단계가 추가됩니다.
- ExtJS는 Ext.grid.Panel 을 상속하고 plugins: 'cellediting' 을 켜서 편집을 활성화합니다. 컬럼별 editor 속성으로 편집 컴포넌트를 지정합니다.
- VanillaFront는 컬럼에 flashTag 를 지정하면 편집 시점에 해당 컴포넌트가 셀에 일시 렌더됩니다. 별도 라이브러리 임포트나 플러그인 설정 없이 프레임워크 표준 방식입니다.
편집 컴포넌트를 셀별로 자유롭게 바꿀 수 있는 것도 VanillaFront의 특성입니다.
columns: [
{ key: 'name', title: '이름', flashTag: { tagName: 'input' } },
{ key: 'region', title: '지역', flashTag: { tagName: 'combobox', data: regions } },
{ key: 'joinDate', title: '입사일', flashTag: { tagName: 'datePicker' } },
{ key: 'color', title: '색상', flashTag: { tagName: 'colorPicker' } }
]
5. 엔터프라이즈 컴포넌트 접근
컴포넌트React 방식ExtJSVanillaFront
| 내용 | React | ExtJs | VanillaFront |
| 엔터프라이즈 그리드 | 별도 라이브러리 선택 | 내장 | 내장 |
| 트리 그리드 | 별도 라이브러리 선택 | 내장 | 내장 |
| 피벗 그리드 | 별도 라이브러리 선택 | 내장 | 내장 |
| 차트 | 별도 라이브러리 선택 | 내장 | 내장 |
| 다이어그램 | 별도 라이브러리 선택 | 내장 | 내장 |
| Excel/PDF 익스포트 | 별도 라이브러리 선택 | 내장 | 내장 |
VanillaFront가 내장으로 제공하는 컴포넌트:
- Grid, TreeGrid, DynamicGrid, PivotGrid — 프로존·다중헤더·집계·필터·엑셀 익스포트 포함
- Chart — Bar, Line, Area, Pie, Gauge, Stock, Radar, TreeMap, BoxPlot 등
- Diagram — 데이터플로우, BPMN, 스케줄 등
- ColorPicker, DatePicker, FileUpload 등 폼 컴포넌트
6. 상태 관리
React는 컴포넌트 로컬, 트리 공유, 전역, 서버 상태를 각각 다른 라이브러리 조합으로 다룹니다.
ExtJS는 자체 Store 시스템이 데이터·CRUD·정렬·필터·이벤트를 통합 처리합니다.
VanillaFront는 Va.DataManager 를 데이터 관리 중심으로, 컴포넌트 참조는 getRef('name') 로, 서비스 호출은 함수 호출로 처리합니다. 하나의 프레임워크 표준 방식 안에서 완결됩니다.
7. 빌드·개발 환경
React는 Node.js 생태계 위에서 번들러·트랜스파일러·린터·스타일 처리기를 조합해 개발합니다.
ExtJS는 전용 커맨드라인 도구로 빌드합니다.
VanillaFront는 빌드 도구 없이 ES6 모듈을 브라우저가 직접 로드하는 방식입니다.
- <script type="module"> 하나로 시작
- 파일 수정 후 브라우저 새로고침으로 즉시 반영
- 사내 인트라넷·폐쇄망 환경에서 파일 복사만으로 배포
8. 컴포넌트 격리
React 생태계는 스타일 격리 방식이 프로젝트별로 다양합니다.
ExtJS는 전역 CSS 클래스로 컴포넌트를 스타일링합니다.
VanillaFront는 Shadow DOM 기반 격리를 프레임워크 표준으로 사용합니다. 각 컴포넌트가 자체 shadow root를 가져 스타일이 외부와 완전히 분리됩니다.
- 기존 시스템 페이지에 iframe 없이 임베드해도 스타일 충돌 없음
- 다른 프레임워크와 같은 페이지에 공존 가능
- 한 페이지에 여러 테마 컴포넌트가 나란히 있어도 서로 영향 없음
9. AI 개발 워크플로우
VanillaFront의 config가 순수 데이터 트리로 표현되어 AI 코드 생성 도구와 잘 맞습니다. LLM이 JSON 유사 구조를 다루는 건 함수 컴포넌트·JSX나 자체 클래스 시스템을 다루는 것보다 예측 가능합니다.
VSCode Extension 안에 WYSIWYG 에디터가 통합되어 있어 다음 흐름이 가능합니다.
- AI 도구에서 VanillaFront 코드 생성
- VSCode에서 파일 열면 에디터 영역에 즉시 시각 프리뷰
- 마우스로 수정 → 파일 자동 저장
- 컴포넌트 팔레트, Undo/Redo, 파일 탐색이 IDE 안에서 완결
이 조합은 VanillaFront가 처음부터 순수 데이터 config 구조로 설계된 결과입니다.
10. 학습 곡선
React는 JSX, hooks, 조합한 라이브러리별 API를 각각 학습합니다. 커뮤니티 자료가 풍부합니다.
ExtJS는 자체 클래스 시스템, Store, ViewModel 개념 학습이 필요합니다.
VanillaFront는 표준 ES6 문법과 선언적 config 트리만 익히면 시작 가능합니다. 자바스크립트 기본을 아는 개발자는 별도 방언 학습 없이 진입할 수 있습니다.
11. 외부 라이브러리 통합
세 도구가 외부 자바스크립트 라이브러리를 결합하는 방식입니다.
React — npm + 번들러
npm install 로 설치하고 import 로 가져옵니다. Webpack·Vite 같은 번들러가 CommonJS·ESM·UMD 등 다양한 포맷을 자동으로 변환·번들링해줍니다.
npm install codemirror
import { EditorView } from 'codemirror';
import { useEffect, useRef } from 'react';
function CodeEditor() {
const ref = useRef(null);
useEffect(() => {
const view = new EditorView({ parent: ref.current });
return () => view.destroy();
}, []);
return <div ref={ref} />;
}
특성: 라이브러리 포맷을 신경 쓸 필요 없음. 대신 번들러 설정·빌드 파이프라인이 전제.
ExtJS — 스크립트 링크 방식
전통적으로 <script> 태그와 Ext.require 자체 로더로 의존성을 관리합니다. ES 모듈이 표준화되기 전에 설계된 시스템이라 ESM 전용으로 배포되는 최신 라이브러리 사용에는 별도 어댑터가 필요합니다.
<script src="lib/codemirror/codemirror.js"></script>
Ext.define('MyApp.view.CodeEditor', {
extend: 'Ext.Component',
afterRender: function() {
this.editor = new CodeMirror(this.getEl().dom, { /* ... */ });
this.callParent();
}
});
특성: 오래된 UMD/전역 노출 라이브러리는 자연스럽게 통합. 최신 ESM 라이브러리는 제약.
VanillaFront — ESM 직접 사용
No-Build 방식 이라 브라우저가 이해할 수 있는 ESM 파일을 직접 사용합니다. 외부 라이브러리 확보 방법이 두 가지 있습니다.
방법 1: npm install 후 ESM 빌드 파일 활용
npm install codemirror
설치 후 node_modules/codemirror/dist/index.js 같은 ESM 출력 파일을 정적 폴더로 복사하거나 그 경로를 직접 참조합니다.
방법 2: GitHub 릴리스·CDN에서 ESM 파일 직접 다운로드 GitHub 릴리스 페이지나 esm.sh·jspm.io·unpkg 같은 ESM 지원 CDN에서 파일을 받아 정적 폴더에 둡니다.
확보한 ESM 파일은 상대 경로로 그대로 import 하면 됩니다.
import Va from '../../lib/va.js';
import { EditorView } from '../../lib/external/codemirror.esm.js';
export default class CodeEditor extends Va.View {
constructor(){ super(arguments); }
mounted(){
this.editor = new EditorView({
parent: this.getRef('editorArea').element
});
}
config(){
return {
tagName: 'div',
tags: [
{ tagName: 'div', ref: 'editorArea', style: { height: '400px' } }
]
};
}
}
Va.registerView('/view/code/CodeEditor', CodeEditor);
라이브러리를 Va 컴포넌트로 래핑해서 config 트리에서 다른 컴포넌트처럼 쓸 수도 있습니다. 이 방식으로 아래와 같이 임의로 컴포넌트를 만들어 쉽게 사용할 수도 있습니다.
- CodeMirror — tagName: 'codemirror'
- OpenLayers — tagName: 'ol'
- VWorld 지도 — tagName: 'vworld'
특성
- 번들러·빌드 파이프라인 없이 즉시 사용
- ESM 표준 위에서 동작하므로 최신 라이브러리와 호환성 좋음
- 폐쇄망 환경에서는 npm 설치 후 ESM 파일만 옮기거나, GitHub에서 직접 다운로드해서 사용 가능
12. 어떤 팀에게 무엇이 맞나
세 도구는 서로 대체 관계가 아니라 각자 잘 맞는 프로젝트 유형이 다릅니다.
React가 잘 맞는 경우
- 소비자용 웹 서비스, 랜딩 페이지, 콘텐츠 사이트
- 컴포넌트 조합의 유연성이 중요한 프로덕트
- 모던 툴체인 유지 여력이 있는 조직
- 커뮤니티 생태계와 채용 시장 규모가 중요한 조직
ExtJS가 잘 맞는 경우
- 기존 ExtJS 시스템을 유지 보수하는 팀
- 대형 프로젝트에서 벤더 지원 계약이 필요한 경우
VanillaFront가 잘 맞는 경우
- 그리드·폼·차트 중심의 사내 시스템·관리자 페이지·대시보드
- 통합 컴포넌트 세트가 필요한 엔터프라이즈 화면
- 빌드 파이프라인 없이 즉시 개발·배포하고 싶은 프로젝트
- AI 개발 워크플로우를 실무에 통합하고 싶은 팀
- 사내 인트라넷·폐쇄망 등 제한된 개발 환경
- 선언적 config 트리 스타일을 선호하는 개발 문화
결론
세 도구는 지향점이 다릅니다. 프로젝트 성격, 팀 구성, 개발 환경에 따라 선택이 달라집니다.
VanillaFront는 다음 자리를 지향합니다.
- 통합 프레임워크의 편의성 — 그리드·차트·폼을 한 세트로
- 모던 웹 표준 위에 구축 — ES6 클래스, Shadow DOM, ES 모듈
- 빌드 파이프라인 없이 즉시 사용 — 파일 수정 → 새로고침
- AI 개발 워크플로우 통합 — VSCode Extension + WYSIWYG 에디터
'왜 바닐라프론트를 만들었나!!' 카테고리의 다른 글
| React Vs VanillaFront (0) | 2026.09.18 |
|---|---|
| ExtJS 사용자를 위한 다음 단계: VanillaFront (0) | 2026.09.18 |
| 왜 VanillaFront를 만들었나? (0) | 2026.09.14 |