코딩으로 만드는 실용적인 가계부: 구조와 스타터 코드
가계부를 코딩으로 만든다는 건 단순히 수입·지출을 기록하는 것을 넘어서 자동화, 시각화, 카테고리 분석, 반복 패턴 관리까지 할 수 있는 “맞춤형 개인 재무 관리 도구”를 만드는 일입니다.
사용자에게 편리하고 효율적인 가계부를 설계할 때는 📌 다음 4가지 관점에서 접근하면 가장 실용적이고 확장성 있는 구조를 만들 수 있습니다:
✅ 1. 입력 방식: “간단하고 직관적이어야 한다”
💡 추천: 폼(Form) 방식 + 날짜 자동 입력
<form>
<input type="date" value="{오늘날짜}" />
<input type="text" placeholder="항목명 (예: 커피)" />
<input type="number" placeholder="금액" />
<select>
<option>식비</option>
<option>교통</option>
<option>쇼핑</option>
</select>
<button>추가</button>
</form>
- 사용자는 클릭 몇 번, 입력 몇 자로 바로 기록 가능
- 모바일에서도 터치 몇 번이면 끝
✅ 2. 저장 방식: “반복 사용이 쉬워야 한다”
💡 추천: LocalStorage 또는 Google Sheets API
방식 | 장점 | 단점 |
---|---|---|
LocalStorage | 빠름, 설치 없이 작동 | 브라우저에만 저장됨 |
Google Sheets API | 백업 가능, 어디서든 접근 | 인증 필요, 초기 설정 다소 복잡 |
✨ 단기 → LocalStorage / 장기 or 공유용 → Google Sheets 연동
✅ 3. 기능 구성: 최소한으로 시작해서 점진적으로 확장
🎯 필수 기능 먼저 만들기
- 수입/지출 입력
- 날짜 필터
- 카테고리 필터
- 총합 계산
🔄 그 다음 추가할 수 있는 기능
- 월간 차트 시각화 (Chart.js or ApexCharts)
- 자동 예산 설정 (예: 식비 30만 원 초과 시 알림)
- 자주 쓰는 항목 자동 완성
- 월말 리포트 PDF 저장
✅ 4. UI/UX: 사용자는 '기록보다 확인'이 중요
🧭 가계부 설계 시 고려할 UX 포인트
- 최근 내역을 항상 위에 보여주기
- 누적 지출/남은 예산을 한눈에 보기
- 터치 한 번으로 지출 수정 또는 삭제
- 날짜별, 카테고리별 정렬 기능
예:오늘 쓴 지출이 자동으로 가장 상단에 표시
“이번 달 식비: 253,000원 / 예산: 300,000원 (잔여: 47,000원)” 실시간 표시
✅ 코딩 기술 추천
목적 | 기술 |
---|---|
빠른 개발 | React + useState / Vue |
모바일 최적화 | PWA (앱처럼 설치 가능) |
시각화 | Chart.js, D3.js |
백엔드 저장 | Firebase, Supabase, Airtable |
로그인 | Firebase Auth, Google OAuth |
✅ 예시 구성 흐름
- ✍️ 수입/지출 입력
- 💾 LocalStorage에 자동 저장
- 📅 날짜별 필터링
- 📊 총합 계산 및 시각화
- 📁 CSV 또는 PDF로 내보내기
✅ 차트 포함 가계부 HTML + JS 전체 코드
이 코드를 .html 파일로 저장한 후 브라우저에서 실행하면 차트와 함께 작동하는 슬기로운 가계부 앱을 바로 사용할 수 있습니다.
📄 HTML 전체 코드
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>📒 차트 가계부</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body { font-family: sans-serif; background: #f4f4f4; padding: 20px; }
.container { max-width: 800px; margin: auto; background: white; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }
input, select, button { padding: 8px; margin: 5px 0; width: 100%; box-sizing: border-box; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #ccc; padding: 8px; text-align: center; }
th { background: #f0f0f0; }
canvas { max-width: 100%; margin-top: 30px; }
.total { margin-top: 15px; font-weight: bold; }
</style>
</head>
<body>
<div class="container">
<h1>📒 슬기로운 가계부 + 차트</h1>
<form id="expense-form">
<input type="date" id="date" required />
<input type="text" id="item" placeholder="항목 (예: 커피)" required />
<input type="number" id="amount" placeholder="금액 (원)" required />
<select id="category">
<option value="식비">식비</option>
<option value="교통">교통</option>
<option value="쇼핑">쇼핑</option>
<option value="기타">기타</option>
</select>
<button type="submit">추가하기</button>
</form>
<div class="total">총 지출: <span id="total">0</span>원</div>
<table>
<thead>
<tr>
<th>날짜</th>
<th>항목</th>
<th>금액</th>
<th>카테고리</th>
<th>삭제</th>
</tr>
</thead>
<tbody id="expense-list"></tbody>
</table>
<canvas id="chart" height="100"></canvas>
</div>
<script>
const form = document.getElementById('expense-form');
const list = document.getElementById('expense-list');
const totalSpan = document.getElementById('total');
const chartCanvas = document.getElementById('chart');
let pieChart;
const getData = () => JSON.parse(localStorage.getItem('expenses')) || [];
const saveData = (data) => localStorage.setItem('expenses', JSON.stringify(data));
const render = () => {
const expenses = getData();
list.innerHTML = '';
let total = 0;
const categoryMap = {};
expenses.forEach((e, i) => {
total += Number(e.amount);
categoryMap[e.category] = (categoryMap[e.category] || 0) + Number(e.amount);
const row = document.createElement('tr');
row.innerHTML = `
<td>${e.date}</td>
<td>${e.item}</td>
<td>${Number(e.amount).toLocaleString()}</td>
<td>${e.category}</td>
<td><button onclick="removeExpense(${i})">❌</button></td>
`;
list.appendChild(row);
});
totalSpan.textContent = total.toLocaleString();
updateChart(categoryMap);
};
const removeExpense = (index) => {
const data = getData();
data.splice(index, 1);
saveData(data);
render();
};
form.addEventListener('submit', (e) => {
e.preventDefault();
const date = document.getElementById('date').value;
const item = document.getElementById('item').value;
const amount = document.getElementById('amount').value;
const category = document.getElementById('category').value;
const newExpense = { date, item, amount: parseInt(amount), category };
const data = getData();
data.unshift(newExpense);
saveData(data);
form.reset();
render();
});
const updateChart = (data) => {
const labels = Object.keys(data);
const values = Object.values(data);
const colors = ['#FF6384', '#36A2EB', '#FFCE56', '#8e44ad'];
if (pieChart) pieChart.destroy();
pieChart = new Chart(chartCanvas, {
type: 'pie',
data: {
labels,
datasets: [{
data: values,
backgroundColor: colors
}]
},
options: {
responsive: true,
plugins: {
legend: { position: 'bottom' }
}
}
});
};
document.getElementById('date').valueAsDate = new Date();
render();
</script>
</body>
</html>
✅ 주요 기능 요약
기능 | 설명 |
---|---|
✅ 지출 기록 | 날짜, 항목, 금액, 카테고리 입력 |
✅ LocalStorage 저장 | 자동 저장 및 삭제 가능 |
✅ 총합 계산 | 총 지출을 실시간으로 계산 |
✅ 카테고리별 차트 | Chart.js 기반 실시간 원형 그래프 표시 |
✅ 삭제 반영 | 항목 삭제 시 차트 자동 반영 |
✅ 사용 방법
- 위 코드를 복사해
.html
파일로 저장 - 브라우저(크롬 등)로 열면 바로 작동
- 데이터는 브라우저에 자동 저장되어 새로고침해도 유지됨
✨ 다음 단계 확장 아이디어
- 📈 월별 지출 분석 (Bar Chart)
- 🧾 PDF 리포트 저장 기능
- 🧠 예산 초과 시 시각적 경고 메시지
- ☁️ Firebase 연동으로 멀티 디바이스 공유
✨ 결론: “작지만 똑똑한 가계부 코딩”을 목표로 하세요
- 복잡한 기능보다 입력과 확인이 쉬운 구조
- 매일 기록하고 싶은 디자인으로 설계
- 단 1개의 JS 파일, 1개의 HTML 페이지로도 충분히 시작 가능
- 내 상황에 맞게 나만의 분석과 예산 관리, 알림 기능을 확장