🚀 프로젝트 개요
엑셀 파일 업로드와 Google Sheets 연동을 하나의 웹앱에서 처리하는 자동화 도구를 만들고 있다.
목표는 단순하다:
“엑셀을 업로드하면 자동으로 정리되고, 필요하면 구글 시트까지 연결되는 시스템”
🧱 기술 스택
Frontend
- Vue 3 (Composition API)
- Vite
- TailwindCSS
- SheetJS (xlsx 처리)
Backend (예정)
- Express
- Google Sheets API
- TypeScript
1️⃣ 엑셀 파일 업로드 및 파싱 (FileReader + SheetJS)
브라우저에서 엑셀 파일을 직접 읽고 JSON으로 변환하는 구조를 사용했다.
핵심 흐름은 다음과 같다:
File → ArrayBuffer → SheetJS → JSON Array
구현 구조
const handleFile = (e) => {
const file = e.target.files[0]
const reader = new FileReader()
reader.readAsArrayBuffer(file)
reader.onload = (e) => {
const workbook = XLSX.read(e.target.result)
const sheetName = workbook.SheetNames[0]
rows.value = XLSX.utils.sheet_to_json(
workbook.Sheets[sheetName]
)
}
}
💡 핵심 포인트
- FileReader는 비동기이기 때문에 onload 안에서 처리해야 한다
- SheetJS는 첫 번째 시트를 기본으로 처리하면 대부분 충분하다
- sheet_to_json()이 자동으로 객체 배열을 만들어준다
2️⃣ 데이터 처리 파이프라인 설계 (processData)
엑셀 데이터는 단순 출력이 아니라 “가공된 결과”가 필요하다.
그래서 아래 3단계 파이프라인을 설계했다:
raw data → dedup → filter → sort → processed data
🔹 1. 중복 제거
JSON 기반 비교 방식:
result = result.filter((row, i, arr) => {
return (
arr.findIndex(
r => JSON.stringify(r) === JSON.stringify(row)
) === i
)
})
👉 같은 객체 구조를 가진 행 제거
🔹 2. 필터 처리
if (filterCol.value && filterVal.value) {
result = result.filter(row =>
String(row[filterCol.value]).includes(filterVal.value)
)
}
👉 특정 컬럼 기준 검색 필터
🔹 3. 정렬
if (sortCol.value) {
result = result.sort((a, b) => {
return String(a[sortCol.value])
.localeCompare(String(b[sortCol.value]))
})
}
👉 문자열 기준 정렬 (한글/영문 모두 대응)
💡 설계 핵심
- raw data와 processed data를 분리
- UI는 processed만 바라보도록 설계
- 데이터 흐름을 단방향으로 유지
3️⃣ Excel 다운로드 기능 (SheetJS writeFile)
가공된 데이터를 다시 엑셀 파일로 저장하는 기능이다.
SheetJS는 읽기/쓰기 구조가 완전히 대칭이다:
sheet_to_json ↔ json_to_sheet
🔹 다운로드 로직
const downloadFile = () => {
const ws = XLSX.utils.json_to_sheet(processed.value)
const wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
XLSX.writeFile(wb, 'result.xlsx', {
compression: true
})
}
💡 핵심 포인트
- JSON 배열 → 엑셀 시트 자동 변환
- 첫 번째 객체의 key가 자동으로 헤더가 된다
- writeFile은 내부적으로 Blob을 생성해 다운로드를 트리거한다
4️⃣ 백엔드 설계 방향 (Express + Google Sheets API)
프론트에서 엑셀 처리를 끝낸 후, 다음 단계는 Google Sheets 연동이다.
📦 서버 역할
Express 서버는 단순하지만 중요한 역할을 한다:
1. API Key 보호
- Google Service Account 키를 서버에만 저장
2. 데이터 중간 처리
- 프론트 ↔ Google Sheets 사이 Proxy 역할
📌 API 구조 설계
GET /api/sheets/:id → 시트 읽기
POST /api/sheets/write → 시트 쓰기
🔐 Google Sheets API (서비스 계정 방식)
const auth = new google.auth.JWT({
email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
key: process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n'),
scopes: ['https://www.googleapis.com/auth/spreadsheets']
})
📌 데이터 변환 구조
const [headers, ...rows] = response.data.values
const formatted = rows.map(row =>
Object.fromEntries(
headers.map((h, i) => [h, row[i] ?? ''])
)
)
💡 핵심 포인트
- Google Sheets는 2D 배열 구조
- 첫 행 = header
- 나머지 = 데이터
- Object.fromEntries로 JSON 변환
📌 전체 구조 요약
[Vue 3]
↓
Excel Upload → SheetJS → JSON
↓
Process Pipeline (dedup → filter → sort)
↓
Processed Data
↓
Download (xlsx)
AND
[Express]
↓
Google Sheets API
↓
Read / Write Spreadsheet
🧠 오늘 배운 핵심
- FileReader는 반드시 onload에서 처리해야 한다
- SheetJS는 read/write 구조가 대칭이다
- 데이터 처리는 반드시 raw / processed 분리해야 한다
- JSON 기반 dedup은 교육용, 실무는 key 기반
- Express는 단순 API proxy 역할로 시작하는 게 좋다
🚀 서비스 링크
- 📊 구글시트 / 엑셀 자동화 웹사이트
→ https://excel-sheets-web.vercel.app/
client
excel-sheets-web.vercel.app