엑셀·CSV 업로드 운영 툴이 필요할 때
엑셀·CSV 데이터를 API로 업로드하고 미리보기까지 구현하는 방법. 서버 언어와 상관없이, UI는 셀렉트 어드민이 자동으로 구성합니다.
엑셀이나 CSV 파일로 받은 데이터를 빠르게 업로드하고 저장하는 기능.
운영툴을 만들다 보면 한 번은 꼭 필요해집니다.
이번 글에서는 셀렉트 어드민(Select Admin)으로
엑셀·CSV 업로드 → 변환 → 저장 → 미리보기까지 구현하는 방법을 소개합니다.
서버 언어는 상관없습니다.
Node.js, Python, Java 등 어떤 환경이든 API만 제공하면,
셀렉트 어드민이 UI를 자동으로 구성합니다.
왜 필요한 기능인가요?
운영팀은 종종 엑셀이나 CSV 데이터를 받아 임시로 시스템에 반입해야 합니다.
예를 들어 다음과 같은 경우입니다.
- 재고 데이터를 엑셀로 받아 업로드해야 할 때
- 파트너사에서 전달한 주문 데이터를 검증해야 할 때
- CSV를 JSON 형태로 가공해 내부 API로 전달해야 할 때
이 예제는 그런 상황을 위한 “업로드 → 변환 → 저장 → 미리보기” 흐름 템플릿입니다.
작동 방식 한눈에 보기
- 엑셀 또는 CSV 파일을 업로드
- 지정된 컬럼(예: 상품명, 수량)으로 데이터 변환
- 지정한 API(
/local/import/save-json)로 전송 및 저장 - 업로드된 파일 목록을 테이블로 표시
- 파일명을 클릭하면 상세 데이터를 모달로 미리보기



예제 코드 (셀렉트 어드민 YAML)
아래 YAML을 그대로 붙여넣으면,
파일 업로드 → 저장 → 목록 조회 → 상세 보기까지 자동으로 구성됩니다.
blocks:
# 1) 파일 업로드 & JSON 저장
- type: http
name: 엑셀 업로드 → JSON 저장
method: POST
display: form
params:
- key: sheet
label: 엑셀/CSV 업로드
width: 400px
format: sheet
accept: .csv,.xlsx
preview: true
sheetOptions:
multiple: true
# ✅ 엑셀 시리얼날짜 자동 변환 (YYYY-MM-DD 형태)
convertDate:
- 시작일
- 종료일
fetchFn: |
try {
if (!Array.isArray(sheet) || sheet.length === 0) {
throw new Error('업로드된 시트에 데이터가 없습니다.')
}
const rows = sheet.map(r => ({
name: String(r['상품명'] ?? ''),
unit: Number(r['수량'] ?? 0),
...(r['시작일'] ? { startDate: r['시작일'] } : {}),
...(r['종료일'] ? { endDate: r['종료일'] } : {})
}))
const base = API || 'http://localhost:9500'
const res = await fetch(`${base}/local/import/save-json`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payload: { rows } })
})
if (!res.ok) throw new Error(`HTTP ${res.status}`)
await res.json().catch(() => ({}))
$toast(`저장 완료 (${rows.length}행)`)
return true
} catch (err) {
$toast(String(err?.message || err), { type: 'error' })
return false
}
# 1-1) 업로드 양식 다운로드
- type: http
method: GET
fetchFn: |
return [
{
"id": "",
"상품명": "",
"수량": "",
"시작일": "",
"종료일": ""
}
]
showDownload: false
tableOptions:
hidden: true
actions:
- label: 업로드 양식 다운로드
button:
icon: mdi-download
showDownload: csv xlsx
single: true
# 2) 업로드된 파일 목록
- type: http
name: 업로드 파일 목록
method: GET
display: table
showDownload: false
fetchFn: |
try {
const base = API || 'http://localhost:9500'
const r = await fetch(`${base}/local/import/list`)
if (!r.ok) throw new Error(`HTTP ${r.status}`)
const data = await r.json().catch(() => ({}))
return (data.files || []).map(f => ({
file: f.file,
size: f.size,
mtime: new Date(f.mtime).toISOString()
}))
} catch (err) {
$toast(`파일 목록을 불러오지 못했습니다: ${String(err?.message || err)}`, { type: 'error' })
return []
}
columns:
file:
width: 520px
openModal: file-detail-:file
size:
formatFn: |
(value > 1024*1024)
? (value/1024/1024).toFixed(1) + ' MB'
: (value/1024).toFixed(1) + ' KB'
mtime:
width: 220px
# 3) 파일 상세 보기 모달
modals:
- path: file-detail-:file
width: 800px
title: 파일 내용 보기
blocks:
- type: http
name: 파일 데이터
method: GET
fetchFn: |
try {
const base = API || 'http://localhost:9500'
const url = new URL(`${base}/local/import/read`)
url.searchParams.set('file', file)
const r = await fetch(url)
if (!r.ok) throw new Error(`HTTP ${r.status}`)
const data = await r.json().catch(() => ({}))
return data.rows || []
} catch (err) {
$toast(`파일을 불러오지 못했습니다: ${String(err?.message || err)}`, { type: 'error' })
return []
}
columns:
name: { width: 300px }
unit: { width: 120px }
startDate:
width: 140px
formatFn: date
endDate:
width: 140px
formatFn: date
params:
- key: file
valueFromRow: file
showDownload: csv xlsx

이런 상황에 유용합니다
- 파트너사 데이터를 업로드 후 바로 검증해야 할 때
- 사내에서 CSV → JSON 변환 플로우를 빠르게 구성해야 할 때
- 로컬 API만 있는 환경에서 UI를 즉시 띄워보고 싶을 때
서버 코드도 빠르게 만들고 싶다면
위 YAML을 기반으로 테스트용 서버 코드까지 빠르게 만들고 싶다면,
LLM에게 아래처럼 요청해보세요.
환경:
- Node.js 20
- "type": "module" (ESM)
- Express
요청:
아래 YAML 스펙에 맞는 API 서버 코드를 작성해주세요.
(프론트엔드가 이 YAML을 기반으로 API를 호출합니다)
<여기에 YAML 코드 붙여넣기>마무리하며
이 예제는 엑셀·CSV 데이터를 업로드 → 저장 → 조회 → 미리보기까지
한 번에 연결하는 완결된 흐름을 보여줍니다.
서버는 단지 API만 제공하면 됩니다.
UI 구성은 셀렉트 어드민이 자동으로 처리합니다.
복잡한 설정 없이 바로 복사해 실행해 보세요.
운영툴의 첫 페이지를, 오늘 안에 완성할 수 있습니다.