AI로 카드 명세서 지출 분석 가계부 만들기

AI로 카드 명세서 지출 분석 가계부 만들기

AI로 카드 명세서 지출 분석 가계부 만들기

매번 복잡하게 분류하던 신용카드 명세서를 텍스트 복사 한 번으로 정리해 봅시다

오늘 만들 것
매번 복잡하게 분류하던 신용카드 명세서를 텍스트 복사 한 번으로 정리해 봅시다

한 달 동안 내가 어디에 돈을 많이 썼는지 파악하는 일은 자산 관리의 첫걸음입니다. 하지만 은행이나 카드사 앱에 들어가 일일이 확인하고 카테고리별로 계산하는 과정은 생각보다 번거롭습니다. 가계부 앱을 설치해도 개인정보 노출이 걱정되거나 광고가 거슬려서, 결국 사용을 미루게 되는 경우도 많습니다.

이번에는 결제 문자나 명세서 텍스트를 쭉 복사해서 붙여넣기만 하면, 내장된 키워드 사전을 통해 식비, 카페, 교통, 쇼핑 같은 항목으로 알아서 분류하고 도넛 그래프로 시각화해 주는 가벼운 로컬 웹앱을 만들어 보겠습니다. 코딩 지식이 전혀 없어도 괜찮습니다. 터미널 기반 AI 비서인 Claude Code에 말 몇 마디만 건네면, 브라우저에서 바로 열어 쓸 수 있는 가계부 화면을 5분 안에 만들 수 있습니다.

텍스트 결제 정보를 카테고리별로 합산하고 시각화하는 원리

텍스트 결제 정보를 카테고리별로 합산하고 시각화하는 원리

이 프로그램은 입력창에 붙여넣은 텍스트를 줄 단위로 나눈 뒤, 사전에 등록된 카테고리별 핵심 단어와 비교해 지출 금액을 자동으로 추출하고 누적합니다. 예를 들어 스타벅스는 카페, 삼겹살은 식비처럼 분류 기준을 미리 정해 두고, 문장 안에서 해당 단어가 보이면 그 카테고리로 금액을 더하는 방식입니다.

금액을 추출할 때는 숫자 사이에 들어가는 콤마를 제거하고, 금액 뒤에 붙는 '원' 표시나 숫자 패턴을 안정적으로 탐지합니다. 분류된 결과는 브라우저 화면에 리스트 형태로 즉시 정렬되고, 차트 라이브러리인 Chart.js를 연결해 비율 그래프를 그립니다. 별도의 백엔드 서버나 외부 데이터베이스를 두지 않고 브라우저 안에서만 작동하므로, 금융 데이터가 외부로 빠질 걱정을 덜 수 있는 구조입니다.

Claude Code를 열고 5분 만에 로컬 가계부 프로젝트 준비하기

Claude Code를 열고 5분 만에 로컬 가계부 프로젝트 준비하기

작업을 시작하려면 먼저 컴퓨터에 프로젝트용 빈 폴더를 만들고 터미널 창을 연 뒤 Claude Code를 실행하면 됩니다.

1
작업 디렉터리를 만들고 개발 비서를 실행하기

명령 프롬프트나 터미널을 실행한 뒤, 다음 명령어를 차례대로 입력해 폴더를 만들고 AI 코딩 비서 세션을 시작합니다.

AI에게 보낸 프롬프트
mkdir ai-expense-tracker
cd ai-expense-tracker
claude

도구가 정상적으로 실행되면 대화창에 원하는 가계부 명세를 한국어로 직접 지시합니다. "결제 문자 텍스트를 붙여넣으면 금액을 추출하고 식비, 카페, 교통, 쇼핑, 기타 카테고리로 분류한 뒤 Chart.js로 도넛 그래프를 그려주는 index.html 파일을 하나 만들어줘. 외부 라이브러리 설치 없이 HTML 파일 하나만 브라우저로 더블클릭해서 실행할 수 있어야 해."라고 요청하면, 비서는 필요한 화면 구조와 자바스크립트 로직이 담긴 소스코드를 바로 생성하기 시작합니다.

단일 HTML 파일로 바로 작동하는 가계부 웹앱 소스코드

브라우저 환경에서 동작하는 가계부 코드입니다. 입력 파싱 논리와 Chart.js 렌더링 코드가 한 파일 안에 깔끔하게 들어 있습니다.

2
index.html 작성하기

AI 비서가 생성할 index.html 파일의 기본 구성입니다. 모던한 다크 톤 테마와 반응형 차트 화면이 들어 있어 시각적으로도 꽤 깔끔합니다.

<!DOCTYPE html>
<html lang='ko'>
<head>
    <meta charset='UTF-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <title>AI 소비 분석 가계부</title>
    <script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #0f172a;
            color: #f8fafc;
            margin: 0;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }
        .container {
            background-color: #1e293b;
            padding: 30px;
            border-radius: 12px;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
            width: 100%;
            max-width: 600px;
        }
        h1 {
            font-size: 24px;
            margin-bottom: 20px;
            text-align: center;
            color: #38bdf8;
        }
        textarea {
            width: 100%;
            height: 150px;
            background-color: #0f172a;
            color: #f8fafc;
            border: 1px solid #475569;
            border-radius: 8px;
            padding: 12px;
            font-size: 14px;
            resize: none;
            box-sizing: border-box;
            margin-bottom: 15px;
        }
        button {
            width: 100%;
            padding: 12px;
            background-color: #38bdf8;
            color: #0f172a;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            font-weight: bold;
            cursor: pointer;
            transition: background-color 0.2s;
        }
        button:hover {
            background-color: #0ea5e9;
        }
        .result-section {
            margin-top: 25px;
            display: none;
        }
        .chart-container {
            position: relative;
            margin: auto;
            height: 250px;
            width: 250px;
            margin-bottom: 20px;
        }
        .summary-list {
            list-style: none;
            padding: 0;
            margin: 0;
        }
        .summary-item {
            display: flex;
            justify-content: space-between;
            padding: 8px 0;
            border-bottom: 1px solid #334155;
        }
        .total-amount {
            font-size: 18px;
            font-weight: bold;
            color: #f43f5e;
            text-align: right;
            margin-top: 15px;
        }
    </style>
</head>
<body>
    <div class='container'>
        <h1>AI 소비 분석 가계부</h1>
        <textarea id='rawInput' placeholder='여기에 카드 결제 문자나 명세서 텍스트를 복사해서 붙여넣으세요.

예시:
[Web발신] 신한카드 승인 Chul* 12,500원 일시불 06/18 스타벅스
KB국민 승인 24,000원 06/18 맛찬들소금구이'></textarea>
        <button >5초 만에 지출 분석하기</button>

        <div class='result-section' id='resultSection'>
            <div class='chart-container'>
                <canvas id='spendingChart'></canvas>
            </div>
            <ul class='summary-list' id='summaryList'></ul>
            <div class='total-amount' id='totalAmount'></div>
        </div>
    </div>

    <script>
        let chartInstance = null;

        function analyzeSpending() {
            const rawText = document.getElementById('rawInput').value;
            if (!rawText.trim()) {
                alert('텍스트를 입력해주세요.');
                return;
            }

            const lines = rawText.split('\n');
            const categories = {
                '식비': 0,
                '카페/디저트': 0,
                '교통/차량': 0,
                '쇼핑/생활': 0,
                '기타': 0
            };

            const keywords = {
                '식비': ['식당', '갈비', '삼겹살', '국밥', '짜장면', '피자', '치킨', '버거', '분식', '마트', '한식', '일식', '중식', '양식'],
                '카페/디저트': ['스타벅스', '스벅', '투썸', '메가커피', '이디야', '카페', '커피', '디저트', '베이커리', '빵'],
                '교통/차량': ['택시', '카카오T', '버스', '지하철', '주유', '충전', '코레일', 'KTX'],
                '쇼핑/생활': ['쿠팡', '네이버페이', '올리브영', '다이소', '패션', '무신사', '백화점']
            };

            let total = 0;

            lines.forEach(line => {
                const moneyMatch = line.replace(/,/g, '').match(/(\d+)\s*원/);
                let amount = 0;
                if (moneyMatch) {
                    amount = parseInt(moneyMatch[1]);
                } else {
                    const numbers = line.replace(/,/g, '').match(/\d+/g);
                    if (numbers) {
                        const candidates = numbers.map(Number).filter(n => n > 1000 && n < 10000000);
                        if (candidates.length > 0) {
                            amount = candidates[0];
                        }
                    }
                }

                if (amount > 0) {
                    total += amount;
                    let matchedCategory = '기타';

                    for (const [cat, words] of Object.entries(keywords)) {
                        if (words.some(word => line.includes(word))) {
                            matchedCategory = cat;
                            break;
                        }
                    }

                    categories[matchedCategory] += amount;
                }
            });

            const summaryList = document.getElementById('summaryList');
            summaryList.innerHTML = '';
            
            for (const [cat, amt] of Object.entries(categories)) {
                if (amt > 0) {
                    const li = document.createElement('li');
                    li.className = 'summary-item';
                    li.innerHTML = '<span>' + cat + '</span><span>' + amt.toLocaleString() + '원</span>';
                    summaryList.appendChild(li);
                }
            }

            document.getElementById('totalAmount').innerText = '총 지출: ' + total.toLocaleString() + '원';
            document.getElementById('resultSection').style.display = 'block';

            const ctx = document.getElementById('spendingChart').getContext('2d');
            
            if (chartInstance) {
                chartInstance.destroy();
            }

            const activeCategories = Object.keys(categories).filter(cat => categories[cat] > 0);
            const activeAmounts = activeCategories.map(cat => categories[cat]);

            chartInstance = new Chart(ctx, {
                type: 'doughnut',
                data: {
                    labels: activeCategories,
                    datasets: [{
                        data: activeAmounts,
                        backgroundColor: ['#f43f5e', '#fb923c', '#fbbf24', '#34d399', '#a78bfa'],
                        borderWidth: 0
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: {
                            display: false
                        }
                    }
                }
            });
        }
    </script>
</body>
</html>

생성된 코드는 index.html로 저장하면 되고, 브라우저를 열면 바로 동작합니다. 이어서 AI 비서에게 지출 분류 규칙을 조금 더 다듬어 한층 안정적인 분석기로 확장해 보겠습니다.

CLAUDE.md를 활용해 분류 기준과 디자인 제약 조건을 고정하기

결제 양식이 더 복잡해지거나 디자인 수정을 반복할 때는, AI 비서가 이미 구현한 레이아웃과 핵심 로직을 함부로 바꾸지 않도록 기준 규칙을 문서로 남겨 두는 편이 안전합니다. 프로젝트 루트 경로에 CLAUDE.md 파일을 두면 이런 제약을 일관되게 유지하기가 편합니다.

3
CLAUDE.md 파일로 파싱 규칙과 테마 가이드 고정하기

작업 공간 안에 아래의 제약 요건을 적어 둔 마크다운 규칙 설정서를 배치합니다.

AI에게 보낸 프롬프트
# Expense Tracker Rules
- 디자인 테마는 현대적인 다크 블루 모드(#0f172a, #1e293b)를 유지할 것.
- 텍스트 파싱 시 한글 금액 표기(예: 1만 2천원)와 쉼표 표기를 안정적으로 처리할 것.
- 로컬 브라우저 구동 전용이므로 외부 API 요청이나 서버 의존 로직은 절대 추가하지 말 것.
- 실행 및 프리뷰 방법: 브라우저로 index.html 파일 실행

이렇게 기준을 적어 두면 나중에 다른 금융 양식을 추가해 달라고 하거나 스타일을 다시 손보게 할 때도, 가벼운 무설치 구조와 전체 톤을 해치지 않으면서 코드를 이어서 다듬기 좋습니다.

더블클릭 실행과 실제 명세 텍스트 테스트

소스 코드와 규칙 문서의 준비가 끝났습니다. 이제 로컬 환경에서 더블클릭으로 화면을 열고, 실제 텍스트 데이터를 넣어 분석 결과를 확인해 보겠습니다.

4
로컬에서 index.html 파일 실행하고 검수하기

윈도우 탐색기나 파인더에서 프로젝트 폴더를 연 뒤, index.html 파일을 웹 브라우저(크롬, 엣지 등)로 더블클릭해 실행합니다.

AI에게 보낸 프롬프트
explorer . (윈도우) 또는 open . (맥)
index.html 더블클릭

깔끔한 다크 블루 톤의 입력 화면이 보이면, 평소 휴대폰으로 전송되는 신용카드 승인 SMS나 결제 알림 텍스트를 통째로 긁어 입력창에 붙여 넣습니다. 이후 '5초 만에 지출 분석하기' 버튼을 누르면 화면 아래에 Chart.js 도넛 그래프가 표시되고, 카테고리별 누적액과 총지출 규모가 한눈에 정리됩니다.

수동으로 엑셀에 한 줄씩 옮겨 적고 숫자를 더하면서 차트를 만들던 번거로움은 이제 줄어듭니다. 가볍고 민감한 정보가 안전한 로컬용 원페이지 가계부를 활용하면, 말 한마디로 소비 요약 대시보드를 띄우는 흐름을 직접 체감할 수 있습니다.

관련 검색어

  • 🔍 AI 가계부 사용법
  • 🔍 AI 가계부 비교
  • 🔍 지출 분석 사용법
  • 🔍 지출 분석 비교
  • 🔍 Claude Code 사용법
  • 🔍 Claude Code 비교

댓글 쓰기

다음 이전