Ext JS Grid와 jQuery ajaxForm 연동: 비동기 파일 업로드 하이브리드 패턴 구현
Ext JS의 UI 강점과 jQuery ajaxForm의 유연성을 결합하여 Grid 컴포넌트 내에서 비동기 파일 업로드를 구현하는 실무적인 하이브리드 패턴을 상세히 분석합니다.
1. Ext JS와 jQuery 하이브리드 아키텍처
이 기술 가이드는 Ext JS의 강력한 UI 프레임워크와 jQuery의 유틸리티성을 결합하여, 단일 프레임워크만으로는 구현하기 까다로운 기능을 해결하는 사례를 다룹니다. 기본 아키텍처는 다음과 같이 구성됩니다.
- Data Model & Store: 게시판(BBS) 데이터를 구조화하고 CRUD 처리를 위한 Proxy 설정이 포함된 스토어 객체입니다.
- Grid Panel: 사용자에게 데이터 목록을 제공하며, 핵심 기능인 파일 첨부를 위한 버튼 렌더러(Renderer)가 포함되어 있습니다.
- Form Panel: Grid에서 선택된 항목의 상세 정보를 보여주며,
selectionchange이벤트를 통해 Grid와 데이터를 실시간으로 동기화합니다.
2. jQuery ajaxForm을 이용한 동적 업로드 로직
Ext JS 내부의 FileField가 가진 제약을 우회하기 위해, 순수 JavaScript와 jQuery를 활용하여 폼을 동적으로 생성하고 전송하는 전략을 채택했습니다.
핵심 기능을 담당하는 createDataForm 함수는 다음의 프로세스로 동작합니다.
- 동적 폼(Form) 생성: DOM에
multipart/form-data속성을 가진 form 태그를 즉시 생성하여 추가합니다. - 이벤트 트리거링: 생성된 파일 input 요소에 대해
click()이벤트를 강제로 호출하여 네이티브 파일 선택 창을 활성화합니다. - 상태 동기화: 사용자가 파일을 선택(change 이벤트)하면, 해당 Grid 행(Row)의 상태를 갱신하여 파일 첨부 여부를 시각적으로 피드백합니다.
3. 데이터 유형별 이원화된 처리 흐름
이 하이브리드 패턴의 핵심은 파일 데이터와 일반 텍스트 데이터를 분리하여 처리하는 이원화된 파이프라인에 있습니다. 로직의 분기 과정을 시각적으로 이해하면 다음과 같습니다.
dataSubmit 함수는 데이터의 성격에 따라 다음과 같이 분기 처리됩니다.
- 파일이 포함된 경우: jQuery의
ajaxForm플러그인을 호출하여 비동기 멀티파트 업로드를 수행합니다. - 파일이 없는 경우: 표준
$.ajaxPOST 요청을 통해 메타 데이터만 가볍게 전송합니다.
동시에 우측의 Form Panel은 Ext JS 표준 방식인 form.submit() 메서드를 유지하여 텍스트 데이터를 별도로 저장합니다. 즉, jQuery 기반의 파일 처리와 Ext JS 기반의 데이터 관리가 충돌 없이 공존하는 구조입니다.
4. 레거시 환경에서의 기술 통합 전략
본 예제는 프레임워크의 한계를 외부 라이브러리와의 전략적 통합으로 해결한 실용적인 케이스 스터디입니다.
최신 모던 웹 프레임워크에서는 더 간결한 해결책이 존재할 수 있으나, 대규모 레거시 시스템 유지보수나 Ext JS 기반의 엔터프라이즈 환경에서 복잡한 파일 처리가 요구될 때 jQuery ajaxForm과의 통합 패턴은 여전히 강력하고 유효한 솔루션을 제공합니다.
5. [부록] 실전 구현 코드 예제
설명된 로직을 실제 프로젝트에 적용할 수 있는 핵심 코드 스니펫입니다. Ext JS의 renderer와 jQuery의 동적 폼 제어가 어떻게 상호작용하는지 확인해보세요.
// 1. Ext JS Grid Column 설정 (Renderer 활용)
{
text: '첨부파일',
dataIndex: 'fileName',
width: 120,
renderer: function(value, meta, record) {
var id = record.get('id');
// 버튼 클릭 시 createDataForm 호출 (Grid Row ID 전달)
return '<button type="button" onclick="createDataForm(\'' + id + '\')">파일선택</button> ' +
(value ? value : '');
}
}
// 2. 동적 폼 생성 및 파일 선택기 실행 (jQuery)
function createDataForm(rowId) {
// 기존에 생성된 임시 폼 제거 (초기화)
$('#tempUploadForm').remove();
// 동적으로 Form 및 Input 생성
var $form = $('<form id="tempUploadForm" method="POST" enctype="multipart/form-data"></form>');
var $fileInput = $('<input type="file" name="uploadFile" style="display:none;">');
// Form을 Body에 추가
$form.append($fileInput);
$('body').append($form);
// 파일 선택 시 이벤트: Grid에 파일명 즉시 반영 (UX 향상)
$fileInput.on('change', function() {
var fileName = $(this).val().split('\\').pop(); // 경로 제거
// Ext JS Store 접근하여 레코드 업데이트
var store = Ext.getCmp('mainGrid').getStore();
var record = store.findRecord('id', rowId);
if(record) {
record.set('fileName', fileName); // 화면 갱신
record.set('isDirty', true); // 수정 상태 플래그
}
});
// 강제로 파일 선택창 오픈
$fileInput.click();
}
// 3. 최종 전송 로직 (분기 처리)
function dataSubmit() {
var $form = $('#tempUploadForm');
var hasFile = $form.find('input[type="file"]').val() != '';
if (hasFile) {
// [Case A] 파일이 있는 경우: jQuery ajaxForm 사용 (Multipart)
$form.ajaxSubmit({
url: '/api/board/upload',
type: 'POST',
dataType: 'json',
success: function(response) {
Ext.Msg.alert('성공', '파일 업로드가 완료되었습니다.');
// 이후 로직: Ext Grid Reload 등
}
});
} else {
// [Case B] 파일이 없는 경우: 일반 Ajax 요청
Ext.Ajax.request({
url: '/api/board/update',
method: 'POST',
params: { /* ... */ },
success: function(response) {
Ext.Msg.alert('성공', '텍스트 데이터가 저장되었습니다.');
}
});
}
}
💡 Tip: ajaxSubmit을 사용하기 위해서는 jquery.form.js 플러그인이 페이지에 로드되어 있어야 합니다. 이 패턴은 Grid 내에서 직접 파일 첨부를 구현할 때 매우 유용합니다.
댓글
댓글 쓰기