문서 파일 정리
38
build-apk-for-device.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 안드로이드 폰에 직접 설치할 APK 빌드 스크립트
|
||||
echo "안드로이드 폰용 APK 빌드 시작: $(date)"
|
||||
|
||||
# 프로젝트 디렉토리로 이동
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# 1. 웹 앱 빌드 (이미 했다면 스킵 가능)
|
||||
echo "웹 앱 빌드 중..."
|
||||
npm run build
|
||||
|
||||
# 2. Capacitor에 웹 코드 복사
|
||||
echo "Capacitor에 웹 코드 복사 중..."
|
||||
npx cap copy android
|
||||
|
||||
# 3. 안드로이드 디버그 APK 빌드
|
||||
echo "안드로이드 APK 빌드 중..."
|
||||
cd android
|
||||
./gradlew assembleDebug
|
||||
|
||||
# 4. APK 파일 위치 확인
|
||||
APK_PATH="app/build/outputs/apk/debug/app-debug.apk"
|
||||
if [ -f "$APK_PATH" ]; then
|
||||
echo "APK 빌드 성공!"
|
||||
echo "APK 파일 위치: $(pwd)/$APK_PATH"
|
||||
|
||||
# 홈 디렉토리로 APK 복사
|
||||
cp "$APK_PATH" ~/zellyy-finance-debug.apk
|
||||
echo "APK를 홈 디렉토리에 복사했습니다: ~/zellyy-finance-debug.apk"
|
||||
|
||||
echo "이제 다음 방법으로 안드로이드 폰에 설치할 수 있습니다:"
|
||||
echo "1. USB 케이블로 폰을 연결하고 파일 전송"
|
||||
echo "2. 이메일이나 메신저로 APK 파일 전송"
|
||||
echo "3. adb 명령어 사용: adb install ~/zellyy-finance-debug.apk"
|
||||
else
|
||||
echo "APK 빌드 실패. 오류를 확인하세요."
|
||||
fi
|
||||
105
docs/00_프로젝트_개요/01_프로젝트_소개.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# 적자 탈출 가계부 프로젝트 소개
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
'적자 탈출 가계부'는 사용자들이 개인 재정을 효과적으로 관리하고 적자 상태에서 벗어날 수 있도록 도와주는 모바일 앱입니다. 단순한 수입/지출 기록을 넘어, 사용자의 소비 패턴을 분석하고 맞춤형 절약 전략을 제안하여 재정 건전성을 개선하는 데 중점을 둡니다.
|
||||
|
||||
## 주요 기능
|
||||
|
||||
### 1단계 (기본 기능)
|
||||
- **지출 기록**: 간편한 UI로 일상 재정 활동 기록
|
||||
- **예산 설정**: 카테고리별 월간/주간 예산 설정 및 알림
|
||||
- **지출 분석**: 기본적인 차트와 그래프로 소비 패턴 시각화
|
||||
- **적자 알림**: 예산 초과 시 실시간 알림 제공
|
||||
- **카드 계좌 연동**: 카드 계좌 연동으로 자동 거래 기록
|
||||
|
||||
### 2단계 (고급 기능)
|
||||
- **수입 기록**: 간편한 UI로 수입 활동 기록
|
||||
- **카테고리 관리**: 사용자 정의 카테고리로 지출 분류
|
||||
- **AI 기반 분석**: 소비 패턴 분석 및 맞춤형 절약 제안
|
||||
- **절약 챌린지**: 사용자 맞춤형 절약 목표 설정 및 달성 보상
|
||||
- **재정 건강 점수**: 사용자의 재정 상태를 점수화하여 개선 동기 부여
|
||||
- **자동 분류**: 영수증 스캔 및 자동 카테고리 분류
|
||||
- **금융 계좌 연동**: 은행 및 기타 금융 계좌 연동으로 자동 거래 기록
|
||||
|
||||
## 타겟 사용자
|
||||
|
||||
- **주 타겟**: 20~40대 직장인 및 대학생
|
||||
- **사용자 특성**:
|
||||
- 재정 관리에 어려움을 겪는 사람들
|
||||
- 적자 상태에서 벗어나고 싶은 사람들
|
||||
- 효율적인 저축과 지출 관리를 원하는 사람들
|
||||
- 재정적 자유를 목표로 하는 사람들
|
||||
|
||||
## 비즈니스 모델
|
||||
|
||||
- **기본 앱**: 무료 (기본적인 가계부 기능)
|
||||
- **프리미엄 구독**: 월정액 또는 연간 구독 방식
|
||||
- AI 기반 분석 및 맞춤형 절약 제안
|
||||
- 고급 보고서 및 예측 기능
|
||||
- 다중 기기 동기화
|
||||
- 광고 제거
|
||||
- **파트너십**: 금융 기관 및 핀테크 회사와의 제휴를 통한 추가 수익
|
||||
|
||||
## 차별화 전략
|
||||
|
||||
- **문제 중심 접근**: 단순 기록이 아닌 '적자 탈출'이라는 구체적 문제 해결에 초점
|
||||
- **행동 경제학 활용**: 사용자의 소비 습관 개선을 위한 심리적 기법 적용
|
||||
- **커뮤니티 기능**: 비슷한 재정 목표를 가진 사용자들 간의 정보 공유 및 동기 부여
|
||||
- **실용적 조언**: 이론적 재정 조언이 아닌 실천 가능한 절약 팁 제공
|
||||
|
||||
## 개발 일정
|
||||
|
||||
### 1단계: 기본 기능 개발 (2024년 Q2 ~ Q3)
|
||||
- 기본 UI/UX 설계
|
||||
- 지출 기록 기능 구현
|
||||
- 예산 설정 및 알림 기능 구현
|
||||
- 지출 분석 및 적자 알림 기능 구현
|
||||
- 카드 계좌 연동 API 개발
|
||||
- 베타 테스트 및 피드백 수집
|
||||
- 앱 스토어 출시 (iOS, Android)
|
||||
|
||||
### 2단계: 고급 기능 개발 (2024년 Q4 ~ 2025년 Q1)
|
||||
- 수입 기록 기능 구현
|
||||
- 카테고리 관리 기능 구현
|
||||
- AI 분석 엔진 개발
|
||||
- 절약 챌린지 및 재정 건강 점수 시스템 구현
|
||||
- 영수증 스캔 및 자동 분류 기능 구현
|
||||
- 금융 계좌 연동 API 확장 개발
|
||||
|
||||
## 기술 스택
|
||||
|
||||
### 모바일 앱
|
||||
- **프론트엔드**: React Native
|
||||
- **상태 관리**: Redux
|
||||
- **스타일링**: Styled Components
|
||||
|
||||
### 백엔드
|
||||
- **서버**: Node.js, Express
|
||||
- **데이터베이스**: MongoDB
|
||||
- **AI/ML**: TensorFlow, Python
|
||||
- **클라우드**: AWS 또는 Firebase
|
||||
|
||||
## 성공 지표
|
||||
|
||||
- **사용자 수**: 첫 해 50,000명 이상의 활성 사용자 확보
|
||||
- **구독 전환율**: 무료 사용자의 8% 이상이 유료 구독으로 전환
|
||||
- **사용자 참여**: 사용자당 주 평균 5회 이상 앱 사용
|
||||
- **재정 개선**: 3개월 이상 사용자의 60%가 지출 감소 또는 저축 증가 보고
|
||||
- **사용자 유지율**: 90일 사용자 유지율 35% 이상
|
||||
|
||||
## 리스크 및 대응 전략
|
||||
|
||||
### 리스크
|
||||
1. **경쟁 앱과의 차별화 부족**: 시장에 다양한 가계부 앱이 존재함
|
||||
2. **사용자 데이터 보안**: 민감한 재정 정보 처리에 따른 보안 우려
|
||||
3. **지속적 사용 유도**: 초기 열정 이후 사용 중단 가능성
|
||||
|
||||
### 대응 전략
|
||||
1. **명확한 가치 제안**: '적자 탈출'이라는 구체적 문제 해결에 초점을 맞춘 마케팅
|
||||
2. **최고 수준의 보안**: 은행급 암호화 및 보안 인증 획득
|
||||
3. **습관 형성 기능**: 게이미피케이션 요소와 리마인더를 통한 지속적 사용 유도
|
||||
|
||||
## 결론
|
||||
|
||||
'적자 탈출 가계부'는 단순한 가계부 앱을 넘어, 사용자들이 재정적 어려움에서 벗어나 건강한 재정 상태를 달성할 수 있도록 돕는 종합적인 재정 관리 솔루션을 목표로 합니다. 사용자 중심의 설계와 AI 기술을 활용하여 개인화된 재정 관리 경험을 제공하고, 궁극적으로는 사용자들의 재정적 웰빙을 향상시키는 데 기여하고자 합니다.
|
||||
16
docs/00_프로젝트_개요/index.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 프로젝트 개요
|
||||
|
||||
이 폴더에는 적자 탈출 가계부 프로젝트의 기본 개요와 목표, 사용자 정의에 관한 문서가 포함되어 있습니다.
|
||||
|
||||
## 문서 목록
|
||||
|
||||
- [[적자 탈출 가계부]] - 프로젝트 메인 문서
|
||||
- [[핵심 문제 정의]] - 해결하고자 하는 문제 정의
|
||||
- [[사용자 페르소나]] - 타겟 사용자 프로필
|
||||
- [[사용자 스토리]] - 사용자 관점의 요구사항
|
||||
|
||||
## 프로젝트 요약
|
||||
|
||||
적자 탈출 가계부는 사용자들이 자신의 재정 상태를 효과적으로 관리하고, 적자 상태에서 벗어날 수 있도록 도와주는 개인 재무 관리 애플리케이션입니다.
|
||||
|
||||
이 프로젝트는 사용자 중심의 설계를 통해 직관적인 인터페이스와 실용적인 기능을 제공하여, 재정 관리에 어려움을 겪는 사용자들이 쉽게 자신의 지출을 추적하고 예산을 계획할 수 있도록 합니다.
|
||||
81
docs/00_프로젝트_개요/사용자 스토리.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# 적자 탈출 가계부 - 사용자 스토리
|
||||
|
||||
## 카드 한도 관리
|
||||
|
||||
1. **카드 한도 설정**
|
||||
- "사용자로서 나는 월간 카드 사용 한도를 설정하고 싶다."
|
||||
- "사용자로서 나는 카테고리별 지출 한도를 설정하고 싶다."
|
||||
- "사용자로서 나는 여러 개의 카드를 등록하고 각각 한도를 설정하고 싶다."
|
||||
- "사용자로서 나는 한도 설정 시 내 실제 상환 능력을 고려한 금액을 추천받고 싶다."
|
||||
|
||||
2. **한도 사용 현황 확인**
|
||||
- "사용자로서 나는 현재 카드 사용액과 남은 한도를 실시간으로 확인하고 싶다."
|
||||
- "사용자로서 나는 카테고리별 한도 사용 현황을 시각적으로 확인하고 싶다."
|
||||
- "사용자로서 나는 한도 대비 사용 비율을 직관적으로 이해할 수 있는 그래프로 보고 싶다."
|
||||
- "사용자로서 나는 일/주/월 단위로 한도 사용 추이를 확인하고 싶다."
|
||||
|
||||
3. **한도 알림**
|
||||
- "사용자로서 나는 한도의 특정 비율(예: 70%, 90%)에 도달했을 때 알림을 받고 싶다."
|
||||
- "사용자로서 나는 특정 카테고리의 한도가 초과되었을 때 알림을 받고 싶다."
|
||||
- "사용자로서 나는 일일 지출이 평소보다 많을 때 경고 알림을 받고 싶다."
|
||||
- "사용자로서 나는 결제일 전에 예상 청구액에 대한 알림을 받고 싶다."
|
||||
|
||||
## 카드 사용 내역 관리
|
||||
|
||||
1. **내역 기록**
|
||||
- "사용자로서 나는 카드 사용 내역을 빠르고 쉽게 기록하고 싶다."
|
||||
- "사용자로서 나는 반복적인 지출을 템플릿으로 저장하여 빠르게 입력하고 싶다."
|
||||
- "사용자로서 나는 영수증 사진을 찍어 자동으로 내역을 기록하고 싶다."
|
||||
- "사용자로서 나는 위치 기반으로 자주 가는 가게의 지출 내역을 자동 완성하고 싶다."
|
||||
|
||||
2. **내역 조회 및 분석**
|
||||
- "사용자로서 나는 날짜, 금액, 카테고리별로 내역을 필터링하여 조회하고 싶다."
|
||||
- "사용자로서 나는 특정 기간의 지출 패턴을 분석하고 싶다."
|
||||
- "사용자로서 나는 자주 가는 가게나 자주 사용하는 카테고리를 확인하고 싶다."
|
||||
- "사용자로서 나는 불필요한 지출을 식별하여 절약 가능한 부분을 찾고 싶다."
|
||||
|
||||
3. **내역 수정 및 관리**
|
||||
- "사용자로서 나는 잘못 입력한 내역을 쉽게 수정하거나 삭제하고 싶다."
|
||||
- "사용자로서 나는 내역에 메모나 태그를 추가하여 더 자세히 관리하고 싶다."
|
||||
- "사용자로서 나는 업무용/개인용과 같이 목적별로 내역을 구분하고 싶다."
|
||||
- "사용자로서 나는 내역을 엑셀이나 PDF로 내보내고 싶다."
|
||||
|
||||
## 대시보드 및 분석
|
||||
|
||||
1. **메인 대시보드**
|
||||
- "사용자로서 나는 앱을 열자마자 현재 카드 사용 현황을 한눈에 파악하고 싶다."
|
||||
- "사용자로서 나는 오늘/이번 주/이번 달의 주요 지출을 대시보드에서 확인하고 싶다."
|
||||
- "사용자로서 나는 다가오는 결제일과 예상 청구액을 대시보드에서 확인하고 싶다."
|
||||
- "사용자로서 나는 한도 대비 사용 현황을 시각적으로 표현한 그래프를 보고 싶다."
|
||||
|
||||
2. **지출 분석**
|
||||
- "사용자로서 나는 카테고리별 지출 비율을 파이 차트로 확인하고 싶다."
|
||||
- "사용자로서 나는 시간대별/요일별 지출 패턴을 분석하고 싶다."
|
||||
- "사용자로서 나는 전월 대비 지출 변화를 비교하고 싶다."
|
||||
- "사용자로서 나는 지출이 많은 상위 5개 카테고리를 확인하고 싶다."
|
||||
|
||||
3. **리포트 및 인사이트**
|
||||
- "사용자로서 나는 월말에 지출 요약 리포트를 받고 싶다."
|
||||
- "사용자로서 나는 내 소비 습관에 대한 인사이트를 얻고 싶다."
|
||||
- "사용자로서 나는 절약 가능한 영역에 대한 제안을 받고 싶다."
|
||||
- "사용자로서 나는 재정 목표 달성을 위한 맞춤형 조언을 받고 싶다."
|
||||
|
||||
## 사용자 관리 및 설정
|
||||
|
||||
1. **프로필 관리**
|
||||
- "사용자로서 나는 간편하게 회원가입하고 로그인하고 싶다."
|
||||
- "사용자로서 나는 내 프로필 정보를 안전하게 관리하고 싶다."
|
||||
- "사용자로서 나는 앱의 알림 설정을 내 선호도에 맞게 조정하고 싶다."
|
||||
- "사용자로서 나는 앱의 테마나 화면 레이아웃을 커스터마이징하고 싶다."
|
||||
|
||||
2. **데이터 관리**
|
||||
- "사용자로서 나는 내 데이터를 백업하고 복원할 수 있기를 원한다."
|
||||
- "사용자로서 나는 내 개인정보가 안전하게 보호되기를 원한다."
|
||||
- "사용자로서 나는 필요시 내 모든 데이터를 삭제할 수 있기를 원한다."
|
||||
- "사용자로서 나는 내 데이터를 다른 기기와 동기화하고 싶다."
|
||||
|
||||
3. **다중 사용자 지원**
|
||||
- "사용자로서 나는 가족 구성원을 초대하여 공동 카드 사용 내역을 공유하고 싶다."
|
||||
- "사용자로서 나는 공유된 계정에서 내 개인 지출은 비공개로 유지하고 싶다."
|
||||
- "사용자로서 나는 가족 구성원과 공동 한도를 설정하고 관리하고 싶다."
|
||||
- "사용자로서 나는 가족 구성원과 재정 목표를 공유하고 함께 달성하고 싶다."
|
||||
109
docs/00_프로젝트_개요/사용자 페르소나.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# 적자 탈출 가계부 - 사용자 페르소나
|
||||
|
||||
## 페르소나 1: 직장인 김미영 (32세, 여성)
|
||||
|
||||
### 기본 정보
|
||||
- **직업**: 대기업 사무직 (5년차)
|
||||
- **월 소득**: 350만원
|
||||
- **거주 형태**: 원룸 월세 (보증금 1000만원, 월 60만원)
|
||||
- **가족 구성**: 1인 가구
|
||||
- **금융 상태**: 신용카드 2개, 체크카드 1개, 적금 1개, 대출 없음
|
||||
|
||||
### 소비 패턴
|
||||
- 월 지출: 약 300만원 (소득의 85%)
|
||||
- 주요 지출: 월세(60만원), 식비(80만원), 교통비(15만원), 통신비(10만원), 문화생활(40만원), 쇼핑(50만원), 기타(45만원)
|
||||
- 충동구매 경향이 있으며, 특히 온라인 쇼핑과 배달음식에 지출이 많음
|
||||
- 매달 월급 후반부에는 항상 돈이 부족하다고 느낌
|
||||
|
||||
### 페인 포인트
|
||||
- 매달 저축을 계획하지만 실천하지 못함
|
||||
- 지출 내역을 제대로 파악하지 못해 어디에 돈이 쓰이는지 모름
|
||||
- 여러 카드와 계좌를 사용하여 총 지출 파악이 어려움
|
||||
- 예상치 못한 지출이 생길 때마다 저축액이 줄어듦
|
||||
- 재테크에 관심은 있으나 시작 방법을 모름
|
||||
|
||||
### 목표
|
||||
- 월 50만원 이상 안정적으로 저축하기
|
||||
- 불필요한 지출 줄이기
|
||||
- 재테크를 시작하여 자산 늘리기
|
||||
- 3년 내 1000만원 이상의 비상금 마련하기
|
||||
|
||||
### 앱 사용 행태
|
||||
- 스마트폰 사용 시간: 하루 평균 5시간
|
||||
- 자주 사용하는 앱: 인스타그램, 유튜브, 배달앱, 쇼핑앱
|
||||
- 금융 앱: 은행 앱 2개, 카드사 앱 2개 (주 1회 정도 확인)
|
||||
- 새로운 앱 설치 주기: 월 1-2개
|
||||
|
||||
---
|
||||
|
||||
## 페르소나 2: 신혼부부 이준호 (35세, 남성)
|
||||
|
||||
### 기본 정보
|
||||
- **직업**: IT 회사 개발자 (8년차)
|
||||
- **월 소득**: 부부 합산 650만원 (본인 400만원, 배우자 250만원)
|
||||
- **거주 형태**: 아파트 전세 (3억)
|
||||
- **가족 구성**: 부부 2인 (자녀 계획 중)
|
||||
- **금융 상태**: 신용카드 3개, 체크카드 2개, 적금 2개, 주택담보대출 5000만원
|
||||
|
||||
### 소비 패턴
|
||||
- 월 지출: 약 500만원 (소득의 77%)
|
||||
- 주요 지출: 대출상환(30만원), 식비(120만원), 교통비(30만원), 통신비(15만원), 문화생활(60만원), 쇼핑(80만원), 여행/레저(100만원), 기타(65만원)
|
||||
- 주말 데이트 및 취미 활동에 지출이 많음
|
||||
- 양가 부모님 용돈과 선물 지출이 정기적으로 발생
|
||||
|
||||
### 페인 포인트
|
||||
- 부부 공동 지출과 개인 지출의 구분이 명확하지 않음
|
||||
- 가계부를 작성해도 지속적인 관리가 어려움
|
||||
- 결혼 후 늘어난 지출에 비해 저축은 오히려 줄어듦
|
||||
- 미래 자녀 교육비와 노후 준비에 대한 불안감
|
||||
- 부부간 소비 성향 차이로 인한 갈등 발생
|
||||
|
||||
### 목표
|
||||
- 월 150만원 이상 안정적으로 저축하기
|
||||
- 부부 공동 재무 계획 수립 및 실천
|
||||
- 1년 내 여행 자금 1000만원 마련하기
|
||||
- 5년 내 주택담보대출 완전 상환하기
|
||||
- 자녀 출산 대비 재정 준비
|
||||
|
||||
### 앱 사용 행태
|
||||
- 스마트폰 사용 시간: 하루 평균 3시간
|
||||
- 자주 사용하는 앱: 유튜브, 뉴스 앱, 주식 앱
|
||||
- 금융 앱: 은행 앱 3개, 카드사 앱 3개, 증권사 앱 1개 (주 2-3회 확인)
|
||||
- 새로운 앱 설치 주기: 분기 2-3개
|
||||
|
||||
---
|
||||
|
||||
## 페르소나 3: 대학생 박지훈 (23세, 남성)
|
||||
|
||||
### 기본 정보
|
||||
- **직업**: 대학교 3학년 재학 중 (아르바이트 병행)
|
||||
- **월 소득**: 120만원 (아르바이트 80만원, 용돈 40만원)
|
||||
- **거주 형태**: 대학가 원룸 월세 (보증금 500만원, 월 40만원)
|
||||
- **가족 구성**: 부모님, 동생 1명 (본가는 지방)
|
||||
- **금융 상태**: 체크카드 1개, 적금 1개, 학자금 대출 1000만원
|
||||
|
||||
### 소비 패턴
|
||||
- 월 지출: 약 110만원 (소득의 92%)
|
||||
- 주요 지출: 월세(40만원), 식비(30만원), 교통비(10만원), 통신비(5만원), 문화생활(15만원), 학비 및 교재비(10만원)
|
||||
- 친구들과의 모임과 데이트 비용이 부담됨
|
||||
- 한정된 수입으로 인해 항상 빠듯한 생활
|
||||
|
||||
### 페인 포인트
|
||||
- 아르바이트와 학업 병행으로 재정 관리할 시간 부족
|
||||
- 예상치 못한 지출 발생 시 대처 방법 부재
|
||||
- 용돈과 아르바이트 수입의 불규칙성
|
||||
- 취업 후 학자금 대출 상환에 대한 부담
|
||||
- 저축의 필요성은 알지만 실천이 어려움
|
||||
|
||||
### 목표
|
||||
- 월 10만원 이상 꾸준히 저축하기
|
||||
- 학자금 대출 이자 관리하기
|
||||
- 졸업 후 취업 대비 자금 마련하기
|
||||
- 불필요한 지출 줄이기
|
||||
- 기본적인 재무 관리 습관 형성하기
|
||||
|
||||
### 앱 사용 행태
|
||||
- 스마트폰 사용 시간: 하루 평균 6시간
|
||||
- 자주 사용하는 앱: 인스타그램, 유튜브, 틱톡, 게임 앱
|
||||
- 금융 앱: 은행 앱 1개, 간편결제 앱 2개 (주 1회 정도 확인)
|
||||
- 새로운 앱 설치 주기: 월 3-4개
|
||||
195
docs/00_프로젝트_개요/적자 탈출 가계부.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# 적자 탈출 가계부 앱 프로젝트 계획서
|
||||
|
||||
## 1. 프로젝트 개요
|
||||
|
||||
### 1.1 프로젝트 배경 및 목적
|
||||
많은 사람들이 신용카드를 사용한 후 상환 관리에 어려움을 겪고 있으며, 실시간으로 지출을 파악하지 못해 적자 상황에 빠지는 경우가 많습니다. 이 프로젝트는 사용자들이 실시간으로 자신의 재정 상태를 파악하고 관리할 수 있는 모바일 가계부 앱을 개발하여 적자 상황을 예방하는 것을 목적으로 합니다.
|
||||
|
||||
### 1.2 목표 사용자
|
||||
- 신용카드 사용 후 상환 관리에 어려움을 겪는 사람들
|
||||
- 지출 관리와 예산 계획이 필요한 개인 및 가족
|
||||
- 재정 상태를 실시간으로 파악하고 싶은 사용자
|
||||
- 적자 상황을 예방하고 싶은 사용자
|
||||
|
||||
### 1.3 핵심 가치 제안
|
||||
- 실시간 지출 추적으로 재정 상태 즉시 파악
|
||||
- 예산 설정 및 알림 기능으로 과소비 방지
|
||||
- 직관적인 UI/UX로 쉽고 빠른 지출 기록
|
||||
- 카테고리별 지출 분석으로 소비 패턴 이해
|
||||
- 적자 예방을 위한 맞춤형 알림 및 조언
|
||||
|
||||
## 2. 프로젝트 범위 및 기능
|
||||
|
||||
### 2.1 MVP(Minimum Viable Product) 핵심 기능
|
||||
- **사용자 관리**
|
||||
- 회원가입 및 로그인
|
||||
- 사용자 프로필 관리
|
||||
|
||||
- **신용카드 한도 관리**
|
||||
- 월간 카드 사용 한도 설정
|
||||
- 카드별 한도 설정 (선택적)
|
||||
- 실시간 사용량 추적 및 시각화
|
||||
- 한도 임계치 접근 시 알림 기능
|
||||
|
||||
- **카드 사용 내역 관리**
|
||||
- 카드 사용 내역 수동 입력
|
||||
- 기본적인 카테고리 분류
|
||||
- 내역 조회 및 필터링
|
||||
|
||||
- **대시보드**
|
||||
- 현재 카드 사용액 및 남은 한도 표시
|
||||
- 월간 카드 사용 요약
|
||||
- 카테고리별 사용 비율 차트
|
||||
|
||||
- **기본 분석**
|
||||
- 카테고리별 카드 사용 분석
|
||||
- 주간/월간 사용 추이 그래프
|
||||
|
||||
### 2.2 향후 확장 기능 (MVP 이후)
|
||||
- 다중 카드 관리 및 통합 분석
|
||||
- 카드사 API 연동을 통한 자동 내역 가져오기
|
||||
- 영수증 스캔 및 자동 분류
|
||||
- 예산 관리 및 저축 목표 설정
|
||||
- 가계부 공유 기능
|
||||
- 지출 패턴 기반 맞춤형 조언
|
||||
- **AI 기반 지능형 재정 어시스턴트**
|
||||
- 경량 LLM을 활용한 소비 패턴 분석
|
||||
- 실시간 지출 조언 및 알림
|
||||
- 맞춤형 절약 전략 제안
|
||||
- 재정 목표 달성을 위한 단계별 가이드
|
||||
- 하이브리드 접근(기기 내 경량 모델 + 서버 기반 심층 분석)
|
||||
|
||||
## 3. 기술 스택 및 아키텍처
|
||||
|
||||
### 3.1 모바일 앱
|
||||
- **프레임워크**: Flutter (iOS/Android 크로스 플랫폼)
|
||||
- **상태 관리**: Provider 또는 Riverpod
|
||||
- **로컬 데이터베이스**: Hive 또는 SQLite
|
||||
- **UI 컴포넌트**: Flutter Material Design
|
||||
|
||||
### 3.2 백엔드 (자체 서버 + Supabase)
|
||||
- **데이터베이스**: PostgreSQL (Supabase 내장)
|
||||
- **인증 시스템**: Supabase Auth
|
||||
- **API**: Supabase 자동 생성 API
|
||||
- **배포 환경**: 자체 서버에 Docker로 Supabase 설치
|
||||
|
||||
### 3.3 데이터 모델
|
||||
- **사용자(users)**: id, email, password, name, created_at
|
||||
- **카드(card)**: id, user_id, card_number, expiration_date, limit, created_at
|
||||
- **카드 사용 내역(card_transactions)**: id, card_id, amount, date, category_id, memo, created_at
|
||||
- **카테고리(categories)**: id, name, icon, color
|
||||
|
||||
## 4. 개발 일정 및 마일스톤
|
||||
|
||||
### 4.1 1단계: 기획 및 설계 (1주)
|
||||
- MVP 범위 정의 및 요구사항 명세
|
||||
- 데이터 모델 및 API 설계
|
||||
- UI/UX 와이어프레임 작성
|
||||
- 기술 스택 최종 결정
|
||||
|
||||
### 4.2 2단계: 백엔드 구축 (1주)
|
||||
- Supabase 자체 서버 설치 및 설정
|
||||
- 데이터베이스 스키마 설정
|
||||
- API 엔드포인트 구성
|
||||
- 인증 시스템 설정
|
||||
|
||||
### 4.3 3단계: 모바일 앱 개발 (2주)
|
||||
- 핵심 UI 컴포넌트 개발
|
||||
- 사용자 인증 기능 구현
|
||||
- 카드 한도 관리 및 사용 내역 관리 기능 구현
|
||||
- 대시보드 및 기본 분석 기능 구현
|
||||
|
||||
### 4.4 4단계: 테스트 및 출시 준비 (1주)
|
||||
- 내부 테스트 및 버그 수정
|
||||
- 성능 최적화
|
||||
- 앱 스토어 등록 준비
|
||||
- 출시 자료 준비
|
||||
|
||||
### 4.5 총 개발 기간: 약 4주
|
||||
- **1주차**: 기획 완료 및 백엔드 구축
|
||||
- **2주차**: 핵심 UI 개발 및 기본 기능 구현
|
||||
- **3주차**: 앱-서버 연동 및 추가 기능 구현
|
||||
- **4주차**: 테스트, 버그 수정 및 출시 준비
|
||||
|
||||
## 5. 역할 분담
|
||||
|
||||
### 5.1 제품 기획 및 테스트 담당 (사용자)
|
||||
- 앱 컨셉 및 요구사항 정의
|
||||
- UI/UX 디자인 검토 및 피드백
|
||||
- 사용자 테스트 케이스 작성
|
||||
- 테스트 진행 및 피드백 제공
|
||||
- 출시 자료 준비
|
||||
|
||||
### 5.2 기술 개발 담당 (AI 어시스턴트)
|
||||
- 기술 스택 선정 및 아키텍처 설계
|
||||
- 백엔드 개발 (Supabase 설정)
|
||||
- 모바일 앱 개발 (Flutter)
|
||||
- 데이터베이스 설계 및 구현
|
||||
- 버그 수정 및 성능 최적화
|
||||
|
||||
## 6. 출시 전략
|
||||
|
||||
### 6.1 앱 스토어 등록
|
||||
- Google Play 스토어 등록 (Android)
|
||||
- App Store 등록 (iOS, 필요시)
|
||||
- 앱 스토어 최적화 (ASO) 적용
|
||||
|
||||
### 6.2 초기 사용자 확보 전략
|
||||
- 지인 네트워크를 통한 초기 사용자 모집
|
||||
- 재정 관리 관련 커뮤니티 홍보
|
||||
- 소셜 미디어 기본 홍보
|
||||
|
||||
### 6.3 피드백 수집 및 개선
|
||||
- 인앱 피드백 시스템 구축
|
||||
- 사용자 리뷰 모니터링
|
||||
- 주요 피드백 기반 빠른 업데이트
|
||||
|
||||
## 7. MVP 이후 로드맵
|
||||
|
||||
### 7.1 단기 업데이트 (출시 후 1-2개월)
|
||||
- 사용자 피드백 기반 UI/UX 개선
|
||||
- 성능 최적화
|
||||
- 기본 버그 수정
|
||||
|
||||
### 7.2 중기 업데이트 (출시 후 3-6개월)
|
||||
- 다중 카드 관리 및 통합 분석
|
||||
- 카드사 API 연동을 통한 자동 내역 가져오기
|
||||
- 고급 분석 대시보드 추가
|
||||
|
||||
### 7.3 장기 업데이트 (출시 후 6개월 이상)
|
||||
- 가계부 공유 기능
|
||||
- 영수증 스캔 및 자동 분류
|
||||
- AI 기반 지출 예측 및 조언 기능
|
||||
|
||||
## 8. 리스크 관리
|
||||
|
||||
### 8.1 기술적 리스크
|
||||
- Supabase 자체 호스팅 안정성 이슈
|
||||
- 모바일 기기 호환성 문제
|
||||
- 데이터 동기화 충돌
|
||||
|
||||
### 8.2 대응 전략
|
||||
- 정기적인 백업 시스템 구축
|
||||
- 다양한 기기에서의 테스트 강화
|
||||
- 오프라인 모드 및 충돌 해결 로직 구현
|
||||
|
||||
## 9. 성공 지표 및 평가
|
||||
|
||||
### 9.1 주요 성공 지표
|
||||
- 사용자 등록 수
|
||||
- 일일 활성 사용자 수 (DAU)
|
||||
- 카드 사용 내역 기록 빈도
|
||||
- 사용자 유지율
|
||||
- 앱 스토어 평점
|
||||
|
||||
### 9.2 목표 수치 (출시 후 3개월)
|
||||
- 사용자 등록: 500명 이상
|
||||
- 일일 활성 사용자: 100명 이상
|
||||
- 사용자 유지율: 40% 이상 (30일 기준)
|
||||
- 앱 스토어 평점: 4.0 이상
|
||||
|
||||
## 10. 결론
|
||||
|
||||
본 프로젝트는 사용자들이 신용카드 사용 후 적자 상황에 빠지는 것을 방지하기 위한 실용적인 가계부 앱을 개발하는 것을 목표로 합니다. MVP 방식으로 약 4주 동안 핵심 기능을 개발하여 빠르게 출시한 후, 사용자 피드백을 바탕으로 지속적으로 개선해 나갈 계획입니다. 자체 서버에 Supabase를 설치하여 비용 효율적으로 백엔드를 구축하고, Flutter를 활용하여 iOS와 Android 플랫폼 모두를 지원하는 앱을 개발할 것입니다.
|
||||
|
||||
이 프로젝트를 통해 사용자들이 자신의 재정 상태를 실시간으로 파악하고 관리할 수 있게 되어, 적자 상황을 예방하고 건강한 재정 습관을 형성하는 데 도움이 될 것으로 기대합니다.
|
||||
52
docs/00_프로젝트_개요/핵심 문제 정의.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# 적자 탈출 가계부 - 핵심 문제 정의
|
||||
|
||||
## 적자 발생 원인 분석
|
||||
|
||||
### 1. 신용카드 사용 관련 문제점
|
||||
- **한도 인식 부재**: 사용자들이 자신의 실제 지불 능력을 초과하는 금액을 신용카드로 사용
|
||||
- **실시간 추적 어려움**: 여러 카드 사용 시 총 사용액을 실시간으로 파악하기 어려움
|
||||
- **충동 구매**: 현금 지출과 달리 신용카드는 심리적 장벽이 낮아 충동 구매 증가
|
||||
- **카드 청구서 충격**: 월말에 예상보다 큰 금액의 청구서를 받아 재정 계획 붕괴
|
||||
- **연체 및 이자 부담**: 상환 능력을 초과한 지출로 인한 연체 및 추가 이자 발생
|
||||
|
||||
### 2. 기존 가계부/금융 앱의 한계
|
||||
- **복잡한 UI/UX**: 너무 많은 기능으로 인해 사용이 복잡하고 지속적 사용이 어려움
|
||||
- **실시간성 부족**: 대부분의 앱이 과거 지출 기록에 초점, 미래 지출 계획 및 관리 부족
|
||||
- **카드 특화 기능 부재**: 일반적인 지출 관리는 있으나 카드 한도 관리 기능 부족
|
||||
- **수동 입력 부담**: 모든 지출을 수동으로 입력해야 하는 부담
|
||||
- **예방적 기능 부족**: 적자 발생 전에 예방할 수 있는 알림 및 조언 기능 부족
|
||||
|
||||
## MVP 접근 방식: 신용카드 관리 중심
|
||||
|
||||
### 문제 해결 전략
|
||||
1. **단순화된 접근**: 모든 재정 관리가 아닌 신용카드 사용 한도 관리에 초점
|
||||
2. **예방적 접근**: 적자가 발생한 후 분석이 아닌, 발생 전에 예방하는 기능 중심
|
||||
3. **행동 변화 유도**: 사용자의 카드 사용 습관을 변화시키는 데 중점
|
||||
|
||||
### MVP 핵심 기능 선정 이유
|
||||
1. **월간 카드 사용 한도 설정**
|
||||
- 사용자가 자신의 실제 상환 능력에 맞는 한도를 설정하도록 유도
|
||||
- 심리적으로 지출 한계를 명확히 인식하게 함
|
||||
|
||||
2. **실시간 사용량 추적**
|
||||
- 현재 사용액과 남은 한도를 시각적으로 표시하여 인지 강화
|
||||
- 남은 한도에 따라 지출 결정을 내릴 수 있도록 지원
|
||||
|
||||
3. **알림 기능**
|
||||
- 한도에 가까워지면 사전에 경고하여 추가 지출 억제
|
||||
- 중요한 시점(월초, 급여일, 결제일 등)에 알림으로 인식 강화
|
||||
|
||||
4. **간단한 카드 사용 내역 기록**
|
||||
- 최소한의 입력으로 카드 사용 내역 기록
|
||||
- 사용자의 지속적인 앱 사용을 유도하기 위한 단순한 UI/UX
|
||||
|
||||
5. **기본적인 카테고리 분류**
|
||||
- 지출 패턴을 파악할 수 있는 최소한의 분류 제공
|
||||
- 향후 맞춤형 조언을 위한 기초 데이터 확보
|
||||
|
||||
### 기대 효과
|
||||
- 사용자의 신용카드 사용 습관 개선
|
||||
- 예상치 못한 과다 청구 방지
|
||||
- 적자 상황 예방 및 재정 건전성 향상
|
||||
- 사용자 만족도 향상으로 인한 지속적 사용
|
||||
- 초기 사용자 피드백을 통한 향후 기능 개선 방향 설정
|
||||
167
docs/01_기획_및_설계/01_요구사항_분석.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# 적자 탈출 가계부 요구사항 분석
|
||||
|
||||
## 사용자 요구사항
|
||||
|
||||
### 핵심 사용자 니즈
|
||||
1. **지출 추적의 용이성**
|
||||
- 일상적인 지출을 쉽고 빠르게 기록할 수 있어야 함
|
||||
- 반복적인 지출은 자동 기록 옵션 필요
|
||||
- 영수증 스캔 또는 사진 촬영으로 지출 정보 자동 입력
|
||||
|
||||
2. **재정 상태 가시화**
|
||||
- 현재 재정 상태를 한눈에 파악할 수 있는 대시보드
|
||||
- 수입 대비 지출 비율을 명확히 표시
|
||||
- 카테고리별 지출 분포를 시각적으로 표현
|
||||
|
||||
3. **적자 원인 분석**
|
||||
- 과도한 지출이 발생하는 카테고리 식별
|
||||
- 예상치 못한 지출 패턴 감지 및 알림
|
||||
- 월별/주별 지출 추세 분석
|
||||
|
||||
4. **절약 가이드**
|
||||
- 개인 소비 패턴에 기반한 맞춤형 절약 제안
|
||||
- 카테고리별 적정 지출 가이드라인 제공
|
||||
- 실천 가능한 구체적 절약 팁 제공
|
||||
|
||||
5. **목표 설정 및 추적**
|
||||
- 저축, 부채 상환 등 재정 목표 설정 기능
|
||||
- 목표 달성 진행 상황 시각화
|
||||
- 목표 달성 시 보상 시스템
|
||||
|
||||
## 기능적 요구사항
|
||||
|
||||
### 1. 사용자 계정 관리
|
||||
- 회원가입 및 로그인 (이메일, 소셜 로그인)
|
||||
- 프로필 설정 및 관리
|
||||
- 다중 기기 동기화
|
||||
- 데이터 백업 및 복원
|
||||
|
||||
### 2. 수입/지출 관리
|
||||
- 수입 및 지출 항목 추가, 편집, 삭제
|
||||
- 정기적인 수입/지출 자동 등록
|
||||
- 카테고리 및 태그 관리
|
||||
- 영수증 스캔 및 자동 정보 추출
|
||||
- 지출 증빙 사진 첨부
|
||||
|
||||
### 3. 예산 관리
|
||||
- 월간/주간 총 예산 설정
|
||||
- 카테고리별 예산 할당
|
||||
- 예산 대비 실제 지출 추적
|
||||
- 예산 초과 시 알림
|
||||
|
||||
### 4. 분석 및 보고서
|
||||
- 기간별 수입/지출 요약
|
||||
- 카테고리별 지출 분석
|
||||
- 지출 패턴 및 추세 분석
|
||||
- 맞춤형 재정 건강 보고서
|
||||
- 절약 가능 영역 식별
|
||||
|
||||
### 5. 절약 도구
|
||||
- AI 기반 맞춤형 절약 제안
|
||||
- 절약 챌린지 생성 및 참여
|
||||
- 절약 팁 라이브러리
|
||||
- 유사 사용자 대비 지출 비교
|
||||
|
||||
### 6. 알림 및 리마인더
|
||||
- 예산 임계치 알림
|
||||
- 정기 지출 리마인더
|
||||
- 재정 목표 진행 상황 알림
|
||||
- 주간/월간 재정 요약 알림
|
||||
|
||||
### 7. 금융 계좌 연동
|
||||
- 은행 계좌 연동
|
||||
- 신용카드 거래 자동 가져오기
|
||||
- 계좌 잔액 실시간 확인
|
||||
- 자산 및 부채 통합 관리
|
||||
|
||||
## 비기능적 요구사항
|
||||
|
||||
### 1. 사용성
|
||||
- 직관적이고 사용하기 쉬운 UI/UX
|
||||
- 최소한의 클릭으로 주요 기능 접근
|
||||
- 초보자도 쉽게 사용할 수 있는 온보딩 경험
|
||||
- 다양한 화면 크기 및 기기 지원
|
||||
|
||||
### 2. 성능
|
||||
- 빠른 앱 로딩 및 반응 시간
|
||||
- 대용량 데이터 처리 시에도 안정적 성능
|
||||
- 오프라인 모드 지원
|
||||
- 배터리 소모 최적화
|
||||
|
||||
### 3. 보안 및 개인정보
|
||||
- 은행급 보안 표준 준수
|
||||
- 개인 재정 데이터 암호화
|
||||
- 생체 인식 로그인 옵션
|
||||
- 개인정보 보호 정책 준수
|
||||
|
||||
### 4. 확장성
|
||||
- 사용자 증가에 따른 시스템 확장성
|
||||
- 새로운 기능 추가를 위한 모듈식 아키텍처
|
||||
- 다양한 금융 API와의 통합 가능성
|
||||
- 다국어 및 다중 통화 지원
|
||||
|
||||
### 5. 신뢰성
|
||||
- 99.9% 이상의 서비스 가용성
|
||||
- 데이터 손실 방지를 위한 자동 백업
|
||||
- 오류 발생 시 자동 복구 메커니즘
|
||||
- 정확한 재정 계산 및 분석
|
||||
|
||||
## 사용자 페르소나
|
||||
|
||||
### 페르소나 1: 신입 직장인 김지현 (27세)
|
||||
- **상황**: 첫 직장 2년차, 독립 생활 시작, 월급의 대부분을 생활비와 여가 활동에 소비
|
||||
- **문제점**: 매달 적자 상태, 저축 부족, 지출 관리 어려움
|
||||
- **목표**: 월급의 20%를 저축하고 불필요한 지출 줄이기
|
||||
- **니즈**: 쉬운 지출 추적, 과소비 영역 식별, 실용적인 절약 팁
|
||||
|
||||
### 페르소나 2: 맞벌이 부부 박서준, 이미나 (35세, 33세)
|
||||
- **상황**: 결혼 3년차, 아파트 대출 상환 중, 자녀 계획 중
|
||||
- **문제점**: 각자의 지출 관리 불일치, 공동 재정 계획 부재
|
||||
- **목표**: 대출 조기 상환 및 자녀 교육비 마련
|
||||
- **니즈**: 공유 가계부, 장기 재정 계획, 가족 예산 관리
|
||||
|
||||
### 페르소나 3: 대학생 이준호 (22세)
|
||||
- **상황**: 대학 3학년, 아르바이트로 생활비 충당, 학자금 대출 있음
|
||||
- **문제점**: 불규칙한 수입, 충동적 소비, 재정 지식 부족
|
||||
- **목표**: 학자금 대출 관리 및 졸업 후 취업 준비 자금 마련
|
||||
- **니즈**: 불규칙한 수입 관리, 기본적인 재정 교육, 저비용 생활 팁
|
||||
|
||||
## 경쟁 분석
|
||||
|
||||
### 주요 경쟁 앱 분석
|
||||
1. **뱅크샐러드**
|
||||
- 강점: 계좌 연동, 자산 관리, 신용 점수
|
||||
- 약점: 절약 가이드 부족, 복잡한 UI
|
||||
|
||||
2. **토스**
|
||||
- 강점: 간편한 UI, 송금 기능, 계좌 연동
|
||||
- 약점: 가계부 기능 제한적, 지출 분석 부족
|
||||
|
||||
3. **머니 매니저**
|
||||
- 강점: 상세한 지출 분석, 다양한 보고서
|
||||
- 약점: 복잡한 설정, 초보자 진입장벽
|
||||
|
||||
4. **캐시워크**
|
||||
- 강점: 리워드 시스템, 게이미피케이션
|
||||
- 약점: 실질적 재정 관리 기능 부족
|
||||
|
||||
### 차별화 포인트
|
||||
1. **적자 탈출 특화**: 단순 기록이 아닌 적자 상태 개선에 초점
|
||||
2. **AI 기반 맞춤형 조언**: 개인 소비 패턴에 기반한 실질적 절약 제안
|
||||
3. **행동 경제학 활용**: 심리적 접근을 통한 소비 습관 개선
|
||||
4. **커뮤니티 기반 동기부여**: 비슷한 목표를 가진 사용자들과의 상호작용
|
||||
|
||||
## 결론 및 우선순위
|
||||
|
||||
### 핵심 기능 우선순위
|
||||
1. 직관적인 수입/지출 기록 시스템
|
||||
2. 명확한 재정 상태 시각화 대시보드
|
||||
3. 카테고리별 예산 설정 및 알림
|
||||
4. 기본적인 지출 분석 및 보고서
|
||||
5. 맞춤형 절약 제안 시스템
|
||||
|
||||
### 개발 접근 방식
|
||||
- MVP(Minimum Viable Product) 접근으로 핵심 기능 우선 개발
|
||||
- 사용자 피드백 기반의 반복적 개선
|
||||
- 데이터 기반 의사결정을 통한 기능 우선순위 조정
|
||||
- 사용자 경험을 최우선으로 하는 설계 철학 유지
|
||||
345
docs/01_기획_및_설계/02_UI_UX_설계.md
Normal file
@@ -0,0 +1,345 @@
|
||||
# 적자 탈출 가계부 UI/UX 설계
|
||||
|
||||
## 디자인 철학
|
||||
|
||||
'적자 탈출 가계부'의 UI/UX 설계는 다음과 같은 핵심 원칙을 기반으로 합니다:
|
||||
|
||||
1. **단순성**: 복잡한 재정 관리를 단순하고 직관적인 인터페이스로 제공
|
||||
2. **접근성**: 재정 지식 수준에 관계없이 누구나 쉽게 사용할 수 있는 설계
|
||||
3. **동기부여**: 사용자의 재정 개선을 위한 지속적인 동기부여 요소 포함
|
||||
4. **개인화**: 사용자의 상황과 목표에 맞춘 개인화된 경험 제공
|
||||
5. **신뢰성**: 재정 데이터의 정확성과 보안을 시각적으로 전달
|
||||
|
||||
## 브랜드 아이덴티티
|
||||
|
||||
### 색상 팔레트
|
||||
|
||||
#### 주요 색상
|
||||
- **주 색상(Primary)**: #4CAF50 (녹색) - 재정적 성장과 안정을 상징
|
||||
- **보조 색상(Secondary)**: #2196F3 (파란색) - 신뢰성과 안정감을 표현
|
||||
- **강조 색상(Accent)**: #FF9800 (주황색) - 주의와 행동 촉구를 위한 색상
|
||||
|
||||
#### 기능적 색상
|
||||
- **긍정/성공**: #4CAF50 (녹색) - 예산 내 지출, 목표 달성 등
|
||||
- **주의/경고**: #FF9800 (주황색) - 예산 임계치 접근, 주의 필요 항목
|
||||
- **부정/위험**: #F44336 (빨간색) - 예산 초과, 적자 상태 등
|
||||
- **중립/정보**: #2196F3 (파란색) - 일반 정보, 팁 등
|
||||
|
||||
#### 배경 색상
|
||||
- **기본 배경**: #FFFFFF (흰색)
|
||||
- **보조 배경**: #F5F5F5 (연한 회색)
|
||||
- **카드 배경**: #FFFFFF (흰색)
|
||||
- **다크 모드 기본 배경**: #121212 (어두운 회색)
|
||||
|
||||
### 타이포그래피
|
||||
|
||||
#### 폰트 패밀리
|
||||
- **기본 폰트**: Noto Sans KR - 가독성이 높고 한글 지원이 우수한 폰트
|
||||
- **숫자 폰트**: Roboto - 숫자 표시에 최적화된 폰트
|
||||
|
||||
#### 폰트 크기
|
||||
- **헤더 1**: 24sp - 화면 제목
|
||||
- **헤더 2**: 20sp - 섹션 제목
|
||||
- **헤더 3**: 18sp - 서브 섹션 제목
|
||||
- **본문 텍스트**: 16sp - 일반 텍스트
|
||||
- **보조 텍스트**: 14sp - 부가 정보
|
||||
- **작은 텍스트**: 12sp - 레이블, 힌트
|
||||
|
||||
#### 폰트 스타일
|
||||
- **굵기**: Regular(400), Medium(500), Bold(700)
|
||||
- **강조**: 중요 금액이나 비율은 Bold 처리
|
||||
- **색상 대비**: 텍스트와 배경 간 충분한 대비 확보 (WCAG 2.1 AA 기준 준수)
|
||||
|
||||
### 아이콘 및 이미지
|
||||
|
||||
#### 아이콘 스타일
|
||||
- **라인 아이콘**: 주요 네비게이션 및 기능에 사용
|
||||
- **필 아이콘**: 활성 상태 및 강조 표시에 사용
|
||||
- **일관된 스타일**: Material Design 아이콘 세트 기반
|
||||
|
||||
#### 이미지 가이드라인
|
||||
- **일러스트레이션**: 미니멀하고 친근한 스타일의 일러스트레이션
|
||||
- **온보딩 이미지**: 각 핵심 기능을 시각적으로 설명하는 이미지
|
||||
- **성취 배지**: 재정 목표 달성 시 제공되는 시각적 보상
|
||||
|
||||
## 화면 구조
|
||||
|
||||
### 주요 화면 흐름
|
||||
|
||||
```
|
||||
1. 온보딩/로그인 → 2. 홈 대시보드 → 3. 상세 기능
|
||||
↑ ↓
|
||||
└───────────────────┘
|
||||
```
|
||||
|
||||
### 네비게이션 구조
|
||||
|
||||
```
|
||||
[바텀 네비게이션]
|
||||
홈 - 거래내역 - 예산 - 분석 - 더보기
|
||||
|
||||
[더보기 메뉴]
|
||||
- 프로필 설정
|
||||
- 카테고리 관리
|
||||
- 알림 설정
|
||||
- 절약 챌린지
|
||||
- 도움말/FAQ
|
||||
- 설정
|
||||
```
|
||||
|
||||
## 주요 화면 설계
|
||||
|
||||
### 1. 온보딩 및 로그인
|
||||
|
||||
#### 온보딩 화면
|
||||
- **목적**: 앱의 핵심 가치와 주요 기능 소개
|
||||
- **구성**:
|
||||
- 4-5개의 슬라이드로 핵심 기능 소개
|
||||
- 각 슬라이드는 일러스트레이션, 제목, 간단한 설명으로 구성
|
||||
- 마지막 슬라이드에 시작하기 버튼
|
||||
- **인터랙션**:
|
||||
- 스와이프로 슬라이드 전환
|
||||
- 건너뛰기 옵션 제공
|
||||
|
||||
#### 로그인/회원가입 화면
|
||||
- **목적**: 사용자 인증 및 계정 생성
|
||||
- **구성**:
|
||||
- 이메일/비밀번호 로그인
|
||||
- 소셜 로그인 옵션 (카카오, 네이버, 구글)
|
||||
- 회원가입 링크
|
||||
- 비밀번호 찾기 링크
|
||||
- **보안 요소**:
|
||||
- 생체인식 로그인 옵션
|
||||
- 자동 로그인 설정
|
||||
|
||||
### 2. 홈 대시보드
|
||||
|
||||
#### 대시보드 화면
|
||||
- **목적**: 재정 상태 한눈에 파악 및 주요 기능 접근
|
||||
- **구성**:
|
||||
- 이번 달 예산 대비 지출 현황 (프로그레스 바)
|
||||
- 오늘/이번 주 지출 요약
|
||||
- 주요 카테고리별 지출 현황 (미니 차트)
|
||||
- 최근 거래내역 (최대 3개)
|
||||
- 맞춤형 절약 팁 또는 알림
|
||||
- **인터랙션**:
|
||||
- 카드 탭으로 상세 화면 이동
|
||||
- 당겨서 새로고침
|
||||
- 빠른 지출/수입 추가 버튼 (FAB)
|
||||
|
||||
#### 재정 건강 점수 카드
|
||||
- **목적**: 사용자의 재정 상태를 점수화하여 동기 부여
|
||||
- **구성**:
|
||||
- 종합 점수 (0-100점)
|
||||
- 주요 평가 영역별 미니 점수 (예산 관리, 저축, 부채 관리)
|
||||
- 전월 대비 변화 표시
|
||||
- 개선 가능 영역 하이라이트
|
||||
- **인터랙션**:
|
||||
- 탭하여 상세 분석 및 개선 방법 확인
|
||||
|
||||
### 3. 거래 관리
|
||||
|
||||
#### 거래 목록 화면
|
||||
- **목적**: 모든 수입/지출 내역 조회 및 관리
|
||||
- **구성**:
|
||||
- 기간 필터 (일/주/월/연/커스텀)
|
||||
- 카테고리/태그 필터
|
||||
- 거래 목록 (날짜별 그룹핑)
|
||||
- 각 거래 항목에 금액, 카테고리, 메모 표시
|
||||
- **인터랙션**:
|
||||
- 스와이프로 수정/삭제
|
||||
- 길게 누르기로 다중 선택
|
||||
- 스크롤 시 날짜 헤더 고정
|
||||
|
||||
#### 거래 추가/편집 화면
|
||||
- **목적**: 새 거래 추가 또는 기존 거래 편집
|
||||
- **구성**:
|
||||
- 수입/지출/이체 탭
|
||||
- 금액 입력 (계산기 스타일)
|
||||
- 날짜 선택
|
||||
- 카테고리 선택 (자주 사용하는 카테고리 상단 표시)
|
||||
- 메모 입력
|
||||
- 반복 거래 설정 옵션
|
||||
- 사진/영수증 첨부 옵션
|
||||
- **편의 기능**:
|
||||
- 최근 사용 카테고리 빠른 접근
|
||||
- 자동 완성 제안
|
||||
- 영수증 스캔 버튼
|
||||
|
||||
### 4. 예산 관리
|
||||
|
||||
#### 예산 개요 화면
|
||||
- **목적**: 전체 및 카테고리별 예산 현황 파악
|
||||
- **구성**:
|
||||
- 월간 총 예산 대비 지출 현황
|
||||
- 카테고리별 예산 카드 (프로그레스 바 포함)
|
||||
- 위험/초과 카테고리 하이라이트
|
||||
- 남은 기간 대비 잔여 예산 분석
|
||||
- **인터랙션**:
|
||||
- 카테고리 카드 탭하여 상세 내역 확인
|
||||
- 예산 편집 버튼
|
||||
|
||||
#### 예산 설정 화면
|
||||
- **목적**: 총 예산 및 카테고리별 예산 설정
|
||||
- **구성**:
|
||||
- 월간 총 수입 입력
|
||||
- 권장 예산 배분 제안
|
||||
- 카테고리별 예산 금액 설정
|
||||
- 예산 기간 설정 (월간/주간)
|
||||
- **스마트 기능**:
|
||||
- 과거 지출 패턴 기반 예산 제안
|
||||
- 적자 위험 알림
|
||||
- 카테고리 간 예산 조정 제안
|
||||
|
||||
### 5. 분석 및 인사이트
|
||||
|
||||
#### 지출 분석 화면
|
||||
- **목적**: 소비 패턴 분석 및 인사이트 제공
|
||||
- **구성**:
|
||||
- 기간별 지출 추이 그래프
|
||||
- 카테고리별 지출 비중 파이/도넛 차트
|
||||
- 전월 대비 변화 분석
|
||||
- 주요 지출처 Top 5
|
||||
- **인터랙션**:
|
||||
- 차트 요소 탭하여 상세 정보 확인
|
||||
- 기간 변경 옵션
|
||||
- 분석 유형 전환 (금액/비율)
|
||||
|
||||
#### 절약 인사이트 화면
|
||||
- **목적**: AI 기반 맞춤형 절약 제안 제공
|
||||
- **구성**:
|
||||
- 주요 절약 가능 영역 카드
|
||||
- 각 제안별 예상 절약 금액
|
||||
- 실천 방법 및 팁
|
||||
- 유사 사용자 대비 지출 비교
|
||||
- **인터랙션**:
|
||||
- 제안 카드 탭하여 상세 정보 확인
|
||||
- 제안 저장 또는 챌린지로 전환 옵션
|
||||
- 피드백 제공 (유용함/유용하지 않음)
|
||||
|
||||
### 6. 절약 챌린지
|
||||
|
||||
#### 챌린지 목록 화면
|
||||
- **목적**: 사용자 참여 가능한 절약 챌린지 제공
|
||||
- **구성**:
|
||||
- 추천 챌린지 카드
|
||||
- 진행 중인 챌린지 진행 상황
|
||||
- 완료한 챌린지 히스토리
|
||||
- 인기 챌린지 랭킹
|
||||
- **인터랙션**:
|
||||
- 챌린지 카드 탭하여 상세 정보 확인
|
||||
- 참여하기 버튼
|
||||
- 진행 상황 업데이트
|
||||
|
||||
#### 챌린지 상세 화면
|
||||
- **목적**: 특정 챌린지의 상세 정보 및 진행 상황 제공
|
||||
- **구성**:
|
||||
- 챌린지 설명 및 목표
|
||||
- 예상 절약 금액
|
||||
- 진행 기간 및 단계
|
||||
- 현재 진행 상황
|
||||
- 참여자 수 및 성공률
|
||||
- **동기부여 요소**:
|
||||
- 진행 상황 시각화
|
||||
- 달성 시 보상 안내
|
||||
- 참여자 익명 후기
|
||||
|
||||
## 주요 인터랙션 패턴
|
||||
|
||||
### 데이터 입력 패턴
|
||||
- **빠른 입력**: 최소한의 탭으로 기본 정보 입력
|
||||
- **단계적 상세화**: 필요에 따라 추가 정보 입력
|
||||
- **자동 제안**: 과거 패턴 기반 자동 완성 제안
|
||||
- **기본값 활용**: 자주 사용하는 값 기본 설정
|
||||
|
||||
### 피드백 패턴
|
||||
- **시각적 피드백**: 상태 변화를 색상과 애니메이션으로 표현
|
||||
- **촉각적 피드백**: 주요 액션 시 햅틱 피드백 제공
|
||||
- **토스트 메시지**: 작업 완료 또는 오류 시 간결한 알림
|
||||
- **진행 상태 표시**: 로딩 중 상태를 명확히 표시
|
||||
|
||||
### 내비게이션 패턴
|
||||
- **바텀 네비게이션**: 주요 섹션 간 빠른 이동
|
||||
- **제스처 기반**: 스와이프, 핀치 등 직관적 제스처 활용
|
||||
- **계층적 구조**: 명확한 뒤로가기 경로 제공
|
||||
- **컨텍스트 유지**: 화면 전환 시 사용자 컨텍스트 유지
|
||||
|
||||
## 접근성 고려사항
|
||||
|
||||
### 시각적 접근성
|
||||
- **충분한 대비**: 텍스트와 배경 간 WCAG 2.1 AA 기준 준수
|
||||
- **확대 가능**: 텍스트 크기 조정 지원
|
||||
- **색상 독립적**: 색맹/색약자를 위한 대체 표시 방법 제공
|
||||
- **다크 모드**: 시스템 설정에 따른 다크 모드 지원
|
||||
|
||||
### 조작 접근성
|
||||
- **충분한 터치 영역**: 최소 44x44dp의 터치 영역 확보
|
||||
- **키보드 접근성**: 외부 키보드 사용 지원
|
||||
- **음성 지원**: 스크린 리더 호환성 확보
|
||||
- **한 손 조작**: 주요 기능 한 손으로 접근 가능하도록 설계
|
||||
|
||||
## 반응형 설계
|
||||
|
||||
### 다양한 화면 크기 및 플랫폼 지원
|
||||
- **반응형 디자인**: 모든 화면 크기에 맞게 자동 조정되는 레이아웃
|
||||
- **모바일 최적화**: 다양한 스마트폰 화면 크기 대응
|
||||
- **태블릿 레이아웃**: 큰 화면에서의 공간 활용 최적화
|
||||
- **데스크톱 뷰**: 웹 브라우저와 데스크톱 앱에서의 확장된 레이아웃
|
||||
- **방향 대응**: 세로/가로 모드 전환 지원
|
||||
- **PWA 지원**: 홈 화면 설치 및 오프라인 기능 제공
|
||||
|
||||
### 적응형 콘텐츠
|
||||
- **우선순위 기반**: 화면 크기에 따라 중요 콘텐츠 우선 표시
|
||||
- **레이아웃 조정**: 화면 크기에 따른 그리드 시스템 조정
|
||||
- **요소 크기 조정**: 터치 영역 및 가독성 유지
|
||||
|
||||
## 프로토타입 및 테스트
|
||||
|
||||
### 프로토타입 계획
|
||||
- **로우 피델리티**: 주요 화면 흐름 및 구조 검증용 와이어프레임
|
||||
- **미디엄 피델리티**: 주요 인터랙션 및 사용성 테스트용 프로토타입
|
||||
- **하이 피델리티**: 시각적 디자인 및 세부 인터랙션 검증용 프로토타입
|
||||
|
||||
### 사용성 테스트 계획
|
||||
- **태스크 기반 테스트**: 주요 사용 시나리오 기반 테스트
|
||||
- **A/B 테스트**: 주요 디자인 결정사항에 대한 비교 테스트
|
||||
- **히트맵 분석**: 사용자 터치 패턴 분석
|
||||
- **사용자 인터뷰**: 정성적 피드백 수집
|
||||
|
||||
## 구현 가이드라인
|
||||
|
||||
### 컴포넌트 시스템
|
||||
- **아토믹 디자인**: 재사용 가능한 UI 컴포넌트 체계 구축
|
||||
- **스타일 가이드**: 일관된 디자인 적용을 위한 가이드라인
|
||||
- **컴포넌트 라이브러리**: Lovable UI 컴포넌트 라이브러리 구축
|
||||
- **뉴모피즘 스타일**: 입체적이고 부드러운 UI 디자인 적용
|
||||
- **Tailwind CSS**: 효율적인 스타일링 및 반응형 디자인 구현
|
||||
|
||||
### 애니메이션 및 전환
|
||||
- **목적성 애니메이션**: 사용자 이해를 돕는 의미 있는 애니메이션
|
||||
- **자연스러운 전환**: 화면 간 부드러운 전환 효과
|
||||
- **CSS 트랜지션**: 웹 표준 기술을 활용한 효율적인 애니메이션 구현
|
||||
- **성능 최적화**: 60fps 유지를 위한 최적화
|
||||
- **하드웨어 가속**: 웹 브라우저의 GPU 가속 활용
|
||||
|
||||
## 구현 기술 스택
|
||||
|
||||
### 프론트엔드 기술
|
||||
- **React**: 컴포넌트 기반 UI 개발
|
||||
- **Vite**: 빠른 개발 및 빌드 환경 제공
|
||||
- **Tailwind CSS**: 효율적인 스타일링 및 반응형 디자인
|
||||
- **Capacitor**: 네이티브 기능 접근 및 앱 패키징
|
||||
- **D3.js/Chart.js**: 데이터 시각화 및 차트 구현
|
||||
|
||||
### 테스트 도구
|
||||
- **Jest**: 단위 테스트 및 컴포넌트 테스트
|
||||
- **Cypress**: E2E 테스트 및 사용자 시나리오 검증
|
||||
- **Lighthouse**: 웹 성능 및 접근성 테스트
|
||||
|
||||
## 결론
|
||||
|
||||
'적자 탈출 가계부'의 UI/UX 설계는 사용자가 재정 관리를 쉽고 효과적으로 할 수 있도록 직관적이고 동기부여적인 경험을 제공하는 데 중점을 두고 있습니다. 단순한 데이터 기록을 넘어, 사용자의 재정 상태 개선을 위한 인사이트와 행동 변화를 유도하는 요소들을 통합하였습니다.
|
||||
|
||||
웹 기반 기술과 Capacitor를 활용하여 다양한 플랫폼에서 일관된 사용자 경험을 제공하면서도, 뉴모피즘 스타일의 Lovable UI 컴포넌트를 통해 차별화된 디자인을 구현합니다. 이러한 접근은 개발 효율성을 높이고 유지보수를 용이하게 하면서도 사용자에게 매력적인 인터페이스를 제공합니다.
|
||||
|
||||
이 설계는 초기 MVP 출시 후 사용자 피드백과 사용 패턴 분석을 통해 지속적으로 개선될 예정입니다. 특히 사용자의 지속적인 앱 사용과 재정 습관 개선을 위한 요소들을 강화해 나갈 계획입니다.
|
||||
127
docs/01_기획_및_설계/MVP_기능_목록.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# 적자 탈출 가계부 - MVP 기능 목록
|
||||
|
||||
이 문서는 적자 탈출 가계부 앱의 MVP(Minimum Viable Product) 기능 목록을 정의합니다. 우선순위는 MoSCoW 방법론에 따라 분류되었습니다:
|
||||
|
||||
- **Must have**: 반드시 포함되어야 하는 핵심 기능
|
||||
- **Should have**: 중요하지만 MVP 출시에 필수적이지는 않은 기능
|
||||
- **Could have**: 있으면 좋지만 없어도 MVP 가치에 크게 영향을 미치지 않는 기능
|
||||
- **Won't have**: MVP에서는 제외되는 기능 (향후 업데이트에서 고려)
|
||||
|
||||
## 카드 한도 관리
|
||||
|
||||
### Must have
|
||||
- 월간 카드 사용 한도 설정 기능
|
||||
- 현재 카드 사용액과 남은 한도 실시간 표시
|
||||
- 한도 대비 사용 비율을 시각적으로 표현하는 그래프/게이지
|
||||
- 한도의 특정 비율(70%, 90%)에 도달했을 때 알림 기능
|
||||
|
||||
### Should have
|
||||
- 카테고리별 지출 한도 설정 기능
|
||||
- 여러 개의 카드 등록 및 개별 한도 설정
|
||||
- 일/주/월 단위 한도 사용 추이 그래프
|
||||
- 결제일 전 예상 청구액 알림
|
||||
|
||||
### Could have
|
||||
- 한도 설정 시 사용자의 상환 능력 기반 금액 추천
|
||||
- 카테고리별 한도 초과 시 세부 알림 설정
|
||||
- 한도 자동 조정 기능 (과거 사용 패턴 기반)
|
||||
- 한도 초과 시 지출 제한 옵션
|
||||
|
||||
### Won't have (MVP)
|
||||
- 신용카드사 API 연동을 통한 자동 한도 설정
|
||||
- 다중 통화 지원
|
||||
- 신용점수 영향 분석
|
||||
- 카드사 혜택 기반 한도 최적화
|
||||
|
||||
## 카드 사용 내역 관리
|
||||
|
||||
### Must have
|
||||
- 카드 사용 내역 수동 입력 기능
|
||||
- 날짜, 금액, 카테고리 기본 정보 입력
|
||||
- 내역 조회 및 기본 필터링 (날짜, 금액)
|
||||
- 내역 수정 및 삭제 기능
|
||||
|
||||
### Should have
|
||||
- 자주 사용하는 내역 템플릿 저장 및 빠른 입력
|
||||
- 카테고리별 내역 필터링 및 검색
|
||||
- 내역에 메모 추가 기능
|
||||
- 월별 내역 요약 보기
|
||||
|
||||
### Could have
|
||||
- 영수증 사진 촬영을 통한 내역 자동 입력
|
||||
- 위치 기반 자주 가는 가게 자동 완성
|
||||
- 내역 태그 지정 및 태그 기반 필터링
|
||||
- 내역 데이터 내보내기 (CSV/Excel)
|
||||
|
||||
### Won't have (MVP)
|
||||
- 은행/카드사 API 연동을 통한 자동 내역 동기화
|
||||
- 음성 인식을 통한 내역 입력
|
||||
- 영수증 OCR 고급 분석 (품목별 상세 내역)
|
||||
- 업무/개인 지출 자동 분류
|
||||
|
||||
## 대시보드 및 분석
|
||||
|
||||
### Must have
|
||||
- 메인 대시보드에 현재 카드 사용 현황 표시
|
||||
- 이번 달 주요 지출 요약
|
||||
- 카테고리별 지출 비율 기본 차트
|
||||
- 다가오는 결제일 및 예상 청구액 표시
|
||||
|
||||
### Should have
|
||||
- 전월 대비 지출 변화 비교
|
||||
- 지출이 많은 상위 카테고리 표시
|
||||
- 주간/월간 지출 트렌드 그래프
|
||||
- 기본 지출 인사이트 제공
|
||||
|
||||
### Could have
|
||||
- 시간대별/요일별 지출 패턴 분석
|
||||
- 불필요한 지출 식별 및 절약 제안
|
||||
- 맞춤형 월간 지출 리포트
|
||||
- 지출 목표 대비 진행 상황 추적
|
||||
|
||||
### Won't have (MVP)
|
||||
- AI 기반 고급 지출 패턴 분석
|
||||
- 다년간 재정 건전성 예측
|
||||
- 소비 성향 심층 분석
|
||||
- 타 사용자 대비 소비 패턴 비교
|
||||
|
||||
## 사용자 관리 및 설정
|
||||
|
||||
### Must have
|
||||
- 기본 회원가입 및 로그인 기능
|
||||
- 프로필 정보 관리
|
||||
- 기본 알림 설정 (켜기/끄기)
|
||||
- 데이터 백업 및 복원 기능
|
||||
|
||||
### Should have
|
||||
- 소셜 로그인 연동
|
||||
- 알림 세부 설정 (시간, 유형별)
|
||||
- 앱 테마 설정 (라이트/다크 모드)
|
||||
- 데이터 동기화 기능
|
||||
|
||||
### Could have
|
||||
- 생체 인증 로그인 (지문, 얼굴 인식)
|
||||
- 앱 화면 레이아웃 커스터마이징
|
||||
- 다국어 지원
|
||||
- 개인정보 보호 강화 설정
|
||||
|
||||
### Won't have (MVP)
|
||||
- 다중 사용자 지원 (가족 계정)
|
||||
- 공동 카드 관리 기능
|
||||
- 고급 데이터 분석 설정
|
||||
- 타 금융 앱과의 연동
|
||||
|
||||
## 제외 기능 (명확한 정의)
|
||||
|
||||
MVP 단계에서는 다음 기능들을 명확히 제외합니다:
|
||||
|
||||
1. **자동 내역 동기화**: 은행/카드사 API 연동을 통한 자동 내역 가져오기는 MVP에서 제외
|
||||
2. **다중 사용자 지원**: 가족 구성원 초대 및 공동 계정 관리는 향후 업데이트에서 구현
|
||||
3. **AI 기반 고급 분석**: 심층적인 AI 분석 및 예측 기능은 MVP에서 제외
|
||||
4. **고급 OCR 기능**: 영수증 상세 분석 및 자동 품목 분류는 향후 업데이트에서 구현
|
||||
5. **타 금융 앱 연동**: 다른 금융 앱이나 서비스와의 연동은 MVP에서 제외
|
||||
6. **다중 통화 지원**: 해외 카드 사용 및 다중 통화 관리는 MVP에서 제외
|
||||
7. **음성 인식 기능**: 음성을 통한 내역 입력 및 명령은 향후 업데이트에서 구현
|
||||
8. **고급 데이터 시각화**: 복잡한 인터랙티브 차트 및 고급 시각화는 MVP에서 제외
|
||||
|
||||
이러한 제외 기능들은 MVP 출시 후 사용자 피드백과 우선순위에 따라 향후 업데이트에서 순차적으로 구현할 계획입니다.
|
||||
354
docs/01_기획_및_설계/UI_와이어프레임_추가화면.md
Normal file
@@ -0,0 +1,354 @@
|
||||
# 적자 탈출 가계부 - UI 와이어프레임 (추가 화면)
|
||||
|
||||
## 1. 예산 설정 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [뒤로] 카드 한도 설정 |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카드 선택 | |
|
||||
| | [신한카드 ▼] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 월간 한도 설정 | |
|
||||
| | | |
|
||||
| | [슬라이더] | |
|
||||
| | 2,000,000원 | |
|
||||
| | | |
|
||||
| | 권장 한도: 1,800,000원 | |
|
||||
| | (월 소득의 40%) | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카테고리별 한도 설정 | |
|
||||
| | | |
|
||||
| | [식비] | |
|
||||
| | [슬라이더] 600,000원 | |
|
||||
| | (전체 한도의 30%) | |
|
||||
| | | |
|
||||
| | [쇼핑] | |
|
||||
| | [슬라이더] 400,000원 | |
|
||||
| | (전체 한도의 20%) | |
|
||||
| | | |
|
||||
| | [교통] | |
|
||||
| | [슬라이더] 200,000원 | |
|
||||
| | (전체 한도의 10%) | |
|
||||
| | | |
|
||||
| | [여가/문화] | |
|
||||
| | [슬라이더] 300,000원 | |
|
||||
| | (전체 한도의 15%) | |
|
||||
| | | |
|
||||
| | [기타] | |
|
||||
| | [슬라이더] 500,000원 | |
|
||||
| | (전체 한도의 25%) | |
|
||||
| | | |
|
||||
| | [+ 카테고리 추가] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 알림 설정 | |
|
||||
| | | |
|
||||
| | [✓] 한도 70% 도달 시 알림 | |
|
||||
| | [✓] 한도 90% 도달 시 알림 | |
|
||||
| | [✓] 결제일 3일 전 알림 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| [초기화] [저장하기] |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| [홈] [내역] [+] [분석] [설정] |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 2. 분석 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [메뉴] 분석 [공유] |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 기간 선택 | |
|
||||
| | [이번 달 ▼] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카테고리별 지출 | |
|
||||
| | | |
|
||||
| | [파이 차트] | |
|
||||
| | | |
|
||||
| | 식비: 30% (600,000원) | |
|
||||
| | 쇼핑: 20% (400,000원) | |
|
||||
| | 교통: 10% (200,000원) | |
|
||||
| | 여가: 15% (300,000원) | |
|
||||
| | 기타: 25% (500,000원) | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 월별 지출 추이 | |
|
||||
| | | |
|
||||
| | [막대 그래프] | |
|
||||
| | 12월 1.5백만원 | |
|
||||
| | 1월 1.8백만원 | |
|
||||
| | 2월 1.4백만원 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 요일별 지출 패턴 | |
|
||||
| | | |
|
||||
| | [선 그래프] | |
|
||||
| | 월 화 수 목 금 토 일 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 지출 인사이트 | |
|
||||
| | | |
|
||||
| | • 이번 달 식비는 전월 대비 | |
|
||||
| | 15% 감소했습니다 | |
|
||||
| | | |
|
||||
| | • 주말 지출이 평일보다 | |
|
||||
| | 30% 높습니다 | |
|
||||
| | | |
|
||||
| | • 카페에서의 지출이 월 | |
|
||||
| | 45,000원으로 높은 편입니다| |
|
||||
| | | |
|
||||
| | [더 보기 >] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| [홈] [내역] [+] [분석] [설정] |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 3. 설정 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [뒤로] 설정 |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 프로필 관리 | |
|
||||
| | | |
|
||||
| | [프로필 이미지] | |
|
||||
| | 홍길동 | |
|
||||
| | example@email.com | |
|
||||
| | | |
|
||||
| | [프로필 편집 >] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카드 관리 | |
|
||||
| | | |
|
||||
| | [카드 목록 >] | |
|
||||
| | [카드 추가 >] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 알림 설정 | |
|
||||
| | | |
|
||||
| | [✓] 한도 알림 | |
|
||||
| | [✓] 결제일 알림 | |
|
||||
| | [✓] 지출 분석 알림 | |
|
||||
| | [✓] 푸시 알림 | |
|
||||
| | [ ] 이메일 알림 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 앱 설정 | |
|
||||
| | | |
|
||||
| | 테마 | |
|
||||
| | [라이트 ⊙] [다크 ○] | |
|
||||
| | | |
|
||||
| | 시작 화면 | |
|
||||
| | [대시보드 ▼] | |
|
||||
| | | |
|
||||
| | 언어 | |
|
||||
| | [한국어 ▼] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 데이터 관리 | |
|
||||
| | | |
|
||||
| | [데이터 백업 >] | |
|
||||
| | [데이터 복원 >] | |
|
||||
| | [데이터 초기화 >] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 앱 정보 | |
|
||||
| | | |
|
||||
| | 버전: 1.0.0 | |
|
||||
| | [이용약관 >] | |
|
||||
| | [개인정보처리방침 >] | |
|
||||
| | [오픈소스 라이선스 >] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| [로그아웃] |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| [홈] [내역] [+] [분석] [설정] |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 4. 카드 관리 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [뒤로] 카드 관리 |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 신한카드 | |
|
||||
| | | |
|
||||
| | [카드 이미지] | |
|
||||
| | **** **** **** 1234 | |
|
||||
| | 월 한도: 2,000,000원 | |
|
||||
| | 결제일: 매월 1일 | |
|
||||
| | | |
|
||||
| | [편집] [삭제] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 현대카드 | |
|
||||
| | | |
|
||||
| | [카드 이미지] | |
|
||||
| | **** **** **** 5678 | |
|
||||
| | 월 한도: 1,500,000원 | |
|
||||
| | 결제일: 매월 15일 | |
|
||||
| | | |
|
||||
| | [편집] [삭제] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 국민카드 | |
|
||||
| | | |
|
||||
| | [카드 이미지] | |
|
||||
| | **** **** **** 9012 | |
|
||||
| | 월 한도: 1,000,000원 | |
|
||||
| | 결제일: 매월 25일 | |
|
||||
| | | |
|
||||
| | [편집] [삭제] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| [+ 카드 추가하기] |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| [홈] [내역] [+] [분석] [설정] |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 5. 카드 추가 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [뒤로] 카드 추가 |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카드 정보 입력 | |
|
||||
| | | |
|
||||
| | 카드 이름 | |
|
||||
| | [신한카드] | |
|
||||
| | | |
|
||||
| | 카드 종류 | |
|
||||
| | [신용카드 ▼] | |
|
||||
| | | |
|
||||
| | 카드 번호 (선택사항) | |
|
||||
| | [**** **** **** 1234] | |
|
||||
| | | |
|
||||
| | 카드사 | |
|
||||
| | [신한카드 ▼] | |
|
||||
| | | |
|
||||
| | 카드 색상 | |
|
||||
| | [색상 선택기] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 결제 정보 설정 | |
|
||||
| | | |
|
||||
| | 월간 한도 | |
|
||||
| | [2,000,000원] | |
|
||||
| | | |
|
||||
| | 결제일 | |
|
||||
| | [매월 1일 ▼] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| [취소] [저장하기] |
|
||||
| |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 화면 간 이동 흐름도
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +----------------+
|
||||
| 로그인/회원가입 |---->| 메인 대시보드 |<--->| 지출 목록 |
|
||||
+----------------+ +----------------+ +----------------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
v v v
|
||||
+----------------+ +----------------+ +----------------+
|
||||
| 카드 관리 |<--->| 설정 화면 | | 지출 입력 |
|
||||
+----------------+ +----------------+ +----------------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
v v v
|
||||
+----------------+ +----------------+ +----------------+
|
||||
| 카드 추가 | | 프로필 관리 | | 필터/검색 |
|
||||
+----------------+ +----------------+ +----------------+
|
||||
^
|
||||
|
|
||||
v
|
||||
+----------------+ +----------------+ +----------------+
|
||||
| 카테고리 관리 |<--->| 분석 화면 |<--->| 예산 설정 |
|
||||
+----------------+ +----------------+ +----------------+
|
||||
```
|
||||
|
||||
## 주요 사용자 흐름
|
||||
|
||||
### 1. 신규 사용자 온보딩 흐름
|
||||
```
|
||||
로그인/회원가입 → 기본 정보 입력 → 카드 추가 → 월간 한도 설정 → 메인 대시보드
|
||||
```
|
||||
|
||||
### 2. 지출 기록 흐름
|
||||
```
|
||||
메인 대시보드 → [+] 버튼 → 지출 입력 → 저장 → 메인 대시보드 (업데이트된 정보)
|
||||
```
|
||||
|
||||
### 3. 지출 분석 흐름
|
||||
```
|
||||
메인 대시보드 → 분석 탭 → 기간 선택 → 카테고리별/월별/요일별 분석 확인
|
||||
```
|
||||
|
||||
### 4. 한도 관리 흐름
|
||||
```
|
||||
메인 대시보드 → 설정 탭 → 카드 관리 → 카드 선택 → 한도 설정 → 저장 → 메인 대시보드
|
||||
```
|
||||
|
||||
### 5. 지출 내역 검색 흐름
|
||||
```
|
||||
메인 대시보드 → 내역 탭 → 검색 아이콘 → 검색어 입력/필터 적용 → 검색 결과 확인
|
||||
```
|
||||
|
||||
## 모바일 반응형 고려사항
|
||||
|
||||
1. **화면 크기 최적화**
|
||||
- 다양한 모바일 화면 크기에 맞게 UI 요소 조정
|
||||
- 작은 화면에서는 중요 정보 우선 표시
|
||||
|
||||
2. **터치 인터랙션**
|
||||
- 모든 터치 영역은 최소 44x44dp 크기 유지
|
||||
- 스와이프, 핀치 줌 등 모바일 제스처 지원
|
||||
|
||||
3. **키보드 입력 최적화**
|
||||
- 숫자 입력 시 숫자 키패드 자동 표시
|
||||
- 입력 필드 포커스 시 자동 스크롤 조정
|
||||
|
||||
4. **오프라인 사용성**
|
||||
- 네트워크 연결 없이도 기본 기능 사용 가능
|
||||
- 데이터 동기화는 네트워크 연결 시 자동 수행
|
||||
317
docs/01_기획_및_설계/UI_와이어프레임_핵심화면.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# 적자 탈출 가계부 - UI 와이어프레임 (핵심 화면)
|
||||
|
||||
## 1. 로그인/회원가입 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| |
|
||||
| [로고 이미지] |
|
||||
| |
|
||||
| 적자 탈출 가계부 |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 이메일 주소 입력 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 비밀번호 입력 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 로그인 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| 비밀번호를 잊으셨나요? [찾기] |
|
||||
| |
|
||||
| --------- 또는 --------- |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 소셜 로그인 버튼 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| 계정이 없으신가요? [회원가입] |
|
||||
| |
|
||||
+----------------------------------+
|
||||
|
||||
+----------------------------------+
|
||||
| |
|
||||
| 회원가입 화면 |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 이름 입력 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 이메일 주소 입력 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 비밀번호 입력 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 비밀번호 확인 입력 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| [ ] 이용약관에 동의합니다 |
|
||||
| [ ] 개인정보 처리방침에 동의합니다 |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 회원가입 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| 이미 계정이 있으신가요? [로그인] |
|
||||
| |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 2. 메인 대시보드 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [메뉴] 대시보드 [알림] |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| 안녕하세요, [사용자 이름]님! |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 이번 달 카드 사용 | |
|
||||
| | | |
|
||||
| | [진행 바: 70% 사용] | |
|
||||
| | | |
|
||||
| | 1,400,000원 / 2,000,000원 | |
|
||||
| | 남은 한도: 600,000원 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카테고리별 지출 현황 | |
|
||||
| | | |
|
||||
| | [파이 차트] | |
|
||||
| | | |
|
||||
| | 식비: 30% | |
|
||||
| | 쇼핑: 25% | |
|
||||
| | 교통: 15% | |
|
||||
| | 기타: 30% | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 최근 지출 내역 | |
|
||||
| | | |
|
||||
| | [아이콘] 스타벅스 | |
|
||||
| | 2월 27일 · 5,800원 | |
|
||||
| | | |
|
||||
| | [아이콘] 마트 | |
|
||||
| | 2월 26일 · 32,500원 | |
|
||||
| | | |
|
||||
| | [아이콘] 택시 | |
|
||||
| | 2월 25일 · 15,000원 | |
|
||||
| | | |
|
||||
| | [더 보기 >] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 다가오는 결제일 | |
|
||||
| | | |
|
||||
| | 신한카드: 3일 후 | |
|
||||
| | 예상 청구액: 1,400,000원 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| [홈] [내역] [+] [분석] [설정] |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 3. 지출 입력 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [뒤로] 지출 입력 [저장] |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 금액 입력 | |
|
||||
| | 15,000 원 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카테고리 선택 | |
|
||||
| | [식비 ▼] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카드 선택 | |
|
||||
| | [신한카드 ▼] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 가맹점 입력 | |
|
||||
| | 식당 이름 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 날짜 선택 | |
|
||||
| | 2025년 2월 27일 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 메모 입력 | |
|
||||
| | (선택사항) | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| [카메라] 영수증 사진 촬영 |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 자주 쓰는 내역 | |
|
||||
| | | |
|
||||
| | [식비] 점심 - 8,000원 | |
|
||||
| | [교통] 택시 - 15,000원 | |
|
||||
| | [카페] 커피 - 5,500원 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| [홈] [내역] [+] [분석] [설정] |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 4. 지출 목록 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [메뉴] 지출 내역 [검색] |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 기간 선택 | |
|
||||
| | [이번 달 ▼] [필터 적용] | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| 총 지출: 1,400,000원 |
|
||||
| |
|
||||
| 2025년 2월 |
|
||||
| +----------------------------+ |
|
||||
| | 27일 목요일 | |
|
||||
| | | |
|
||||
| | [아이콘] 스타벅스 | |
|
||||
| | 카페/음료 · 신한카드 | |
|
||||
| | 5,800원 | |
|
||||
| | | |
|
||||
| | [아이콘] 식당 | |
|
||||
| | 식비 · 신한카드 | |
|
||||
| | 15,000원 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 26일 수요일 | |
|
||||
| | | |
|
||||
| | [아이콘] 마트 | |
|
||||
| | 식료품 · 신한카드 | |
|
||||
| | 32,500원 | |
|
||||
| | | |
|
||||
| | [아이콘] 편의점 | |
|
||||
| | 식료품 · 현대카드 | |
|
||||
| | 8,500원 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 25일 화요일 | |
|
||||
| | | |
|
||||
| | [아이콘] 택시 | |
|
||||
| | 교통 · 신한카드 | |
|
||||
| | 15,000원 | |
|
||||
| | | |
|
||||
| | [아이콘] 온라인 쇼핑 | |
|
||||
| | 쇼핑 · 현대카드 | |
|
||||
| | 45,000원 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| [더 불러오기] |
|
||||
| |
|
||||
+----------------------------------+
|
||||
| [홈] [내역] [+] [분석] [설정] |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 5. 필터 및 검색 화면
|
||||
|
||||
```
|
||||
+----------------------------------+
|
||||
| [뒤로] 필터 적용 |
|
||||
+----------------------------------+
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 기간 선택 | |
|
||||
| | | |
|
||||
| | [시작일] ~ [종료일] | |
|
||||
| | 2025.02.01 ~ 2025.02.28 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카드 선택 | |
|
||||
| | | |
|
||||
| | [✓] 전체 | |
|
||||
| | [✓] 신한카드 | |
|
||||
| | [ ] 현대카드 | |
|
||||
| | [ ] 국민카드 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 카테고리 선택 | |
|
||||
| | | |
|
||||
| | [✓] 전체 | |
|
||||
| | [✓] 식비 | |
|
||||
| | [ ] 교통 | |
|
||||
| | [ ] 쇼핑 | |
|
||||
| | [ ] 여가/문화 | |
|
||||
| | [ ] 주거/통신 | |
|
||||
| | [ ] 기타 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| +----------------------------+ |
|
||||
| | 금액 범위 | |
|
||||
| | | |
|
||||
| | [최소금액] ~ [최대금액] | |
|
||||
| | 0원 ~ 제한없음 | |
|
||||
| +----------------------------+ |
|
||||
| |
|
||||
| [초기화] [적용하기] |
|
||||
| |
|
||||
+----------------------------------+
|
||||
```
|
||||
|
||||
## 디자인 노트
|
||||
|
||||
### 1. 색상 팔레트
|
||||
- **주요 색상**: #3498DB (파란색) - 앱의 주요 브랜드 색상
|
||||
- **보조 색상**: #2ECC71 (녹색) - 긍정적인 지표, 저축 목표 달성
|
||||
- **경고 색상**: #E74C3C (빨간색) - 한도 초과, 경고 알림
|
||||
- **중립 색상**: #ECF0F1 (연한 회색) - 배경
|
||||
- **텍스트 색상**: #2C3E50 (진한 회색) - 주요 텍스트
|
||||
|
||||
### 2. 타이포그래피
|
||||
- **주요 폰트**: 'Noto Sans KR' - 한글 가독성 최적화
|
||||
- **크기 계층**:
|
||||
- 대제목: 24px
|
||||
- 중제목: 18px
|
||||
- 본문: 14px
|
||||
- 작은 텍스트: 12px
|
||||
|
||||
### 3. 아이콘 및 시각적 요소
|
||||
- 각 카테고리별 직관적인 아이콘 사용
|
||||
- 원형 프로그레스 바와 게이지로 한도 사용 현황 표시
|
||||
- 파이 차트와 막대 그래프로 지출 분석 시각화
|
||||
|
||||
### 4. 사용자 경험 고려사항
|
||||
- 한 손 조작을 위한 하단 탭 바 디자인
|
||||
- 자주 사용하는 기능에 빠르게 접근할 수 있는 플로팅 액션 버튼(+)
|
||||
- 직관적인 색상 코딩 (초과 지출은 빨간색, 안전 지출은 녹색)
|
||||
- 카드 스와이프 제스처로 추가 작업 접근 (수정, 삭제 등)
|
||||
|
||||
### 5. 접근성 고려사항
|
||||
- 충분한 대비를 갖는 색상 조합
|
||||
- 터치 가능한 요소는 최소 44x44dp 크기 유지
|
||||
- 스크린 리더 호환성을 위한 적절한 레이블 제공
|
||||
- 다크 모드 지원
|
||||
16
docs/01_기획_및_설계/index.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 기획 및 설계
|
||||
|
||||
이 폴더에는 적자 탈출 가계부 프로젝트의 기획 및 UI/UX 설계에 관한 문서가 포함되어 있습니다.
|
||||
|
||||
## 문서 목록
|
||||
|
||||
- [[1. Project/2. ZELLYY/젤리의 적자 탈출/01_기획_및_설계/MVP_기능_목록]] - 최소 기능 제품(MVP)의 기능 목록
|
||||
- [[주요 사용 시나리오]] - 주요 사용 사례 시나리오
|
||||
- [[1. Project/2. ZELLYY/젤리의 적자 탈출/01_기획_및_설계/UI_와이어프레임_핵심화면]] - 핵심 화면 와이어프레임
|
||||
- [[1. Project/2. ZELLYY/젤리의 적자 탈출/01_기획_및_설계/UI_와이어프레임_추가화면]] - 추가 화면 와이어프레임
|
||||
|
||||
## 기획 요약
|
||||
|
||||
적자 탈출 가계부 프로젝트는 사용자 중심의 설계 원칙을 바탕으로, 직관적이고 사용하기 쉬운 인터페이스를 통해 개인 재무 관리를 지원합니다.
|
||||
|
||||
주요 기능으로는 수입/지출 기록, 예산 설정 및 관리, 재무 분석 및 보고서, 알림 및 목표 설정 등이 있으며, 이를 통해 사용자가 자신의 재정 상태를 명확히 파악하고 개선할 수 있도록 돕습니다.
|
||||
315
docs/01_기획_및_설계/사용자_경험_전략.md
Normal file
@@ -0,0 +1,315 @@
|
||||
# 적자 탈출 가계부 - 사용자 경험 전략
|
||||
|
||||
## 1. 개요
|
||||
|
||||
이 문서는 적자 탈출 가계부 애플리케이션의 사용자 경험(UX) 전략을 정의합니다. 사용자 중심 설계 원칙을 바탕으로, 사용자가 재정 관리를 쉽고 효과적으로 할 수 있도록 하는 경험을 제공하는 것을 목표로 합니다.
|
||||
|
||||
## 2. 사용자 경험 비전
|
||||
|
||||
### 비전 선언문
|
||||
"적자 탈출 가계부는 사용자가 재정 관리에 대한 부담감 없이, 직관적이고 보람 있는 방식으로 지출을 추적하고 관리할 수 있게 함으로써, 재정적 안정과 목표 달성을 지원합니다."
|
||||
|
||||
### 핵심 UX 원칙
|
||||
|
||||
1. **단순함(Simplicity)**: 복잡한 재정 관리를 단순하고 접근하기 쉬운 경험으로 변환
|
||||
2. **투명성(Transparency)**: 사용자의 재정 상태를 명확하고 이해하기 쉽게 표현
|
||||
3. **통찰력(Insightfulness)**: 단순한 데이터 표시를 넘어 의미 있는 통찰력 제공
|
||||
4. **동기부여(Motivation)**: 긍정적인 재정 습관 형성을 위한 동기 부여 요소 통합
|
||||
5. **개인화(Personalization)**: 사용자의 고유한 재정 상황과 목표에 맞춘 경험 제공
|
||||
|
||||
## 3. 사용자 여정 맵
|
||||
|
||||
### 3.1 신규 사용자 온보딩 여정
|
||||
|
||||
| 단계 | 사용자 행동 | 사용자 생각/감정 | 터치포인트 | UX 전략 |
|
||||
|------|------------|-----------------|-----------|---------|
|
||||
| 인지 | 앱 발견 및 다운로드 | "재정 관리가 필요한데 쉽게 할 수 있을까?" | 앱스토어, 광고 | 명확한 가치 제안, 간결한 스크린샷 |
|
||||
| 설치 | 앱 설치 및 실행 | "설정이 복잡하지 않았으면 좋겠다" | 앱 설치 화면 | 빠른 설치, 최소한의 권한 요청 |
|
||||
| 가입 | 계정 생성 | "개인정보가 안전할까? 가입이 오래 걸리지 않을까?" | 가입 화면 | 간소화된 가입 프로세스, 소셜 로그인 옵션 |
|
||||
| 온보딩 | 기본 설정 및 튜토리얼 | "이 앱을 어떻게 사용해야 할까?" | 온보딩 화면 | 대화형 튜토리얼, 단계별 가이드 |
|
||||
| 초기 설정 | 카드 정보 및 예산 설정 | "내 상황에 맞게 설정할 수 있을까?" | 설정 화면 | 가이드 제공, 기본값 추천, 나중에 수정 가능함을 안내 |
|
||||
| 첫 사용 | 첫 지출 기록 | "입력이 쉬울까? 내 데이터가 정확히 반영될까?" | 지출 입력 화면 | 간편한 입력 UI, 즉각적인 피드백, 성공 메시지 |
|
||||
|
||||
### 3.2 일상적 사용 여정
|
||||
|
||||
| 단계 | 사용자 행동 | 사용자 생각/감정 | 터치포인트 | UX 전략 |
|
||||
|------|------------|-----------------|-----------|---------|
|
||||
| 접속 | 앱 열기 | "오늘의 재정 상태를 확인해야지" | 앱 아이콘, 알림 | 빠른 로딩, 주요 정보 즉시 표시 |
|
||||
| 지출 확인 | 최근 지출 및 잔액 확인 | "얼마나 썼지? 한도가 얼마나 남았지?" | 대시보드 | 시각적 표현, 한눈에 파악 가능한 UI |
|
||||
| 지출 입력 | 새 지출 기록 | "이 지출을 빠르게 기록하고 싶다" | 지출 입력 화면 | 빠른 입력 옵션, 자주 쓰는 항목 제안 |
|
||||
| 분석 확인 | 지출 패턴 분석 | "내 소비 패턴이 어떻게 되지?" | 분석 화면 | 직관적인 차트, 의미 있는 인사이트 제공 |
|
||||
| 예산 조정 | 예산 검토 및 조정 | "이번 달 예산을 조정해야 할까?" | 예산 화면 | 쉬운 조정 UI, 변경 영향 미리보기 |
|
||||
| 목표 확인 | 저축 목표 진행 상황 확인 | "목표 달성이 얼마나 남았지?" | 목표 화면 | 진행 상황 시각화, 격려 메시지 |
|
||||
|
||||
### 3.3 알림 및 피드백 여정
|
||||
|
||||
| 단계 | 사용자 행동 | 사용자 생각/감정 | 터치포인트 | UX 전략 |
|
||||
|------|------------|-----------------|-----------|---------|
|
||||
| 알림 수신 | 한도 접근 알림 확인 | "이번 달 지출이 많았나?" | 푸시 알림 | 명확한 메시지, 행동 유도 버튼 |
|
||||
| 대응 결정 | 알림에 대한 대응 결정 | "어떻게 대응해야 할까?" | 알림 상세 화면 | 상황 설명 및 추천 행동 제시 |
|
||||
| 행동 실행 | 지출 조정 또는 한도 변경 | "이렇게 조정하면 괜찮을까?" | 지출/한도 조정 화면 | 쉬운 조정 옵션, 결과 미리보기 |
|
||||
| 피드백 확인 | 조치 결과 확인 | "내 조치가 효과가 있을까?" | 결과 화면 | 즉각적인 피드백, 긍정적 강화 |
|
||||
| 습관 형성 | 정기적인 재정 검토 | "정기적으로 확인하는 습관이 생겼다" | 주간/월간 리포트 | 정기 리포트, 개선 추세 강조 |
|
||||
|
||||
## 4. 핵심 UX 전략
|
||||
|
||||
### 4.1 직관적인 데이터 시각화
|
||||
|
||||
사용자가 복잡한 재정 데이터를 쉽게 이해할 수 있도록 직관적인 시각화 전략을 적용합니다.
|
||||
|
||||
**구현 방안:**
|
||||
- 한도 대비 사용량을 원형 또는 선형 게이지로 표시
|
||||
- 카테고리별 지출을 도넛 차트로 시각화
|
||||
- 시간에 따른 지출 추이를 선 그래프로 표현
|
||||
- 색상 코드를 활용하여 상태 표시 (녹색: 안전, 노란색: 주의, 빨간색: 위험)
|
||||
- 숫자와 그래프의 균형 있는 조합으로 정보 전달
|
||||
|
||||
**기대 효과:**
|
||||
- 복잡한 재정 정보의 이해도 향상
|
||||
- 직관적인 상태 인식으로 빠른 의사결정 지원
|
||||
- 시각적 패턴 인식을 통한 지출 습관 파악
|
||||
|
||||
### 4.2 마찰 없는 데이터 입력
|
||||
|
||||
사용자가 지출 데이터를 쉽고 빠르게 입력할 수 있도록 마찰을 최소화합니다.
|
||||
|
||||
**구현 방안:**
|
||||
- 홈 화면에서 바로 접근 가능한 빠른 입력 버튼
|
||||
- 자주 사용하는 지출 항목 원터치 입력
|
||||
- 최근 방문한 가맹점 자동 제안
|
||||
- 영수증 사진 촬영을 통한 자동 데이터 추출 (향후 기능)
|
||||
- 음성 인식을 통한 지출 입력 (향후 기능)
|
||||
|
||||
**기대 효과:**
|
||||
- 데이터 입력에 대한 심리적 장벽 감소
|
||||
- 지속적인 앱 사용 유도
|
||||
- 더 정확하고 완전한 재정 데이터 확보
|
||||
|
||||
### 4.3 맥락 기반 인사이트
|
||||
|
||||
단순한 데이터 표시를 넘어, 사용자의 상황과 목표에 맞는 맥락화된 인사이트를 제공합니다.
|
||||
|
||||
**구현 방안:**
|
||||
- "지난 달 대비" 비교 분석 제공
|
||||
- 비정상적인 지출 패턴 감지 및 알림
|
||||
- 카테고리별 지출 추세 분석
|
||||
- 사용자 목표 기반 맞춤형 조언
|
||||
- 유사한 사용자 그룹과의 익명 비교 (향후 기능)
|
||||
|
||||
**기대 효과:**
|
||||
- 의미 있는 재정 통찰력 제공
|
||||
- 사용자의 재정 의사결정 개선
|
||||
- 앱의 지속적인 가치 인식 강화
|
||||
|
||||
### 4.4 점진적 동기 부여
|
||||
|
||||
사용자가 재정 관리를 지속할 수 있도록 점진적인 동기 부여 요소를 통합합니다.
|
||||
|
||||
**구현 방안:**
|
||||
- 작은 성취에 대한 축하 메시지 및 애니메이션
|
||||
- 연속 사용 스트릭 및 마일스톤 보상
|
||||
- 목표 달성 진행률 시각화
|
||||
- 주간/월간 챌린지 제공
|
||||
- 재정 건전성 점수 및 개선 추적
|
||||
|
||||
**기대 효과:**
|
||||
- 재정 관리의 습관화 촉진
|
||||
- 앱 사용의 즐거움 증가
|
||||
- 장기적인 사용자 유지율 향상
|
||||
|
||||
### 4.5 상황별 알림 전략
|
||||
|
||||
사용자에게 적시에 관련성 높은 정보를 제공하는 알림 전략을 구현합니다.
|
||||
|
||||
**구현 방안:**
|
||||
- 한도 도달 임계값 기반 알림 (70%, 90% 등)
|
||||
- 비정상적인 지출 패턴 감지 시 알림
|
||||
- 결제일 접근 시 예상 청구액 알림
|
||||
- 목표 달성 또는 중요 마일스톤 알림
|
||||
- 사용자 설정 기반 맞춤형 알림 옵션
|
||||
|
||||
**기대 효과:**
|
||||
- 재정적 위험 상황의 사전 인지
|
||||
- 적시에 조치를 취할 수 있는 기회 제공
|
||||
- 중요한 재정 이벤트 누락 방지
|
||||
|
||||
## 5. 화면별 UX 전략
|
||||
|
||||
### 5.1 대시보드 화면
|
||||
|
||||
**목적**: 사용자의 현재 재정 상태를 한눈에 파악할 수 있게 함
|
||||
|
||||
**UX 전략:**
|
||||
- 가장 중요한 정보(남은 한도, 주요 지출)를 상단에 배치
|
||||
- 시각적 계층 구조로 정보의 중요도 표현
|
||||
- 스크롤 없이 핵심 정보 확인 가능한 레이아웃
|
||||
- 탭 또는 스와이프로 다양한 기간(일/주/월) 전환
|
||||
- 주요 행동(지출 추가, 분석 보기)에 쉽게 접근 가능한 버튼
|
||||
|
||||
**주요 인터랙션:**
|
||||
- 카드 한도 게이지 탭 시 상세 내역으로 이동
|
||||
- 최근 거래 목록 스와이프로 빠른 작업(편집, 삭제)
|
||||
- 풀다운 제스처로 데이터 새로고침
|
||||
- 그래프 요소 탭하여 상세 데이터 확인
|
||||
|
||||
### 5.2 지출 입력 화면
|
||||
|
||||
**목적**: 사용자가 빠르고 정확하게 지출 정보를 입력할 수 있게 함
|
||||
|
||||
**UX 전략:**
|
||||
- 단계적 입력 흐름으로 복잡성 감소
|
||||
- 가장 자주 사용하는 필드 우선 배치
|
||||
- 스마트 기본값 제안으로 입력 시간 단축
|
||||
- 명확한 시각적 피드백으로 입력 상태 인지
|
||||
- 오류 발생 시 즉각적이고 구체적인 안내
|
||||
|
||||
**주요 인터랙션:**
|
||||
- 금액 입력 시 숫자 키패드 자동 활성화
|
||||
- 카테고리 선택 시 시각적 아이콘으로 빠른 인식
|
||||
- 자주 방문하는 가맹점 자동완성
|
||||
- 저장 버튼은 항상 화면에 고정되어 접근성 확보
|
||||
- 뒤로 가기 시 입력 데이터 임시 저장
|
||||
|
||||
### 5.3 분석 화면
|
||||
|
||||
**목적**: 사용자의 지출 패턴과 트렌드를 이해하기 쉽게 시각화
|
||||
|
||||
**UX 전략:**
|
||||
- 가장 관련성 높은 인사이트를 상단에 배치
|
||||
- 다양한 시각화 방식으로 다각적 데이터 표현
|
||||
- 복잡한 분석을 쉬운 언어로 설명하는 텍스트 요약
|
||||
- 필터 및 기간 설정으로 맞춤형 분석 지원
|
||||
- 발견된 패턴에 기반한 실행 가능한 제안 제공
|
||||
|
||||
**주요 인터랙션:**
|
||||
- 차트 요소 탭하여 세부 정보 확인
|
||||
- 기간 선택기로 다양한 시간대 분석
|
||||
- 카테고리 필터로 특정 지출 유형 집중 분석
|
||||
- 차트 간 스와이프로 다양한 분석 뷰 전환
|
||||
- 인사이트 카드 저장 및 공유 기능
|
||||
|
||||
### 5.4 예산 및 목표 화면
|
||||
|
||||
**목적**: 사용자가 재정 목표를 설정하고 진행 상황을 추적할 수 있게 함
|
||||
|
||||
**UX 전략:**
|
||||
- 목표 진행 상황의 시각적 표현
|
||||
- 목표 달성까지 남은 금액/시간 명확히 표시
|
||||
- 목표 달성 가능성에 대한 예측 제공
|
||||
- 목표 조정이 쉬운 인터페이스
|
||||
- 성취감을 주는 마일스톤 및 축하 요소
|
||||
|
||||
**주요 인터랙션:**
|
||||
- 슬라이더로 목표 금액/기간 쉽게 조정
|
||||
- 목표 카드 탭하여 상세 정보 및 히스토리 확인
|
||||
- 목표 달성 시 축하 애니메이션 및 공유 옵션
|
||||
- 목표 템플릿으로 빠른 새 목표 생성
|
||||
- 목표 우선순위 드래그 앤 드롭으로 조정
|
||||
|
||||
### 5.5 설정 화면
|
||||
|
||||
**목적**: 사용자가 앱 경험을 자신의 필요에 맞게 커스터마이징할 수 있게 함
|
||||
|
||||
**UX 전략:**
|
||||
- 논리적 카테고리로 설정 옵션 그룹화
|
||||
- 가장 자주 변경하는 설정을 상단에 배치
|
||||
- 각 설정의 목적과 영향을 명확히 설명
|
||||
- 복잡한 설정은 단계별 가이드 제공
|
||||
- 설정 변경 시 즉각적인 피드백 제공
|
||||
|
||||
**주요 인터랙션:**
|
||||
- 토글 스위치로 간단한 켜기/끄기 설정
|
||||
- 중요 설정 변경 시 확인 대화상자
|
||||
- 설정 검색 기능으로 빠른 접근
|
||||
- 설정 프로필 저장 및 불러오기
|
||||
- 모든 설정 초기화 옵션 (안전장치 포함)
|
||||
|
||||
## 6. 마이크로인터랙션 전략
|
||||
|
||||
마이크로인터랙션은 사용자 경험의 감성적 측면을 강화하고, 앱 사용의 즐거움을 높이는 중요한 요소입니다.
|
||||
|
||||
### 6.1 피드백 애니메이션
|
||||
|
||||
- **지출 입력 완료**: 저장 버튼 클릭 시 성공적인 저장을 나타내는 체크 마크 애니메이션
|
||||
- **한도 임계값 도달**: 한도의 75%, 90% 도달 시 시각적 경고 애니메이션
|
||||
- **목표 달성**: 저축 목표 달성 시 축하 애니메이션 및 색종이 효과
|
||||
- **데이터 로딩**: 스켈레톤 로딩 상태로 데이터 로드 진행 상황 표시
|
||||
- **오류 발생**: 부드러운 흔들림 애니메이션으로 오류 상태 표시
|
||||
|
||||
### 6.2 전환 효과
|
||||
|
||||
- **화면 전환**: 자연스러운 슬라이드 또는 페이드 전환 효과
|
||||
- **모달 표시**: 배경 흐림 효과와 함께 모달이 부드럽게 나타남
|
||||
- **목록 항목 추가/삭제**: 항목이 추가되거나 삭제될 때 부드러운 확장/축소 효과
|
||||
- **탭 전환**: 탭 간 전환 시 콘텐츠가 자연스럽게 전환되는 효과
|
||||
- **카드 확장/축소**: 카드 탭 시 부드럽게 확장되어 상세 정보 표시
|
||||
|
||||
### 6.3 햅틱 피드백
|
||||
|
||||
- **중요 작업 완료**: 지출 저장, 목표 달성 등 중요 작업 완료 시 긍정적 햅틱 피드백
|
||||
- **경고 상황**: 한도 초과, 오류 발생 등 주의가 필요한 상황에서 경고성 햅틱 피드백
|
||||
- **상호작용 확인**: 버튼 탭, 슬라이더 조정 등 사용자 입력 확인을 위한 미세한 햅틱 피드백
|
||||
- **진행 상태 변화**: 목표 진행률이 10% 단위로 증가할 때마다 성취감을 주는 햅틱 피드백
|
||||
- **알림 수신**: 중요도에 따라 다른 패턴의 햅틱 피드백으로 알림 구분
|
||||
|
||||
## 7. 접근성 전략
|
||||
|
||||
모든 사용자가 앱을 효과적으로 사용할 수 있도록 포괄적인 접근성 전략을 구현합니다.
|
||||
|
||||
### 7.1 시각적 접근성
|
||||
|
||||
- **고대비 모드**: 시각 장애가 있는 사용자를 위한 고대비 색상 테마
|
||||
- **텍스트 크기 조정**: 시스템 설정에 반응하는 동적 텍스트 크기
|
||||
- **색상 독립적 정보 전달**: 색맹/색약 사용자를 위해 색상에만 의존하지 않는 정보 전달
|
||||
- **스크린 리더 지원**: 모든 UI 요소에 적절한 접근성 레이블 제공
|
||||
- **충분한 터치 타겟**: 최소 44x44pt 크기의 터치 영역으로 정확한 조작 지원
|
||||
|
||||
### 7.2 인지적 접근성
|
||||
|
||||
- **명확한 언어**: 전문 용어 대신 이해하기 쉬운 일상 언어 사용
|
||||
- **일관된 패턴**: 앱 전체에 걸쳐 일관된 UI 패턴 및 상호작용 방식 유지
|
||||
- **단계적 복잡성**: 복잡한 작업을 관리 가능한 단계로 분할
|
||||
- **오류 복구**: 실수를 쉽게 복구할 수 있는 방법 제공
|
||||
- **도움말 및 툴팁**: 컨텍스트에 맞는 도움말 및 설명 제공
|
||||
|
||||
### 7.3 운동 능력 접근성
|
||||
|
||||
- **제스처 대안**: 복잡한 제스처에 대한 대체 상호작용 방법 제공
|
||||
- **조정 가능한 타이밍**: 시간 제한이 있는 상호작용의 시간 조정 가능
|
||||
- **최소한의 입력**: 반복적인 입력을 최소화하는 설계
|
||||
- **음성 입력**: 텍스트 입력의 대안으로 음성 입력 지원 (향후 기능)
|
||||
- **키보드 접근성**: 외부 키보드 사용 시 완전한 기능 접근성 보장
|
||||
|
||||
## 8. 사용자 경험 측정 및 개선
|
||||
|
||||
지속적인 UX 개선을 위한 측정 및 피드백 수집 전략을 수립합니다.
|
||||
|
||||
### 8.1 핵심 UX 지표
|
||||
|
||||
- **작업 완료율**: 사용자가 주요 작업(지출 입력, 예산 설정 등)을 성공적으로 완료하는 비율
|
||||
- **작업 완료 시간**: 주요 작업 완료에 소요되는 평균 시간
|
||||
- **오류율**: 사용자가 경험하는 오류 빈도
|
||||
- **사용자 유지율**: 일일, 주간, 월간 활성 사용자 비율
|
||||
- **사용자 만족도**: NPS(Net Promoter Score) 및 사용자 만족도 설문 결과
|
||||
|
||||
### 8.2 데이터 수집 방법
|
||||
|
||||
- **인앱 분석**: 사용자 행동 및 상호작용 패턴 추적
|
||||
- **히트맵 및 세션 녹화**: 사용자 상호작용의 시각적 분석 (개인정보 보호 준수)
|
||||
- **인앱 피드백**: 간단한 인앱 설문 및 피드백 메커니즘
|
||||
- **사용성 테스트**: 정기적인 사용성 테스트 세션
|
||||
- **앱스토어 리뷰 분석**: 사용자 리뷰 및 평점 분석
|
||||
|
||||
### 8.3 지속적 개선 프로세스
|
||||
|
||||
- **정기적 UX 감사**: 분기별 UX 감사를 통한 개선 영역 식별
|
||||
- **A/B 테스트**: 주요 UX 변경사항에 대한 A/B 테스트
|
||||
- **사용자 피드백 루프**: 사용자 피드백 수집, 분석, 구현의 지속적 순환
|
||||
- **UX 개선 로드맵**: 우선순위가 지정된 UX 개선 계획 유지
|
||||
- **경쟁 분석**: 경쟁 앱의 UX 모니터링 및 벤치마킹
|
||||
|
||||
## 9. 결론
|
||||
|
||||
적자 탈출 가계부의 사용자 경험 전략은 사용자가 재정 관리를 쉽고, 효과적이며, 지속 가능하게 할 수 있도록 설계되었습니다. 단순함, 투명성, 통찰력, 동기부여, 개인화라는 핵심 원칙을 바탕으로, 사용자의 재정적 웰빙을 지원하는 직관적이고 보람 있는 경험을 제공하는 것을 목표로 합니다.
|
||||
|
||||
이 전략은 고정된 것이 아니라, 사용자 피드백과 행동 데이터를 바탕으로 지속적으로 발전하고 개선될 것입니다. 사용자의 필요와 기대가 변화함에 따라, 우리의 UX 전략도 함께 진화할 것입니다.
|
||||
118
docs/01_기획_및_설계/주요 사용 시나리오.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# 적자 탈출 가계부 - 주요 사용 시나리오
|
||||
|
||||
## 시나리오 1: 월간 카드 한도 설정 및 관리
|
||||
|
||||
### 사용자: 김미영 (32세, 여성, 직장인)
|
||||
|
||||
#### 배경
|
||||
김미영은 매달 급여 350만원을 받는 직장인입니다. 최근 몇 개월간 신용카드 사용이 늘어 매달 말에 카드 대금이 예상보다 많이 나와 재정적 스트레스를 느끼고 있습니다. 이번 달부터는 카드 사용을 체계적으로 관리하기로 결심했습니다.
|
||||
|
||||
#### 시나리오 흐름
|
||||
|
||||
1. **앱 설치 및 가입**
|
||||
- 미영은 앱스토어에서 '적자 탈출 가계부' 앱을 검색하여 설치합니다.
|
||||
- 이메일과 기본 정보로 간단하게 회원가입을 완료합니다.
|
||||
|
||||
2. **카드 정보 등록**
|
||||
- 미영은 자주 사용하는 신용카드 정보(카드명, 결제일)를 등록합니다.
|
||||
- 보안을 위해 카드 번호는 일부만 입력합니다.
|
||||
|
||||
3. **월간 한도 설정**
|
||||
- 미영은 이번 달 카드 사용 한도를 설정합니다.
|
||||
- 월 급여 350만원 중 고정 지출(월세, 공과금 등)을 제외한 금액을 고려하여 카드 사용 한도를 150만원으로 설정합니다.
|
||||
- 식비, 교통비, 쇼핑, 문화생활 등 카테고리별 세부 한도도 설정합니다.
|
||||
|
||||
4. **일상적인 사용**
|
||||
- 점심 식사 후 카페에서 커피를 마시고 12,000원을 카드로 결제합니다.
|
||||
- 앱에 접속하여 지출 내역을 '식비' 카테고리로 간단히 기록합니다.
|
||||
- 대시보드에서 현재까지 사용한 금액(48만원)과 남은 한도(102만원)를 한눈에 확인합니다.
|
||||
|
||||
5. **한도 접근 알림**
|
||||
- 월 중반, 쇼핑 카테고리의 한도(30만원)의 80%에 도달했을 때 앱에서 알림을 받습니다.
|
||||
- 미영은 알림을 확인하고 이번 달 남은 기간 동안 쇼핑을 자제하기로 결정합니다.
|
||||
|
||||
6. **월말 결산**
|
||||
- 월말에 미영은 앱에서 이번 달 지출 분석 리포트를 확인합니다.
|
||||
- 카테고리별 지출 비율과 전월 대비 변화를 확인하고, 다음 달 한도를 조정할 계획을 세웁니다.
|
||||
|
||||
#### 결과
|
||||
미영은 앱을 통해 카드 사용을 실시간으로 추적하고 한도를 관리함으로써, 이전보다 20% 적은 금액을 카드로 사용하게 되었습니다. 예상치 못한 과다 청구 없이 계획된 범위 내에서 지출하게 되어 재정적 스트레스가 크게 줄었습니다.
|
||||
|
||||
---
|
||||
|
||||
## 시나리오 2: 충동 구매 방지를 위한 실시간 알림
|
||||
|
||||
### 사용자: 박지훈 (23세, 남성, 대학생)
|
||||
|
||||
#### 배경
|
||||
박지훈은 아르바이트와 용돈으로 월 120만원의 수입이 있는 대학생입니다. 온라인 쇼핑과 배달 앱 사용이 잦아 종종 계획에 없던 지출이 발생하고, 월말에는 항상 돈이 부족한 상황입니다. 특히 친구들과 어울릴 때 충동적으로 카드를 사용하는 습관이 있습니다.
|
||||
|
||||
#### 시나리오 흐름
|
||||
|
||||
1. **앱 설정**
|
||||
- 지훈은 친구의 추천으로 '적자 탈출 가계부' 앱을 설치합니다.
|
||||
- 학생 신분임을 고려하여 월 카드 사용 한도를 60만원으로 설정합니다.
|
||||
- 특히 '엔터테인먼트' 카테고리에 15만원, '식비(배달음식)' 카테고리에 20만원의 한도를 설정합니다.
|
||||
|
||||
2. **실시간 알림 설정**
|
||||
- 지훈은 충동 구매를 방지하기 위해 다음과 같은 알림을 설정합니다:
|
||||
- 하루 지출이 2만원을 초과할 경우
|
||||
- 특정 카테고리 한도의 70% 도달 시
|
||||
- 주말 저녁(충동 구매가 잦은 시간대)에 카드 사용 전 확인 알림
|
||||
|
||||
3. **일상적인 사용**
|
||||
- 수업 후 친구들과 만나 저녁 식사와 영화 관람을 계획합니다.
|
||||
- 식사 비용 15,000원을 결제하려는 순간, 앱에서 "오늘 지출이 이미 18,000원 발생했습니다. 추가 지출 시 일일 한도를 초과합니다."라는 알림을 받습니다.
|
||||
- 지훈은 알림을 확인하고 더 저렴한 메뉴로 변경하여 주문합니다.
|
||||
|
||||
4. **충동 구매 상황**
|
||||
- 주말 저녁, 온라인 쇼핑몰에서 세일 중인 옷을 발견하고 구매하려고 합니다.
|
||||
- 결제 직전, 앱에서 "엔터테인먼트 카테고리 한도의 85%를 사용했습니다. 신중한 소비를 권장합니다."라는 알림을 받습니다.
|
||||
- 지훈은 잠시 생각한 후, 정말 필요한 물건인지 재고하고 구매를 다음 달로 미루기로 결정합니다.
|
||||
|
||||
5. **주간 리포트 확인**
|
||||
- 일요일 저녁, 지훈은 앱에서 이번 주 지출 요약 리포트를 확인합니다.
|
||||
- 지난주보다 배달음식 지출이 30% 감소했음을 확인하고 만족감을 느낍니다.
|
||||
- 절약한 금액을 학자금 대출 이자 납부를 위한 저축 목표에 할당합니다.
|
||||
|
||||
#### 결과
|
||||
지훈은 앱의 실시간 알림 기능을 통해 충동 구매를 크게 줄일 수 있었습니다. 특히 소비 결정을 내리기 전에 현재 재정 상태를 상기시켜주는 알림이 효과적이었습니다. 3개월 사용 후, 월 평균 15만원을 추가로 저축할 수 있게 되었습니다.
|
||||
|
||||
---
|
||||
|
||||
## 시나리오 3: 부부 공동 카드 관리
|
||||
|
||||
### 사용자: 이준호 (35세, 남성, IT 개발자) & 김수진 (33세, 여성, 마케터)
|
||||
|
||||
#### 배경
|
||||
이준호와 김수진은 결혼 2년차 맞벌이 부부입니다. 두 사람 모두 각자의 신용카드와 함께 공동 카드도 사용하고 있어 지출 관리가 복잡합니다. 특히 누가 얼마나 사용했는지 실시간으로 파악하기 어려워 종종 예상보다 많은 카드 대금이 청구되어 갈등이 발생하곤 합니다.
|
||||
|
||||
#### 시나리오 흐름
|
||||
|
||||
1. **가족 계정 설정**
|
||||
- 준호가 '적자 탈출 가계부' 앱을 설치하고 가족 계정을 생성합니다.
|
||||
- 수진을 가족 구성원으로 초대하여 두 사람이 공동으로 앱을 사용할 수 있도록 설정합니다.
|
||||
- 개인 카드와 공동 카드를 모두 등록하고, 공동 카드의 월 사용 한도를 200만원으로 설정합니다.
|
||||
|
||||
2. **카드별 사용자 지정**
|
||||
- 공동 카드에 대해 준호와 수진 모두 사용자로 지정합니다.
|
||||
- 각자의 개인 카드는 해당 소유자만 관리할 수 있도록 설정합니다.
|
||||
- 공동 카드의 카테고리별 한도를 설정합니다: 식비(80만원), 생활용품(50만원), 교통비(30만원), 기타(40만원)
|
||||
|
||||
3. **일상적인 사용**
|
||||
- 준호가 퇴근길에 공동 카드로 마트에서 장을 봐 65,000원을 결제합니다.
|
||||
- 앱에 지출을 '생활용품' 카테고리로 기록합니다.
|
||||
- 수진은 실시간으로 준호의 지출 내역을 확인하고, 자신이 계획했던 생활용품 구매를 조정합니다.
|
||||
|
||||
4. **한도 관리**
|
||||
- 월 중반, 식비 카테고리가 한도의 75%에 도달했다는 알림을 두 사람 모두 받습니다.
|
||||
- 부부는 앱 내 채팅 기능을 통해 남은 기간 동안의 식비 계획을 논의합니다.
|
||||
- 외식 횟수를 줄이고 집에서 식사를 더 자주 하기로 결정합니다.
|
||||
|
||||
5. **월말 결산 및 계획**
|
||||
- 월말에 부부는 함께 앱에서 이번 달 지출 분석을 검토합니다.
|
||||
- 공동 카드 사용 내역을 카테고리별, 사용자별로 확인합니다.
|
||||
- 다음 달 예상 지출(차량 보험료 갱신)을 고려하여 카테고리별 한도를 조정합니다.
|
||||
|
||||
#### 결과
|
||||
준호와 수진은 앱을 통해 공동 카드 사용 내역을 실시간으로 공유하고 관리함으로써, 예상치 못한 과다 지출을 방지할 수 있었습니다. 특히 서로의 지출을 투명하게 확인할 수 있어 재정 관련 갈등이 크게 줄었고, 매달 100만원 이상을 안정적으로 저축할 수 있게 되었습니다.
|
||||
227
docs/02_기술_문서/01_시스템_아키텍처.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# 적자 탈출 가계부 시스템 아키텍처
|
||||
|
||||
## 시스템 개요
|
||||
|
||||
'적자 탈출 가계부' 애플리케이션은 사용자의 재정 데이터를 안전하게 관리하고, 효과적인 분석을 제공하며, 다양한 기기에서 일관된 사용자 경험을 제공하기 위한 클라이언트-서버 아키텍처를 채택합니다. 본 문서는 시스템의 전반적인 아키텍처와 주요 구성 요소를 설명합니다.
|
||||
|
||||
## 아키텍처 다이어그램
|
||||
|
||||
```
|
||||
+---------------------------+ +---------------------------+
|
||||
| | | |
|
||||
| 클라이언트 애플리케이션 | | 백엔드 서버 |
|
||||
| | | |
|
||||
| +---------------------+ | | +---------------------+ |
|
||||
| | 프레젠테이션 계층 | | | | API 계층 | |
|
||||
| | | | | | | |
|
||||
| | - React UI | | | | - RESTful API | |
|
||||
| | - Tailwind CSS | | | | - GraphQL API | |
|
||||
| | - Capacitor | | | | - 인증/인가 | |
|
||||
| +---------------------+ | | +---------------------+ |
|
||||
| | | | | |
|
||||
| +---------------------+ | | +---------------------+ |
|
||||
| | 비즈니스 로직 계층 | | | | 서비스 계층 | |
|
||||
| | | | | | | |
|
||||
| | - 데이터 검증 | | | | - 비즈니스 로직 | |
|
||||
| | - 상태 관리 | | | | - 데이터 처리 | |
|
||||
| | - API 통신 | | | | - 외부 서비스 통합 | |
|
||||
| +---------------------+ | | +---------------------+ |
|
||||
| | | | | |
|
||||
| +---------------------+ | | +---------------------+ |
|
||||
| | 데이터 계층 | | | | 데이터 접근 계층 | |
|
||||
| | | | | | | |
|
||||
| | - 웹 스토리지 | | | | - ORM | |
|
||||
| | - IndexedDB | | | | - 데이터베이스 연결 | |
|
||||
| | - 데이터 동기화 | | | | - 캐싱 | |
|
||||
| +---------------------+ | | +---------------------+ |
|
||||
| | | | | |
|
||||
| +---------------------+ | | +---------------------+ |
|
||||
| | 네이티브 계층 | | | | 데이터베이스 | |
|
||||
| | | | | | | |
|
||||
| | - Capacitor 플러그인 | | | | - Supabase(PostgreSQL) | |
|
||||
| | - 네이티브 API 접근 | | | | - Redis 캐시 | |
|
||||
| +---------------------+ | | +---------------------+ |
|
||||
| | | |
|
||||
+---------------------------+ +---------------------------+
|
||||
|
|
||||
+---------------------------+
|
||||
| |
|
||||
| 외부 서비스 통합 |
|
||||
| |
|
||||
| - 금융 기관 API |
|
||||
| - 영수증 OCR 서비스 |
|
||||
| - 푸시 알림 서비스 |
|
||||
| - 클라우드 스토리지 |
|
||||
| - AI/ML 분석 서비스 |
|
||||
| |
|
||||
+---------------------------+
|
||||
```
|
||||
|
||||
## 주요 구성 요소
|
||||
|
||||
### 1. 클라이언트 애플리케이션
|
||||
|
||||
#### 프레젠테이션 계층
|
||||
- **기술 스택**: React, Vite, Tailwind CSS, Capacitor
|
||||
- **주요 기능**:
|
||||
- 사용자 인터페이스 렌더링
|
||||
- 사용자 입력 처리
|
||||
- 화면 전환 및 네비게이션
|
||||
- 반응형 디자인 구현
|
||||
- 뉴모피즘 스타일 UI 컴포넌트
|
||||
|
||||
#### 비즈니스 로직 계층
|
||||
- **기술 스택**: JavaScript/TypeScript, React Hooks
|
||||
- **주요 기능**:
|
||||
- 클라이언트 측 데이터 검증
|
||||
- 상태 관리 및 업데이트
|
||||
- API 요청 처리
|
||||
- 오프라인 작업 관리
|
||||
|
||||
#### 데이터 계층
|
||||
- **기술 스택**: LocalStorage, IndexedDB, Capacitor Storage API
|
||||
- **주요 기능**:
|
||||
- 로컬 데이터 저장 및 관리
|
||||
- 서버와의 데이터 동기화
|
||||
- 오프라인 캐싱
|
||||
- 민감 데이터 암호화
|
||||
|
||||
#### 네이티브 계층
|
||||
- **기술 스택**: Capacitor, 네이티브 플러그인
|
||||
- **주요 기능**:
|
||||
- 네이티브 기기 기능 접근 (카메라, 파일 시스템 등)
|
||||
- 푸시 알림 처리
|
||||
- 앱 생명주기 관리
|
||||
- 네이티브 UI 요소 통합
|
||||
|
||||
### 2. 백엔드 서버
|
||||
|
||||
#### API 계층
|
||||
- **기술 스택**: Node.js, Express, Apollo Server
|
||||
- **주요 기능**:
|
||||
- RESTful API 엔드포인트 제공
|
||||
- GraphQL API 제공 (고급 쿼리용)
|
||||
- 인증 및 인가 처리
|
||||
- 요청 검증 및 응답 포맷팅
|
||||
|
||||
#### 서비스 계층
|
||||
- **기술 스택**: Node.js, TypeScript
|
||||
- **주요 기능**:
|
||||
- 핵심 비즈니스 로직 구현
|
||||
- 데이터 처리 및 변환
|
||||
- 외부 서비스 통합
|
||||
- 트랜잭션 관리
|
||||
|
||||
#### 데이터 접근 계층
|
||||
- **기술 스택**: Supabase SDK, Redis
|
||||
- **주요 기능**:
|
||||
- 데이터베이스 연결 관리
|
||||
- 쿼리 최적화
|
||||
- 데이터 캐싱
|
||||
- 데이터 무결성 보장
|
||||
|
||||
#### 데이터베이스
|
||||
- **기술 스택**: Supabase(PostgreSQL), Redis
|
||||
- **주요 기능**:
|
||||
- 사용자 데이터 영구 저장
|
||||
- 트랜잭션 데이터 관리
|
||||
- 분석 데이터 저장
|
||||
- 세션 및 캐시 데이터 관리
|
||||
- 실시간 데이터 구독 및 웨브소켓 기반 업데이트
|
||||
- Row-level 보안 정책 적용
|
||||
- PostgreSQL 확장 기능 활용
|
||||
|
||||
### 3. 외부 서비스 통합
|
||||
|
||||
- **금융 기관 API**: 은행 계좌 및 카드 거래 데이터 연동
|
||||
- **영수증 OCR 서비스**: 영수증 이미지에서 텍스트 및 금액 추출
|
||||
- **푸시 알림 서비스**: Firebase Cloud Messaging 또는 Apple Push Notification Service
|
||||
- **클라우드 스토리지**: AWS S3 또는 Firebase Storage
|
||||
- **AI/ML 분석 서비스**: TensorFlow 기반 소비 패턴 분석 및 예측
|
||||
|
||||
## 데이터 흐름
|
||||
|
||||
### 1. 사용자 인증 흐름
|
||||
1. 사용자가 앱에 로그인 정보 입력
|
||||
2. 클라이언트가 인증 요청을 백엔드 서버로 전송
|
||||
3. 서버가 인증 정보 검증 후 JWT 토큰 발급
|
||||
4. 클라이언트가 토큰을 저장하고 이후 요청에 포함
|
||||
5. 토큰 만료 시 자동 갱신 또는 재로그인 요청
|
||||
|
||||
### 2. 데이터 동기화 흐름
|
||||
1. 사용자가 오프라인 상태에서 데이터 입력
|
||||
2. 데이터가 로컬 데이터베이스에 저장
|
||||
3. 네트워크 연결 시 자동 동기화 시작
|
||||
4. 서버에서 충돌 감지 및 해결
|
||||
5. 최신 데이터로 클라이언트 상태 업데이트
|
||||
|
||||
### 3. 분석 데이터 흐름
|
||||
1. 사용자 거래 데이터가 서버에 저장
|
||||
2. 배치 프로세스가 정기적으로 데이터 분석 수행
|
||||
3. 분석 결과가 데이터베이스에 저장
|
||||
4. 사용자가 분석 화면 접근 시 데이터 요청
|
||||
5. 서버가 분석 결과 반환 및 클라이언트 렌더링
|
||||
|
||||
## 보안 아키텍처
|
||||
|
||||
### 데이터 보안
|
||||
- **전송 중 데이터**: TLS/SSL 암호화
|
||||
- **저장 데이터**: AES-256 암호화
|
||||
- **민감 정보**: 토큰화 및 해싱 처리
|
||||
- **데이터베이스**: 접근 제어 및 암호화
|
||||
|
||||
### 인증 및 인가
|
||||
- **사용자 인증**: JWT 기반 인증
|
||||
- **소셜 로그인**: OAuth 2.0 통합
|
||||
- **다중 인증**: 2FA 옵션 제공
|
||||
- **권한 관리**: RBAC(Role-Based Access Control)
|
||||
|
||||
### 보안 모니터링
|
||||
- **로깅**: 모든 API 요청 및 중요 이벤트 로깅
|
||||
- **모니터링**: 실시간 보안 이벤트 모니터링
|
||||
- **알림**: 의심스러운 활동 감지 시 알림
|
||||
- **감사**: 정기적인 보안 감사 및 취약점 스캔
|
||||
|
||||
## 확장성 및 성능
|
||||
|
||||
### 수평적 확장
|
||||
- **서버리스 아키텍처**: AWS Lambda 또는 Firebase Functions
|
||||
- **컨테이너화**: Docker 및 Kubernetes 활용
|
||||
- **로드 밸런싱**: 트래픽 분산 처리
|
||||
|
||||
### 성능 최적화
|
||||
- **데이터베이스 인덱싱**: 쿼리 성능 최적화
|
||||
- **캐싱 전략**: Redis를 활용한 다층 캐싱
|
||||
- **CDN 활용**: 정적 자산 전송 최적화
|
||||
- **코드 분할**: 필요한 코드만 로드하는 지연 로딩
|
||||
|
||||
### 모니터링 및 분석
|
||||
- **성능 모니터링**: New Relic 또는 Datadog
|
||||
- **오류 추적**: Sentry
|
||||
- **사용자 행동 분석**: Google Analytics
|
||||
- **서버 모니터링**: Prometheus 및 Grafana
|
||||
|
||||
## 배포 아키텍처
|
||||
|
||||
### Supabase On-Premise 배포
|
||||
- **Docker 컨테이너**: 로컬 서버에 Supabase 서비스 배포
|
||||
- **자체 호스팅**: 내부 네트워크에서 안전하게 데이터 관리
|
||||
- **백업 및 복구**: 자동화된 백업 및 복구 프로세스
|
||||
- **확장성**: 필요에 따라 리소스 확장 가능
|
||||
|
||||
### 개발 환경
|
||||
- **로컬 개발**: Docker 컨테이너
|
||||
- **테스트 환경**: CI/CD 파이프라인 통합
|
||||
- **스테이징 환경**: 프로덕션과 동일한 구성
|
||||
|
||||
### 프로덕션 환경
|
||||
- **클라우드 제공자**: AWS 또는 Google Cloud Platform
|
||||
- **컨테이너 오케스트레이션**: Kubernetes
|
||||
- **CI/CD**: GitHub Actions 또는 Jenkins
|
||||
- **인프라 관리**: Terraform 또는 CloudFormation
|
||||
|
||||
## 결론
|
||||
|
||||
'적자 탈출 가계부' 시스템 아키텍처는 확장성, 보안, 성능을 고려하여 설계되었습니다. 클라이언트-서버 모델을 기반으로 하며, 모바일 환경에서의 사용성과 오프라인 기능을 중요시합니다. 또한 AI/ML 기능을 통합하여 사용자에게 맞춤형 재정 관리 경험을 제공하는 것을 목표로 합니다.
|
||||
|
||||
이 아키텍처는 초기 MVP 단계에서 시작하여 사용자 피드백과 요구사항에 따라 점진적으로 확장될 수 있도록 설계되었습니다. 모듈식 접근 방식을 통해 새로운 기능을 쉽게 추가하고 기존 기능을 개선할 수 있습니다.
|
||||
527
docs/02_기술_문서/02_데이터_모델_설계.md
Normal file
@@ -0,0 +1,527 @@
|
||||
# 적자 탈출 가계부 데이터 모델 설계
|
||||
|
||||
## 개요
|
||||
|
||||
'적자 탈출 가계부' 애플리케이션의 데이터 모델은 사용자의 재정 데이터를 효율적으로 저장, 관리, 분석할 수 있도록 설계되었습니다. 본 문서는 데이터베이스 스키마, 주요 엔티티 간의 관계, 그리고 데이터 접근 패턴에 대해 설명합니다.
|
||||
|
||||
## 데이터베이스 선택
|
||||
|
||||
### 주요 데이터베이스: MongoDB
|
||||
|
||||
MongoDB를 주요 데이터베이스로 선택한 이유:
|
||||
- **유연한 스키마**: 사용자별 맞춤형 카테고리, 태그 등 다양한 확장 가능성 지원
|
||||
- **문서 지향적 구조**: 계층적 데이터(예: 거래 내역과 관련 메타데이터) 저장에 적합
|
||||
- **확장성**: 사용자 증가에 따른 수평적 확장 용이
|
||||
- **쿼리 성능**: 복잡한 집계 및 분석 쿼리 지원
|
||||
|
||||
### 보조 데이터베이스: Redis
|
||||
|
||||
Redis를 보조 데이터베이스로 활용:
|
||||
- **캐싱**: 자주 접근하는 데이터(예: 사용자 대시보드 요약) 캐싱
|
||||
- **세션 관리**: 사용자 세션 및 인증 토큰 관리
|
||||
- **실시간 데이터**: 알림 및 실시간 업데이트 관리
|
||||
- **작업 큐**: 비동기 작업(예: 데이터 분석, 보고서 생성) 관리
|
||||
|
||||
## 주요 데이터 엔티티
|
||||
|
||||
### 1. 사용자 (Users)
|
||||
|
||||
사용자 계정 및 프로필 정보를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 사용자 고유 ID
|
||||
email: String, // 이메일 (로그인 ID)
|
||||
password: String, // 암호화된 비밀번호
|
||||
name: String, // 사용자 이름
|
||||
profileImage: String, // 프로필 이미지 URL
|
||||
phoneNumber: String, // 전화번호 (선택사항)
|
||||
dateOfBirth: Date, // 생년월일 (선택사항)
|
||||
gender: String, // 성별 (선택사항)
|
||||
occupation: String, // 직업 (선택사항)
|
||||
monthlyIncome: Number, // 월 평균 수입
|
||||
financialGoals: [ // 재정 목표 목록
|
||||
{
|
||||
_id: ObjectId, // 목표 ID
|
||||
name: String, // 목표 이름
|
||||
targetAmount: Number, // 목표 금액
|
||||
currentAmount: Number, // 현재 금액
|
||||
deadline: Date, // 목표 기한
|
||||
category: String, // 목표 카테고리
|
||||
isCompleted: Boolean, // 완료 여부
|
||||
createdAt: Date // 생성 일시
|
||||
}
|
||||
],
|
||||
preferences: { // 사용자 설정
|
||||
currency: String, // 통화 단위
|
||||
language: String, // 언어 설정
|
||||
theme: String, // UI 테마
|
||||
notificationSettings: { // 알림 설정
|
||||
budgetAlerts: Boolean, // 예산 알림
|
||||
transactionReminders: Boolean, // 거래 리마인더
|
||||
weeklyReports: Boolean, // 주간 보고서
|
||||
savingsTips: Boolean // 절약 팁
|
||||
}
|
||||
},
|
||||
subscriptionTier: String, // 구독 등급 (free, premium)
|
||||
subscriptionExpiresAt: Date, // 구독 만료일
|
||||
createdAt: Date, // 계정 생성일
|
||||
updatedAt: Date, // 최종 업데이트일
|
||||
lastLoginAt: Date, // 최근 로그인일
|
||||
isActive: Boolean, // 계정 활성화 상태
|
||||
deactivatedAt: Date, // 계정 비활성화일
|
||||
refreshToken: String // 리프레시 토큰
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 거래 내역 (Transactions)
|
||||
|
||||
사용자의 모든 수입, 지출, 이체 거래를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 거래 고유 ID
|
||||
userId: ObjectId, // 사용자 ID (참조)
|
||||
type: String, // 거래 유형 (income, expense, transfer)
|
||||
amount: Number, // 거래 금액
|
||||
currency: String, // 통화 단위
|
||||
categoryId: ObjectId, // 카테고리 ID (참조)
|
||||
subcategoryId: ObjectId, // 서브카테고리 ID (참조, 선택사항)
|
||||
paymentMethodId: ObjectId, // 결제 수단 ID (참조)
|
||||
accountId: ObjectId, // 계좌 ID (참조)
|
||||
description: String, // 거래 설명
|
||||
memo: String, // 추가 메모
|
||||
transactionDate: Date, // 거래 일시
|
||||
location: { // 거래 위치 (선택사항)
|
||||
name: String, // 장소 이름
|
||||
latitude: Number, // 위도
|
||||
longitude: Number // 경도
|
||||
},
|
||||
tags: [String], // 태그 목록
|
||||
attachments: [ // 첨부 파일 (영수증 등)
|
||||
{
|
||||
url: String, // 파일 URL
|
||||
type: String, // 파일 유형
|
||||
name: String, // 파일 이름
|
||||
uploadedAt: Date // 업로드 일시
|
||||
}
|
||||
],
|
||||
isRecurring: Boolean, // 정기 거래 여부
|
||||
recurringDetails: { // 정기 거래 상세 (선택사항)
|
||||
frequency: String, // 빈도 (daily, weekly, monthly, yearly)
|
||||
interval: Number, // 간격
|
||||
startDate: Date, // 시작일
|
||||
endDate: Date, // 종료일 (선택사항)
|
||||
lastProcessedDate: Date // 마지막 처리일
|
||||
},
|
||||
status: String, // 상태 (pending, completed, cancelled)
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date, // 수정일
|
||||
deletedAt: Date, // 삭제일 (소프트 삭제)
|
||||
isDeleted: Boolean // 삭제 여부
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 카테고리 (Categories)
|
||||
|
||||
거래를 분류하기 위한 카테고리 정보를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 카테고리 고유 ID
|
||||
userId: ObjectId, // 사용자 ID (참조, null이면 기본 카테고리)
|
||||
name: String, // 카테고리 이름
|
||||
type: String, // 카테고리 유형 (income, expense)
|
||||
icon: String, // 아이콘 식별자
|
||||
color: String, // 색상 코드
|
||||
isDefault: Boolean, // 기본 카테고리 여부
|
||||
isActive: Boolean, // 활성화 상태
|
||||
parentId: ObjectId, // 부모 카테고리 ID (참조, 선택사항)
|
||||
order: Number, // 표시 순서
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date // 수정일
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 예산 (Budgets)
|
||||
|
||||
사용자의 예산 설정 정보를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 예산 고유 ID
|
||||
userId: ObjectId, // 사용자 ID (참조)
|
||||
name: String, // 예산 이름
|
||||
amount: Number, // 예산 금액
|
||||
currency: String, // 통화 단위
|
||||
period: String, // 기간 유형 (daily, weekly, monthly, yearly)
|
||||
startDate: Date, // 시작일
|
||||
endDate: Date, // 종료일
|
||||
categoryIds: [ObjectId], // 카테고리 ID 목록 (참조)
|
||||
isRecurring: Boolean, // 반복 여부
|
||||
notificationThreshold: Number, // 알림 임계값 (%)
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date, // 수정일
|
||||
isActive: Boolean // 활성화 상태
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 계좌 (Accounts)
|
||||
|
||||
사용자의 금융 계좌 정보를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 계좌 고유 ID
|
||||
userId: ObjectId, // 사용자 ID (참조)
|
||||
name: String, // 계좌 이름
|
||||
type: String, // 계좌 유형 (checking, savings, credit, investment)
|
||||
institutionName: String, // 금융 기관 이름
|
||||
accountNumber: String, // 계좌 번호 (마스킹 처리)
|
||||
balance: Number, // 현재 잔액
|
||||
currency: String, // 통화 단위
|
||||
isLinked: Boolean, // 외부 API 연동 여부
|
||||
externalId: String, // 외부 API 식별자 (선택사항)
|
||||
lastSyncAt: Date, // 마지막 동기화 일시
|
||||
icon: String, // 아이콘 식별자
|
||||
color: String, // 색상 코드
|
||||
isDefault: Boolean, // 기본 계좌 여부
|
||||
isActive: Boolean, // 활성화 상태
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date // 수정일
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 결제 수단 (PaymentMethods)
|
||||
|
||||
사용자의 결제 수단 정보를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 결제 수단 고유 ID
|
||||
userId: ObjectId, // 사용자 ID (참조)
|
||||
name: String, // 결제 수단 이름
|
||||
type: String, // 유형 (cash, credit_card, debit_card, bank_transfer, mobile_payment)
|
||||
accountId: ObjectId, // 연결된 계좌 ID (참조, 선택사항)
|
||||
cardInfo: { // 카드 정보 (선택사항)
|
||||
lastFourDigits: String, // 카드 번호 마지막 4자리
|
||||
expiryDate: String, // 만료일
|
||||
cardNetwork: String // 카드 네트워크 (Visa, Mastercard 등)
|
||||
},
|
||||
icon: String, // 아이콘 식별자
|
||||
color: String, // 색상 코드
|
||||
isDefault: Boolean, // 기본 결제 수단 여부
|
||||
isActive: Boolean, // 활성화 상태
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date // 수정일
|
||||
}
|
||||
```
|
||||
|
||||
### 7. 절약 챌린지 (SavingChallenges)
|
||||
|
||||
사용자의 절약 챌린지 정보를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 챌린지 고유 ID
|
||||
title: String, // 챌린지 제목
|
||||
description: String, // 챌린지 설명
|
||||
type: String, // 챌린지 유형 (system, custom)
|
||||
creatorId: ObjectId, // 생성자 ID (참조, system이면 null)
|
||||
targetAmount: Number, // 목표 절약 금액
|
||||
duration: Number, // 기간 (일 단위)
|
||||
difficulty: String, // 난이도 (easy, medium, hard)
|
||||
categoryIds: [ObjectId], // 관련 카테고리 ID 목록 (참조)
|
||||
tips: [String], // 절약 팁 목록
|
||||
imageUrl: String, // 챌린지 이미지 URL
|
||||
isPublic: Boolean, // 공개 여부
|
||||
participantCount: Number, // 참여자 수
|
||||
successRate: Number, // 성공률 (%)
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date, // 수정일
|
||||
isActive: Boolean // 활성화 상태
|
||||
}
|
||||
```
|
||||
|
||||
### 8. 사용자 챌린지 참여 (UserChallenges)
|
||||
|
||||
사용자의 챌린지 참여 정보를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 참여 고유 ID
|
||||
userId: ObjectId, // 사용자 ID (참조)
|
||||
challengeId: ObjectId, // 챌린지 ID (참조)
|
||||
startDate: Date, // 시작일
|
||||
endDate: Date, // 종료일
|
||||
targetAmount: Number, // 개인 목표 금액
|
||||
currentAmount: Number, // 현재 절약 금액
|
||||
status: String, // 상태 (in_progress, completed, failed)
|
||||
progress: Number, // 진행률 (%)
|
||||
dailyLogs: [ // 일일 기록
|
||||
{
|
||||
date: Date, // 날짜
|
||||
amount: Number, // 절약 금액
|
||||
note: String // 메모
|
||||
}
|
||||
],
|
||||
completedAt: Date, // 완료일 (선택사항)
|
||||
reward: { // 보상 정보 (선택사항)
|
||||
type: String, // 보상 유형
|
||||
description: String, // 보상 설명
|
||||
claimedAt: Date // 수령일
|
||||
},
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date // 수정일
|
||||
}
|
||||
```
|
||||
|
||||
### 9. 재정 분석 (FinancialAnalytics)
|
||||
|
||||
사용자의 재정 분석 데이터를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 분석 고유 ID
|
||||
userId: ObjectId, // 사용자 ID (참조)
|
||||
period: String, // 기간 유형 (daily, weekly, monthly, yearly)
|
||||
startDate: Date, // 시작일
|
||||
endDate: Date, // 종료일
|
||||
totalIncome: Number, // 총 수입
|
||||
totalExpense: Number, // 총 지출
|
||||
netCashflow: Number, // 순 현금 흐름
|
||||
savingsRate: Number, // 저축률 (%)
|
||||
categoryBreakdown: [ // 카테고리별 지출 분석
|
||||
{
|
||||
categoryId: ObjectId, // 카테고리 ID (참조)
|
||||
amount: Number, // 금액
|
||||
percentage: Number, // 비율 (%)
|
||||
trend: Number // 전기 대비 변화율 (%)
|
||||
}
|
||||
],
|
||||
topExpenses: [ // 주요 지출 항목
|
||||
{
|
||||
transactionId: ObjectId, // 거래 ID (참조)
|
||||
amount: Number, // 금액
|
||||
description: String, // 설명
|
||||
date: Date // 날짜
|
||||
}
|
||||
],
|
||||
trends: { // 추세 분석
|
||||
incomeGrowth: Number, // 수입 증가율 (%)
|
||||
expenseGrowth: Number, // 지출 증가율 (%)
|
||||
savingsGrowth: Number // 저축 증가율 (%)
|
||||
},
|
||||
financialHealthScore: { // 재정 건강 점수
|
||||
overall: Number, // 종합 점수
|
||||
budgetAdherence: Number, // 예산 준수 점수
|
||||
savingsRate: Number, // 저축률 점수
|
||||
debtManagement: Number, // 부채 관리 점수
|
||||
expenseEfficiency: Number // 지출 효율성 점수
|
||||
},
|
||||
insights: [ // 인사이트 목록
|
||||
{
|
||||
type: String, // 인사이트 유형
|
||||
description: String, // 설명
|
||||
potentialSavings: Number, // 잠재적 절약 금액
|
||||
priority: String // 우선순위 (high, medium, low)
|
||||
}
|
||||
],
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date // 수정일
|
||||
}
|
||||
```
|
||||
|
||||
### 10. 알림 (Notifications)
|
||||
|
||||
사용자에게 전송되는 알림 정보를 저장합니다.
|
||||
|
||||
```javascript
|
||||
{
|
||||
_id: ObjectId, // 알림 고유 ID
|
||||
userId: ObjectId, // 사용자 ID (참조)
|
||||
type: String, // 알림 유형 (budget_alert, transaction_reminder, saving_tip, etc)
|
||||
title: String, // 알림 제목
|
||||
message: String, // 알림 내용
|
||||
data: { // 관련 데이터
|
||||
entityType: String, // 엔티티 유형 (budget, transaction, challenge, etc)
|
||||
entityId: ObjectId, // 엔티티 ID (참조)
|
||||
action: String // 필요한 액션
|
||||
},
|
||||
isRead: Boolean, // 읽음 여부
|
||||
readAt: Date, // 읽은 일시
|
||||
isActionTaken: Boolean, // 액션 수행 여부
|
||||
actionTakenAt: Date, // 액션 수행 일시
|
||||
expiresAt: Date, // 만료일 (선택사항)
|
||||
priority: String, // 우선순위 (high, medium, low)
|
||||
createdAt: Date, // 생성일
|
||||
updatedAt: Date // 수정일
|
||||
}
|
||||
```
|
||||
|
||||
## 데이터 관계 다이어그램
|
||||
|
||||
```
|
||||
+-------------+ +----------------+ +-------------+
|
||||
| Users |------>| Transactions |<------| Categories |
|
||||
+-------------+ +----------------+ +-------------+
|
||||
| | |
|
||||
| | |
|
||||
v v v
|
||||
+-------------+ +----------------+ +-------------+
|
||||
| Accounts |------>| PaymentMethods | | Budgets |
|
||||
+-------------+ +----------------+ +-------------+
|
||||
| |
|
||||
| |
|
||||
v v
|
||||
+-------------+ +----------------+ +-------------+
|
||||
| UserChallenges|<---->|SavingChallenges| |FinancialAnalytics|
|
||||
+-------------+ +----------------+ +-------------+
|
||||
|
|
||||
|
|
||||
v
|
||||
+-------------+
|
||||
|Notifications |
|
||||
+-------------+
|
||||
```
|
||||
|
||||
## 인덱싱 전략
|
||||
|
||||
효율적인 쿼리 성능을 위한 인덱스 설계:
|
||||
|
||||
### 사용자 컬렉션
|
||||
- `email`: 로그인 및 사용자 조회
|
||||
- `subscriptionTier`, `subscriptionExpiresAt`: 구독 관리
|
||||
|
||||
### 거래 내역 컬렉션
|
||||
- `userId`: 사용자별 거래 조회
|
||||
- `userId` + `transactionDate`: 날짜별 거래 조회
|
||||
- `userId` + `categoryId`: 카테고리별 거래 조회
|
||||
- `userId` + `type`: 수입/지출별 조회
|
||||
- `userId` + `isRecurring`: 정기 거래 조회
|
||||
|
||||
### 카테고리 컬렉션
|
||||
- `userId`: 사용자별 카테고리 조회
|
||||
- `userId` + `type`: 수입/지출 카테고리 조회
|
||||
|
||||
### 예산 컬렉션
|
||||
- `userId`: 사용자별 예산 조회
|
||||
- `userId` + `period` + `startDate`: 기간별 예산 조회
|
||||
|
||||
### 계좌 컬렉션
|
||||
- `userId`: 사용자별 계좌 조회
|
||||
- `userId` + `type`: 계좌 유형별 조회
|
||||
|
||||
### 절약 챌린지 컬렉션
|
||||
- `isPublic`: 공개 챌린지 조회
|
||||
- `difficulty`: 난이도별 챌린지 조회
|
||||
|
||||
### 사용자 챌린지 참여 컬렉션
|
||||
- `userId`: 사용자별 챌린지 참여 조회
|
||||
- `userId` + `status`: 상태별 챌린지 조회
|
||||
- `challengeId`: 챌린지별 참여자 조회
|
||||
|
||||
### 재정 분석 컬렉션
|
||||
- `userId`: 사용자별 분석 조회
|
||||
- `userId` + `period` + `startDate`: 기간별 분석 조회
|
||||
|
||||
### 알림 컬렉션
|
||||
- `userId`: 사용자별 알림 조회
|
||||
- `userId` + `isRead`: 읽지 않은 알림 조회
|
||||
- `userId` + `priority`: 우선순위별 알림 조회
|
||||
|
||||
## 데이터 접근 패턴
|
||||
|
||||
주요 사용 사례에 따른 데이터 접근 패턴:
|
||||
|
||||
### 1. 대시보드 로딩
|
||||
- 사용자 기본 정보 조회
|
||||
- 최근 거래 내역 조회 (제한된 수)
|
||||
- 현재 월 예산 대비 지출 현황 조회
|
||||
- 재정 건강 점수 조회
|
||||
- 읽지 않은 알림 조회
|
||||
|
||||
### 2. 거래 내역 조회
|
||||
- 기간별 거래 내역 페이지네이션 조회
|
||||
- 카테고리별 필터링
|
||||
- 금액별 정렬
|
||||
|
||||
### 3. 예산 관리
|
||||
- 현재 활성 예산 조회
|
||||
- 카테고리별 예산 대비 지출 현황 조회
|
||||
- 예산 초과 카테고리 식별
|
||||
|
||||
### 4. 재정 분석
|
||||
- 기간별 수입/지출 추이 조회
|
||||
- 카테고리별 지출 분석 조회
|
||||
- 전월 대비 변화율 계산
|
||||
- 절약 인사이트 생성
|
||||
|
||||
### 5. 절약 챌린지
|
||||
- 추천 챌린지 조회
|
||||
- 사용자 참여 챌린지 상태 조회
|
||||
- 챌린지 진행 상황 업데이트
|
||||
|
||||
## 데이터 마이그레이션 전략
|
||||
|
||||
애플리케이션 발전에 따른 데이터 마이그레이션 전략:
|
||||
|
||||
### 1. 스키마 변경 관리
|
||||
- 하위 호환성 유지: 필드 추가 시 기본값 설정
|
||||
- 버전 관리: 스키마 버전 필드 추가
|
||||
- 점진적 마이그레이션: 대규모 데이터 세트의 경우 배치 처리
|
||||
|
||||
### 2. 데이터 백업
|
||||
- 정기적인 전체 백업: 일일 단위
|
||||
- 증분 백업: 시간 단위
|
||||
- 지리적 복제: 재해 복구 대비
|
||||
|
||||
### 3. 데이터 보존 정책
|
||||
- 트랜잭션 데이터: 7년 보존
|
||||
- 분석 데이터: 집계 데이터는 영구 보존, 원시 데이터는 2년 보존
|
||||
- 사용자 활동 로그: 1년 보존
|
||||
- 삭제된 계정 데이터: 30일 후 완전 삭제
|
||||
|
||||
## 데이터 보안
|
||||
|
||||
사용자 재정 데이터 보호를 위한 보안 조치:
|
||||
|
||||
### 1. 데이터 암호화
|
||||
- 저장 데이터(Data at Rest): AES-256 암호화
|
||||
- 전송 중 데이터(Data in Transit): TLS 1.3
|
||||
- 민감 정보(계좌 번호, 카드 정보): 필드 수준 암호화
|
||||
|
||||
### 2. 접근 제어
|
||||
- 역할 기반 접근 제어(RBAC) 구현
|
||||
- 최소 권한 원칙 적용
|
||||
- API 키 및 토큰 관리
|
||||
|
||||
### 3. 감사 및 모니터링
|
||||
- 데이터 접근 로깅
|
||||
- 이상 행동 감지
|
||||
- 정기적인 보안 감사
|
||||
|
||||
## 성능 최적화
|
||||
|
||||
대규모 데이터 처리를 위한 성능 최적화 전략:
|
||||
|
||||
### 1. 쿼리 최적화
|
||||
- 적절한 인덱스 사용
|
||||
- 프로젝션을 통한 필요 필드만 조회
|
||||
- 페이지네이션 구현
|
||||
|
||||
### 2. 캐싱 전략
|
||||
- 자주 접근하는 데이터 Redis 캐싱
|
||||
- 사용자별 대시보드 데이터 캐싱
|
||||
- 분석 결과 캐싱
|
||||
|
||||
### 3. 데이터 집계
|
||||
- 실시간 집계 대신 사전 계산된 집계 데이터 활용
|
||||
- 배치 처리를 통한 분석 데이터 생성
|
||||
- 시계열 데이터 최적화
|
||||
|
||||
## 결론
|
||||
|
||||
'적자 탈출 가계부' 애플리케이션의 데이터 모델은 사용자의 재정 데이터를 효율적으로 관리하고 분석하기 위해 설계되었습니다. MongoDB의 유연한 스키마를 활용하여 다양한 사용자 요구사항을 수용하고, Redis를 통한 캐싱으로 성능을 최적화하였습니다.
|
||||
|
||||
이 데이터 모델은 초기 MVP 출시 후 사용자 피드백과 실제 사용 패턴에 따라 지속적으로 개선될 예정입니다. 특히 AI 기반 분석 및 추천 기능 강화를 위한 데이터 구조 최적화가 향후 중점적으로 이루어질 계획입니다.
|
||||
135
docs/02_기술_문서/ERD_다이어그램.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# 적자 탈출 가계부 - ERD 다이어그램
|
||||
|
||||
## 엔티티 관계 다이어그램 (ERD)
|
||||
|
||||
아래는 적자 탈출 가계부 앱의 데이터베이스 구조를 표현한 ERD입니다. 이 다이어그램은 각 테이블 간의 관계와 주요 필드를 보여줍니다.
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +----------------+
|
||||
| Users | | Cards | | Categories |
|
||||
+----------------+ +----------------+ +----------------+
|
||||
| PK id |<----->| PK id | | PK id |
|
||||
| email | | FK user_id | | name |
|
||||
| password_hash | | name | | icon |
|
||||
| name | | card_type | | color |
|
||||
| profile_image | | card_number_4 | | FK parent_id |
|
||||
| created_at | | issuer | | is_system |
|
||||
| updated_at | | color | | is_active |
|
||||
| last_login_at | | payment_day | | created_at |
|
||||
| notif_settings | | monthly_limit | | updated_at |
|
||||
| theme_pref | | is_active | +----------------+
|
||||
| is_active | | created_at | ^
|
||||
+----------------+ | updated_at | |
|
||||
^ +----------------+ |
|
||||
| ^ |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
+----------------+ +----------------+ +----------------+
|
||||
| Notifications | | Expenses | | Templates |
|
||||
+----------------+ +----------------+ +----------------+
|
||||
| PK id | | PK id | | PK id |
|
||||
| FK user_id | | FK user_id | | FK user_id |
|
||||
| title | | FK card_id | | name |
|
||||
| message | | FK category_id | | FK category_id |
|
||||
| type | | amount | | amount |
|
||||
| entity_type | | merchant | | merchant |
|
||||
| entity_id | | transaction_dt | | description |
|
||||
| is_read | | description | | is_favorite |
|
||||
| created_at | | location | | created_at |
|
||||
| read_at | | is_recurring | | updated_at |
|
||||
+----------------+ | receipt_image | +----------------+
|
||||
| tags |
|
||||
| created_at |
|
||||
| updated_at |
|
||||
+----------------+
|
||||
^
|
||||
|
|
||||
|
|
||||
+----------------+
|
||||
| Limits |
|
||||
+----------------+
|
||||
| PK id |
|
||||
| FK user_id |
|
||||
| FK card_id |
|
||||
| FK category_id |
|
||||
| amount |
|
||||
| period |
|
||||
| start_date |
|
||||
| end_date |
|
||||
| is_active |
|
||||
| created_at |
|
||||
| updated_at |
|
||||
+----------------+
|
||||
```
|
||||
|
||||
## 관계 설명
|
||||
|
||||
1. **Users (사용자)**
|
||||
- 사용자는 여러 개의 카드를 가질 수 있음 (1:N)
|
||||
- 사용자는 여러 개의 지출 내역을 가질 수 있음 (1:N)
|
||||
- 사용자는 여러 개의 한도를 설정할 수 있음 (1:N)
|
||||
- 사용자는 여러 개의 알림을 받을 수 있음 (1:N)
|
||||
- 사용자는 여러 개의 템플릿을 생성할 수 있음 (1:N)
|
||||
|
||||
2. **Cards (카드)**
|
||||
- 카드는 한 명의 사용자에게 속함 (N:1)
|
||||
- 카드는 여러 개의 지출 내역과 연결됨 (1:N)
|
||||
- 카드는 여러 개의 한도 설정과 연결될 수 있음 (1:N)
|
||||
|
||||
3. **Categories (카테고리)**
|
||||
- 카테고리는 여러 개의 지출 내역과 연결됨 (1:N)
|
||||
- 카테고리는 여러 개의 한도 설정과 연결될 수 있음 (1:N)
|
||||
- 카테고리는 여러 개의 템플릿과 연결될 수 있음 (1:N)
|
||||
- 카테고리는 자기 참조 관계를 가짐 (부모-자식 계층 구조)
|
||||
|
||||
4. **Expenses (지출)**
|
||||
- 지출은 한 명의 사용자에게 속함 (N:1)
|
||||
- 지출은 하나의 카드와 연결됨 (N:1)
|
||||
- 지출은 하나의 카테고리와 연결됨 (N:1)
|
||||
|
||||
5. **Limits (한도)**
|
||||
- 한도는 한 명의 사용자에게 속함 (N:1)
|
||||
- 한도는 선택적으로 하나의 카드와 연결될 수 있음 (N:1)
|
||||
- 한도는 선택적으로 하나의 카테고리와 연결될 수 있음 (N:1)
|
||||
|
||||
6. **Notifications (알림)**
|
||||
- 알림은 한 명의 사용자에게 속함 (N:1)
|
||||
- 알림은 선택적으로 다른 엔티티(카드, 지출 등)와 연결될 수 있음
|
||||
|
||||
7. **Templates (템플릿)**
|
||||
- 템플릿은 한 명의 사용자에게 속함 (N:1)
|
||||
- 템플릿은 하나의 카테고리와 연결됨 (N:1)
|
||||
|
||||
## 주요 제약 조건
|
||||
|
||||
1. **외래 키 제약 조건**
|
||||
- 모든 외래 키는 참조 무결성을 유지해야 함
|
||||
- 사용자가 삭제되면 해당 사용자의 모든 관련 데이터도 삭제됨 (CASCADE)
|
||||
- 카테고리가 삭제되면 관련 지출은 '기타' 카테고리로 이동 (SET DEFAULT)
|
||||
|
||||
2. **유일성 제약 조건**
|
||||
- 사용자 이메일은 유일해야 함
|
||||
- 카테고리 이름은 같은 부모 내에서 유일해야 함
|
||||
|
||||
3. **필수 필드**
|
||||
- 지출에는 반드시 금액, 날짜, 카테고리가 있어야 함
|
||||
- 한도에는 반드시 금액, 기간, 시작일이 있어야 함
|
||||
|
||||
## 인덱스 전략
|
||||
|
||||
성능 최적화를 위해 다음과 같은 인덱스가 생성됩니다:
|
||||
|
||||
1. **검색 최적화**
|
||||
- expenses(user_id, transaction_date): 날짜별 지출 검색 최적화
|
||||
- expenses(user_id, category_id): 카테고리별 지출 검색 최적화
|
||||
- expenses(user_id, card_id): 카드별 지출 검색 최적화
|
||||
|
||||
2. **정렬 최적화**
|
||||
- expenses(amount): 금액별 정렬 최적화
|
||||
- notifications(created_at): 알림 시간순 정렬 최적화
|
||||
|
||||
3. **필터링 최적화**
|
||||
- cards(is_active): 활성 카드 필터링
|
||||
- limits(is_active): 활성 한도 필터링
|
||||
- notifications(is_read): 읽지 않은 알림 필터링
|
||||
396
docs/02_기술_문서/Lovable_UI_컴포넌트_정리.md
Normal file
@@ -0,0 +1,396 @@
|
||||
# Lovable UI 컴포넌트 정리
|
||||
|
||||
## 개요
|
||||
|
||||
Zellyy Finance 앱은 Flutter에서 React와 Tailwind CSS를 사용한 Capacitor 기반 웹 앱으로 전환되었으며, UI 디자인은 뉴모피즘 스타일의 Lovable UI 컴포넌트를 적용하여 차별화된 사용자 경험을 제공하고자 합니다. 이 문서는 Lovable UI 컴포넌트와 관련된 내용을 정리합니다.
|
||||
|
||||
## Lovable UI 컴포넌트 관련 문서
|
||||
|
||||
### 1. UI/UX 설계 문서에서의 Lovable UI
|
||||
|
||||
**위치**: `/01_기획_및_설계/02_UI_UX_설계.md`
|
||||
|
||||
**주요 내용**:
|
||||
- **컴포넌트 라이브러리**: Lovable UI 컴포넌트 라이브러리 구축
|
||||
- **뉴모피즘 스타일**: 입체적이고 부드러운 UI 디자인 적용
|
||||
- **디자인 철학**: 웹 기반 기술과 Capacitor를 활용하여 다양한 플랫폼에서 일관된 사용자 경험을 제공하면서도, 뉴모피즘 스타일의 Lovable UI 컴포넌트를 통해 차별화된 디자인을 구현
|
||||
|
||||
### 2. 시스템 아키텍처 문서에서의 Lovable UI
|
||||
|
||||
**위치**: `/02_기술_문서/01_시스템_아키텍처.md`
|
||||
|
||||
**주요 내용**:
|
||||
- **프레젠테이션 계층**: 뉴모피즘 스타일 UI 컴포넌트 적용
|
||||
|
||||
### 3. 개발 로드맵 문서에서의 Lovable UI
|
||||
|
||||
**위치**: `/03_개발_단계/01_개발_로드맵.md`
|
||||
|
||||
**주요 내용**:
|
||||
- **개발 작업**: 뉴모피즘 스타일 UI 컴포넌트 개발 계획
|
||||
|
||||
### 4. README 문서에서의 Lovable UI
|
||||
|
||||
**위치**: `/README.md`
|
||||
|
||||
**주요 내용**:
|
||||
- **변경 사항**: 2025-03-09: 개발 방법 변경 - Flutter에서 React, Tailwind CSS, Capacitor 기반 웹 앱으로 전환, Lovable UI 컴포넌트 스타일 적용
|
||||
|
||||
## 필요한 Lovable UI 컴포넌트 목록
|
||||
|
||||
Zellyy Finance 앱의 홈 화면을 Lovable UI 컴포넌트로 변경하는 작업을 진행 중입니다. 기존 홈 화면의 기능을 유지하면서 Lovable UI 디자인 시스템의 컴포넌트로 UI를 개선하려고 합니다.
|
||||
|
||||
### 주요 변경 사항
|
||||
1. FloatingActionButton을 LovableAddTransactionButton으로 교체
|
||||
2. 기존 Card를 LovableCard로 교체
|
||||
3. 거래 내역 리스트 아이템을 LovableTransactionCard로 교체
|
||||
4. 전체적인 UI 디자인을 뉴모피즘 스타일로 변경
|
||||
|
||||
### 필요한 컴포넌트
|
||||
- **LovableButton**: 기본 버튼 컴포넌트
|
||||
- **LovableCard**: 카드 컴포넌트
|
||||
- **LovableTransactionCard**: 거래 내역 표시용 카드 컴포넌트
|
||||
- **LovableAddTransactionButton**: 거래 추가용 플로팅 액션 버튼
|
||||
|
||||
### 홈 화면 파일 경로
|
||||
`/Users/hansoo./Dev/Zellyy_Finance/neumofinance/src/pages/Home.tsx`
|
||||
|
||||
## 뉴모피즘 디자인 특징
|
||||
|
||||
뉴모피즘(Neumorphism)은 다음과 같은 특징을 가진 UI 디자인 스타일입니다:
|
||||
|
||||
1. **입체감**: 요소가 배경에서 살짝 튀어나온 것처럼 보이는 효과
|
||||
2. **부드러운 그림자**: 요소의 위쪽과 왼쪽에는 밝은 그림자, 아래쪽과 오른쪽에는 어두운 그림자를 적용
|
||||
3. **단일 색상 사용**: 배경과 요소가 비슷한 색상을 사용하여 미묘한 차이로 구분
|
||||
4. **미니멀리즘**: 깔끔하고 단순한 디자인 요소 사용
|
||||
5. **낮은 대비**: 강한 색상 대비보다는 미묘한 그림자와 하이라이트로 구분
|
||||
|
||||
## 구현 방향
|
||||
|
||||
1. **Tailwind CSS 활용**: 웹 기반 앱에서는 Tailwind CSS를 활용하여 뉴모피즘 효과 구현
|
||||
2. **React 컴포넌트 모듈화**: 재사용 가능한 React 컴포넌트로 설계
|
||||
3. **반응형 디자인**: 다양한 화면 크기에 대응하는 디자인 적용
|
||||
4. **접근성 고려**: 시각적 효과가 접근성을 해치지 않도록 주의
|
||||
5. **성능 최적화**: 그림자 효과 등이 성능에 영향을 미치지 않도록 최적화
|
||||
|
||||
## React 기반 Lovable UI 컴포넌트 구현
|
||||
|
||||
### 1. LovableButton 컴포넌트
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
interface LovableButtonProps {
|
||||
children: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
className?: string;
|
||||
variant?: 'primary' | 'secondary' | 'outline';
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const LovableButton: React.FC<LovableButtonProps> = ({
|
||||
children,
|
||||
onClick,
|
||||
className = '',
|
||||
variant = 'primary',
|
||||
size = 'md',
|
||||
disabled = false,
|
||||
}) => {
|
||||
const baseStyles = 'rounded-xl font-medium transition-all duration-200 focus:outline-none';
|
||||
|
||||
const variantStyles = {
|
||||
primary: 'bg-primary-100 text-primary-900 shadow-neumo hover:shadow-neumo-pressed active:shadow-neumo-pressed',
|
||||
secondary: 'bg-secondary-100 text-secondary-900 shadow-neumo hover:shadow-neumo-pressed active:shadow-neumo-pressed',
|
||||
outline: 'bg-transparent border-2 border-primary-200 text-primary-900 hover:bg-primary-50 active:bg-primary-100',
|
||||
};
|
||||
|
||||
const sizeStyles = {
|
||||
sm: 'px-3 py-1 text-sm',
|
||||
md: 'px-4 py-2',
|
||||
lg: 'px-6 py-3 text-lg',
|
||||
};
|
||||
|
||||
const disabledStyles = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer';
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
className={twMerge(
|
||||
baseStyles,
|
||||
variantStyles[variant],
|
||||
sizeStyles[size],
|
||||
disabledStyles,
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default LovableButton;
|
||||
```
|
||||
|
||||
### 2. LovableCard 컴포넌트
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
interface LovableCardProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
elevated?: boolean;
|
||||
pressed?: boolean;
|
||||
}
|
||||
|
||||
const LovableCard: React.FC<LovableCardProps> = ({
|
||||
children,
|
||||
className = '',
|
||||
onClick,
|
||||
elevated = false,
|
||||
pressed = false,
|
||||
}) => {
|
||||
const baseStyles = 'bg-primary-50 rounded-2xl p-4 transition-all duration-200';
|
||||
|
||||
const shadowStyles = {
|
||||
default: 'shadow-neumo',
|
||||
elevated: 'shadow-neumo-elevated',
|
||||
pressed: 'shadow-neumo-pressed',
|
||||
};
|
||||
|
||||
const selectedShadow = pressed ? shadowStyles.pressed : (elevated ? shadowStyles.elevated : shadowStyles.default);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
baseStyles,
|
||||
selectedShadow,
|
||||
onClick ? 'cursor-pointer' : '',
|
||||
className
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LovableCard;
|
||||
```
|
||||
|
||||
### 3. LovableTransactionCard 컴포넌트
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import LovableCard from './LovableCard';
|
||||
import { formatCurrency } from '../utils/formatters';
|
||||
|
||||
interface TransactionType {
|
||||
id: string;
|
||||
title: string;
|
||||
amount: number;
|
||||
date: string;
|
||||
category: string;
|
||||
type: 'income' | 'expense';
|
||||
}
|
||||
|
||||
interface LovableTransactionCardProps {
|
||||
transaction: TransactionType;
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const LovableTransactionCard: React.FC<LovableTransactionCardProps> = ({
|
||||
transaction,
|
||||
className = '',
|
||||
onClick,
|
||||
}) => {
|
||||
const { title, amount, date, category, type } = transaction;
|
||||
|
||||
// 카테고리에 따른 아이콘 선택
|
||||
const getCategoryIcon = (category: string) => {
|
||||
switch (category.toLowerCase()) {
|
||||
case '식비':
|
||||
return '🍴';
|
||||
case '교통':
|
||||
return '🚗';
|
||||
case '쇼핑':
|
||||
return '🛍️';
|
||||
case '여가':
|
||||
return '⛲️';
|
||||
case '금융':
|
||||
return '💰';
|
||||
case '급여':
|
||||
return '💸';
|
||||
default:
|
||||
return '📃';
|
||||
}
|
||||
};
|
||||
|
||||
const formattedDate = new Date(date).toLocaleDateString('ko-KR', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
});
|
||||
|
||||
return (
|
||||
<LovableCard
|
||||
className={twMerge('flex items-center justify-between', className)}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="w-10 h-10 rounded-full bg-primary-100 flex items-center justify-center mr-3 shadow-neumo-sm">
|
||||
<span className="text-xl">{getCategoryIcon(category)}</span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-medium text-primary-900">{title}</h3>
|
||||
<p className="text-sm text-primary-600">{formattedDate}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`font-bold ${type === 'income' ? 'text-green-600' : 'text-red-600'}`}>
|
||||
{type === 'income' ? '+' : '-'}{formatCurrency(amount)}
|
||||
</div>
|
||||
</LovableCard>
|
||||
);
|
||||
};
|
||||
|
||||
export default LovableTransactionCard;
|
||||
```
|
||||
|
||||
### 4. LovableAddTransactionButton 컴포넌트
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
interface LovableAddTransactionButtonProps {
|
||||
onAddIncome?: () => void;
|
||||
onAddExpense?: () => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const LovableAddTransactionButton: React.FC<LovableAddTransactionButtonProps> = ({
|
||||
onAddIncome,
|
||||
onAddExpense,
|
||||
className = '',
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const toggleOpen = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
const handleAddIncome = () => {
|
||||
if (onAddIncome) {
|
||||
onAddIncome();
|
||||
}
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const handleAddExpense = () => {
|
||||
if (onAddExpense) {
|
||||
onAddExpense();
|
||||
}
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={twMerge('fixed bottom-6 right-6 z-50', className)}>
|
||||
{isOpen && (
|
||||
<div className="flex flex-col items-end mb-4 space-y-3">
|
||||
<button
|
||||
onClick={handleAddIncome}
|
||||
className="flex items-center bg-primary-50 text-green-600 px-4 py-2 rounded-xl shadow-neumo hover:shadow-neumo-pressed transition-all duration-200"
|
||||
>
|
||||
<span className="mr-2">💸</span>
|
||||
<span>수입 추가</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleAddExpense}
|
||||
className="flex items-center bg-primary-50 text-red-600 px-4 py-2 rounded-xl shadow-neumo hover:shadow-neumo-pressed transition-all duration-200"
|
||||
>
|
||||
<span className="mr-2">💳</span>
|
||||
<span>지출 추가</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
onClick={toggleOpen}
|
||||
className={`w-14 h-14 rounded-full bg-primary-100 text-primary-900 flex items-center justify-center shadow-neumo-elevated hover:shadow-neumo transition-all duration-300 ${isOpen ? 'rotate-45' : ''}`}
|
||||
>
|
||||
<span className="text-2xl font-bold">+</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LovableAddTransactionButton;
|
||||
```
|
||||
|
||||
### 5. Tailwind CSS 구성
|
||||
|
||||
```ts
|
||||
// tailwind.config.ts
|
||||
import type { Config } from 'tailwindcss';
|
||||
|
||||
const config: Config = {
|
||||
content: [
|
||||
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: {
|
||||
50: '#f5f7fa',
|
||||
100: '#e4e7eb',
|
||||
200: '#cbd2d9',
|
||||
300: '#9aa5b1',
|
||||
400: '#7b8794',
|
||||
500: '#616e7c',
|
||||
600: '#52606d',
|
||||
700: '#3e4c59',
|
||||
800: '#323f4b',
|
||||
900: '#1f2933',
|
||||
},
|
||||
secondary: {
|
||||
50: '#e3f8ff',
|
||||
100: '#b3ecff',
|
||||
200: '#81defd',
|
||||
300: '#5ed0fa',
|
||||
400: '#40c3f7',
|
||||
500: '#2bb0ed',
|
||||
600: '#1992d4',
|
||||
700: '#127fbf',
|
||||
800: '#0b69a3',
|
||||
900: '#035388',
|
||||
},
|
||||
},
|
||||
boxShadow: {
|
||||
'neumo': '5px 5px 10px #d1d9e6, -5px -5px 10px #ffffff',
|
||||
'neumo-sm': '3px 3px 6px #d1d9e6, -3px -3px 6px #ffffff',
|
||||
'neumo-pressed': 'inset 5px 5px 10px #d1d9e6, inset -5px -5px 10px #ffffff',
|
||||
'neumo-elevated': '10px 10px 20px #d1d9e6, -10px -10px 20px #ffffff',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
## 결론
|
||||
|
||||
Lovable UI 컴포넌트는 Zellyy Finance 앱의 차별화된 사용자 경험을 제공하기 위한 핵심 요소입니다. Flutter에서 React와 Tailwind CSS를 사용한 웹 기반 앱으로 전환하면서, 뉴모피즘 스타일을 적용하여 입체적이고 부드러운 디자인을 구현하였습니다.
|
||||
|
||||
React의 컴포넌트 기반 아키텍처와 Tailwind CSS의 유틸리티 클래스를 활용하여 재사용 가능한 컴포넌트를 구축함으로써, 개발 효율성을 높이고 일관된 사용자 경험을 제공할 수 있습니다. 특히 커스텀 그림자 효과를 활용한 뉴모피즘 스타일은 사용자에게 매력적인 인터페이스를 제공합니다.
|
||||
|
||||
이러한 Lovable UI 컴포넌트 라이브러리는 앞으로도 지속적으로 개선되고 확장될 예정이며, 사용자 피드백을 반영하여 더욱 향상된 경험을 제공할 계획입니다. 이를 통해 Zellyy Finance 앱은 사용자에게 차별화된 가치를 제공하고, 재무 관리에 도움이 되는 유용한 도구로 자리매김할 것입니다.
|
||||
408
docs/02_기술_문서/Nginx_Supabase_설치_가이드.md
Normal file
@@ -0,0 +1,408 @@
|
||||
# Nginx와 Supabase 설치 가이드
|
||||
|
||||
이 문서는 Debian 12 서버에 Nginx와 Supabase를 설치하고 설정하는 과정을 안내합니다.
|
||||
|
||||
## 1. 서버 접속
|
||||
|
||||
SSH 키를 사용하여 서버에 접속합니다:
|
||||
|
||||
```bash
|
||||
ssh a11
|
||||
```
|
||||
|
||||
또는 전체 명령어를 사용할 수도 있습니다:
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/id_ed25519_ism ism-admin@a11.ism.kr
|
||||
```
|
||||
|
||||
## 2. 시스템 업데이트
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt upgrade -y
|
||||
```
|
||||
|
||||
## 3. Nginx 설치 및 설정
|
||||
|
||||
### 3.1 Nginx 설치
|
||||
|
||||
```bash
|
||||
sudo apt install -y nginx
|
||||
```
|
||||
|
||||
### 3.2 방화벽 설정
|
||||
|
||||
```bash
|
||||
sudo apt install -y ufw
|
||||
sudo ufw allow 'Nginx Full' # 80, 443 포트 허용
|
||||
sudo ufw allow 'OpenSSH' # SSH 포트 허용
|
||||
sudo ufw enable
|
||||
```
|
||||
|
||||
### 3.3 SSL 인증서 발급 (Let's Encrypt)
|
||||
|
||||
```bash
|
||||
sudo apt install -y certbot python3-certbot-nginx
|
||||
sudo certbot --nginx -d a11.ism.kr
|
||||
```
|
||||
|
||||
### 3.4 Nginx 설정 파일 생성
|
||||
|
||||
```bash
|
||||
sudo nano /etc/nginx/sites-available/supabase
|
||||
```
|
||||
|
||||
다음 내용을 파일에 추가합니다:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name a11.ism.kr;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name a11.ism.kr;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/a11.ism.kr/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/a11.ism.kr/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
# Kong API
|
||||
location /api {
|
||||
proxy_pass http://localhost:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Kong Admin API
|
||||
location /kong {
|
||||
proxy_pass http://localhost:8001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Studio
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# GoTrue
|
||||
location /auth {
|
||||
proxy_pass http://localhost:9999;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# PostgREST
|
||||
location /rest/v1 {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Storage
|
||||
location /storage/v1 {
|
||||
proxy_pass http://localhost:5000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# WebSocket 지원
|
||||
location /realtime/v1 {
|
||||
proxy_pass http://localhost:4000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
설정 파일을 활성화하고 Nginx를 재시작합니다:
|
||||
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/supabase /etc/nginx/sites-enabled/
|
||||
sudo nginx -t # 설정 파일 문법 검사
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
## 4. Docker 및 Docker Compose 설치
|
||||
|
||||
### 4.1 Docker 설치
|
||||
|
||||
```bash
|
||||
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
sudo apt update
|
||||
sudo apt install -y docker-ce docker-ce-cli containerd.io
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
### 4.2 Docker Compose 설치
|
||||
|
||||
```bash
|
||||
sudo apt install -y docker-compose-plugin
|
||||
```
|
||||
|
||||
## 5. Supabase 설치
|
||||
|
||||
### 5.1 Supabase 프로젝트 클론
|
||||
|
||||
```bash
|
||||
mkdir -p ~/supabase
|
||||
cd ~/supabase
|
||||
git clone --depth 1 https://github.com/supabase/supabase
|
||||
cd supabase/docker
|
||||
```
|
||||
|
||||
### 5.2 환경 변수 설정
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
다음과 같이 환경 변수를 설정합니다:
|
||||
|
||||
```
|
||||
# Supabase 설정
|
||||
POSTGRES_PASSWORD=zellyy_finance_secure_password_2025
|
||||
JWT_SECRET=$(openssl rand -base64 32)
|
||||
ANON_KEY=$(openssl rand -base64 32)
|
||||
SERVICE_ROLE_KEY=$(openssl rand -base64 32)
|
||||
|
||||
# API 및 사이트 URL
|
||||
SITE_URL=https://a11.ism.kr
|
||||
API_EXTERNAL_URL=https://a11.ism.kr
|
||||
STUDIO_PORT=3000
|
||||
|
||||
# 대시보드 인증
|
||||
DASHBOARD_USERNAME=hansoo
|
||||
DASHBOARD_PASSWORD=zellyy_secure_dashboard_password_2025
|
||||
|
||||
# 이메일 설정 (선택 사항)
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
SMTP_USER=
|
||||
SMTP_PASS=
|
||||
SMTP_SENDER_NAME=
|
||||
```
|
||||
|
||||
### 5.3 Supabase 실행
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 5.4 상태 확인
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
## 6. 인증 정보 기록
|
||||
|
||||
설치 후 생성된 API 키와 JWT 시크릿을 기록합니다. 이 정보는 `.env` 파일에서 확인할 수 있습니다:
|
||||
|
||||
```bash
|
||||
cd ~/supabase/supabase/docker
|
||||
grep -E "JWT_SECRET|ANON_KEY|SERVICE_ROLE_KEY" .env
|
||||
```
|
||||
|
||||
이 정보를 `/Users/hansoo./Documents/my vault/1. Project/ZELLYY/적자 탈출 가계부/02_기술_문서/Supabase_인증_정보.md` 파일에 기록합니다.
|
||||
|
||||
## 7. 데이터베이스 초기 설정
|
||||
|
||||
### 7.1 PostgreSQL 접속
|
||||
|
||||
```bash
|
||||
docker exec -it supabase-db psql -U postgres
|
||||
```
|
||||
|
||||
### 7.2 기본 스키마 생성
|
||||
|
||||
```sql
|
||||
-- 사용자 스키마 생성
|
||||
CREATE SCHEMA app;
|
||||
|
||||
-- Row Level Security 활성화
|
||||
ALTER TABLE app.users ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- 기본 정책 설정
|
||||
CREATE POLICY "사용자는 자신의 데이터만 볼 수 있음" ON app.users
|
||||
FOR ALL
|
||||
USING (auth.uid() = user_id);
|
||||
```
|
||||
|
||||
## 8. 백업 설정
|
||||
|
||||
### 8.1 자동 백업 스크립트 생성
|
||||
|
||||
```bash
|
||||
mkdir -p ~/backup-scripts
|
||||
nano ~/backup-scripts/backup-postgres.sh
|
||||
```
|
||||
|
||||
다음 내용을 파일에 추가합니다:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
BACKUP_DIR="/home/ism-admin/backups"
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
BACKUP_FILE="$BACKUP_DIR/postgres_backup_$TIMESTAMP.sql.gz"
|
||||
|
||||
# 백업 디렉토리 생성
|
||||
mkdir -p $BACKUP_DIR
|
||||
|
||||
# 데이터베이스 백업
|
||||
docker exec supabase-db pg_dumpall -U postgres | gzip > $BACKUP_FILE
|
||||
|
||||
# 30일 이상 된 백업 삭제
|
||||
find $BACKUP_DIR -name "postgres_backup_*.sql.gz" -type f -mtime +30 -delete
|
||||
```
|
||||
|
||||
스크립트에 실행 권한 부여:
|
||||
|
||||
```bash
|
||||
chmod +x ~/backup-scripts/backup-postgres.sh
|
||||
```
|
||||
|
||||
### 8.2 Cron 작업 설정
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
다음 내용을 추가하여 매일 새벽 3시에 백업을 실행합니다:
|
||||
|
||||
```
|
||||
0 3 * * * /home/ism-admin/backup-scripts/backup-postgres.sh
|
||||
```
|
||||
|
||||
## 9. 모니터링 설정
|
||||
|
||||
### 9.1 기본 모니터링
|
||||
|
||||
```bash
|
||||
sudo apt install -y htop
|
||||
```
|
||||
|
||||
### 9.2 로그 모니터링
|
||||
|
||||
```bash
|
||||
# 모든 컨테이너 로그 확인
|
||||
docker compose logs
|
||||
|
||||
# 특정 서비스 로그 확인 (예: PostgreSQL)
|
||||
docker compose logs db
|
||||
```
|
||||
|
||||
## 10. 문제 해결
|
||||
|
||||
### 10.1 Nginx 문제
|
||||
|
||||
```bash
|
||||
# Nginx 상태 확인
|
||||
sudo systemctl status nginx
|
||||
|
||||
# Nginx 로그 확인
|
||||
sudo tail -f /var/log/nginx/error.log
|
||||
```
|
||||
|
||||
### 10.2 Docker 문제
|
||||
|
||||
```bash
|
||||
# Docker 상태 확인
|
||||
docker ps
|
||||
|
||||
# Docker 로그 확인
|
||||
docker logs supabase-db
|
||||
```
|
||||
|
||||
### 10.3 인증서 갱신
|
||||
|
||||
```bash
|
||||
sudo certbot renew --dry-run
|
||||
```
|
||||
|
||||
## 11. 유지 관리
|
||||
|
||||
### 11.1 Supabase 업데이트
|
||||
|
||||
```bash
|
||||
cd ~/supabase/supabase/docker
|
||||
git pull
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 11.2 시스템 업데이트
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt upgrade -y
|
||||
```
|
||||
|
||||
## 12. 보안 강화
|
||||
|
||||
### 12.1 SSH 보안 강화
|
||||
|
||||
```bash
|
||||
sudo nano /etc/ssh/sshd_config
|
||||
```
|
||||
|
||||
다음 설정을 추가/수정합니다:
|
||||
|
||||
```
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
X11Forwarding no
|
||||
```
|
||||
|
||||
SSH 서비스 재시작:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart sshd
|
||||
```
|
||||
|
||||
### 12.2 방화벽 확인
|
||||
|
||||
```bash
|
||||
sudo ufw status
|
||||
```
|
||||
|
||||
## 13. 완료
|
||||
|
||||
이제 Nginx와 Supabase가 설치되었습니다. 다음 URL로 접속하여 확인할 수 있습니다:
|
||||
|
||||
- Supabase Studio: https://a11.ism.kr
|
||||
- API 엔드포인트: https://a11.ism.kr/api
|
||||
|
||||
설치 후 생성된 API 키와 JWT 시크릿을 `Supabase_인증_정보.md` 파일에 기록하는 것을 잊지 마세요.
|
||||
657
docs/02_기술_문서/Supabase_설정_가이드.md
Normal file
@@ -0,0 +1,657 @@
|
||||
# Supabase 설정 가이드 - Debian 12 서버 설치
|
||||
|
||||
## 1. Supabase 소개
|
||||
|
||||
Supabase는 PostgreSQL 데이터베이스를 기반으로 하는 백엔드 서비스입니다. 다음과 같은 기능을 제공합니다:
|
||||
|
||||
- **데이터베이스**: PostgreSQL 데이터베이스
|
||||
- **인증**: 사용자 인증 및 권한 관리
|
||||
- **스토리지**: 파일 저장 및 관리
|
||||
- **API**: 자동 생성되는 RESTful API 및 실시간 구독
|
||||
- **Edge Functions**: 서버리스 함수
|
||||
|
||||
이 가이드에서는 Debian 12 서버에 Supabase를 직접 설치하고 설정하는 방법을 안내합니다.
|
||||
|
||||
## 2. Debian 12 서버에 Supabase 설치
|
||||
|
||||
### 2.1 사전 요구 사항
|
||||
|
||||
1. Debian 12가 설치된 서버
|
||||
2. 루트 또는 sudo 권한이 있는 사용자
|
||||
3. 최소 사양:
|
||||
- CPU: 2코어 이상
|
||||
- RAM: 4GB 이상
|
||||
- 저장공간: 20GB 이상
|
||||
- 고정 IP 주소 (권장)
|
||||
|
||||
### 2.2 Docker 및 Docker Compose 설치
|
||||
|
||||
Supabase는 Docker 컨테이너로 실행되므로 먼저 Docker와 Docker Compose를 설치해야 합니다:
|
||||
|
||||
```bash
|
||||
# 시스템 업데이트
|
||||
sudo apt update
|
||||
sudo apt upgrade -y
|
||||
|
||||
# 필요한 패키지 설치
|
||||
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
|
||||
|
||||
# Docker 공식 GPG 키 추가
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
|
||||
# Docker 저장소 추가
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# Docker 설치
|
||||
sudo apt update
|
||||
sudo apt install -y docker-ce docker-ce-cli containerd.io
|
||||
|
||||
# 현재 사용자를 docker 그룹에 추가 (sudo 없이 Docker 사용 가능)
|
||||
sudo usermod -aG docker $USER
|
||||
|
||||
# Docker Compose 설치
|
||||
sudo apt install -y docker-compose-plugin
|
||||
```
|
||||
|
||||
설치 후 로그아웃했다가 다시 로그인하거나 다음 명령을 실행하여 그룹 변경사항을 적용합니다:
|
||||
```bash
|
||||
newgrp docker
|
||||
```
|
||||
|
||||
### 2.3 Supabase 설치
|
||||
|
||||
1. Supabase 프로젝트 디렉토리 생성:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/supabase
|
||||
cd ~/supabase
|
||||
```
|
||||
|
||||
2. GitHub에서 Supabase Docker 프로젝트 클론:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/supabase/supabase.git
|
||||
cd supabase/docker
|
||||
```
|
||||
|
||||
3. 환경 변수 설정:
|
||||
|
||||
```bash
|
||||
# .env 파일 편집
|
||||
nano .env
|
||||
```
|
||||
|
||||
다음 중요 변수들을 설정합니다. 예시는 적자 탈출 가계부 프로젝트의 실제 설정입니다 (실제 사용 시 보안키는 변경하세요):
|
||||
|
||||
```bash
|
||||
# Supabase 설정
|
||||
POSTGRES_PASSWORD=zellyy_finance_secure_password_2025
|
||||
JWT_SECRET=$(openssl rand -base64 32)
|
||||
ANON_KEY=$(openssl rand -base64 32)
|
||||
SERVICE_ROLE_KEY=$(openssl rand -base64 32)
|
||||
|
||||
# API 및 사이트 URL
|
||||
SITE_URL=https://your-domain.com
|
||||
API_EXTERNAL_URL=https://your-domain.com
|
||||
SUPABASE_PUBLIC_URL=https://your-domain.com
|
||||
STUDIO_PORT=3000
|
||||
|
||||
# 대시보드 인증
|
||||
DASHBOARD_USERNAME=your_username
|
||||
DASHBOARD_PASSWORD=your_secure_dashboard_password
|
||||
|
||||
# PostgreSQL 설정
|
||||
POSTGRES_HOST=db
|
||||
POSTGRES_DB=postgres
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_USER=postgres
|
||||
|
||||
# Kong 설정
|
||||
KONG_HTTP_PORT=8000
|
||||
KONG_HTTPS_PORT=8443
|
||||
|
||||
# 인증 설정
|
||||
JWT_EXPIRY=3600
|
||||
ENABLE_EMAIL_SIGNUP=true
|
||||
ENABLE_EMAIL_AUTOCONFIRM=true
|
||||
ENABLE_PHONE_SIGNUP=true
|
||||
ENABLE_PHONE_AUTOCONFIRM=true
|
||||
DISABLE_SIGNUP=false
|
||||
ENABLE_ANONYMOUS_USERS=false
|
||||
GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED=false
|
||||
|
||||
# 이메일 설정 (필요한 경우)
|
||||
SMTP_ADMIN_EMAIL=admin@example.com
|
||||
SMTP_HOST=mail.example.com
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=smtp_user
|
||||
SMTP_PASS=smtp_password
|
||||
SMTP_SENDER_NAME=Zellyy Finance
|
||||
|
||||
# URL 경로 설정
|
||||
MAILER_URLPATHS_CONFIRMATION=/auth/v1/verify
|
||||
MAILER_URLPATHS_INVITE=/auth/v1/verify
|
||||
MAILER_URLPATHS_RECOVERY=/auth/v1/verify
|
||||
MAILER_URLPATHS_EMAIL_CHANGE=/auth/v1/verify
|
||||
|
||||
# 추가 설정
|
||||
PGRST_DB_SCHEMAS=public,storage,graphql_public
|
||||
SECRET_KEY_BASE=$(openssl rand -base64 32)
|
||||
STUDIO_DEFAULT_ORGANIZATION=Default Organization
|
||||
STUDIO_DEFAULT_PROJECT=Default Project
|
||||
IMGPROXY_ENABLE_WEBP_DETECTION=true
|
||||
FUNCTIONS_VERIFY_JWT=true
|
||||
POOLER_TENANT_ID=tenant1
|
||||
POOLER_DEFAULT_POOL_SIZE=20
|
||||
POOLER_MAX_CLIENT_CONN=100
|
||||
VAULT_ENC_KEY=$(openssl rand -base64 32)
|
||||
POOLER_PROXY_PORT_TRANSACTION=6543
|
||||
```
|
||||
|
||||
4. Supabase 시작:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
이 명령은 모든 Supabase 서비스(PostgreSQL, Kong, GoTrue, PostgREST, Storage 등)를 백그라운드에서 시작합니다.
|
||||
|
||||
### 2.4 SSL/TLS 설정
|
||||
|
||||
프로덕션 환경에서는 HTTPS를 사용하는 것이 필수적입니다. Nginx와 Let's Encrypt를 사용하여 SSL을 설정하세요:
|
||||
|
||||
1. Nginx 및 Certbot 설치:
|
||||
|
||||
```bash
|
||||
sudo apt install -y nginx certbot python3-certbot-nginx
|
||||
```
|
||||
|
||||
2. Let's Encrypt를 통한 SSL 인증서 발급:
|
||||
|
||||
```bash
|
||||
sudo certbot --nginx -d your-domain.com
|
||||
```
|
||||
|
||||
3. Nginx 설정 파일 생성:
|
||||
|
||||
```bash
|
||||
sudo nano /etc/nginx/sites-available/default
|
||||
```
|
||||
|
||||
다음 내용을 추가합니다:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name your-domain.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
||||
|
||||
# Supabase Studio
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
}
|
||||
|
||||
# Supabase API (Kong)
|
||||
location /rest/v1/ {
|
||||
proxy_pass http://localhost:8000/rest/v1/;
|
||||
}
|
||||
|
||||
# Supabase Auth
|
||||
location /auth/v1/ {
|
||||
proxy_pass http://localhost:8000/auth/v1/;
|
||||
}
|
||||
|
||||
# Supabase Storage
|
||||
location /storage/v1/ {
|
||||
proxy_pass http://localhost:8000/storage/v1/;
|
||||
}
|
||||
|
||||
# Supabase Realtime
|
||||
location /realtime/v1/ {
|
||||
proxy_pass http://localhost:8000/realtime/v1/;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. Nginx 설정 테스트 및 재시작:
|
||||
|
||||
```bash
|
||||
sudo nginx -t
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
※ 주의: Nginx 설정에서 `proxy_set_header` 지시문을 사용할 때 문법에 주의하세요. 필요한 경우 더 복잡한 헤더 설정을 사용할 수 있지만, 기본 설정으로도 충분히 작동합니다.
|
||||
|
||||
### 2.5 방화벽 설정
|
||||
|
||||
필요한 포트만 열도록 방화벽을 설정합니다:
|
||||
|
||||
```bash
|
||||
sudo apt install -y ufw
|
||||
sudo ufw allow ssh
|
||||
sudo ufw allow http
|
||||
sudo ufw allow https
|
||||
sudo ufw enable
|
||||
```
|
||||
|
||||
### 2.6 Supabase 관리
|
||||
|
||||
Supabase 서비스 관리를 위한 기본 명령어:
|
||||
|
||||
```bash
|
||||
# 서비스 상태 확인
|
||||
cd ~/supabase
|
||||
docker compose ps
|
||||
|
||||
# 로그 확인
|
||||
docker compose logs -f
|
||||
|
||||
# 서비스 중지
|
||||
docker compose down
|
||||
|
||||
# 서비스 시작
|
||||
docker compose up -d
|
||||
|
||||
# 서비스 재시작
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
### 2.7 백업 설정
|
||||
|
||||
정기적인 데이터베이스 백업을 설정하는 것이 좋습니다:
|
||||
|
||||
1. 백업 스크립트 생성:
|
||||
|
||||
```bash
|
||||
nano ~/backup-supabase.sh
|
||||
```
|
||||
|
||||
다음 내용을 추가합니다:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
BACKUP_DIR=~/supabase-backups
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
mkdir -p $BACKUP_DIR
|
||||
|
||||
# PostgreSQL 백업
|
||||
cd ~/supabase
|
||||
docker compose exec db pg_dump -U postgres -d postgres > $BACKUP_DIR/supabase_$TIMESTAMP.sql
|
||||
|
||||
# 오래된 백업 삭제 (30일 이상)
|
||||
find $BACKUP_DIR -name "supabase_*.sql" -type f -mtime +30 -delete
|
||||
```
|
||||
|
||||
2. 스크립트에 실행 권한 부여:
|
||||
|
||||
```bash
|
||||
chmod +x ~/backup-supabase.sh
|
||||
```
|
||||
|
||||
3. Cron 작업 설정 (매일 백업):
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
다음 줄을 추가합니다:
|
||||
|
||||
```
|
||||
0 2 * * * ~/backup-supabase.sh
|
||||
```
|
||||
|
||||
### 2.8 모니터링 설정 (선택 사항)
|
||||
|
||||
서버 상태 모니터링을 위해 Prometheus와 Grafana를 설정할 수 있습니다:
|
||||
|
||||
```bash
|
||||
# Prometheus와 Grafana 설치를 위한 Docker Compose 파일 다운로드
|
||||
mkdir -p ~/monitoring
|
||||
cd ~/monitoring
|
||||
curl -L https://raw.githubusercontent.com/stefanprodan/dockprom/master/docker-compose.yml -o docker-compose.yml
|
||||
|
||||
# 서비스 시작
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Grafana는 기본적으로 http://your-server-ip:3000에서 접근할 수 있으며, 기본 사용자 이름과 비밀번호는 admin/admin입니다.
|
||||
|
||||
## 3. 데이터베이스 설정
|
||||
|
||||
### 3.1 데이터베이스 접속
|
||||
|
||||
Supabase 설치 후 PostgreSQL 데이터베이스에 직접 접속할 수 있습니다:
|
||||
|
||||
```bash
|
||||
cd ~/supabase
|
||||
docker compose exec db psql -U postgres
|
||||
```
|
||||
|
||||
### 3.2 테이블 생성 예시
|
||||
|
||||
다음과 같이 SQL 명령을 사용하여 테이블을 생성할 수 있습니다:
|
||||
|
||||
```sql
|
||||
-- 사용자 테이블 생성
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
full_name TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- RLS(Row Level Security) 정책 설정
|
||||
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 데이터만 볼 수 있음" ON users
|
||||
FOR SELECT USING (auth.uid() = id);
|
||||
CREATE POLICY "사용자는 자신의 데이터만 수정할 수 있음" ON users
|
||||
FOR UPDATE USING (auth.uid() = id);
|
||||
```
|
||||
|
||||
## 4. 인증 설정
|
||||
|
||||
### 4.1 이메일/비밀번호 인증 설정
|
||||
|
||||
자체 호스팅된 Supabase에서 이메일/비밀번호 인증을 설정하려면:
|
||||
|
||||
1. `.env` 파일에서 이메일 설정을 구성합니다:
|
||||
```
|
||||
SMTP_HOST=your-smtp-host
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=your-smtp-user
|
||||
SMTP_PASS=your-smtp-password
|
||||
SMTP_SENDER_NAME=Zellyy Finance
|
||||
```
|
||||
|
||||
2. 변경 후 서비스를 재시작합니다:
|
||||
```bash
|
||||
cd ~/supabase
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 4.2 소셜 로그인 설정 (선택 사항)
|
||||
|
||||
소셜 로그인을 추가하려면 각 제공업체의 설정을 `.env` 파일에 추가해야 합니다:
|
||||
|
||||
```
|
||||
# Google OAuth
|
||||
GOTRUE_EXTERNAL_GOOGLE_ENABLED=true
|
||||
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID=your-google-client-id
|
||||
GOTRUE_EXTERNAL_GOOGLE_SECRET=your-google-client-secret
|
||||
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI=https://your-domain.com/auth/v1/callback
|
||||
|
||||
# GitHub OAuth
|
||||
GOTRUE_EXTERNAL_GITHUB_ENABLED=true
|
||||
GOTRUE_EXTERNAL_GITHUB_CLIENT_ID=your-github-client-id
|
||||
GOTRUE_EXTERNAL_GITHUB_SECRET=your-github-client-secret
|
||||
GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI=https://your-domain.com/auth/v1/callback
|
||||
```
|
||||
|
||||
## 5. 스토리지 설정
|
||||
|
||||
영수증 이미지 등을 저장하기 위한 스토리지 버킷을 설정합니다:
|
||||
|
||||
### 5.1 스토리지 버킷 생성
|
||||
|
||||
SQL을 사용하여 스토리지 버킷을 생성할 수 있습니다:
|
||||
|
||||
```sql
|
||||
-- PostgreSQL에 접속
|
||||
cd ~/supabase
|
||||
docker compose exec db psql -U postgres
|
||||
|
||||
-- 스토리지 버킷 생성
|
||||
INSERT INTO storage.buckets (id, name, public)
|
||||
VALUES ('receipts', 'receipts', false);
|
||||
```
|
||||
|
||||
### 5.2 스토리지 보안 정책 설정
|
||||
|
||||
스토리지 버킷에 대한 접근 권한을 설정합니다:
|
||||
|
||||
```sql
|
||||
-- 사용자는 자신의 파일만 업로드할 수 있음
|
||||
CREATE POLICY "사용자는 자신의 파일만 업로드할 수 있음" ON storage.objects
|
||||
FOR INSERT WITH CHECK (auth.uid() = owner);
|
||||
|
||||
-- 사용자는 자신의 파일만 조회할 수 있음
|
||||
CREATE POLICY "사용자는 자신의 파일만 조회할 수 있음" ON storage.objects
|
||||
FOR SELECT USING (auth.uid() = owner);
|
||||
|
||||
-- 사용자는 자신의 파일만 삭제할 수 있음
|
||||
CREATE POLICY "사용자는 자신의 파일만 삭제할 수 있음" ON storage.objects
|
||||
FOR DELETE USING (auth.uid() = owner);
|
||||
```
|
||||
|
||||
## 6. API 및 클라이언트 라이브러리
|
||||
|
||||
### 6.1 Supabase 클라이언트 설정 (Flutter)
|
||||
|
||||
Flutter 프로젝트에서 자체 호스팅된 Supabase를 사용하기 위한 설정:
|
||||
|
||||
1. 필요한 패키지 추가:
|
||||
|
||||
```yaml
|
||||
# pubspec.yaml
|
||||
dependencies:
|
||||
supabase_flutter: ^1.10.14
|
||||
```
|
||||
|
||||
2. 초기화 코드:
|
||||
|
||||
```dart
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
await Supabase.initialize(
|
||||
url: 'https://your-domain.com', // 자체 호스팅 서버 URL
|
||||
anonKey: 'your-anon-key', // .env 파일에서 설정한 ANON_KEY
|
||||
);
|
||||
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
// 어디서나 클라이언트에 접근
|
||||
final supabase = Supabase.instance.client;
|
||||
```
|
||||
|
||||
### 6.2 기본 API 사용 예시
|
||||
|
||||
```dart
|
||||
// 사용자 등록
|
||||
Future<void> signUp(String email, String password) async {
|
||||
await supabase.auth.signUp(
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
}
|
||||
|
||||
// 로그인
|
||||
Future<void> signIn(String email, String password) async {
|
||||
await supabase.auth.signInWithPassword(
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
}
|
||||
|
||||
// 데이터 조회
|
||||
Future<List<Map<String, dynamic>>> getExpenses() async {
|
||||
final response = await supabase
|
||||
.from('expenses')
|
||||
.select()
|
||||
.eq('user_id', supabase.auth.currentUser!.id);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// 데이터 추가
|
||||
Future<void> addExpense(Map<String, dynamic> expenseData) async {
|
||||
await supabase
|
||||
.from('expenses')
|
||||
.insert(expenseData);
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 유지 관리 및 모니터링
|
||||
|
||||
### 7.1 서비스 관리 명령어
|
||||
|
||||
Supabase 서비스 관리를 위한 기본 명령어:
|
||||
|
||||
```bash
|
||||
# 서비스 상태 확인
|
||||
cd ~/supabase
|
||||
docker compose ps
|
||||
|
||||
# 로그 확인
|
||||
docker compose logs -f
|
||||
|
||||
# 서비스 중지
|
||||
docker compose down
|
||||
|
||||
# 서비스 시작
|
||||
docker compose up -d
|
||||
|
||||
# 서비스 재시작
|
||||
docker compose restart
|
||||
|
||||
# 특정 서비스만 재시작 (예: PostgreSQL)
|
||||
docker compose restart db
|
||||
```
|
||||
|
||||
### 7.2 데이터베이스 백업 및 복원
|
||||
|
||||
#### 백업
|
||||
|
||||
```bash
|
||||
cd ~/supabase
|
||||
docker compose exec db pg_dump -U postgres -d postgres > backup_$(date +%Y%m%d).sql
|
||||
```
|
||||
|
||||
#### 복원
|
||||
|
||||
```bash
|
||||
cd ~/supabase
|
||||
cat backup_file.sql | docker compose exec -T db psql -U postgres -d postgres
|
||||
```
|
||||
|
||||
### 7.3 업데이트
|
||||
|
||||
Supabase를 최신 버전으로 업데이트하려면:
|
||||
|
||||
```bash
|
||||
cd ~/supabase
|
||||
docker compose pull
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## 8. 보안 모범 사례
|
||||
|
||||
1. **API 키 보호**: `service_role` 키는 절대 클라이언트 코드에 포함하지 마세요.
|
||||
2. **RLS(Row Level Security)**: 모든 테이블에 RLS 정책을 설정하세요.
|
||||
3. **환경 변수**: API 키와 같은 민감한 정보는 환경 변수로 관리하세요.
|
||||
4. **정기적인 비밀번호 변경**: 데이터베이스 비밀번호를 정기적으로 변경하세요.
|
||||
5. **최소 권한 원칙**: 각 사용자와 서비스에 필요한 최소한의 권한만 부여하세요.
|
||||
6. **방화벽 설정**: 필요한 포트만 개방하세요.
|
||||
7. **정기적인 업데이트**: 보안 패치를 위해 정기적으로 시스템을 업데이트하세요.
|
||||
|
||||
## 9. 문제 해결
|
||||
|
||||
### 9.1 문제 해결
|
||||
|
||||
1. **데이터베이스 연결 오류**: `.env` 파일의 POSTGRES_PASSWORD 및 관련 데이터베이스 설정을 확인하세요.
|
||||
2. **SSL 인증서 오류**: Certbot 설정 및 Nginx 구성을 확인하세요.
|
||||
3. **스토리지 문제**: `.env` 파일의 STORAGE_BACKEND 설정을 확인하세요.
|
||||
4. **인증 오류**: `.env` 파일의 JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY 설정을 확인하세요.
|
||||
5. **Pooler 서비스 재시작 문제**:
|
||||
- 문제: `supabase-pooler` 서비스가 계속 재시작되는 문제
|
||||
- 해결: `.env` 파일에 `SUPAVISOR_ENCRYPTION_KEY` 변수를 추가하고 유효한 암호화 키를 설정
|
||||
- 추가 설정: `POOLER_ENABLE_TENANT_SHARDING=true` 옵션 추가로 성능 향상
|
||||
|
||||
6. **Realtime 서비스 Unhealthy 상태**:
|
||||
- 문제: `realtime-dev.supabase-realtime` 서비스가 Unhealthy 상태로 표시됨
|
||||
- 참고: 기본 CRUD 작업에는 영향을 주지 않으며, 실시간 기능을 사용하지 않는 경우 무시 가능
|
||||
- 디버깅: `docker logs realtime-dev.supabase-realtime`로 구체적인 오류 확인 가능
|
||||
|
||||
7. **Nginx 리버스 프록시 502 오류**:
|
||||
- 문제: Nginx에서 502 Bad Gateway 오류 발생
|
||||
- 해결:
|
||||
- Supabase Studio 컨테이너에 포트 매핑 추가 (3000:3000)
|
||||
- Nginx 설정에서 프록시 패스 설정 올바르게 구성
|
||||
- Docker 컨테이너와 Nginx 모두 재시작
|
||||
|
||||
8. **호스트 네임 설정 문제**:
|
||||
- 문제: `SITE_URL` 설정이 올바르지 않아 인증 콜백 오류 발생
|
||||
- 해결: `.env` 파일에서 `SITE_URL`을 정확한 도메인으로 설정 (https://a11.ism.kr)
|
||||
|
||||
### 9.2 지원 받기
|
||||
|
||||
1. [Supabase 문서](https://supabase.com/docs)
|
||||
2. [GitHub 이슈](https://github.com/supabase/supabase/issues)
|
||||
3. [Discord 커뮤니티](https://discord.supabase.com)
|
||||
|
||||
## 10. 다음 단계
|
||||
|
||||
Supabase 설치가 완료되면 다음 단계로 진행하세요:
|
||||
|
||||
1. 데이터베이스 스키마 구현
|
||||
2. API 엔드포인트 개발
|
||||
3. 인증 시스템 테스트
|
||||
4. 프론트엔드 연동 준비
|
||||
|
||||
## 3. 데이터베이스 설정
|
||||
|
||||
### 3.3 Supabase Studio 접근
|
||||
|
||||
Supabase Studio는 데이터베이스 관리, API 탐색, 인증 설정 등을 위한 웹 기반 관리 인터페이스입니다.
|
||||
|
||||
```
|
||||
https://your-domain.com
|
||||
```
|
||||
|
||||
자체 호스팅 환경에서는 Supabase Studio에 별도의 로그인 없이 바로 접근할 수 있습니다. 이는 기본 설정이며, 추가적인 보안이 필요한 경우 Nginx 수준에서 기본 인증을 구성하는 것이 좋습니다.
|
||||
|
||||
> 참고: 클라우드 호스팅 Supabase와 달리, 자체 호스팅 환경에서는 Studio 접근에 대한 인증이 기본적으로 활성화되어 있지 않습니다. 프로덕션 환경에서는 추가 보안 조치를 고려하세요.
|
||||
|
||||
#### Nginx를 통한 기본 인증 추가 (선택 사항)
|
||||
|
||||
보안 강화를 위해 Nginx 설정에 기본 인증을 추가할 수 있습니다:
|
||||
|
||||
```bash
|
||||
# htpasswd 파일 생성
|
||||
sudo apt install apache2-utils
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd your-username
|
||||
```
|
||||
|
||||
Nginx 설정 파일에 다음을 추가:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
# 기존 설정...
|
||||
|
||||
location / {
|
||||
# 기본 인증 추가
|
||||
auth_basic "Restricted Access";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||
|
||||
# 기존 프록시 설정...
|
||||
proxy_pass http://localhost:3000;
|
||||
# ...
|
||||
}
|
||||
|
||||
# 다른 위치 블록...
|
||||
}
|
||||
38
docs/02_기술_문서/Supabase_인증_정보.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Supabase 인증 정보
|
||||
|
||||
## 서버 접속 정보
|
||||
- **서버 주소**: a11.ism.kr
|
||||
- **접속 방법**: SSH 키 인증
|
||||
- **사용자**: ism-admin
|
||||
- **공개 키**: `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHXL6O0/Ydj2Tmsu3kjo0ypVPUCjNV/bxgFPMjM1dzHD ism-admin`
|
||||
- **개인 키 파일**: `~/.ssh/id_ed25519_ism`
|
||||
- **간편 접속 명령어**: `ssh a11` (SSH config에 설정됨)
|
||||
|
||||
## Supabase 환경 변수
|
||||
- **SITE_URL**: https://a11.ism.kr
|
||||
- **API_EXTERNAL_URL**: https://a11.ism.kr
|
||||
- **POSTGRES_PASSWORD**: zellyy_finance_secure_password_2025
|
||||
- **DASHBOARD_USERNAME**: hansoo
|
||||
- **DASHBOARD_PASSWORD**: zellyy_secure_dashboard_password_2025
|
||||
|
||||
## Nginx 인증서 정보
|
||||
- **인증서 발급 방법**: Let's Encrypt (Certbot)
|
||||
- **인증서 갱신 주기**: 자동 (90일)
|
||||
- **인증서 저장 위치**: /etc/letsencrypt/live/a11.ism.kr/
|
||||
|
||||
## API 키 정보
|
||||
- **ANON_KEY**: (설치 후 자동 생성됨 - 여기에 기록 필요)
|
||||
- **SERVICE_ROLE_KEY**: (설치 후 자동 생성됨 - 여기에 기록 필요)
|
||||
- **JWT_SECRET**: (설치 후 자동 생성됨 - 여기에 기록 필요)
|
||||
|
||||
## 데이터베이스 접속 정보
|
||||
- **호스트**: localhost
|
||||
- **포트**: 5432
|
||||
- **데이터베이스**: postgres
|
||||
- **사용자**: postgres
|
||||
- **비밀번호**: zellyy_finance_secure_password_2025
|
||||
|
||||
## 방화벽 설정
|
||||
- 허용 포트: 80(HTTP), 443(HTTPS), 22(SSH)
|
||||
|
||||
> **중요**: 이 문서에는 민감한 보안 정보가 포함되어 있습니다. 안전하게 보관하고 공개 저장소에 업로드하지 마세요.
|
||||
25
docs/02_기술_문서/index.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# 기술 문서
|
||||
|
||||
이 폴더에는 적자 탈출 가계부 프로젝트의 기술적 구현에 관한 문서가 포함되어 있습니다.
|
||||
|
||||
## 문서 목록
|
||||
|
||||
1. [[데이터 모델 설계]] - 데이터 모델 설계 문서
|
||||
2. [[ERD 다이어그램]] - 엔티티 관계 다이어그램
|
||||
3. [[데이터베이스 스키마 스크립트.sql]] - 데이터베이스 스키마 SQL 스크립트
|
||||
4. [[Supabase 설정 가이드]] - Supabase 자체 호스팅 설정 가이드
|
||||
5. [[Supabase 인증 정보]] - Supabase 인증 및 보안 정보 (비공개)
|
||||
6. [[Nginx Supabase 설치 가이드]] - Nginx와 Supabase 설치 및 설정 방법
|
||||
|
||||
## 기술 스택 요약
|
||||
|
||||
적자 탈출 가계부 프로젝트는 다음과 같은 기술 스택을 사용합니다:
|
||||
|
||||
- **프론트엔드**: Flutter (크로스 플랫폼 모바일 앱)
|
||||
- **백엔드**: Supabase (자체 호스팅)
|
||||
- **데이터베이스**: PostgreSQL (Supabase 내장)
|
||||
- **인증**: Supabase Auth
|
||||
- **스토리지**: Supabase Storage
|
||||
- **배포 환경**: Debian 12 서버
|
||||
|
||||
이 문서들은 프로젝트의 기술적 구현에 필요한 상세 정보를 제공하며, 개발자가 시스템을 이해하고 구현하는 데 도움을 줍니다.
|
||||
42
docs/02_기술_문서/기술문서_관리.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 기술 문서 관리
|
||||
|
||||
## 개요
|
||||
Zellyy Finance 프로젝트의 기술 문서는 코드와 함께 Gitea 저장소에서 관리됩니다. 이 문서는 기술 문서의 위치와 관리 방법에 대한 정보를 제공합니다.
|
||||
|
||||
## 기술 문서 위치
|
||||
- **소스 코드 저장소**: `/Users/hansoo./Dev/Zellyy_Finance/docs/`
|
||||
- **Git 저장소 URL**: [Zellyy_Finance Git Repository](https://gitea.com/hansoo/Zellyy_Finance)
|
||||
|
||||
## 문서 관리 원칙
|
||||
- **단일 소스 원칙**: 모든 코드 관련 기술 문서는 Gitea에서만 관리합니다.
|
||||
- **옵시디언 참조 원칙**: 옵시디언에는 Gitea의 문서를 참조하는 링크만 저장합니다.
|
||||
|
||||
## 주요 기술 문서 목록
|
||||
|
||||
### API 문서
|
||||
- [API 엔드포인트](/Users/hansoo./Dev/Zellyy_Finance/docs/api/api_endpoints.md): Zellyy Finance API의 모든 엔드포인트 설명
|
||||
- [API 인증](/Users/hansoo./Dev/Zellyy_Finance/docs/api/authentication.md): API 인증 방법 설명
|
||||
|
||||
### 데이터베이스 문서
|
||||
- [데이터베이스 스키마](/Users/hansoo./Dev/Zellyy_Finance/docs/database/schema.md): 데이터베이스 테이블 구조 및 관계 설명
|
||||
|
||||
### 설계 문서
|
||||
- [아키텍처 설계](/Users/hansoo./Dev/Zellyy_Finance/docs/design/architecture.md): 시스템 아키텍처 설명
|
||||
|
||||
### 요구사항 문서
|
||||
- [기능 요구사항](/Users/hansoo./Dev/Zellyy_Finance/docs/requirements/features.md): 시스템 기능 요구사항 설명
|
||||
|
||||
## 문서 업데이트 방법
|
||||
기술 문서를 업데이트해야 할 경우, 다음 절차를 따릅니다:
|
||||
|
||||
1. Gitea 저장소의 문서만 수정합니다.
|
||||
2. 변경 사항을 커밋하고 푸시합니다.
|
||||
3. 필요한 경우 이 문서에 중요한 변경 사항을 기록합니다.
|
||||
|
||||
## 주의사항
|
||||
- 옵시디언에는 코드나 코드 관련 기술 문서를 저장하지 않는 원칙을 따릅니다.
|
||||
- 기술 문서와 코드의 일관성을 유지하기 위해 항상 Gitea의 문서를 참조하세요.
|
||||
|
||||
## 최근 업데이트
|
||||
- 2025-02-27: 기술 문서 관리 원칙 수립 (Gitea에서만 관리)
|
||||
- 2025-02-27: 기술 문서 참조 링크 추가
|
||||
271
docs/02_기술_문서/데이터_모델_설계.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# 적자 탈출 가계부 - 데이터 모델 설계
|
||||
|
||||
## 1. 핵심 데이터 엔티티
|
||||
|
||||
### 1.1 사용자(Users) 테이블
|
||||
|
||||
```
|
||||
users
|
||||
- id: UUID (PK)
|
||||
- email: STRING (UNIQUE)
|
||||
- password_hash: STRING
|
||||
- name: STRING
|
||||
- profile_image: STRING (nullable)
|
||||
- created_at: TIMESTAMP
|
||||
- updated_at: TIMESTAMP
|
||||
- last_login_at: TIMESTAMP (nullable)
|
||||
- notification_settings: JSON
|
||||
- theme_preference: STRING (default: 'light')
|
||||
- is_active: BOOLEAN (default: true)
|
||||
```
|
||||
|
||||
### 1.2 카드(Cards) 테이블
|
||||
|
||||
```
|
||||
cards
|
||||
- id: UUID (PK)
|
||||
- user_id: UUID (FK -> users.id)
|
||||
- name: STRING
|
||||
- card_type: ENUM ('credit', 'debit', 'prepaid')
|
||||
- card_number_last4: STRING
|
||||
- issuer: STRING
|
||||
- color: STRING (for UI)
|
||||
- payment_day: INTEGER (1-31)
|
||||
- monthly_limit: DECIMAL
|
||||
- is_active: BOOLEAN (default: true)
|
||||
- created_at: TIMESTAMP
|
||||
- updated_at: TIMESTAMP
|
||||
```
|
||||
|
||||
### 1.3 카테고리(Categories) 테이블
|
||||
|
||||
```
|
||||
categories
|
||||
- id: UUID (PK)
|
||||
- name: STRING
|
||||
- icon: STRING
|
||||
- color: STRING
|
||||
- parent_id: UUID (FK -> categories.id, nullable)
|
||||
- is_system: BOOLEAN (default: false)
|
||||
- is_active: BOOLEAN (default: true)
|
||||
- created_at: TIMESTAMP
|
||||
- updated_at: TIMESTAMP
|
||||
```
|
||||
|
||||
### 1.4 지출(Expenses) 테이블
|
||||
|
||||
```
|
||||
expenses
|
||||
- id: UUID (PK)
|
||||
- user_id: UUID (FK -> users.id)
|
||||
- card_id: UUID (FK -> cards.id)
|
||||
- category_id: UUID (FK -> categories.id)
|
||||
- amount: DECIMAL
|
||||
- merchant: STRING
|
||||
- transaction_date: TIMESTAMP
|
||||
- description: TEXT (nullable)
|
||||
- location: GEOGRAPHY (nullable)
|
||||
- is_recurring: BOOLEAN (default: false)
|
||||
- receipt_image: STRING (nullable)
|
||||
- tags: STRING[] (nullable)
|
||||
- created_at: TIMESTAMP
|
||||
- updated_at: TIMESTAMP
|
||||
```
|
||||
|
||||
### 1.5 한도(Limits) 테이블
|
||||
|
||||
```
|
||||
limits
|
||||
- id: UUID (PK)
|
||||
- user_id: UUID (FK -> users.id)
|
||||
- card_id: UUID (FK -> cards.id, nullable)
|
||||
- category_id: UUID (FK -> categories.id, nullable)
|
||||
- amount: DECIMAL
|
||||
- period: ENUM ('daily', 'weekly', 'monthly')
|
||||
- start_date: DATE
|
||||
- end_date: DATE (nullable)
|
||||
- is_active: BOOLEAN (default: true)
|
||||
- created_at: TIMESTAMP
|
||||
- updated_at: TIMESTAMP
|
||||
```
|
||||
|
||||
### 1.6 알림(Notifications) 테이블
|
||||
|
||||
```
|
||||
notifications
|
||||
- id: UUID (PK)
|
||||
- user_id: UUID (FK -> users.id)
|
||||
- title: STRING
|
||||
- message: TEXT
|
||||
- type: ENUM ('limit_warning', 'payment_reminder', 'tip', 'system')
|
||||
- related_entity_type: STRING (nullable)
|
||||
- related_entity_id: UUID (nullable)
|
||||
- is_read: BOOLEAN (default: false)
|
||||
- created_at: TIMESTAMP
|
||||
- read_at: TIMESTAMP (nullable)
|
||||
```
|
||||
|
||||
### 1.7 템플릿(Templates) 테이블
|
||||
|
||||
```
|
||||
templates
|
||||
- id: UUID (PK)
|
||||
- user_id: UUID (FK -> users.id)
|
||||
- name: STRING
|
||||
- category_id: UUID (FK -> categories.id)
|
||||
- amount: DECIMAL (nullable)
|
||||
- merchant: STRING (nullable)
|
||||
- description: TEXT (nullable)
|
||||
- is_favorite: BOOLEAN (default: false)
|
||||
- created_at: TIMESTAMP
|
||||
- updated_at: TIMESTAMP
|
||||
```
|
||||
|
||||
## 2. 데이터 관계 및 제약 조건
|
||||
|
||||
### 2.1 테이블 간 관계 (ERD)
|
||||
|
||||
```
|
||||
Users (1) --- (*) Cards
|
||||
Users (1) --- (*) Expenses
|
||||
Users (1) --- (*) Limits
|
||||
Users (1) --- (*) Notifications
|
||||
Users (1) --- (*) Templates
|
||||
|
||||
Cards (1) --- (*) Expenses
|
||||
Cards (1) --- (*) Limits
|
||||
|
||||
Categories (1) --- (*) Expenses
|
||||
Categories (1) --- (*) Limits
|
||||
Categories (1) --- (*) Templates
|
||||
Categories (1) --- (*) Categories (자기 참조: 부모-자식 관계)
|
||||
```
|
||||
|
||||
### 2.2 기본 카테고리 목록
|
||||
|
||||
시스템에서 기본적으로 제공하는 카테고리 목록입니다:
|
||||
|
||||
1. **식비**
|
||||
- 식료품
|
||||
- 외식
|
||||
- 카페/음료
|
||||
|
||||
2. **주거/통신**
|
||||
- 월세/관리비
|
||||
- 전기/수도/가스
|
||||
- 인터넷/통신비
|
||||
- 가구/가전
|
||||
|
||||
3. **교통**
|
||||
- 대중교통
|
||||
- 자동차/유류비
|
||||
- 택시
|
||||
|
||||
4. **쇼핑**
|
||||
- 의류/패션
|
||||
- 화장품/미용
|
||||
- 전자기기
|
||||
- 생활용품
|
||||
|
||||
5. **여가/문화**
|
||||
- 영화/공연
|
||||
- 취미/레저
|
||||
- 여행/숙박
|
||||
- 도서/음악
|
||||
|
||||
6. **의료/건강**
|
||||
- 병원/약국
|
||||
- 운동/피트니스
|
||||
|
||||
7. **교육**
|
||||
- 학비/등록금
|
||||
- 학원/강의
|
||||
- 교재/학습도구
|
||||
|
||||
8. **금융**
|
||||
- 보험
|
||||
- 세금
|
||||
- 대출이자
|
||||
- 투자
|
||||
|
||||
9. **기타**
|
||||
- 기부/후원
|
||||
- 용돈/선물
|
||||
- 기타 지출
|
||||
|
||||
### 2.3 데이터 유효성 검사 규칙
|
||||
|
||||
#### 사용자(Users)
|
||||
- 이메일은 유효한 형식이어야 하며 중복될 수 없음
|
||||
- 비밀번호는 최소 8자 이상, 영문/숫자/특수문자 조합
|
||||
- 이름은 필수 입력 항목
|
||||
|
||||
#### 카드(Cards)
|
||||
- 카드 이름은 필수 입력 항목
|
||||
- 월 한도는 0보다 커야 함
|
||||
- 결제일은 1-31 사이의 값이어야 함
|
||||
|
||||
#### 지출(Expenses)
|
||||
- 금액은 0보다 커야 함
|
||||
- 거래 날짜는 현재 날짜보다 미래일 수 없음
|
||||
- 카테고리는 필수 선택 항목
|
||||
|
||||
#### 한도(Limits)
|
||||
- 한도 금액은 0보다 커야 함
|
||||
- 카드 ID와 카테고리 ID는 둘 다 null이거나, 둘 중 하나만 지정되어야 함
|
||||
- 시작 날짜는 필수 입력 항목
|
||||
|
||||
#### 템플릿(Templates)
|
||||
- 템플릿 이름은 필수 입력 항목
|
||||
- 카테고리는 필수 선택 항목
|
||||
|
||||
## 3. 데이터베이스 인덱스 설계
|
||||
|
||||
성능 최적화를 위한 인덱스 설계:
|
||||
|
||||
```
|
||||
users: (email)
|
||||
cards: (user_id, is_active)
|
||||
expenses: (user_id, card_id), (user_id, category_id), (user_id, transaction_date), (is_recurring)
|
||||
limits: (user_id, card_id), (user_id, category_id), (user_id, is_active)
|
||||
notifications: (user_id, is_read), (user_id, created_at)
|
||||
templates: (user_id, is_favorite)
|
||||
categories: (parent_id), (is_system)
|
||||
```
|
||||
|
||||
## 4. 데이터 마이그레이션 전략
|
||||
|
||||
1. **초기 설정**
|
||||
- 기본 카테고리 데이터 생성
|
||||
- 시스템 설정 데이터 생성
|
||||
|
||||
2. **버전 관리**
|
||||
- 데이터베이스 스키마 버전 관리 시스템 도입
|
||||
- 각 마이그레이션에 고유 ID 부여
|
||||
|
||||
3. **업그레이드 경로**
|
||||
- 이전 버전에서 새 버전으로의 마이그레이션 스크립트 준비
|
||||
- 데이터 무결성 검증 단계 포함
|
||||
|
||||
4. **롤백 전략**
|
||||
- 각 마이그레이션에 대한 롤백 스크립트 준비
|
||||
- 중요 데이터 변경 전 백업 수행
|
||||
|
||||
## 5. 데이터 보안 고려사항
|
||||
|
||||
1. **개인정보 보호**
|
||||
- 사용자 비밀번호는 단방향 해시로 저장 (bcrypt 또는 Argon2)
|
||||
- 카드 번호는 마지막 4자리만 저장
|
||||
- 개인식별정보(PII)는 암호화하여 저장
|
||||
|
||||
2. **접근 제어**
|
||||
- 사용자는 자신의 데이터만 접근 가능
|
||||
- 관리자 권한은 최소 필요 인원에게만 부여
|
||||
|
||||
3. **데이터 백업**
|
||||
- 정기적인 데이터베이스 백업 수행
|
||||
- 백업 데이터 암호화 저장
|
||||
|
||||
4. **감사 로깅**
|
||||
- 중요 데이터 변경에 대한 감사 로그 유지
|
||||
- 비정상적인 접근 패턴 모니터링
|
||||
298
docs/02_기술_문서/데이터베이스_스키마_구현.md
Normal file
@@ -0,0 +1,298 @@
|
||||
# 적자 탈출 가계부 - 데이터베이스 스키마 구현
|
||||
|
||||
## 1. 개요
|
||||
|
||||
적자 탈출 가계부 애플리케이션의 데이터베이스 스키마 구현에 대한 문서입니다. 이 문서는 Supabase 자체 호스팅 환경에서 PostgreSQL 데이터베이스를 사용하여 구현된 데이터베이스 스키마를 설명합니다.
|
||||
|
||||
## 2. 마이그레이션 파일 구조
|
||||
|
||||
데이터베이스 스키마는 다음과 같은 마이그레이션 파일로 구성되어 있습니다:
|
||||
|
||||
1. `01_users.sql`: 사용자 정보 관리
|
||||
2. `02_categories.sql`: 지출 카테고리 관리
|
||||
3. `03_expenses.sql`: 지출 내역 관리
|
||||
4. `04_budgets.sql`: 예산 관리
|
||||
5. `05_cards.sql`: 카드 정보 관리
|
||||
6. `06_limits.sql`: 지출 한도 관리
|
||||
7. `07_templates.sql`: 템플릿 관리
|
||||
8. `08_notifications.sql`: 알림 시스템
|
||||
9. `09_analysis_settings.sql`: 분석 설정
|
||||
|
||||
각 마이그레이션 파일은 테이블 생성, 인덱스 생성, RLS(Row Level Security) 정책 설정, 관련 함수 및 트리거를 포함합니다.
|
||||
|
||||
## 3. 테이블 구조
|
||||
|
||||
### 3.1 사용자(users) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 사용자 정보 저장
|
||||
- **RLS 정책**: 사용자는 자신의 정보만 조회/수정 가능
|
||||
- **관련 트리거**: Supabase Auth와 연동하여 사용자 생성 시 프로필 자동 생성
|
||||
|
||||
### 3.2 카테고리(categories) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS categories (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
name VARCHAR(50) NOT NULL,
|
||||
icon VARCHAR(50) NOT NULL,
|
||||
color VARCHAR(20) NOT NULL,
|
||||
parent_id UUID REFERENCES categories(id),
|
||||
is_income BOOLEAN DEFAULT FALSE,
|
||||
is_default BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 지출/수입 카테고리 관리
|
||||
- **RLS 정책**: 모든 사용자가 조회 가능, 수정은 관리자만 가능
|
||||
- **기본 데이터**: 40개 이상의 기본 카테고리 제공 (지출 및 수입 카테고리)
|
||||
- **계층 구조**: 부모-자식 관계를 통한 카테고리 계층화
|
||||
|
||||
### 3.3 지출(expenses) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS expenses (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
amount NUMERIC(12,2) NOT NULL,
|
||||
date DATE NOT NULL,
|
||||
category_id UUID REFERENCES categories(id),
|
||||
memo TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 사용자의 지출/수입 내역 저장
|
||||
- **RLS 정책**: 사용자는 자신의 지출 데이터만 접근 가능
|
||||
- **관련 함수**: 월별 지출 합계 조회 함수 제공
|
||||
|
||||
### 3.4 예산(budgets) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS budgets (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
amount NUMERIC(12,2) NOT NULL,
|
||||
month INTEGER NOT NULL CHECK (month BETWEEN 1 AND 12),
|
||||
year INTEGER NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
UNIQUE(user_id, month, year)
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 사용자의 월별 예산 관리
|
||||
- **RLS 정책**: 사용자는 자신의 예산 데이터만 접근 가능
|
||||
- **관련 함수**: 예산 대비 지출 비율 조회 함수 제공
|
||||
|
||||
### 3.5 카드(cards) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS cards (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
card_type VARCHAR(20) NOT NULL CHECK (card_type IN ('credit', 'debit', 'prepaid')),
|
||||
card_number_last4 VARCHAR(4),
|
||||
issuer VARCHAR(50),
|
||||
color VARCHAR(20),
|
||||
payment_day INTEGER CHECK (payment_day BETWEEN 1 AND 31),
|
||||
monthly_limit NUMERIC(12,2),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 사용자의 카드 정보 관리
|
||||
- **RLS 정책**: 사용자는 자신의 카드 데이터만 접근 가능
|
||||
- **관련 함수**: 사용자별 카드 목록 조회 함수 제공
|
||||
|
||||
### 3.6 한도(limits) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS limits (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
card_id UUID REFERENCES cards(id) ON DELETE CASCADE,
|
||||
category_id UUID REFERENCES categories(id) ON DELETE SET NULL,
|
||||
amount NUMERIC(12,2) NOT NULL CHECK (amount > 0),
|
||||
period VARCHAR(20) NOT NULL CHECK (period IN ('daily', 'weekly', 'monthly')),
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
CONSTRAINT card_or_category_required CHECK (card_id IS NOT NULL OR category_id IS NOT NULL),
|
||||
CONSTRAINT valid_date_range CHECK (end_date IS NULL OR end_date >= start_date)
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 카드 또는 카테고리별 지출 한도 관리
|
||||
- **RLS 정책**: 사용자는 자신의 한도 데이터만 접근 가능
|
||||
- **관련 함수**: 활성화된 한도 조회 및 사용량 계산 함수 제공
|
||||
|
||||
### 3.7 템플릿(templates) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS templates (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
card_id UUID REFERENCES cards(id) ON DELETE SET NULL,
|
||||
category_id UUID REFERENCES categories(id) ON DELETE SET NULL,
|
||||
amount NUMERIC(12,2) NOT NULL CHECK (amount > 0),
|
||||
description TEXT,
|
||||
location VARCHAR(255),
|
||||
is_income BOOLEAN DEFAULT FALSE,
|
||||
is_favorite BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
UNIQUE(user_id, name)
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 자주 사용하는 지출/수입 템플릿 관리
|
||||
- **RLS 정책**: 사용자는 자신의 템플릿 데이터만 접근 가능
|
||||
- **관련 함수**: 템플릿으로 지출 생성 함수 제공
|
||||
|
||||
### 3.8 알림(notifications) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS notifications (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
title VARCHAR(100) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
type VARCHAR(20) NOT NULL CHECK (type IN ('limit_warning', 'payment_due', 'tip', 'system')),
|
||||
related_id UUID,
|
||||
related_type VARCHAR(50),
|
||||
is_read BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
read_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 사용자 알림 관리 (한도 경고, 결제일 알림 등)
|
||||
- **RLS 정책**: 사용자는 자신의 알림 데이터만 접근 가능
|
||||
- **관련 트리거**: 지출 한도 초과 시 자동 알림 생성
|
||||
|
||||
### 3.9 분석 설정(analysis_settings) 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS analysis_settings (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
budget_period VARCHAR(20) DEFAULT 'monthly' CHECK (budget_period IN ('daily', 'weekly', 'monthly')),
|
||||
saving_goal NUMERIC(12,2),
|
||||
analysis_period INTEGER DEFAULT 3 CHECK (analysis_period > 0),
|
||||
notification_frequency VARCHAR(20) DEFAULT 'weekly' CHECK (notification_frequency IN ('daily', 'weekly', 'monthly', 'none')),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
UNIQUE(user_id)
|
||||
);
|
||||
```
|
||||
|
||||
- **주요 기능**: 사용자별 분석 설정 관리
|
||||
- **RLS 정책**: 사용자는 자신의 분석 설정 데이터만 접근 가능
|
||||
- **관련 트리거**: 사용자 생성 시 기본 분석 설정 자동 생성
|
||||
- **관련 함수**: 지출 분석 및 추세 분석 함수 제공
|
||||
|
||||
## 4. Row Level Security(RLS) 정책
|
||||
|
||||
모든 테이블에는 Row Level Security 정책이 적용되어 있습니다. 이를 통해 사용자는 자신의 데이터만 접근할 수 있으며, 다른 사용자의 데이터에는 접근할 수 없습니다.
|
||||
|
||||
기본적인 RLS 정책 패턴:
|
||||
|
||||
```sql
|
||||
-- 테이블에 RLS 활성화
|
||||
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- 조회 정책
|
||||
CREATE POLICY "select_policy" ON table_name
|
||||
FOR SELECT USING (auth.uid() = user_id);
|
||||
|
||||
-- 삽입 정책
|
||||
CREATE POLICY "insert_policy" ON table_name
|
||||
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
-- 수정 정책
|
||||
CREATE POLICY "update_policy" ON table_name
|
||||
FOR UPDATE USING (auth.uid() = user_id);
|
||||
|
||||
-- 삭제 정책
|
||||
CREATE POLICY "delete_policy" ON table_name
|
||||
FOR DELETE USING (auth.uid() = user_id);
|
||||
```
|
||||
|
||||
## 5. 인덱스
|
||||
|
||||
성능 최적화를 위해 각 테이블에 적절한 인덱스가 생성되어 있습니다:
|
||||
|
||||
- 외래 키 컬럼에 대한 인덱스
|
||||
- 자주 조회되는 컬럼에 대한 인덱스
|
||||
- 복합 인덱스 (예: `user_id`와 `date` 조합)
|
||||
|
||||
## 6. 함수 및 트리거
|
||||
|
||||
다양한 비즈니스 로직을 지원하기 위해 여러 함수와 트리거가 구현되어 있습니다:
|
||||
|
||||
### 6.1 주요 함수
|
||||
|
||||
- `get_monthly_expenses`: 월별 지출 합계 조회
|
||||
- `get_budget_usage`: 예산 대비 지출 비율 조회
|
||||
- `get_user_cards`: 사용자별 카드 목록 조회
|
||||
- `get_active_limits`: 활성화된 한도 및 사용량 조회
|
||||
- `create_expense_from_template`: 템플릿으로 지출 생성
|
||||
- `mark_notification_as_read`: 알림 읽음 표시
|
||||
- `get_expense_analysis`: 카테고리별 지출 분석
|
||||
- `get_monthly_expense_trend`: 월별 지출 추세 분석
|
||||
|
||||
### 6.2 주요 트리거
|
||||
|
||||
- `update_updated_at_column`: 레코드 업데이트 시 `updated_at` 자동 갱신
|
||||
- `create_user_profile`: Supabase Auth 사용자 생성 시 프로필 자동 생성
|
||||
- `create_limit_warning_notification`: 지출 한도 초과 시 알림 자동 생성
|
||||
- `create_default_analysis_settings`: 사용자 생성 시 기본 분석 설정 자동 생성
|
||||
|
||||
## 7. 마이그레이션 실행 방법
|
||||
|
||||
마이그레이션 파일을 실행하기 위한 스크립트가 제공됩니다:
|
||||
|
||||
```bash
|
||||
# 실행 권한 부여
|
||||
chmod +x run_migrations.sh
|
||||
|
||||
# 스크립트 실행
|
||||
./run_migrations.sh
|
||||
```
|
||||
|
||||
환경 변수를 통해 데이터베이스 연결 정보를 설정할 수 있습니다:
|
||||
|
||||
```bash
|
||||
DB_HOST=localhost DB_PORT=5432 DB_NAME=postgres DB_USER=postgres DB_PASSWORD=postgres ./run_migrations.sh
|
||||
```
|
||||
|
||||
## 8. 향후 확장 계획
|
||||
|
||||
1. **데이터 동기화**: 오프라인 모드 지원을 위한 동기화 메커니즘 구현
|
||||
2. **데이터 분석**: 더 다양한 분석 함수 및 뷰 추가
|
||||
3. **데이터 마이그레이션**: 버전 관리 및 롤백 메커니즘 개선
|
||||
4. **성능 최적화**: 대규모 데이터셋에 대한 쿼리 성능 최적화
|
||||
|
||||
## 9. 참고 사항
|
||||
|
||||
- 모든 날짜/시간 데이터는 타임존 정보를 포함합니다 (`TIMESTAMP WITH TIME ZONE`).
|
||||
- 금액 데이터는 `NUMERIC(12,2)` 타입을 사용하여 정확한 소수점 계산을 보장합니다.
|
||||
- UUID를 기본 키로 사용하여 분산 환경에서의 확장성을 고려했습니다.
|
||||
- 모든 테이블에는 생성 시간(`created_at`)이 자동으로 기록됩니다.
|
||||
292
docs/02_기술_문서/데이터베이스_스키마_스크립트.sql
Normal file
@@ -0,0 +1,292 @@
|
||||
-- Zellyy Finance 데이터베이스 스키마 스크립트
|
||||
-- 작성일: 2023년
|
||||
|
||||
-- UUID 확장 활성화
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
-- 타임스탬프 함수 생성 (자동 업데이트용)
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- 1. 사용자 테이블
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
full_name TEXT NOT NULL,
|
||||
profile_image_url TEXT,
|
||||
monthly_income DECIMAL(12, 2),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 사용자 테이블 업데이트 트리거
|
||||
CREATE TRIGGER update_users_updated_at
|
||||
BEFORE UPDATE ON users
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- 사용자 테이블 RLS 정책
|
||||
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 정보만 볼 수 있음" ON users
|
||||
FOR SELECT USING (auth.uid() = id);
|
||||
CREATE POLICY "사용자는 자신의 정보만 수정할 수 있음" ON users
|
||||
FOR UPDATE USING (auth.uid() = id);
|
||||
|
||||
-- 2. 카테고리 테이블
|
||||
CREATE TABLE categories (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
color TEXT NOT NULL,
|
||||
icon TEXT,
|
||||
is_income BOOLEAN DEFAULT FALSE,
|
||||
is_default BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
UNIQUE(user_id, name)
|
||||
);
|
||||
|
||||
-- 카테고리 테이블 업데이트 트리거
|
||||
CREATE TRIGGER update_categories_updated_at
|
||||
BEFORE UPDATE ON categories
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- 카테고리 테이블 RLS 정책
|
||||
ALTER TABLE categories ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 카테고리와 기본 카테고리를 볼 수 있음" ON categories
|
||||
FOR SELECT USING (auth.uid() = user_id OR is_default = TRUE);
|
||||
CREATE POLICY "사용자는 자신의 카테고리만 수정할 수 있음" ON categories
|
||||
FOR UPDATE USING (auth.uid() = user_id AND is_default = FALSE);
|
||||
CREATE POLICY "사용자는 자신의 카테고리만 삭제할 수 있음" ON categories
|
||||
FOR DELETE USING (auth.uid() = user_id AND is_default = FALSE);
|
||||
CREATE POLICY "사용자는 자신의 카테고리만 생성할 수 있음" ON categories
|
||||
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
-- 3. 카드 테이블
|
||||
CREATE TABLE cards (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
card_number TEXT,
|
||||
card_type TEXT NOT NULL,
|
||||
bank_name TEXT,
|
||||
color TEXT,
|
||||
billing_day INTEGER,
|
||||
payment_day INTEGER,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
UNIQUE(user_id, name)
|
||||
);
|
||||
|
||||
-- 카드 테이블 업데이트 트리거
|
||||
CREATE TRIGGER update_cards_updated_at
|
||||
BEFORE UPDATE ON cards
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- 카드 테이블 RLS 정책
|
||||
ALTER TABLE cards ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 카드만 볼 수 있음" ON cards
|
||||
FOR SELECT USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 카드만 수정할 수 있음" ON cards
|
||||
FOR UPDATE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 카드만 삭제할 수 있음" ON cards
|
||||
FOR DELETE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 카드만 생성할 수 있음" ON cards
|
||||
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
-- 4. 한도 테이블
|
||||
CREATE TABLE limits (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
card_id UUID REFERENCES cards(id) ON DELETE CASCADE,
|
||||
category_id UUID REFERENCES categories(id) ON DELETE SET NULL,
|
||||
amount DECIMAL(12, 2) NOT NULL,
|
||||
period TEXT NOT NULL, -- 'monthly', 'weekly', 'daily'
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
CONSTRAINT card_or_category_required CHECK (card_id IS NOT NULL OR category_id IS NOT NULL)
|
||||
);
|
||||
|
||||
-- 한도 테이블 업데이트 트리거
|
||||
CREATE TRIGGER update_limits_updated_at
|
||||
BEFORE UPDATE ON limits
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- 한도 테이블 RLS 정책
|
||||
ALTER TABLE limits ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 한도만 볼 수 있음" ON limits
|
||||
FOR SELECT USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 한도만 수정할 수 있음" ON limits
|
||||
FOR UPDATE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 한도만 삭제할 수 있음" ON limits
|
||||
FOR DELETE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 한도만 생성할 수 있음" ON limits
|
||||
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
-- 5. 지출 테이블
|
||||
CREATE TABLE expenses (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
card_id UUID REFERENCES cards(id) ON DELETE SET NULL,
|
||||
category_id UUID REFERENCES categories(id) ON DELETE SET NULL,
|
||||
amount DECIMAL(12, 2) NOT NULL,
|
||||
description TEXT,
|
||||
date TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
location TEXT,
|
||||
receipt_image_url TEXT,
|
||||
is_income BOOLEAN DEFAULT FALSE,
|
||||
is_recurring BOOLEAN DEFAULT FALSE,
|
||||
recurring_period TEXT, -- 'monthly', 'weekly', 'daily'
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 지출 테이블 업데이트 트리거
|
||||
CREATE TRIGGER update_expenses_updated_at
|
||||
BEFORE UPDATE ON expenses
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- 지출 테이블 RLS 정책
|
||||
ALTER TABLE expenses ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 지출만 볼 수 있음" ON expenses
|
||||
FOR SELECT USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 지출만 수정할 수 있음" ON expenses
|
||||
FOR UPDATE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 지출만 삭제할 수 있음" ON expenses
|
||||
FOR DELETE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 지출만 생성할 수 있음" ON expenses
|
||||
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
-- 6. 템플릿 테이블
|
||||
CREATE TABLE templates (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
card_id UUID REFERENCES cards(id) ON DELETE SET NULL,
|
||||
category_id UUID REFERENCES categories(id) ON DELETE SET NULL,
|
||||
amount DECIMAL(12, 2) NOT NULL,
|
||||
description TEXT,
|
||||
location TEXT,
|
||||
is_income BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
UNIQUE(user_id, name)
|
||||
);
|
||||
|
||||
-- 템플릿 테이블 업데이트 트리거
|
||||
CREATE TRIGGER update_templates_updated_at
|
||||
BEFORE UPDATE ON templates
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- 템플릿 테이블 RLS 정책
|
||||
ALTER TABLE templates ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 템플릿만 볼 수 있음" ON templates
|
||||
FOR SELECT USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 템플릿만 수정할 수 있음" ON templates
|
||||
FOR UPDATE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 템플릿만 삭제할 수 있음" ON templates
|
||||
FOR DELETE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 템플릿만 생성할 수 있음" ON templates
|
||||
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
-- 7. 알림 테이블
|
||||
CREATE TABLE notifications (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
type TEXT NOT NULL, -- 'limit_warning', 'payment_due', 'tip', 'system'
|
||||
related_id UUID, -- 관련된 항목의 ID (카드, 한도 등)
|
||||
is_read BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 알림 테이블 업데이트 트리거
|
||||
CREATE TRIGGER update_notifications_updated_at
|
||||
BEFORE UPDATE ON notifications
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- 알림 테이블 RLS 정책
|
||||
ALTER TABLE notifications ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 알림만 볼 수 있음" ON notifications
|
||||
FOR SELECT USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 알림만 수정할 수 있음" ON notifications
|
||||
FOR UPDATE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 알림만 삭제할 수 있음" ON notifications
|
||||
FOR DELETE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "시스템만 알림을 생성할 수 있음" ON notifications
|
||||
FOR INSERT WITH CHECK (auth.uid() = user_id OR auth.uid() IS NULL);
|
||||
|
||||
-- 8. 분석 설정 테이블
|
||||
CREATE TABLE analysis_settings (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
budget_period TEXT DEFAULT 'monthly', -- 'monthly', 'weekly', 'daily'
|
||||
saving_goal DECIMAL(12, 2),
|
||||
analysis_period INTEGER DEFAULT 3, -- 분석에 사용할 과거 데이터 기간 (개월)
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
UNIQUE(user_id)
|
||||
);
|
||||
|
||||
-- 분석 설정 테이블 업데이트 트리거
|
||||
CREATE TRIGGER update_analysis_settings_updated_at
|
||||
BEFORE UPDATE ON analysis_settings
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- 분석 설정 테이블 RLS 정책
|
||||
ALTER TABLE analysis_settings ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY "사용자는 자신의 분석 설정만 볼 수 있음" ON analysis_settings
|
||||
FOR SELECT USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 분석 설정만 수정할 수 있음" ON analysis_settings
|
||||
FOR UPDATE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 분석 설정만 삭제할 수 있음" ON analysis_settings
|
||||
FOR DELETE USING (auth.uid() = user_id);
|
||||
CREATE POLICY "사용자는 자신의 분석 설정만 생성할 수 있음" ON analysis_settings
|
||||
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
-- 기본 카테고리 데이터 삽입
|
||||
INSERT INTO categories (name, color, icon, is_income, is_default) VALUES
|
||||
('식비', '#FF5722', 'restaurant', FALSE, TRUE),
|
||||
('교통', '#2196F3', 'directions_car', FALSE, TRUE),
|
||||
('주거/통신', '#9C27B0', 'home', FALSE, TRUE),
|
||||
('쇼핑', '#4CAF50', 'shopping_bag', FALSE, TRUE),
|
||||
('의료/건강', '#F44336', 'local_hospital', FALSE, TRUE),
|
||||
('문화/여가', '#FFEB3B', 'movie', FALSE, TRUE),
|
||||
('교육', '#795548', 'school', FALSE, TRUE),
|
||||
('경조사/기부', '#607D8B', 'card_giftcard', FALSE, TRUE),
|
||||
('기타', '#9E9E9E', 'more_horiz', FALSE, TRUE),
|
||||
('급여', '#4CAF50', 'payments', TRUE, TRUE),
|
||||
('용돈', '#8BC34A', 'savings', TRUE, TRUE),
|
||||
('상여금', '#CDDC39', 'card_giftcard', TRUE, TRUE),
|
||||
('환불', '#FFC107', 'replay', TRUE, TRUE),
|
||||
('투자수익', '#00BCD4', 'trending_up', TRUE, TRUE),
|
||||
('기타수입', '#9E9E9E', 'more_horiz', TRUE, TRUE);
|
||||
|
||||
-- 인덱스 생성
|
||||
CREATE INDEX idx_expenses_user_id ON expenses(user_id);
|
||||
CREATE INDEX idx_expenses_date ON expenses(date);
|
||||
CREATE INDEX idx_expenses_category_id ON expenses(category_id);
|
||||
CREATE INDEX idx_expenses_card_id ON expenses(card_id);
|
||||
CREATE INDEX idx_limits_user_id ON limits(user_id);
|
||||
CREATE INDEX idx_cards_user_id ON cards(user_id);
|
||||
CREATE INDEX idx_categories_user_id ON categories(user_id);
|
||||
CREATE INDEX idx_notifications_user_id ON notifications(user_id);
|
||||
CREATE INDEX idx_notifications_is_read ON notifications(is_read);
|
||||
87
docs/02_기술_문서/데이터베이스_스키마_요약.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# 적자 탈출 가계부 - 데이터베이스 스키마 요약
|
||||
|
||||
## 개요
|
||||
이 문서는 적자 탈출 가계부 애플리케이션의 데이터베이스 스키마를 요약합니다. 모든 테이블은 PostgreSQL 기반으로 설계되었으며, Supabase 환경에 최적화되어 있습니다.
|
||||
|
||||
## 기술적 특징
|
||||
- **UUID 기반 기본 키**: 모든 테이블은 UUID 타입의 기본 키를 사용합니다.
|
||||
- **타임존 지원**: 날짜/시간 데이터는 `TIMESTAMP WITH TIME ZONE` 타입을 사용하여 국제적 사용을 지원합니다.
|
||||
- **정확한 금액 계산**: 모든 금액은 `DECIMAL(12, 2)` 타입을 사용하여 정확한 계산을 보장합니다.
|
||||
- **Row Level Security (RLS)**: 모든 테이블에 RLS 정책이 적용되어 사용자는 자신의 데이터만 접근할 수 있습니다.
|
||||
- **자동 생성 시간**: 모든 테이블은 `created_at`과 `updated_at` 필드를 포함하여 데이터 생성 및 수정 시간을 자동으로 기록합니다.
|
||||
- **계층적 카테고리**: 카테고리는 계층 구조를 지원하여 상위/하위 카테고리 관계를 표현할 수 있습니다.
|
||||
- **인덱스 최적화**: 자주 조회되는 필드에 인덱스를 적용하여 성능을 최적화했습니다.
|
||||
|
||||
## 테이블 구조
|
||||
|
||||
### 1. users (01_users.sql)
|
||||
사용자 정보를 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, email, name, created_at, updated_at
|
||||
- **관련 함수**: 사용자 프로필 자동 생성 트리거
|
||||
- **보안**: RLS 정책으로 사용자는 자신의 정보만 접근 가능
|
||||
|
||||
### 2. categories (02_categories.sql)
|
||||
지출/수입 카테고리를 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, user_id, name, parent_id, type, icon, color, is_system
|
||||
- **계층 구조**: parent_id를 통해 상위/하위 카테고리 관계 표현
|
||||
- **기본 데이터**: 15개 이상의 기본 카테고리와 하위 카테고리 제공
|
||||
- **관련 함수**: 카테고리 계층 조회 함수
|
||||
|
||||
### 3. expenses (03_expenses.sql)
|
||||
지출/수입 내역을 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, user_id, amount, is_income, category_id, card_id, date, memo
|
||||
- **관련 함수**: 월별 지출 합계, 카테고리별 지출 분석 함수
|
||||
- **인덱스**: user_id, category_id, date에 인덱스 적용
|
||||
|
||||
### 4. budgets (04_budgets.sql)
|
||||
월별/카테고리별 예산을 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, user_id, category_id, year, month, amount
|
||||
- **관련 함수**: 예산 대비 지출 비율 조회 함수
|
||||
- **인덱스**: user_id, category_id, year, month에 인덱스 적용
|
||||
|
||||
### 5. cards (05_cards.sql)
|
||||
카드 정보를 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, user_id, name, card_number, payment_day, is_active
|
||||
- **관련 함수**: 월별 카드 사용 현황 조회 함수
|
||||
- **보안**: 카드 번호는 마스킹 처리
|
||||
|
||||
### 6. limits (06_limits.sql)
|
||||
지출 한도를 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, user_id, card_id, category_id, amount, period, start_date, end_date
|
||||
- **관련 함수**: 활성화된 한도 및 사용량 조회 함수, 한도 경고 알림 트리거
|
||||
- **제약 조건**: 카드 또는 카테고리 중 하나는 반드시 지정되어야 함
|
||||
|
||||
### 7. templates (07_templates.sql)
|
||||
자주 사용하는 지출/수입 템플릿을 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, user_id, name, amount, is_income, category_id, card_id, usage_count
|
||||
- **관련 함수**: 템플릿 사용 카운터 증가, 템플릿으로 지출/수입 생성, 자주 사용하는 템플릿 조회
|
||||
|
||||
### 8. notifications (08_notifications.sql)
|
||||
알림 시스템을 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, user_id, title, message, type, related_id, is_read, priority
|
||||
- **알림 타입**: limit_warning, budget_warning, payment_reminder, system_message, custom
|
||||
- **관련 함수**: 알림 읽음 표시, 사용자 알림 조회, 예산 초과 알림 생성, 카드 결제일 알림 생성
|
||||
|
||||
### 9. analysis_settings (09_analysis_settings.sql)
|
||||
사용자별 분석 설정을 관리하는 테이블입니다.
|
||||
- **주요 필드**: id, user_id, setting_key, setting_value (JSONB)
|
||||
- **설정 키**: dashboard_widgets, report_preferences, analysis_period, chart_colors 등
|
||||
- **관련 함수**: 분석 설정 가져오기/저장, 기본 분석 설정 생성, 지출 분석 함수(카테고리별 지출 비율, 기간별 지출 추이)
|
||||
|
||||
## 마이그레이션 실행 방법
|
||||
1. `run_migrations.sh` 스크립트를 사용하여 모든 마이그레이션 파일을 순서대로 실행합니다.
|
||||
2. 환경 변수를 통해 데이터베이스 연결 정보를 설정할 수 있습니다.
|
||||
```bash
|
||||
DB_HOST=localhost DB_PORT=5432 DB_NAME=mydb DB_USER=user DB_PASSWORD=pass ./run_migrations.sh
|
||||
```
|
||||
|
||||
## 확장 계획
|
||||
- **데이터 동기화**: 여러 기기 간 데이터 동기화 메커니즘 구현
|
||||
- **분석 기능 확장**: 고급 재무 분석 및 예측 기능 추가
|
||||
- **성능 최적화**: 대량의 트랜잭션 데이터 처리를 위한 파티셔닝 및 인덱싱 최적화
|
||||
- **API 엔드포인트**: RESTful API 및 GraphQL 엔드포인트 개발
|
||||
|
||||
## 참고 사항
|
||||
- 모든 SQL 파일은 `migrations` 디렉토리에 순서대로 번호가 매겨져 있습니다.
|
||||
- 각 테이블은 자체 SQL 파일에 정의되어 있어 관리가 용이합니다.
|
||||
- 트리거와 함수는 관련 테이블과 동일한 파일에 정의되어 있습니다.
|
||||
68
docs/02_기술_문서/마이그레이션_관리.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# 마이그레이션 파일 관리
|
||||
|
||||
## 개요
|
||||
Zellyy Finance 프로젝트의 데이터베이스 마이그레이션 파일은 Gitea 저장소에서 단일 소스로 관리됩니다. 이 문서는 마이그레이션 파일의 관리 방법과 위치에 대한 정보를 제공합니다.
|
||||
|
||||
## 마이그레이션 파일 위치
|
||||
- **소스 코드 저장소**: `/Users/hansoo./Dev/Zellyy_Finance/backend/migrations/`
|
||||
- **Git 저장소 URL**: [Zellyy_Finance Git Repository](https://gitea.com/hansoo/Zellyy_Finance)
|
||||
- **옵시디언 참조 디렉토리**: `/1. Project/ZELLYY/적자 탈출 가계부/02_기술_문서/migrations/`
|
||||
(참고: 이 디렉토리는 실제 SQL 파일을 포함하지 않으며, 참조용 디렉토리입니다.)
|
||||
|
||||
## 코드 관리 원칙
|
||||
- **단일 소스 원칙**: 모든 코드는 Gitea에서만 관리합니다.
|
||||
- **옵시디언 문서화 원칙**: 옵시디언에는 문서만 저장하고 코드는 저장하지 않습니다.
|
||||
- **참조 링크 사용**: 옵시디언에서는 Gitea의 코드를 참조하는 링크를 사용합니다.
|
||||
|
||||
> 참고: 코드 관련 기술 문서도 Gitea에서만 관리합니다. 자세한 내용은 [기술문서_관리](/1.%20Project/ZELLYY/적자%20탈출%20가계부/02_기술_문서/기술문서_관리.md) 문서를 참조하세요.
|
||||
|
||||
## 마이그레이션 파일 목록
|
||||
마이그레이션 파일은 다음과 같은 순서로 실행됩니다:
|
||||
|
||||
1. `01_users.sql`: 사용자 테이블 및 인증 관련 기능
|
||||
2. `02_categories.sql`: 카테고리 테이블 및 계층 구조
|
||||
3. `03_expenses.sql`: 지출/수입 내역 테이블
|
||||
4. `04_budgets.sql`: 예산 관리 테이블
|
||||
5. `05_cards.sql`: 카드 정보 관리 테이블
|
||||
6. `06_limits.sql`: 지출 한도 관리 테이블
|
||||
7. `07_templates.sql`: 자주 사용하는 지출/수입 템플릿
|
||||
8. `08_notifications.sql`: 알림 시스템 테이블
|
||||
9. `09_analysis_settings.sql`: 사용자별 분석 설정 테이블
|
||||
|
||||
## 마이그레이션 실행 방법
|
||||
마이그레이션은 `run_migrations.sh` 스크립트를 통해 실행됩니다:
|
||||
```bash
|
||||
cd /Users/hansoo./Dev/Zellyy_Finance/backend
|
||||
./run_migrations.sh
|
||||
```
|
||||
|
||||
## 변경 관리
|
||||
마이그레이션 파일을 변경해야 할 경우, 다음 절차를 따릅니다:
|
||||
|
||||
1. Gitea 저장소의 파일만 수정합니다.
|
||||
2. 변경 사항을 커밋하고 푸시합니다.
|
||||
3. 이 문서에 중요한 변경 사항을 기록합니다.
|
||||
|
||||
## 주의사항
|
||||
- 옵시디언에는 코드를 저장하지 않는 원칙에 따라, 원래 있던 SQL 파일들은 삭제되었습니다.
|
||||
- 코드는 Gitea 저장소에서만 관리되므로, 코드 작업 시에는 항상 Gitea 저장소를 참조하세요.
|
||||
- 옵시디언의 한글 디렉토리명으로 인해 일부 명령어에서 경로 문제가 발생할 수 있습니다. 스크립트나 명령어에서 경로를 사용할 때는 Gitea의 영문 경로를 사용하세요.
|
||||
|
||||
## 디렉토리 구조 관련 참고사항
|
||||
- **옵시디언 디렉토리 구조**:
|
||||
- `/1. Project/ZELLYY/적자 탈출 가계부/02_기술_문서/migrations/`: 참조용 빈 디렉토리
|
||||
- `/1. Project/ZELLYY/적자 탈출 가계부/02_기술_문서/마이그레이션_관리.md`: 이 문서
|
||||
|
||||
- **Gitea 디렉토리 구조**:
|
||||
- `/Users/hansoo./Dev/Zellyy_Finance/backend/migrations/`: 실제 SQL 파일 포함
|
||||
- `/Users/hansoo./Dev/Zellyy_Finance/backend/run_migrations.sh`: 마이그레이션 실행 스크립트
|
||||
|
||||
한글 디렉토리명을 사용하는 옵시디언 경로는 일부 도구나 명령어에서 문제가 발생할 수 있으므로, 코드 작업 시에는 항상 Gitea의 영문 경로를 사용하는 것이 좋습니다.
|
||||
|
||||
## 최근 업데이트
|
||||
- 2025-02-27: 옵시디언과 Gitea의 마이그레이션 파일을 통합하여 Gitea를 단일 소스로 지정
|
||||
- 2025-02-27: 디렉토리 구조 관련 주의사항 추가
|
||||
- 2025-02-27: 옵시디언의 SQL 파일 삭제 및 백업 정보 추가
|
||||
- 2025-02-27: 문서 통합 (migrations/README.md 삭제 및 내용 통합)
|
||||
- 2025-02-27: migrations_backup 디렉토리 삭제
|
||||
- 2025-02-27: 옵시디언의 run_migrations.sh 파일 삭제 (Gitea에서만 관리)
|
||||
265
docs/02_기술_문서/보안_전략_및_구현.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# 적자 탈출 가계부 - 보안 전략 및 구현
|
||||
|
||||
## 1. 개요
|
||||
|
||||
이 문서는 적자 탈출 가계부 애플리케이션의 보안 전략과 구현 방법을 정의합니다. 사용자의 재정 데이터를 다루는 앱으로서, 데이터 보안과 개인정보 보호는 최우선 과제입니다.
|
||||
|
||||
## 2. 보안 원칙
|
||||
|
||||
적자 탈출 가계부는 다음과 같은 보안 원칙을 따릅니다:
|
||||
|
||||
1. **최소 권한 원칙**: 각 구성 요소는 필요한 최소한의 권한만 가집니다.
|
||||
2. **심층 방어**: 여러 계층의 보안 통제를 구현하여 단일 방어선 실패에 대비합니다.
|
||||
3. **기본적 보안**: 모든 시스템은 기본적으로 안전한 설정으로 구성됩니다.
|
||||
4. **개인정보 보호 중심 설계**: 개인정보 보호는 설계 단계부터 고려됩니다.
|
||||
5. **투명성**: 사용자에게 데이터 수집 및 사용 방식을 명확히 알립니다.
|
||||
|
||||
## 3. 데이터 보안
|
||||
|
||||
### 3.1 저장 데이터(Data at Rest) 보안
|
||||
|
||||
#### 로컬 저장소 보안
|
||||
- **암호화**: 모든 민감한 로컬 데이터는 AES-256 암호화를 사용하여 저장됩니다.
|
||||
- **키 관리**: 암호화 키는 안전한 키체인/키스토어에 저장됩니다.
|
||||
- **민감 정보 처리**: 카드 번호와 같은 민감한 정보는 부분적으로만 저장하고 마스킹 처리합니다.
|
||||
|
||||
#### 서버 측 데이터 보안
|
||||
- **데이터베이스 암호화**: Supabase의 RLS(Row Level Security)를 활용한 데이터 접근 제어
|
||||
- **백업 암호화**: 모든 데이터베이스 백업은 암호화되어 저장됩니다.
|
||||
- **데이터 분리**: 사용자 인증 정보와 트랜잭션 데이터는 별도의 테이블에 저장됩니다.
|
||||
|
||||
### 3.2 전송 데이터(Data in Transit) 보안
|
||||
|
||||
- **TLS/SSL**: 모든 API 통신은 TLS 1.3을 사용하여 암호화됩니다.
|
||||
- **인증서 핀닝**: 모바일 앱에서는 인증서 핀닝을 구현하여 중간자 공격을 방지합니다.
|
||||
- **안전한 API 설계**: 모든 API 엔드포인트는 인증 및 권한 검사를 수행합니다.
|
||||
|
||||
### 3.3 데이터 접근 제어
|
||||
|
||||
- **사용자 기반 접근 제어**: 각 사용자는 자신의 데이터만 접근할 수 있습니다.
|
||||
- **역할 기반 접근 제어**: 관리자, 지원팀 등 역할에 따라 접근 권한이 다르게 설정됩니다.
|
||||
- **API 접근 제한**: API 키는 필요한 최소한의 권한만 부여받습니다.
|
||||
|
||||
## 4. 사용자 인증 및 권한 부여
|
||||
|
||||
### 4.1 인증 메커니즘
|
||||
|
||||
- **강력한 비밀번호 정책**: 최소 8자, 대소문자, 숫자, 특수문자 포함 필요
|
||||
- **다중 인증(MFA)**: 선택적 2단계 인증 지원 (이메일, SMS, 인증 앱)
|
||||
- **소셜 로그인**: OAuth 2.0 기반의 안전한 소셜 로그인 통합
|
||||
- **세션 관리**: 안전한 세션 생성, 만료 및 갱신 메커니즘
|
||||
|
||||
### 4.2 권한 부여
|
||||
|
||||
- **JWT 기반 인증**: 서명된 JWT 토큰을 사용한 API 접근 제어
|
||||
- **토큰 만료**: 액세스 토큰은 짧은 수명(15분)을 가지며, 리프레시 토큰으로 갱신
|
||||
- **권한 검증**: 모든 API 요청은 권한 검증 미들웨어를 통과해야 함
|
||||
|
||||
### 4.3 계정 보안
|
||||
|
||||
- **계정 잠금**: 연속된 로그인 실패 시 일시적 계정 잠금
|
||||
- **비밀번호 재설정**: 안전한 비밀번호 재설정 프로세스 (시간 제한 토큰 사용)
|
||||
- **로그인 알림**: 새로운 기기에서 로그인 시 사용자에게 알림
|
||||
- **세션 관리**: 활성 세션 목록 확인 및 원격 로그아웃 기능
|
||||
|
||||
## 5. 애플리케이션 보안
|
||||
|
||||
### 5.1 모바일 앱 보안
|
||||
|
||||
- **코드 난독화**: 앱 코드 난독화를 통한 리버스 엔지니어링 방지
|
||||
- **루팅/탈옥 감지**: 루팅/탈옥된 기기 감지 및 보안 경고
|
||||
- **스크린샷 방지**: 민감한 화면에서 스크린샷 방지 기능
|
||||
- **자동 잠금**: 일정 시간 미사용 시 앱 자동 잠금
|
||||
- **메모리 보안**: 민감한 데이터는 사용 후 메모리에서 즉시 제거
|
||||
|
||||
### 5.2 API 보안
|
||||
|
||||
- **입력 검증**: 모든 사용자 입력은 서버와 클라이언트 양쪽에서 검증
|
||||
- **출력 인코딩**: 모든 출력 데이터는 적절히 인코딩하여 XSS 방지
|
||||
- **CSRF 방지**: 상태 변경 작업에 CSRF 토큰 사용
|
||||
- **속도 제한**: API 요청에 속도 제한 적용하여 DoS 공격 방지
|
||||
- **보안 헤더**: 적절한 보안 HTTP 헤더 사용 (HSTS, CSP, X-Content-Type-Options 등)
|
||||
|
||||
### 5.3 서버 보안
|
||||
|
||||
- **최신 패치**: 모든 서버 소프트웨어는 최신 보안 패치 유지
|
||||
- **방화벽 구성**: 필요한 포트만 개방하는 엄격한 방화벽 정책
|
||||
- **침입 탐지**: 비정상적인 접근 패턴 모니터링 및 알림
|
||||
- **로그 관리**: 보안 관련 로그 중앙 집중화 및 분석
|
||||
- **취약점 스캔**: 정기적인 취약점 스캔 및 패치
|
||||
|
||||
## 6. 개인정보 보호
|
||||
|
||||
### 6.1 데이터 최소화
|
||||
|
||||
- **필수 정보만 수집**: 서비스 제공에 필요한 최소한의 개인정보만 수집
|
||||
- **데이터 보존 정책**: 목적 달성 후 불필요한 데이터 자동 삭제
|
||||
- **익명화/가명화**: 가능한 경우 데이터 익명화 또는 가명화 처리
|
||||
|
||||
### 6.2 사용자 통제권
|
||||
|
||||
- **개인정보 접근**: 사용자가 자신의 모든 데이터에 접근할 수 있는 기능
|
||||
- **데이터 내보내기**: 표준 형식으로 데이터 내보내기 기능
|
||||
- **계정 삭제**: 완전한 계정 및 데이터 삭제 기능
|
||||
- **동의 관리**: 명확한 동의 획득 및 철회 프로세스
|
||||
|
||||
### 6.3 개인정보 처리방침
|
||||
|
||||
- **명확한 설명**: 이해하기 쉬운 언어로 데이터 수집 및 사용 방식 설명
|
||||
- **제3자 공유**: 데이터가 공유되는 제3자 명시
|
||||
- **연락처 정보**: 개인정보 관련 문의를 위한 연락처 제공
|
||||
- **정기 업데이트**: 정책 변경 시 사용자에게 알림
|
||||
|
||||
## 7. 보안 모니터링 및 대응
|
||||
|
||||
### 7.1 모니터링 시스템
|
||||
|
||||
- **로그 모니터링**: 보안 관련 로그 실시간 모니터링
|
||||
- **이상 탐지**: 비정상적인 사용자 행동 패턴 감지
|
||||
- **성능 모니터링**: 서비스 가용성 및 성능 모니터링
|
||||
- **알림 시스템**: 보안 이벤트 발생 시 즉시 알림
|
||||
|
||||
### 7.2 인시던트 대응
|
||||
|
||||
- **대응 계획**: 보안 사고 유형별 대응 절차 문서화
|
||||
- **에스컬레이션 프로세스**: 심각도에 따른 에스컬레이션 경로 정의
|
||||
- **복구 절차**: 데이터 및 서비스 복구 절차 정의
|
||||
- **사후 분석**: 사고 원인 분석 및 재발 방지 대책 수립
|
||||
|
||||
### 7.3 정기적인 보안 평가
|
||||
|
||||
- **취약점 스캔**: 월간 자동화된 취약점 스캔
|
||||
- **침투 테스트**: 연간 전문가에 의한 침투 테스트
|
||||
- **코드 리뷰**: 보안 중심의 코드 리뷰 프로세스
|
||||
- **위험 평가**: 분기별 보안 위험 평가 및 대응 계획 업데이트
|
||||
|
||||
## 8. 규정 준수
|
||||
|
||||
### 8.1 관련 법규 준수
|
||||
|
||||
- **개인정보 보호법**: 국내 개인정보 보호법 준수
|
||||
- **GDPR**: 유럽 사용자를 위한 GDPR 요구사항 준수
|
||||
- **CCPA**: 캘리포니아 소비자 개인정보 보호법 준수
|
||||
- **금융 관련 규정**: 금융 데이터 처리 관련 규정 준수
|
||||
|
||||
### 8.2 내부 정책
|
||||
|
||||
- **보안 정책**: 직원 및 개발자를 위한 보안 정책 문서화
|
||||
- **접근 제어 정책**: 내부 시스템 및 데이터 접근 정책
|
||||
- **인시던트 대응 정책**: 보안 사고 대응 정책 및 절차
|
||||
- **변경 관리 정책**: 시스템 변경에 대한 보안 검토 절차
|
||||
|
||||
## 9. 구현 세부 사항
|
||||
|
||||
### 9.1 사용자 인증 구현
|
||||
|
||||
```typescript
|
||||
// JWT 토큰 생성 함수
|
||||
function generateJWT(userId: string): string {
|
||||
const payload = {
|
||||
sub: userId,
|
||||
iat: Math.floor(Date.now() / 1000),
|
||||
exp: Math.floor(Date.now() / 1000) + (15 * 60), // 15분 유효
|
||||
role: 'user'
|
||||
};
|
||||
|
||||
return jwt.sign(payload, process.env.JWT_SECRET, { algorithm: 'HS256' });
|
||||
}
|
||||
|
||||
// 비밀번호 해싱 함수
|
||||
async function hashPassword(password: string): Promise<string> {
|
||||
const salt = await bcrypt.genSalt(12);
|
||||
return bcrypt.hash(password, salt);
|
||||
}
|
||||
|
||||
// 비밀번호 검증 함수
|
||||
async function verifyPassword(password: string, hashedPassword: string): Promise<boolean> {
|
||||
return bcrypt.compare(password, hashedPassword);
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2 데이터 암호화 구현
|
||||
|
||||
```typescript
|
||||
// 데이터 암호화 함수
|
||||
function encryptData(data: string, key: Buffer): string {
|
||||
const iv = crypto.randomBytes(16);
|
||||
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
|
||||
|
||||
let encrypted = cipher.update(data, 'utf8', 'hex');
|
||||
encrypted += cipher.final('hex');
|
||||
|
||||
const authTag = cipher.getAuthTag();
|
||||
|
||||
// IV와 인증 태그를 암호문과 함께 저장
|
||||
return iv.toString('hex') + ':' + authTag.toString('hex') + ':' + encrypted;
|
||||
}
|
||||
|
||||
// 데이터 복호화 함수
|
||||
function decryptData(encryptedData: string, key: Buffer): string {
|
||||
const parts = encryptedData.split(':');
|
||||
const iv = Buffer.from(parts[0], 'hex');
|
||||
const authTag = Buffer.from(parts[1], 'hex');
|
||||
const encryptedText = parts[2];
|
||||
|
||||
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
|
||||
decipher.setAuthTag(authTag);
|
||||
|
||||
let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
|
||||
decrypted += decipher.final('utf8');
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
```
|
||||
|
||||
### 9.3 API 보안 구현
|
||||
|
||||
```typescript
|
||||
// API 요청 인증 미들웨어
|
||||
function authMiddleware(req, res, next) {
|
||||
const authHeader = req.headers.authorization;
|
||||
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
return res.status(401).json({ error: '인증 토큰이 필요합니다' });
|
||||
}
|
||||
|
||||
const token = authHeader.split(' ')[1];
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
||||
req.user = decoded;
|
||||
next();
|
||||
} catch (error) {
|
||||
return res.status(401).json({ error: '유효하지 않은 토큰입니다' });
|
||||
}
|
||||
}
|
||||
|
||||
// API 속도 제한 미들웨어
|
||||
const rateLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000, // 15분
|
||||
max: 100, // IP당 최대 요청 수
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
message: { error: '너무 많은 요청을 보냈습니다. 잠시 후 다시 시도해주세요.' }
|
||||
});
|
||||
```
|
||||
|
||||
## 10. 보안 테스트
|
||||
|
||||
### 10.1 자동화된 보안 테스트
|
||||
|
||||
- **정적 코드 분석**: SonarQube를 사용한 코드 취약점 분석
|
||||
- **의존성 검사**: npm audit을 통한 취약한 의존성 검사
|
||||
- **API 보안 테스트**: OWASP ZAP을 사용한 자동화된 API 보안 테스트
|
||||
- **모의 침투 테스트**: 정기적인 모의 침투 테스트 수행
|
||||
|
||||
### 10.2 수동 보안 검토
|
||||
|
||||
- **코드 리뷰**: 보안 중심의 코드 리뷰 체크리스트
|
||||
- **아키텍처 검토**: 정기적인 보안 아키텍처 검토
|
||||
- **구성 검토**: 서버 및 클라우드 구성 보안 검토
|
||||
- **권한 검토**: 사용자 권한 및 접근 제어 검토
|
||||
|
||||
## 11. 결론
|
||||
|
||||
적자 탈출 가계부의 보안 전략은 사용자 데이터 보호를 최우선으로 합니다. 이 문서에 정의된 보안 조치들은 지속적으로 평가되고 개선되어야 합니다. 보안은 일회성 작업이 아닌 지속적인 프로세스임을 인식하고, 새로운 위협과 취약점에 대응하기 위해 보안 전략을 정기적으로 업데이트할 것입니다.
|
||||
204
docs/03_개발_단계/01_개발_로드맵.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# 적자 탈출 가계부 개발 로드맵
|
||||
|
||||
## 개발 접근 방식
|
||||
|
||||
'적자 탈출 가계부' 프로젝트는 애자일 방법론을 기반으로 개발될 예정입니다. 2주 단위의 스프린트로 진행하며, 각 스프린트마다 사용 가능한 기능을 구현하고 테스트하는 방식으로 진행합니다. MVP(Minimum Viable Product) 접근법을 통해 핵심 기능을 우선적으로 개발하고, 사용자 피드백을 바탕으로 점진적으로 기능을 확장해 나갈 계획입니다.
|
||||
|
||||
## 개발 단계
|
||||
|
||||
### 1단계: 기획 및 설계 (2024년 Q1)
|
||||
|
||||
#### 1월: 요구사항 분석 및 기획
|
||||
- [x] 사용자 요구사항 수집 및 분석
|
||||
- [x] 경쟁 앱 분석 및 차별화 전략 수립
|
||||
- [x] 핵심 기능 정의 및 우선순위 설정
|
||||
- [x] 사용자 페르소나 및 사용자 여정 맵 작성
|
||||
|
||||
#### 2월: UI/UX 설계
|
||||
- [ ] 앱 정보 구조 설계
|
||||
- [ ] 주요 화면 와이어프레임 작성
|
||||
- [ ] 디자인 시스템 구축 (색상, 타이포그래피, 컴포넌트)
|
||||
- [ ] 프로토타입 제작 및 사용성 테스트
|
||||
|
||||
#### 3월: 기술 설계
|
||||
- [ ] 시스템 아키텍처 설계
|
||||
- [ ] 데이터베이스 스키마 설계
|
||||
- [ ] API 명세 작성
|
||||
- [ ] 보안 및 개인정보 보호 전략 수립
|
||||
|
||||
### 2단계: MVP 개발 (2024년 Q2)
|
||||
|
||||
#### 4월: 기본 인프라 구축
|
||||
- [ ] 개발 환경 설정
|
||||
- [ ] CI/CD 파이프라인 구축
|
||||
- [ ] 백엔드 서버 기본 구조 개발
|
||||
- [ ] 데이터베이스 구축 및 연결
|
||||
|
||||
#### 5월: 핵심 기능 개발 (1)
|
||||
- [ ] 사용자 인증 시스템 구현
|
||||
- [ ] 기본 수입/지출 기록 기능 개발
|
||||
- [ ] 카테고리 관리 기능 개발
|
||||
- [ ] 기본 대시보드 구현 (D3.js/Chart.js 활용)
|
||||
- [ ] 뉴모피즘 스타일 UI 컴포넌트 개발
|
||||
|
||||
#### 6월: 핵심 기능 개발 (2)
|
||||
- [ ] 예산 설정 및 관리 기능 개발
|
||||
- [ ] 기본 분석 보고서 구현
|
||||
- [ ] 알림 시스템 구현
|
||||
- [ ] 데이터 백업 및 복원 기능 개발
|
||||
|
||||
### 3단계: 베타 테스트 및 개선 (2024년 Q3)
|
||||
|
||||
#### 7월: 베타 버전 완성
|
||||
- [ ] 기능 통합 및 안정화
|
||||
- [ ] 성능 최적화
|
||||
- [ ] 사용자 피드백 수집 시스템 구현
|
||||
- [ ] 베타 테스트 환경 구축
|
||||
|
||||
#### 8월: 베타 테스트 진행
|
||||
- [ ] 클로즈드 베타 테스트 진행 (100명 규모)
|
||||
- [ ] 사용자 피드백 수집 및 분석
|
||||
- [ ] 버그 수정 및 UI/UX 개선
|
||||
- [ ] 성능 모니터링 및 최적화
|
||||
|
||||
#### 9월: 개선 및 추가 기능 개발
|
||||
- [ ] 베타 테스트 피드백 기반 개선사항 적용
|
||||
- [ ] 추가 기능 개발 (사용자 요구 기반)
|
||||
- [ ] 앱 안정성 및 성능 최적화
|
||||
- [ ] 출시 준비 (앱스토어 등록 준비)
|
||||
|
||||
### 4단계: 출시 및 확장 (2024년 Q4)
|
||||
|
||||
#### 10월: 공식 출시
|
||||
- [ ] 앱스토어 및 구글 플레이 스토어 등록 (Capacitor 앱 배포)
|
||||
- [ ] 웹 버전 공개 및 PWA 배포
|
||||
- [ ] 마케팅 캠페인 실행
|
||||
- [ ] 사용자 지원 시스템 구축
|
||||
- [ ] 실시간 모니터링 및 이슈 대응
|
||||
|
||||
#### 11월: 고급 기능 개발 (1)
|
||||
- [ ] AI 기반 지출 분석 엔진 개발
|
||||
- [ ] 맞춤형 절약 제안 시스템 구현
|
||||
- [ ] 영수증 스캔 및 자동 분류 기능 개발
|
||||
- [ ] 사용자 행동 분석 시스템 구현
|
||||
|
||||
#### 12월: 고급 기능 개발 (2)
|
||||
- [ ] 금융 계좌 연동 기능 개발
|
||||
- [ ] 절약 챌린지 시스템 구현
|
||||
- [ ] 커뮤니티 기능 개발
|
||||
- [ ] 프리미엄 구독 모델 구현
|
||||
|
||||
### 5단계: 확장 및 고도화 (2025년 Q1-Q2)
|
||||
|
||||
#### 3월 추가 작업: 기술 스택 전환 (Flutter → React, MongoDB → Supabase)
|
||||
- [x] 문서 업데이트 (README.md, 시스템 아키텍처, Lovable UI 컴포넌트 정리)
|
||||
- [x] Lovable UI 컴포넌트 React 구현 (LovableButton, LovableCard, LovableBudgetCard, LovableTransactionCard, LovableAddTransactionButton)
|
||||
- [x] 홈 화면 React 리팩토링
|
||||
- [x] Supabase 기본 연동 설정 (데이터 모델, 실시간 구독)
|
||||
- [ ] Supabase 인증 구현 및 완전한 통합
|
||||
- [ ] Capacitor 설정 및 네이티브 기능 연동
|
||||
|
||||
#### 3-4월: 서비스 확장 및 안정화
|
||||
- [ ] 상태 관리 시스템 구현 (React Context 또는 Redux)
|
||||
- [ ] 추가 화면 개발 (통계, 예산 설정, 프로필)
|
||||
- [ ] 다중 기기 동기화 기능 구현
|
||||
- [ ] 데스크톱 앱 버전 개발 (Electron 활용)
|
||||
- [ ] 국제화 및 현지화 (다국어 지원)
|
||||
|
||||
#### 5-6월: 서비스 고도화
|
||||
- [ ] 고급 데이터 시각화 도구 개발
|
||||
- [ ] 고급 AI 예측 모델 개발
|
||||
- [ ] 금융 교육 콘텐츠 통합
|
||||
- [ ] 파트너십 확대 (금융 기관, 핀테크 등)
|
||||
- [ ] 사용자 데이터 기반 서비스 개인화 강화
|
||||
|
||||
## 개발 팀 구성
|
||||
|
||||
### 핵심 팀 (초기 단계)
|
||||
- **프로젝트 매니저**: 1명 - 전체 프로젝트 조정 및 일정 관리
|
||||
- **UI/UX 디자이너**: 1명 - 사용자 경험 설계 및 시각적 디자인
|
||||
- **프론트엔드 개발자**: 2명 - 웹 앱 개발 (React, Capacitor)
|
||||
- **백엔드 개발자**: 2명 - 서버 및 API 개발 (Node.js)
|
||||
- **데이터 엔지니어**: 1명 - 데이터 모델링 및 분석 시스템 개발
|
||||
- **QA 엔지니어**: 1명 - 품질 보증 및 테스트 자동화
|
||||
|
||||
### 확장 팀 (후기 단계)
|
||||
- **AI/ML 엔지니어**: 1명 - 인공지능 및 기계학습 모델 개발
|
||||
- **DevOps 엔지니어**: 1명 - 인프라 관리 및 배포 자동화
|
||||
- **마케팅 전문가**: 1명 - 사용자 확보 및 브랜딩 전략
|
||||
- **콘텐츠 제작자**: 1명 - 재정 교육 콘텐츠 및 가이드 제작
|
||||
- **고객 지원 담당자**: 1-2명 - 사용자 문의 대응 및 지원
|
||||
|
||||
## 개발 환경 및 도구
|
||||
|
||||
### 개발 환경
|
||||
- **프론트엔드**: React, Vite, Tailwind CSS, Capacitor, TypeScript
|
||||
- **상태 관리**: React Context API (또는 Redux 검토 중)
|
||||
- **백엔드**: Supabase(PostgreSQL) On-Premise
|
||||
- **인증**: Supabase Auth
|
||||
- **AI/ML**: Python, TensorFlow, Pandas
|
||||
- **인프라**: Docker, Kubernetes
|
||||
|
||||
### 개발 도구
|
||||
- **프로젝트 관리**: Jira, Confluence
|
||||
- **소스 코드 관리**: GitHub
|
||||
- **CI/CD**: GitHub Actions, Jenkins
|
||||
- **커뮤니케이션**: Slack, Zoom
|
||||
- **디자인**: Figma, Adobe XD
|
||||
- **테스트**: Jest, Cypress, Postman
|
||||
|
||||
## 품질 보증 전략
|
||||
|
||||
### 테스트 전략
|
||||
- **단위 테스트**: 개별 함수 및 컴포넌트 테스트 (Jest)
|
||||
- **통합 테스트**: 컴포넌트 간 상호작용 테스트
|
||||
- **E2E 테스트**: 사용자 시나리오 기반 전체 흐름 테스트 (Cypress)
|
||||
- **성능 테스트**: 로드 테스트 및 스트레스 테스트
|
||||
- **보안 테스트**: 취약점 스캔 및 침투 테스트
|
||||
|
||||
### 코드 품질 관리
|
||||
- **코드 리뷰**: 모든 코드 변경에 대한 동료 검토
|
||||
- **정적 코드 분석**: ESLint, SonarQube
|
||||
- **코드 컨벤션**: 일관된 코딩 스타일 가이드
|
||||
- **문서화**: 코드 및 API 문서 자동화
|
||||
|
||||
## 위험 관리
|
||||
|
||||
### 잠재적 위험 및 대응 전략
|
||||
1. **일정 지연**
|
||||
- 대응: 우선순위 재조정, 스프린트 계획 유연성 확보
|
||||
- 완화: 버퍼 시간 확보, 주기적 진행 상황 검토
|
||||
|
||||
2. **기술적 복잡성**
|
||||
- 대응: 전문가 자문, 기술 스파이크 활용
|
||||
- 완화: 단계적 구현, 대안 기술 검토
|
||||
|
||||
3. **사용자 채택 저조**
|
||||
- 대응: 사용자 피드백 기반 개선, 마케팅 전략 조정
|
||||
- 완화: 초기 사용자 테스트, 경쟁 분석 강화
|
||||
|
||||
4. **보안 및 개인정보 이슈**
|
||||
- 대응: 즉각적인 취약점 패치, 투명한 커뮤니케이션
|
||||
- 완화: 정기적인 보안 감사, 개인정보 보호 설계
|
||||
|
||||
## 성공 기준
|
||||
|
||||
### 기술적 성공 기준
|
||||
- 99.9% 이상의 서비스 가용성
|
||||
- 앱 크래시 비율 0.1% 미만
|
||||
- 평균 앱 로딩 시간 2초 이내
|
||||
- 데이터 손실 사고 0건
|
||||
|
||||
### 비즈니스 성공 기준
|
||||
- 출시 6개월 내 50,000명 이상의 활성 사용자 확보
|
||||
- 무료 사용자의 8% 이상 유료 구독 전환
|
||||
- 앱스토어 평점 4.5/5.0 이상
|
||||
- 사용자 유지율 30일 기준 40% 이상
|
||||
|
||||
## 결론
|
||||
|
||||
'적자 탈출 가계부' 개발 로드맵은 사용자 중심의 접근 방식과 애자일 방법론을 기반으로 설계되었습니다. MVP 접근법을 통해 핵심 기능을 우선적으로 개발하고, 사용자 피드백을 지속적으로 반영하여 서비스를 개선해 나갈 계획입니다.
|
||||
|
||||
개발 과정에서 발생할 수 있는 위험을 사전에 식별하고 대응 전략을 마련하여, 프로젝트의 성공적인 완수를 위한 기반을 마련하였습니다. 또한, 명확한 성공 기준을 설정하여 프로젝트의 진행 상황을 객관적으로 평가할 수 있도록 하였습니다.
|
||||
|
||||
이 로드맵은 프로젝트의 진행 상황과 사용자 피드백에 따라 유연하게 조정될 수 있으며, 궁극적으로는 사용자들이 재정적 어려움에서 벗어나 건강한 재정 상태를 달성할 수 있도록 돕는 가치 있는 서비스를 제공하는 것을 목표로 합니다.
|
||||
122
docs/03_개발_단계/1단계/1단계_산출물_요약.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# 적자 탈출 가계부 - 1단계 산출물 요약
|
||||
|
||||
## 1. 요구사항 문서
|
||||
|
||||
### 1.1 사용자 페르소나
|
||||
- 3개의 대표 페르소나 정의 (직장인, 신혼부부, 대학생)
|
||||
- 각 페르소나의 재정적 특성, 소비 패턴, 목표 정의
|
||||
- 페르소나별 주요 문제점과 니즈 식별
|
||||
|
||||
### 1.2 핵심 문제 정의
|
||||
- 신용카드 사용 관련 문제점 분석
|
||||
- 기존 가계부/금융 앱의 한계 정리
|
||||
- MVP 접근 방식 및 문제 해결 전략 수립
|
||||
|
||||
### 1.3 주요 사용 시나리오
|
||||
- 3개의 사용자 시나리오 작성
|
||||
- 월간 카드 한도 관리
|
||||
- 충동 구매 방지
|
||||
- 부부 공동 카드 관리
|
||||
- 각 시나리오별 사용자 여정 및 앱 기능 요구사항 정의
|
||||
|
||||
### 1.4 프로젝트 개요
|
||||
- 프로젝트 목표, 범위, 기술 스택 정의
|
||||
- MVP 핵심 기능 신용카드 관리 중심으로 수정
|
||||
- 확장 기능에 AI 기반 재정 어시스턴트 추가
|
||||
|
||||
## 2. 사용자 스토리 및 기능 목록
|
||||
|
||||
### 2.1 사용자 스토리
|
||||
- 카드 한도 관리 관련 스토리 (한도 설정, 현황 확인, 알림)
|
||||
- 카드 사용 내역 관리 관련 스토리 (내역 기록, 조회/분석, 수정/관리)
|
||||
- 대시보드 및 분석 관련 스토리 (메인 대시보드, 지출 분석, 리포트/인사이트)
|
||||
- 사용자 관리 및 설정 관련 스토리 (프로필 관리, 데이터 관리, 다중 사용자 지원)
|
||||
|
||||
### 2.2 MVP 기능 목록 (MoSCoW 방법론)
|
||||
- Must have: 월간 카드 한도 설정, 실시간 사용량 표시, 기본 알림 등
|
||||
- Should have: 카테고리별 한도, 내역 템플릿, 기본 분석 기능 등
|
||||
- Could have: 영수증 사진 촬영, 위치 기반 자동 완성, 맞춤형 리포트 등
|
||||
- Won't have: 자동 내역 동기화, 다중 사용자 지원, AI 고급 분석 등
|
||||
|
||||
### 2.3 제외 기능 명확한 정의
|
||||
- 자동 내역 동기화, 다중 사용자 지원, AI 기반 고급 분석 등 MVP에서 제외되는 기능 명확히 정의
|
||||
|
||||
## 3. 데이터 모델 설계
|
||||
|
||||
### 3.1 핵심 데이터 엔티티
|
||||
- 사용자(Users) 테이블 구조
|
||||
- 카드(Cards) 테이블 구조
|
||||
- 카테고리(Categories) 테이블 구조
|
||||
- 지출(Expenses) 테이블 구조
|
||||
- 한도(Limits) 테이블 구조
|
||||
- 알림(Notifications) 테이블 구조
|
||||
- 템플릿(Templates) 테이블 구조
|
||||
|
||||
### 3.2 데이터 관계 및 제약 조건
|
||||
- 테이블 간 관계 정의 (ERD 작성)
|
||||
- 기본 카테고리 목록 정의
|
||||
- 데이터 유효성 검사 규칙 정의
|
||||
|
||||
### 3.3 데이터베이스 인덱스 설계
|
||||
- 성능 최적화를 위한 인덱스 설계
|
||||
- 데이터 마이그레이션 전략
|
||||
- 데이터 보안 고려사항
|
||||
|
||||
## 4. UI/UX 와이어프레임
|
||||
|
||||
### 4.1 핵심 화면 와이어프레임
|
||||
- 로그인/회원가입 화면
|
||||
- 메인 대시보드 화면
|
||||
- 지출 입력 화면
|
||||
- 지출 목록 화면
|
||||
- 필터 및 검색 화면
|
||||
|
||||
### 4.2 추가 화면 와이어프레임
|
||||
- 예산 설정 화면
|
||||
- 분석 화면
|
||||
- 설정 화면
|
||||
- 카드 관리 화면
|
||||
- 카드 추가 화면
|
||||
|
||||
### 4.3 화면 간 이동 흐름도
|
||||
- 주요 사용자 흐름 정의
|
||||
- 신규 사용자 온보딩 흐름
|
||||
- 지출 기록 흐름
|
||||
- 지출 분석 흐름
|
||||
- 한도 관리 흐름
|
||||
- 지출 내역 검색 흐름
|
||||
|
||||
### 4.4 디자인 노트
|
||||
- 색상 팔레트
|
||||
- 타이포그래피
|
||||
- 아이콘 및 시각적 요소
|
||||
- 사용자 경험 고려사항
|
||||
- 접근성 고려사항
|
||||
|
||||
## 5. 기술 스택 및 개발 환경
|
||||
|
||||
### 5.1 기술 스택
|
||||
- 모바일 앱: Flutter (크로스 플랫폼)
|
||||
- 백엔드: Supabase (PostgreSQL)
|
||||
- AI 모델:
|
||||
- 기기 내: TensorFlow Lite, 경량 모델 (DistilBERT)
|
||||
- 서버: Hugging Face 또는 OpenAI 모델
|
||||
|
||||
### 5.2 개발 환경 설정 계획
|
||||
- 개발 환경 요구사항
|
||||
- 필요한 개발 도구 목록
|
||||
- 로컬 개발 환경과 서버 환경 설정 단계
|
||||
|
||||
## 6. 다음 단계 계획
|
||||
|
||||
### 6.1 2단계 목표
|
||||
- 백엔드 구축 (Supabase 설정)
|
||||
- 데이터베이스 스키마 구현
|
||||
- 기본 API 엔드포인트 개발
|
||||
- 인증 시스템 구현
|
||||
|
||||
### 6.2 향후 고려사항
|
||||
- 개인정보 보호 방안
|
||||
- LLM 모델 선택 및 최적화
|
||||
- 사용자 피드백 반영 전략
|
||||
- 단계별 기능 확장 계획
|
||||
131
docs/03_개발_단계/1단계/1단계_첫주차_할일.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# 적자 탈출 가계부 앱 - 1단계 첫 주차 할 일
|
||||
|
||||
## 역할 구분
|
||||
- [사용자] : 제품 기획 및 테스트 담당자가 수행할 작업
|
||||
- [AI] : AI 어시스턴트가 수행할 작업
|
||||
- [공동] : 함께 논의하고 결정할 작업
|
||||
|
||||
## 1일차: 프로젝트 초기화 및 요구사항 정의
|
||||
|
||||
### 오전
|
||||
- [공동] 프로젝트 관리 환경 설정 ✅
|
||||
- [사용자] 프로젝트 폴더 구조 생성 ✅
|
||||
- [AI] 문서 템플릿 준비 (요구사항, 디자인 등) ✅
|
||||
- [사용자] 일정 관리 도구 설정 (선택적)
|
||||
|
||||
### 오후
|
||||
- [사용자] MVP(Minimum Viable Product) 핵심 요구사항 정의
|
||||
- [사용자] 사용자 페르소나 작성 (주 사용자층 정의) ✅
|
||||
- [사용자] 핵심 문제 정의 (적자 발생 원인 분석) ✅
|
||||
- [사용자] 주요 사용 시나리오 작성 (2-3개) ✅
|
||||
- [AI] 요구사항 문서화 및 정리 ✅
|
||||
|
||||
## 2일차: 사용자 스토리 및 기능 목록 작성
|
||||
|
||||
### 오전
|
||||
- [공동] 사용자 스토리 작성
|
||||
- [사용자] 핵심 사용자 니즈 정의
|
||||
- [AI] 사용자 스토리 형식으로 문서화: ✅
|
||||
- "사용자로서 나는 지출을 빠르게 기록하고 싶다"
|
||||
- "사용자로서 나는 현재 사용 가능한 잔액을 실시간으로 확인하고 싶다"
|
||||
- "사용자로서 나는 월별 예산을 설정하고 진행 상황을 확인하고 싶다"
|
||||
- "사용자로서 나는 지출 패턴을 카테고리별로 분석하고 싶다"
|
||||
- "사용자로서 나는 예산 초과 시 알림을 받고 싶다"
|
||||
|
||||
### 오후
|
||||
- [공동] MVP 기능 목록 및 우선순위 설정 ✅
|
||||
- [사용자] 필수 기능 결정 ✅
|
||||
- [AI] 기능별 우선순위 부여 (MoSCoW 방법: Must have, Should have, Could have, Won't have) ✅
|
||||
- [공동] 제외할 기능 명확히 정의 ✅
|
||||
|
||||
## 3일차: 데이터 모델 설계
|
||||
|
||||
### 오전
|
||||
- [AI] 핵심 데이터 엔티티 정의 ✅
|
||||
- [AI] 사용자(users) 테이블 구조 설계 ✅
|
||||
- [AI] 지출(expenses) 테이블 구조 설계 ✅
|
||||
- [AI] 카테고리(categories) 테이블 구조 설계 ✅
|
||||
- [AI] 예산(budgets) 테이블 구조 설계 ✅
|
||||
|
||||
### 오후
|
||||
- [공동] 데이터 관계 및 제약 조건 설계 ✅
|
||||
- [AI] 테이블 간 관계 정의 (ERD 작성) ✅
|
||||
- [사용자] 기본 카테고리 목록 정의 ✅
|
||||
- [AI] 데이터 유효성 검사 규칙 정의 ✅
|
||||
- [사용자] 데이터 모델 검토 및 피드백 ✅
|
||||
|
||||
## 4-5일차: UI/UX 와이어프레임 작성
|
||||
|
||||
### 4일차
|
||||
- [공동] 핵심 화면 와이어프레임 스케치 ✅
|
||||
- [AI] 초기 와이어프레임 제안: ✅
|
||||
- 로그인/회원가입 화면 ✅
|
||||
- 메인 대시보드 화면 ✅
|
||||
- 지출 입력 화면 ✅
|
||||
- 지출 목록 화면 ✅
|
||||
- [사용자] 와이어프레임 검토 및 피드백 ✅
|
||||
|
||||
### 5일차
|
||||
- [공동] 추가 화면 및 사용자 흐름 설계 ✅
|
||||
- [AI] 추가 와이어프레임 제안: ✅
|
||||
- 예산 설정 화면 ✅
|
||||
- 분석 화면 ✅
|
||||
- 설정 화면 ✅
|
||||
- [AI] 화면 간 이동 흐름도 작성 ✅
|
||||
- [사용자] 최종 와이어프레임 검토 및 승인 ✅
|
||||
|
||||
## 6일차: 기술 스택 결정 및 개발 환경 설정 계획
|
||||
|
||||
### 오전
|
||||
- [AI] 최종 기술 스택 결정 ✅
|
||||
- [AI] Flutter 버전 선택 ✅
|
||||
- [AI] 필요한 Flutter 패키지 목록 작성 ✅
|
||||
- [AI] Supabase 설치 요구사항 확인 ✅
|
||||
- [사용자] 기술 스택 검토 및 승인 ✅
|
||||
|
||||
### 오후
|
||||
- [AI] 개발 환경 설정 계획 수립 ✅
|
||||
- [AI] 개발 환경 요구사항 문서화 ✅
|
||||
- [AI] 필요한 개발 도구 목록 작성 ✅
|
||||
- [AI] 로컬 개발 환경과 서버 환경 설정 단계 정의 ✅
|
||||
- [사용자] 서버 환경 정보 공유 ✅
|
||||
|
||||
## 7일차: 1단계 검토 및 2단계 준비
|
||||
|
||||
### 오전
|
||||
- [공동] 1단계 산출물 검토
|
||||
- [사용자] 요구사항 문서 검토 및 피드백
|
||||
- [사용자] 와이어프레임 최종 검토
|
||||
- [AI] 데이터 모델 최종 검토
|
||||
- [AI] 문서 보완 및 수정
|
||||
|
||||
### 오후
|
||||
- [공동] 2단계 계획 수립
|
||||
- [AI] 2단계 작업 목록 초안 작성
|
||||
- [사용자] 2단계 일정 및 우선순위 결정
|
||||
- [공동] 2단계 목표 및 성공 기준 정의
|
||||
- [AI] 1단계 결과물 최종 정리 및 문서화
|
||||
|
||||
## 주간 산출물 목록
|
||||
|
||||
1. **요구사항 문서** [공동]
|
||||
- MVP 핵심 요구사항 정의서
|
||||
- 사용자 스토리 목록
|
||||
- 기능 우선순위 목록
|
||||
|
||||
2. **데이터 모델 문서** [AI 주도]
|
||||
- 데이터베이스 스키마 설계서
|
||||
- ERD(Entity Relationship Diagram)
|
||||
- 기본 카테고리 목록 [사용자 정의]
|
||||
|
||||
3. **디자인 문서** [공동]
|
||||
- 핵심 화면 와이어프레임
|
||||
- 사용자 흐름도
|
||||
- UI 컴포넌트 목록
|
||||
|
||||
4. **기술 문서** [AI 주도]
|
||||
- 기술 스택 명세서
|
||||
- 개발 환경 설정 가이드
|
||||
- 2단계 백엔드 구축 계획
|
||||
|
||||
이 일정은 유연하게 조정 가능하며, 각 태스크의 완료 상황에 따라 일정을 앞당기거나 미룰 수 있습니다. 중요한 것은 1주차 말에 2단계 백엔드 구축을 시작할 수 있도록 필요한 모든 계획과 설계가 완료되는 것입니다.
|
||||
303
docs/03_개발_단계/2단계/2단계_계획.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# 적자 탈출 가계부 - 2단계 계획
|
||||
|
||||
## 1. 2단계 목표
|
||||
|
||||
2단계의 주요 목표는 적자 탈출 가계부 앱의 백엔드 인프라를 구축하고, 데이터베이스를 설계하며, 기본적인 API 엔드포인트를 개발하는 것입니다. 이를 통해 3단계에서 진행될 프론트엔드 개발을 위한 기반을 마련합니다.
|
||||
|
||||
### 핵심 목표
|
||||
1. [x] Supabase 기반 백엔드 인프라 구축
|
||||
2. [x] 데이터베이스 스키마 구현
|
||||
3. [x] 기본 API 엔드포인트 개발
|
||||
4. [x] 사용자 인증 시스템 구현
|
||||
5. [ ] 초기 테스트 환경 구성
|
||||
|
||||
## 2. 작업 목록 및 일정
|
||||
|
||||
### 1일차: Supabase 프로젝트 설정
|
||||
|
||||
#### 오전
|
||||
- [x] [사용자] Supabase 계정 생성 및 프로젝트 생성
|
||||
- [x] [AI] Supabase 프로젝트 설정 가이드 작성
|
||||
- [x] [공동] 프로젝트 환경 변수 및 보안 설정
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 데이터베이스 연결 테스트 코드 작성
|
||||
- [x] [사용자] 데이터베이스 연결 테스트
|
||||
- [x] [AI] 기본 백엔드 구조 설계 문서 작성
|
||||
|
||||
### 2일차: 데이터베이스 스키마 구현
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] SQL 스키마 스크립트 작성
|
||||
- [x] Users 테이블 생성
|
||||
- [x] Cards 테이블 생성
|
||||
- [x] Categories 테이블 생성
|
||||
- [x] Expenses 테이블 생성
|
||||
- [x] Limits 테이블 생성
|
||||
- [x] Notifications 테이블 생성
|
||||
- [x] Templates 테이블 생성
|
||||
|
||||
#### 오후
|
||||
- [x] [사용자] SQL 스키마 스크립트 실행 및 검증
|
||||
- [x] [AI] 기본 카테고리 데이터 삽입 스크립트 작성
|
||||
- [x] [사용자] 기본 데이터 삽입 및 확인
|
||||
- [x] [공동] 데이터베이스 인덱스 및 제약 조건 검토
|
||||
- [x] [공동] 코드 및 문서 관리 원칙 수립 (Gitea와 옵시디언 통합)
|
||||
|
||||
### 3-4일차: API 엔드포인트 개발
|
||||
|
||||
#### 3일차 오전
|
||||
- [x] [AI] 사용자 관리 API 개발
|
||||
- [x] 회원가입 API
|
||||
- [x] 로그인 API
|
||||
- [x] 프로필 조회/수정 API
|
||||
- [x] 비밀번호 변경/재설정 API
|
||||
|
||||
#### 3일차 오후
|
||||
- [x] [AI] 카드 관리 API 개발
|
||||
- [x] 카드 등록 API
|
||||
- [x] 카드 조회 API
|
||||
- [x] 카드 수정/삭제 API
|
||||
- [x] 카드 한도 설정 API
|
||||
|
||||
#### 4일차 오전
|
||||
- [x] [AI] 지출 관리 API 개발
|
||||
- [x] 지출 등록 API
|
||||
- [x] 지출 조회 API
|
||||
- [x] 지출 수정/삭제 API
|
||||
- [x] 지출 필터링/검색 API
|
||||
|
||||
#### 4일차 오후
|
||||
- [x] [AI] 분석 및 대시보드 API 개발
|
||||
- [x] 카테고리별 지출 분석 API
|
||||
- [x] 기간별 지출 추이 API
|
||||
- [x] 한도 사용 현황 API
|
||||
- [x] 대시보드 요약 정보 API
|
||||
|
||||
### 5일차: 인증 및 보안 구현
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 사용자 인증 시스템 구현
|
||||
- [x] JWT 토큰 기반 인증 설정
|
||||
- [x] 소셜 로그인 연동 (Google, Kakao, Naver, Apple)
|
||||
- [x] 권한 관리 시스템 구현
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 데이터 보안 구현
|
||||
- [x] 민감 정보 암호화 설정
|
||||
- [x] API 요청 검증 미들웨어 구현
|
||||
- [x] CORS 및 보안 헤더 설정
|
||||
|
||||
### 6일차: 테스트 및 문서화
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] API 테스트 스크립트 작성
|
||||
- [x] 단위 테스트 작성
|
||||
- [x] 통합 테스트 작성
|
||||
- [x] 성능 테스트 작성
|
||||
|
||||
#### 오후
|
||||
- [x] [공동] API 문서 작성
|
||||
- [x] Swagger/OpenAPI 문서 생성
|
||||
- [x] API 엔드포인트 사용 예제 작성
|
||||
- [x] 에러 코드 및 응답 형식 문서화
|
||||
|
||||
### 7일차: 2단계 검토 및 3단계 준비
|
||||
|
||||
#### 오전
|
||||
- [x] [공동] 2단계 산출물 검토
|
||||
- [x] 백엔드 기능 테스트
|
||||
- [x] API 응답 검증
|
||||
- [x] 성능 및 보안 검토
|
||||
|
||||
#### 오후
|
||||
- [ ] [공동] 3단계 계획 수립
|
||||
- [ ] 3단계 작업 목록 초안 작성
|
||||
- [ ] 3단계 일정 및 우선순위 결정
|
||||
- [ ] 3단계 목표 및 성공 기준 정의
|
||||
- [ ] [AI] 2단계 결과물 최종 정리 및 문서화
|
||||
|
||||
## 3. 기술적 고려사항
|
||||
|
||||
### 3.1 Supabase 설정
|
||||
- Supabase 프로젝트 리전: 서울 (ap-northeast-2)
|
||||
- 데이터베이스 성능 티어: 스타터 플랜
|
||||
- 스토리지 설정: 영수증 이미지 저장용 버킷 구성
|
||||
- 백업 설정: 일일 자동 백업 활성화
|
||||
|
||||
### 3.2 API 설계 원칙
|
||||
- RESTful API 설계 원칙 준수
|
||||
- JSON 응답 형식 표준화
|
||||
- HTTP 상태 코드 적절히 활용
|
||||
- 페이지네이션 및 필터링 지원
|
||||
- 일관된 에러 처리 및 응답 형식
|
||||
|
||||
### 3.3 보안 고려사항
|
||||
- 모든 API 요청에 인증 필요 (공개 API 제외)
|
||||
- 비밀번호 해싱에 bcrypt 사용
|
||||
- API 요청 속도 제한 설정
|
||||
- 민감한 정보는 서버 측에서만 처리
|
||||
- HTTPS 강제 적용
|
||||
|
||||
### 3.4 성능 최적화
|
||||
- 데이터베이스 쿼리 최적화
|
||||
- 적절한 인덱스 설정
|
||||
- 캐싱 전략 구현 (Redis 고려)
|
||||
- 대량 데이터 처리를 위한 페이지네이션
|
||||
- 비동기 처리가 필요한 작업 식별
|
||||
|
||||
## 4. 산출물 목록
|
||||
|
||||
2단계 완료 시 다음과 같은 산출물이 생성될 예정입니다:
|
||||
|
||||
1. **Supabase 프로젝트 설정 문서**
|
||||
- 프로젝트 구성 정보
|
||||
- 환경 변수 목록
|
||||
- 접근 권한 설정
|
||||
|
||||
2. **데이터베이스 스키마 문서**
|
||||
- SQL 스키마 스크립트
|
||||
- ER 다이어그램 (구현 버전)
|
||||
- 인덱스 및 제약 조건 목록
|
||||
|
||||
3. **API 문서**
|
||||
- API 엔드포인트 목록 및 설명
|
||||
- 요청/응답 형식 예제
|
||||
- 인증 및 권한 요구사항
|
||||
|
||||
4. **테스트 문서**
|
||||
- 테스트 케이스 목록
|
||||
- 테스트 결과 보고서
|
||||
- 성능 테스트 결과
|
||||
|
||||
5. **개발 가이드**
|
||||
- 로컬 개발 환경 설정 방법
|
||||
- API 사용 예제 코드
|
||||
- 문제 해결 가이드
|
||||
|
||||
## 5. 위험 요소 및 대응 계획
|
||||
|
||||
### 5.1 기술적 위험
|
||||
- **Supabase 제한 사항**: 무료/스타터 플랜의 제한 사항 파악 및 대응 계획 수립
|
||||
- **데이터베이스 성능**: 대량 데이터 처리 시 성능 이슈 대응 방안 마련
|
||||
- **API 응답 시간**: 복잡한 쿼리의 응답 시간 최적화 전략 수립
|
||||
|
||||
### 5.2 일정 관련 위험
|
||||
- **기술 학습 시간**: Supabase 학습에 필요한 추가 시간 고려
|
||||
- **예상치 못한 문제**: 버퍼 시간을 일정에 포함하여 계획
|
||||
|
||||
### 5.3 보안 관련 위험
|
||||
- **데이터 보안**: 민감 정보 보호를 위한 추가 보안 조치 계획
|
||||
- **인증 시스템**: 보안 취약점 방지를 위한 철저한 테스트 계획
|
||||
|
||||
## 6. 성공 기준
|
||||
|
||||
2단계는 다음 기준이 충족될 때 성공적으로 완료된 것으로 간주합니다:
|
||||
|
||||
1. 모든 데이터베이스 테이블이 성공적으로 생성되고 관계가 설정됨
|
||||
2. 모든 필수 API 엔드포인트가 구현되고 테스트됨
|
||||
3. 사용자 인증 시스템이 안전하게 작동함
|
||||
4. API 응답 시간이 목표 성능 기준을 충족함 (평균 응답 시간 < 300ms)
|
||||
5. 모든 API가 문서화되고 프론트엔드 개발에 사용할 준비가 됨
|
||||
|
||||
## 7. 다음 단계 미리보기
|
||||
|
||||
2단계 완료 후 진행될 3단계의 주요 내용은 다음과 같습니다:
|
||||
|
||||
1. Flutter 프로젝트 설정 및 기본 구조 구현
|
||||
2. UI 컴포넌트 개발 및 스타일 가이드 작성
|
||||
3. 백엔드 API와의 연동 구현
|
||||
4. 핵심 화면 및 기능 구현
|
||||
5. 사용자 테스트 및 피드백 수집
|
||||
|
||||
## 8. 진행 상황
|
||||
|
||||
### 8.1 완료된 작업
|
||||
1. [x] **Supabase 프로젝트 설정**
|
||||
- [x] 프로젝트 생성 및 기본 설정
|
||||
- [x] 데이터베이스 연결 설정
|
||||
- [x] 스토리지 버킷 구성
|
||||
- [x] 백업 설정 구성
|
||||
|
||||
2. [x] **데이터베이스 스키마 구현**
|
||||
- [x] 사용자 테이블 생성
|
||||
- [x] 카테고리 테이블 생성
|
||||
- [x] 지출/수입 테이블 생성
|
||||
- [x] 예산 테이블 생성
|
||||
- [x] 카드 테이블 생성
|
||||
- [x] 한도 테이블 생성
|
||||
- [x] 템플릿 테이블 생성
|
||||
- [x] 알림 테이블 생성
|
||||
- [x] 분석 설정 테이블 생성
|
||||
|
||||
3. [x] **기본 데이터 삽입**
|
||||
- [x] 기본 카테고리 데이터 삽입
|
||||
- [x] 테스트 사용자 데이터 삽입
|
||||
- [x] 샘플 지출/수입 데이터 삽입
|
||||
|
||||
4. [x] **API 엔드포인트 개발**
|
||||
- [x] 사용자 관리 API 함수 구현
|
||||
- [x] 카테고리 관리 API 함수 구현
|
||||
- [x] 지출/수입 관리 API 함수 구현
|
||||
- [x] 예산 관리 API 함수 구현
|
||||
- [x] 카드 관리 API 함수 구현
|
||||
- [x] 한도 관리 API 함수 구현
|
||||
- [x] 템플릿 관리 API 함수 구현
|
||||
- [x] 알림 관리 API 함수 구현
|
||||
- [x] 분석 관리 API 함수 구현
|
||||
|
||||
5. [x] **사용자 인증 시스템 구현**
|
||||
- [x] JWT 토큰 기반 인증
|
||||
- [x] 비밀번호 암호화 (bcrypt)
|
||||
- [x] 소셜 로그인 연동 (Google, Kakao, Naver, Apple)
|
||||
- [x] 이메일 인증 및 비밀번호 재설정
|
||||
- [x] Row Level Security (RLS) 정책 구현
|
||||
- [x] 토큰 블랙리스트 관리 (로그아웃)
|
||||
|
||||
6. [x] **데이터 보안 구현**
|
||||
- [x] 민감 정보 암호화 설정
|
||||
- [x] API 요청 검증 미들웨어 구현
|
||||
- [x] CORS 및 보안 헤더 설정
|
||||
- [x] 데이터 암호화 전략 수립
|
||||
- [x] 보안 감사 및 검증
|
||||
|
||||
7. [x] **성능 테스트 및 최적화**
|
||||
- [x] 데이터베이스 쿼리 성능 테스트
|
||||
- [x] 성능 병목 지점 식별
|
||||
- [x] 성능 최적화 전략 수립
|
||||
- [x] 성능 테스트 보고서 작성
|
||||
|
||||
### 8.2 진행 중인 작업
|
||||
- [x] 보안 감사 및 검증
|
||||
- [x] 보안 취약점 분석
|
||||
- [x] 보안 테스트 및 검증
|
||||
|
||||
### 8.3 다음 단계
|
||||
- [ ] 백엔드 테스트
|
||||
- [x] 단위 테스트 작성 및 실행
|
||||
- [x] 인증 시스템 단위 테스트 작성 및 실행
|
||||
- [x] 기타 API 함수 단위 테스트 작성 및 실행
|
||||
- [x] 통합 테스트 구현
|
||||
- [x] 보안 테스트 및 취약점 분석
|
||||
|
||||
- [ ] 3단계 준비
|
||||
- [ ] 프론트엔드 개발 환경 설정
|
||||
- [ ] API 연동 계획 수립
|
||||
- [ ] 3단계 세부 일정 및 작업 목록 작성
|
||||
|
||||
## 9. 이슈 및 고려사항
|
||||
|
||||
1. [ ] **Supabase Realtime 서비스 상태**
|
||||
- [ ] Realtime 서비스가 현재 Unhealthy 상태로 표시됨
|
||||
- [ ] 실시간 기능이 필요한 경우 추가 디버깅 필요
|
||||
- [ ] 우선순위: 중간 (기본 CRUD 작업에는 영향 없음)
|
||||
|
||||
2. [ ] **대용량 데이터 처리 전략**
|
||||
- [ ] 장기적인 데이터 보관 정책 수립 필요
|
||||
- [ ] 오래된 데이터 아카이빙 전략 고려
|
||||
- [ ] 우선순위: 낮음 (초기 단계에서는 문제 없음)
|
||||
|
||||
3. [ ] **API 성능 최적화**
|
||||
- [ ] 복잡한 분석 쿼리 최적화 필요
|
||||
- [ ] 캐싱 전략 구현 고려
|
||||
- [ ] 우선순위: 중간 (기본 기능에는 영향 없음)
|
||||
223
docs/03_개발_단계/3단계/3단계_계획.md
Normal file
@@ -0,0 +1,223 @@
|
||||
/Users/hansoo./Documents/my vault/3. Resource/Users/hansoo./Documents/my vault/3. Resource# 적자 탈출 가계부 - 3단계 계획
|
||||
|
||||
## 1. 3단계 목표
|
||||
|
||||
3단계의 주요 목표는 적자 탈출 가계부 앱의 프론트엔드를 개발하고, 백엔드 API와 연동하여 완전한 사용자 경험을 제공하는 것입니다. 이 단계에서는 Flutter를 사용하여 크로스 플랫폼 모바일 앱을 개발합니다.
|
||||
|
||||
### 핵심 목표
|
||||
1. [x] Flutter 프로젝트 설정 및 기본 구조 구현
|
||||
2. [x] UI 컴포넌트 개발 및 디자인 시스템 구축
|
||||
3. [ ] 백엔드 API와의 연동 구현
|
||||
4. [x] 핵심 화면 및 기능 구현
|
||||
5. [ ] 사용자 테스트 및 피드백 수집
|
||||
|
||||
## 2. 작업 목록 및 일정
|
||||
|
||||
### 1일차: 개발 환경 설정 및 프로젝트 구조 설계
|
||||
|
||||
#### 오전
|
||||
- [x] [사용자] Flutter 개발 환경 설정
|
||||
- [x] [AI] Flutter 프로젝트 생성 및 기본 설정 가이드 작성
|
||||
- [x] [공동] 프로젝트 구조 및 아키텍처 설계
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 상태 관리 전략 수립 (Provider, Bloc, Riverpod 등)
|
||||
- [x] [AI] 라우팅 및 네비게이션 설계
|
||||
- [x] [사용자] 기본 프로젝트 구조 검증 및 테스트
|
||||
|
||||
### 2일차: 디자인 시스템 및 UI 컴포넌트 개발
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 디자인 시스템 설계
|
||||
- [x] 색상 팔레트 및 테마 설정
|
||||
- [x] 타이포그래피 스타일 정의
|
||||
- [x] 공통 UI 컴포넌트 디자인
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 기본 UI 컴포넌트 구현
|
||||
- [x] 버튼, 입력 필드, 카드 등 기본 컴포넌트
|
||||
- [x] 커스텀 위젯 및 애니메이션
|
||||
- [x] 반응형 레이아웃 구현
|
||||
|
||||
### 3-4일차: 화면 개발 및 API 연동
|
||||
|
||||
#### 3일차 오전
|
||||
- [x] [AI] 인증 관련 화면 개발
|
||||
- [x] 로그인 화면
|
||||
- [x] 회원가입 화면
|
||||
- [x] 비밀번호 재설정 화면
|
||||
|
||||
#### 3일차 오후
|
||||
- [x] [AI] 인증 API 연동
|
||||
|
||||
{{ ... }}
|
||||
|
||||
### 5일차: 지출 관리 기능 개발
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 지출 추가/편집 화면 개발
|
||||
- [x] [AI] 지출 목록 및 상세 화면 개발
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 지출 관리 API 연동
|
||||
- [x] [AI] 지출 필터링 및 검색 기능 구현
|
||||
|
||||
### 6일차: 예산 관리 및 프로필 기능 개발
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 예산 관리 화면 개발
|
||||
- [x] 예산 설정 화면
|
||||
- [x] 예산 사용 현황 표시
|
||||
- [x] 카테고리별 예산 관리
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 프로필 화면 개발
|
||||
- [x] 사용자 정보 표시 및 수정
|
||||
- [x] 테마 설정 (라이트/다크 모드)
|
||||
- [x] 언어 설정
|
||||
- [x] 로그아웃 기능
|
||||
|
||||
### 7일차: 통계 및 분석 기능 개발
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 통계 화면 개발
|
||||
- [x] 지출 추이 차트
|
||||
- [x] 카테고리별 지출 분석
|
||||
- [x] 기간별 지출 비교
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 분석 기능 구현
|
||||
- [x] 지출 패턴 분석
|
||||
- [x] 예산 대비 지출 분석
|
||||
- [x] 절약 제안 기능
|
||||
|
||||
### 8일차: 오프라인 동기화 기능 개발
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 오프라인 동기화 인프라 구축
|
||||
- [x] 동기화 큐 서비스 구현
|
||||
- [x] 로컬 데이터베이스 서비스 구현
|
||||
- [x] 네트워크 연결 상태 모니터링 서비스 구현
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 동기화 UI/UX 구현
|
||||
- [x] 동기화 상태 위젯 개발
|
||||
- [x] 동기화 대시보드 위젯 개발
|
||||
- [x] 동기화 상태 화면 개발
|
||||
- [x] 동기화 정책 설정 기능 구현
|
||||
|
||||
### 9일차: 오프라인 동기화 기능 테스트 및 개선
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 동기화 기능 테스트
|
||||
- [x] 다양한 네트워크 상황에서의 동기화 테스트
|
||||
- [x] 오류 처리 및 재시도 메커니즘 테스트
|
||||
- [x] 대용량 데이터 동기화 테스트
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 동기화 기능 개선
|
||||
- [x] 성능 최적화
|
||||
- [x] 사용자 경험 개선
|
||||
- [x] 오류 처리 메커니즘 강화
|
||||
|
||||
{{ ... }}
|
||||
|
||||
## 5. 진행 상황 요약 (2025-02-28 업데이트)
|
||||
|
||||
### 완료된 작업
|
||||
1. **프로젝트 기본 구조 구현**
|
||||
- Flutter 프로젝트 생성 및 설정
|
||||
- 디렉토리 구조 및 아키텍처 설계
|
||||
- Provider 패턴 기반 상태 관리 구현
|
||||
|
||||
2. **디자인 시스템 구축**
|
||||
- 앱 테마 설정 (라이트/다크 모드)
|
||||
- 색상 팔레트 및 타이포그래피 정의
|
||||
- 공통 UI 컴포넌트 구현
|
||||
|
||||
3. **핵심 화면 개발**
|
||||
- 스플래시 화면
|
||||
- 로그인/회원가입 화면
|
||||
- 홈 화면 (지출 요약 및 최근 지출 목록)
|
||||
- 지출 추가/편집/상세 화면
|
||||
- 예산 관리 화면
|
||||
- 프로필 화면
|
||||
- 동기화 상태 화면
|
||||
- 통계 및 분석 화면
|
||||
|
||||
4. **서비스 레이어 구현**
|
||||
- StorageService: Hive를 사용한 로컬 데이터 저장
|
||||
- AuthService: 사용자 인증 관리
|
||||
- ExpenseService: 지출 데이터 관리
|
||||
- BudgetService: 예산 데이터 관리
|
||||
- ApiService: 백엔드 API 통신
|
||||
- SyncQueueService: 오프라인 동기화 작업 관리
|
||||
- LocalDatabaseService: 로컬 데이터베이스 관리
|
||||
- ConnectivityService: 네트워크 연결 상태 모니터링
|
||||
|
||||
5. **모델 구현**
|
||||
- UserModel: 사용자 정보 모델
|
||||
- ExpenseModel: 지출 정보 모델
|
||||
- BudgetModel: 예산 정보 모델
|
||||
- CategoryConstants: 카테고리 상수 정의
|
||||
- SyncOperation: 동기화 작업 모델
|
||||
- SyncOperationType: 작업 유형 열거형
|
||||
- SyncStatus: 작업 상태 열거형
|
||||
|
||||
6. **프로바이더 구현**
|
||||
- UserProvider: 사용자 상태 관리
|
||||
- ExpenseProvider: 지출 상태 관리
|
||||
- BudgetProvider: 예산 상태 관리
|
||||
- ThemeProvider: 테마 상태 관리
|
||||
- ConnectivityProvider: 네트워크 연결 상태 관리
|
||||
|
||||
7. **오프라인 동기화 기능 구현**
|
||||
- 오프라인 작업 큐 관리 시스템
|
||||
- 동기화 상태 위젯 (SyncStatusWidget)
|
||||
- 동기화 대시보드 위젯 (SyncDashboardWidget)
|
||||
- 동기화 상태 화면 (SyncStatusScreen)
|
||||
- 네트워크 상태에 따른 자동/수동 동기화 정책
|
||||
- 작업 재시도 및 오류 처리 메커니즘
|
||||
- 동기화 작업 상태 추적 (대기, 진행 중, 완료, 실패)
|
||||
|
||||
8. **통계 및 분석 기능 구현**
|
||||
- 지출 추이 차트 구현
|
||||
- 카테고리별 지출 분석 시각화
|
||||
- 기간별 지출 비교 기능
|
||||
- 지출 패턴 분석 알고리즘
|
||||
- 예산 대비 지출 분석 대시보드
|
||||
- 절약 제안 기능
|
||||
|
||||
### 진행 중인 작업
|
||||
1. 오프라인 동기화 기능 테스트 및 안정화
|
||||
2. 테스트 환경 구성 (웹, 에뮬레이터)
|
||||
3. 대용량 데이터 동기화 성능 최적화
|
||||
|
||||
### 다음 작업 계획
|
||||
1. 동기화 작업 우선순위 설정 기능 구현
|
||||
2. 충돌 해결 메커니즘 구현
|
||||
3. 동기화 통계 및 로그 기능 강화
|
||||
4. 성능 최적화 및 버그 수정
|
||||
5. 사용자 테스트 및 피드백 수집
|
||||
6. 앱 출시 준비 (앱 스토어 등록 등)
|
||||
|
||||
### 기술적 이슈 및 해결 방안
|
||||
1. **폰트 호환성 문제**
|
||||
- 문제: Pretendard 폰트 사용 시 오류 발생
|
||||
- 해결: Google Fonts의 Noto Sans로 대체하여 해결
|
||||
|
||||
2. **라우팅 충돌 문제**
|
||||
- 문제: 라우트 이름과 변수명 충돌
|
||||
- 해결: 라우트 이름 변수를 더 명확한 이름으로 변경 (settings → settingsRoute)
|
||||
|
||||
3. **API 연동 문제**
|
||||
- 문제: 싱글톤 패턴 구현 시 의존성 주입 이슈
|
||||
- 해결: 생성자에서 선택적 매개변수를 통한 의존성 주입 방식 개선
|
||||
|
||||
4. **오프라인 동기화 이슈**
|
||||
- 문제: 네트워크 연결 복구 시 동기화 작업 중복 실행
|
||||
- 해결: 작업 ID 기반 중복 방지 메커니즘 구현
|
||||
|
||||
5. **로컬 데이터베이스 성능 이슈**
|
||||
- 문제: 대용량 데이터 처리 시 지연 발생
|
||||
- 해결: 인덱싱 및 페이지네이션 적용, 비동기 처리 최적화
|
||||
296
docs/03_개발_단계/4단계/4단계_계획.md
Normal file
@@ -0,0 +1,296 @@
|
||||
# 적자 탈출 가계부 - 4단계 계획
|
||||
|
||||
## 1. 4단계 목표
|
||||
|
||||
4단계의 주요 목표는 적자 탈출 가계부 앱의 품질을 향상시키고, 사용자 경험을 개선하며, 앱 스토어 출시를 준비하는 것입니다. 이 단계에서는 테스트, 최적화, 안정화 작업을 중점적으로 진행합니다.
|
||||
|
||||
### 핵심 목표
|
||||
1. [x] 앱 성능 최적화 및 안정화 (2025년 2월 28일 완료)
|
||||
2. [ ] 사용자 테스트 및 피드백 수집/반영
|
||||
3. [x] 오프라인 동기화 기능 안정화 (2025년 2월 25일 완료)
|
||||
4. [ ] 앱 출시 준비 및 배포
|
||||
5. [ ] 사용자 가이드 및 문서 작성
|
||||
|
||||
## 2. 작업 목록 및 일정
|
||||
|
||||
### 1일차: 성능 최적화 및 코드 리팩토링 (2025년 2월 24일 완료)
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 성능 분석 및 병목 지점 식별
|
||||
- [x] 메모리 사용량 분석
|
||||
- [x] 렌더링 성능 분석
|
||||
- [x] 네트워크 요청 최적화 분석
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 코드 리팩토링 및 최적화
|
||||
- [x] 불필요한 빌드 최소화
|
||||
- [x] 메모리 누수 해결
|
||||
- [x] 이미지 및 리소스 최적화
|
||||
|
||||
### 2일차: 오프라인 동기화 기능 안정화 (2025년 2월 25일 완료)
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 동기화 성능 최적화
|
||||
- [x] 대용량 데이터 동기화 테스트
|
||||
- [x] 동기화 작업 우선순위 설정 기능 구현
|
||||
- [x] 충돌 해결 메커니즘 구현
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 동기화 오류 처리 강화
|
||||
- [x] 네트워크 불안정 상황 테스트
|
||||
- [x] 동기화 실패 복구 메커니즘 개선
|
||||
- [x] 동기화 로그 및 통계 기능 구현
|
||||
|
||||
### 3일차: 개발자 모드 및 성능 모니터링 도구 구현 (2025년 2월 26-27일 완료)
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 개발자 모드 기능 구현
|
||||
- [x] 개발자 모드 활성화/비활성화 기능
|
||||
- [x] 7번 클릭으로 개발자 모드 전환 기능
|
||||
- [x] SharedPreferences를 사용한 상태 지속
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 성능 모니터링 도구 구현
|
||||
- [x] 프레임 렌더링 타이밍 추적
|
||||
- [x] 빌드 시간 및 래스터 시간 기록
|
||||
- [x] 느린 프레임 및 프레임 드롭 감지
|
||||
- [x] 성능 측정 데이터 저장 및 분석
|
||||
|
||||
### 4일차: 메모리 관리 및 성능 프로필 화면 구현 (2025년 2월 28일 완료)
|
||||
|
||||
#### 오전
|
||||
- [x] [AI] 메모리 관리 기능 강화
|
||||
- [x] 메모리 사용량 기록
|
||||
- [x] 리소스(구독, 타이머, 애니메이션 컨트롤러) 추적
|
||||
- [x] 메모리 정리 및 가비지 컬렉션 기능
|
||||
|
||||
#### 오후
|
||||
- [x] [AI] 성능 프로필 화면 구현
|
||||
- [x] 앱 및 기기 정보 표시
|
||||
- [x] 빌드 시간 차트
|
||||
- [x] 메모리 사용량 차트
|
||||
- [x] 메모리 정리 및 보고서 생성 버튼
|
||||
- [x] [AI] 오프라인 모드 및 테스트 모드 구현
|
||||
- [x] 인증 서비스 테스트 모드 추가
|
||||
- [x] 오프라인 상태에서 로그인/회원가입 기능 구현
|
||||
- [x] 동기화 큐에 인증 작업 추가 기능 구현
|
||||
- [x] 로컬 데이터베이스에 사용자 정보 저장 기능 추가
|
||||
|
||||
### 5일차: 사용자 테스트 준비 및 진행 (2025년 3월 1일 예정)
|
||||
|
||||
#### 오전
|
||||
- [ ] [AI] 테스트 시나리오 및 설문지 작성
|
||||
- [ ] 핵심 기능 테스트 시나리오
|
||||
- [ ] 사용성 테스트 항목
|
||||
- [ ] 피드백 수집 설문지
|
||||
|
||||
#### 오후
|
||||
- [ ] [사용자] 내부 테스트 진행
|
||||
- [ ] 테스트 참가자 모집
|
||||
- [ ] 테스트 세션 진행
|
||||
- [ ] 피드백 수집
|
||||
|
||||
### 6일차: 피드백 분석 및 개선 (2025년 3월 2일 예정)
|
||||
|
||||
#### 오전
|
||||
- [ ] [AI] 수집된 피드백 분석
|
||||
- [ ] 주요 이슈 및 개선점 식별
|
||||
- [ ] 우선순위 설정
|
||||
- [ ] 개선 계획 수립
|
||||
|
||||
#### 오후
|
||||
- [ ] [AI] 핵심 개선사항 구현
|
||||
- [ ] UI/UX 개선
|
||||
- [ ] 기능 개선
|
||||
- [ ] 버그 수정
|
||||
|
||||
### 7일차: 보안 및 데이터 무결성 강화 (2025년 3월 3일 예정)
|
||||
|
||||
#### 오전
|
||||
- [ ] [AI] 보안 감사 및 개선
|
||||
- [ ] 데이터 암호화 검토
|
||||
- [ ] 인증 및 권한 관리 강화
|
||||
- [ ] 개인정보 보호 검토
|
||||
|
||||
#### 오후
|
||||
- [ ] [AI] 데이터 무결성 강화
|
||||
- [ ] 데이터 백업 및 복구 기능
|
||||
- [ ] 데이터 검증 로직 강화
|
||||
- [ ] 오류 발생 시 데이터 보호 메커니즘
|
||||
|
||||
### 8일차: 앱 출시 준비 (2025년 3월 4일 예정)
|
||||
|
||||
#### 오전
|
||||
- [ ] [AI] 앱 스토어 최적화
|
||||
- [ ] 앱 아이콘 및 스크린샷 준비
|
||||
- [ ] 앱 설명 및 키워드 최적화
|
||||
- [ ] 개인정보 처리방침 작성
|
||||
|
||||
#### 오후
|
||||
- [ ] [AI] 출시 버전 빌드 및 테스트
|
||||
- [ ] 릴리스 빌드 생성
|
||||
- [ ] 최종 테스트 진행
|
||||
- [ ] 배포 준비
|
||||
|
||||
### 9일차: 사용자 가이드 및 문서 작성 (2025년 3월 5일 예정)
|
||||
|
||||
#### 오전
|
||||
- [ ] [AI] 사용자 가이드 작성
|
||||
- [ ] 주요 기능 사용법
|
||||
- [ ] 자주 묻는 질문 (FAQ)
|
||||
- [ ] 문제 해결 가이드
|
||||
|
||||
#### 오후
|
||||
- [ ] [AI] 개발자 문서 작성
|
||||
- [ ] 아키텍처 문서
|
||||
- [ ] API 문서
|
||||
- [ ] 유지보수 가이드
|
||||
|
||||
## 3. 기술 스택 및 도구
|
||||
|
||||
### 테스트 도구
|
||||
- Flutter 테스트 프레임워크
|
||||
- Firebase Test Lab
|
||||
- Flutter Performance 모니터링 도구
|
||||
- 자체 개발한 성능 프로파일링 도구
|
||||
|
||||
### 성능 최적화 도구
|
||||
- Flutter DevTools
|
||||
- Lighthouse (웹 버전)
|
||||
- Firebase Performance Monitoring
|
||||
- 자체 개발한 메모리 관리 및 성능 모니터링 도구
|
||||
|
||||
### 배포 도구
|
||||
- Fastlane
|
||||
- Firebase App Distribution
|
||||
- Google Play Console
|
||||
- Apple App Store Connect
|
||||
|
||||
## 4. 품질 지표 및 목표
|
||||
|
||||
### 성능 목표
|
||||
- 앱 시작 시간: 2초 이내
|
||||
- 화면 전환 시간: 300ms 이내
|
||||
- 메모리 사용량: 최대 100MB
|
||||
- 배터리 소모: 1시간 사용 시 5% 이내
|
||||
- 프레임 드롭률: 1% 이하
|
||||
|
||||
### 안정성 목표
|
||||
- 크래시 비율: 0.1% 이하
|
||||
- ANR (Application Not Responding): 0.05% 이하
|
||||
- 오프라인 동기화 성공률: 99% 이상
|
||||
- 메모리 누수 발생률: 0%
|
||||
|
||||
### 사용자 경험 목표
|
||||
- 앱 스토어 평점: 4.5 이상
|
||||
- 사용자 이탈률: 20% 이하
|
||||
- 일일 활성 사용자 (DAU): 초기 목표 1,000명
|
||||
|
||||
## 5. 출시 전략
|
||||
|
||||
### 단계적 출시
|
||||
1. 내부 테스트 (알파)
|
||||
- 개발팀 및 내부 사용자 대상
|
||||
- 주요 버그 및 성능 이슈 식별
|
||||
- 개발자 모드를 통한 성능 데이터 수집
|
||||
|
||||
2. 제한된 공개 테스트 (베타)
|
||||
- 선별된 외부 사용자 대상
|
||||
- 사용자 피드백 수집 및 개선
|
||||
- 성능 모니터링 데이터 분석
|
||||
|
||||
3. 정식 출시
|
||||
- 구글 플레이 스토어 및 애플 앱 스토어 출시
|
||||
- 마케팅 활동 시작
|
||||
|
||||
### 마케팅 전략
|
||||
- 소셜 미디어 홍보
|
||||
- 금융/가계부 관련 커뮤니티 홍보
|
||||
- 보도자료 배포
|
||||
- 인플루언서 협업
|
||||
|
||||
## 6. 위험 요소 및 대응 계획
|
||||
|
||||
### 잠재적 위험
|
||||
1. **성능 이슈**
|
||||
- 위험: 대용량 데이터 처리 시 성능 저하
|
||||
- 대응: 페이지네이션 및 지연 로딩 구현, 데이터 캐싱 최적화, 개발자 모드를 통한 지속적인 성능 모니터링
|
||||
|
||||
2. **동기화 충돌**
|
||||
- 위험: 오프라인 모드에서 동일 데이터 수정 시 충돌
|
||||
- 대응: 충돌 해결 알고리즘 구현, 사용자 선택 옵션 제공, 동기화 로그 및 통계 기능을 통한 문제 추적
|
||||
|
||||
3. **Provider 관련 오류**
|
||||
- 위험: Provider 패턴 사용 시 의존성 주입 문제로 앱 실행 오류 발생
|
||||
- 대응: 모든 Provider를 MultiProvider에 등록하고, 의존성 주입을 통해 서비스 공유, 일관된 네이밍 컨벤션 적용
|
||||
|
||||
4. **API 요청 실패**
|
||||
- 위험: 서버 연결 불안정 또는 API 오류로 인한 데이터 로딩 실패
|
||||
- 대응: 모든 API 호출에 대한 로컬 데이터 대체 로직 구현, 오프라인 모드 강화, 사용자 친화적 오류 메시지 제공
|
||||
|
||||
5. **사용자 수용성**
|
||||
- 위험: 복잡한 기능으로 인한 사용자 혼란
|
||||
- 대응: 직관적인 UI/UX 개선, 튜토리얼 및 도움말 강화
|
||||
|
||||
6. **보안 취약점**
|
||||
- 위험: 개인 금융 데이터 유출 가능성
|
||||
- 대응: 데이터 암호화, 보안 감사, 취약점 테스트
|
||||
|
||||
## 7. 해결된 주요 이슈
|
||||
|
||||
### Provider 관련 오류
|
||||
- **문제**: ConnectivityProvider를 찾을 수 없는 `ProviderNotFoundException` 오류 발생
|
||||
- **원인**:
|
||||
1. `main.dart`에 `ConnectivityProvider`가 MultiProvider 목록에 포함되지 않음
|
||||
2. `ConnectivityProvider` 생성자가 새로운 `ConnectivityService` 인스턴스를 생성하여 의존성 공유 불가
|
||||
- **해결**:
|
||||
1. `main.dart`의 MultiProvider 목록에 `ConnectivityProvider` 추가
|
||||
2. `ConnectivityProvider` 생성자 수정하여 외부에서 `ConnectivityService` 주입 가능하도록 변경
|
||||
3. `isConnected` getter 추가하여 `isOnline`과 동일하게 동작하도록 함
|
||||
|
||||
### 예산 데이터 로딩 오류
|
||||
- **문제**: 예산 화면에서 "예산 사용 현황을 불러오는 중 오류가 발생했습니다: Exception: 예산 사용 현황 조회 실패: Exception: 서버 오류: 404" 메시지 표시
|
||||
- **원인**: 서버에서 예산 데이터를 가져오는 API 요청이 404 오류를 반환하고, 오류 발생 시 로컬 데이터를 사용하는 대체 로직이 없었음
|
||||
- **해결**: `BudgetService`의 `getBudgetUsage` 메서드를 수정하여 API 호출이 실패할 경우 로컬 데이터를 사용하도록 변경
|
||||
|
||||
## 8. 유지보수 계획
|
||||
|
||||
### 정기 업데이트
|
||||
- 월 1회 기능 업데이트
|
||||
- 2주 1회 버그 수정 및 안정성 개선
|
||||
- 사용자 피드백 기반 개선 사항 우선순위 지정
|
||||
|
||||
### 모니터링 시스템
|
||||
- Firebase Crashlytics를 통한 오류 모니터링
|
||||
- Firebase Analytics를 통한 사용자 행동 분석
|
||||
- 자체 개발한 성능 모니터링 도구를 통한 성능 데이터 수집 및 분석
|
||||
- 사용자 피드백 수집 및 분석 시스템
|
||||
|
||||
## 9. 개발자 모드 및 성능 모니터링 도구 활용 계획
|
||||
|
||||
### 개발자 모드 활용
|
||||
- 내부 테스트 중 성능 데이터 수집
|
||||
- 사용자 환경에서의 실제 성능 측정
|
||||
- 문제 발생 시 상세 진단 정보 수집
|
||||
|
||||
### 성능 모니터링 도구 활용
|
||||
- 프레임 렌더링 성능 지속적 모니터링
|
||||
- 메모리 사용량 추적 및 최적화
|
||||
- 성능 병목 현상 조기 발견 및 해결
|
||||
- 사용자 기기별 성능 차이 분석
|
||||
|
||||
### 메모리 관리 도구 활용
|
||||
- 메모리 누수 조기 발견 및 해결
|
||||
- 리소스 사용 최적화
|
||||
- 저사양 기기에서의 성능 개선
|
||||
|
||||
## 10. 결론 및 기대 효과
|
||||
|
||||
### 기대 효과
|
||||
- 앱의 안정성과 성능이 향상되어 사용자滿足도가 증가할 것으로 기대
|
||||
- 사용자 피드백을 반영한 지속적인 개선으로 앱의 품질이 유지될 것으로 기대
|
||||
- 마케팅 활동을 통해 사용자 수와 앱 스토어 평점이 개선될 것으로 기대
|
||||
|
||||
## 11. 참고자료
|
||||
|
||||
- [Git 이슈 트래킹 시스템 설정](1.%20Project/2.%20ZELLYY/젤리의%20적자%20탈출/04_참고자료/Git_이슈_트래킹_시스템.md)
|
||||
185
docs/04_참고자료/01_시장_조사_보고서.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# 가계부 앱 시장 조사 보고서
|
||||
|
||||
## 1. 시장 개요
|
||||
|
||||
### 글로벌 시장 현황
|
||||
개인 재정 관리(Personal Finance Management, PFM) 앱 시장은 전 세계적으로 꾸준한 성장세를 보이고 있습니다. 2023년 기준 글로벌 PFM 앱 시장 규모는 약 1,120억 달러로 평가되며, 2023-2028년 동안 연평균 성장률(CAGR) 16.2%로 성장하여 2028년에는 2,380억 달러에 이를 것으로 전망됩니다.
|
||||
|
||||
### 국내 시장 현황
|
||||
국내 PFM 앱 시장은 2023년 기준 약 8,500억 원 규모로 추정되며, 향후 5년간 연평균 14.5%의 성장률을 보일 것으로 예상됩니다. 특히 MZ세대를 중심으로 한 디지털 네이티브 사용자들의 재정 관리 니즈가 증가하면서 시장이 확대되고 있습니다.
|
||||
|
||||
### 주요 성장 동인
|
||||
1. **금융 불안정성 증가**: 경기 침체, 물가 상승, 취업난 등으로 인한 재정적 불안감 증가
|
||||
2. **디지털 금융 서비스 확산**: 오픈뱅킹, 마이데이터 등 금융 데이터 접근성 향상
|
||||
3. **금융 교육 수요 증가**: 개인 재정 관리에 대한 관심과 교육 수요 증가
|
||||
4. **모바일 기기 보급 확대**: 스마트폰 사용자 증가 및 모바일 앱 사용 일상화
|
||||
5. **AI 기술 발전**: 개인화된 재정 분석 및 조언 서비스 가능성 확대
|
||||
|
||||
## 2. 소비자 행동 분석
|
||||
|
||||
### 주요 사용자 층
|
||||
- **연령대**: 20-40대가 주 사용자층 (20대 35%, 30대 42%, 40대 18%, 기타 5%)
|
||||
- **성별**: 여성 사용자 비율이 다소 높음 (여성 55%, 남성 45%)
|
||||
- **직업**: 사무직(38%), 전문직(22%), 자영업(15%), 학생(12%), 기타(13%)
|
||||
- **소득 수준**: 중간~중상위 소득층이 주 사용자층 (월 소득 300만원 이상)
|
||||
|
||||
### 사용 목적
|
||||
1. **지출 추적**: 일상 지출 기록 및 관리 (87%)
|
||||
2. **예산 관리**: 카테고리별 예산 설정 및 관리 (76%)
|
||||
3. **저축 목표**: 특정 목표를 위한 저축 계획 (65%)
|
||||
4. **부채 관리**: 대출, 카드 부채 등 관리 (48%)
|
||||
5. **재정 분석**: 소비 패턴 분석 및 개선점 파악 (42%)
|
||||
|
||||
### 사용 행태
|
||||
- **사용 빈도**: 주 3-4회 이상 앱 접속 (활성 사용자 기준)
|
||||
- **사용 시간**: 평균 세션 시간 5-7분
|
||||
- **주요 사용 시점**: 저녁 시간(19-23시), 월초/월말, 급여일 전후
|
||||
- **이탈 원인**: 복잡한 UI(32%), 수동 입력 부담(28%), 실질적 도움 부족(24%), 보안 우려(16%)
|
||||
|
||||
## 3. 경쟁 환경 분석
|
||||
|
||||
### 국내 주요 경쟁사
|
||||
|
||||
#### 1. 뱅크샐러드
|
||||
- **강점**: 계좌 연동, 자산 관리, 신용 점수 관리, 금융 상품 추천
|
||||
- **약점**: 실질적 절약 가이드 부족, 복잡한 UI
|
||||
- **사용자 규모**: 약 800만 명
|
||||
- **수익 모델**: 금융 상품 중개 수수료, 프리미엄 구독
|
||||
|
||||
#### 2. 토스
|
||||
- **강점**: 간편한 UI/UX, 송금 기능, 계좌 연동, 브랜드 인지도
|
||||
- **약점**: 가계부 기능이 주력이 아님, 지출 분석 기능 제한적
|
||||
- **사용자 규모**: 약 2,000만 명
|
||||
- **수익 모델**: 금융 상품 중개, 결제 수수료, 프리미엄 구독
|
||||
|
||||
#### 3. 핀크
|
||||
- **강점**: 자동 분류, 예산 관리, 저축 챌린지
|
||||
- **약점**: 마케팅 부족, 사용자 경험 개선 필요
|
||||
- **사용자 규모**: 약 300만 명
|
||||
- **수익 모델**: 금융 상품 중개, 제휴 마케팅
|
||||
|
||||
#### 4. 머니 매니저
|
||||
- **강점**: 상세한 분석 기능, 다양한 보고서, 커스터마이징
|
||||
- **약점**: 복잡한 설정, 초보자 진입장벽, 계좌 연동 제한
|
||||
- **사용자 규모**: 약 150만 명
|
||||
- **수익 모델**: 앱 내 구매, 프리미엄 구독
|
||||
|
||||
### 해외 주요 경쟁사
|
||||
|
||||
#### 1. Mint (미국)
|
||||
- **강점**: 종합적인 재정 관리, 계좌 연동, 예산 설정, 신용 점수
|
||||
- **약점**: 해외 계좌 지원 제한, 광고 과다
|
||||
- **사용자 규모**: 약 2,500만 명
|
||||
- **수익 모델**: 광고, 금융 상품 추천 수수료
|
||||
|
||||
#### 2. YNAB (You Need A Budget, 미국)
|
||||
- **강점**: 예산 중심 접근법, 교육 콘텐츠, 커뮤니티
|
||||
- **약점**: 높은 구독료, 계좌 연동 제한적
|
||||
- **사용자 규모**: 약 500만 명
|
||||
- **수익 모델**: 월/연간 구독제
|
||||
|
||||
#### 3. Money Lover (베트남)
|
||||
- **강점**: 직관적 UI, 다국어 지원, 여행 경비 관리
|
||||
- **약점**: 고급 분석 기능 부족, 계좌 연동 제한
|
||||
- **사용자 규모**: 약 1,000만 명
|
||||
- **수익 모델**: 프리미엄 구독, 앱 내 구매
|
||||
|
||||
## 4. 시장 기회 및 위협 요인
|
||||
|
||||
### 기회 요인
|
||||
1. **적자 가구 증가**: 코로나19 이후 가계 부채 증가 및 적자 가구 비율 상승
|
||||
2. **금융 데이터 접근성 향상**: 마이데이터 사업 본격화로 금융 정보 통합 용이
|
||||
3. **AI 기술 활용**: 개인화된 재정 조언 및 예측 서비스 제공 가능
|
||||
4. **금융 교육 수요**: 재정 관리 교육에 대한 관심 증가
|
||||
5. **틈새 시장**: '적자 탈출'이라는 명확한 목표를 가진 특화 서비스 부재
|
||||
|
||||
### 위협 요인
|
||||
1. **시장 포화**: 다수의 유사 서비스 존재로 인한 경쟁 심화
|
||||
2. **대형 플랫폼의 진입**: 네이버, 카카오 등 대형 IT 기업의 금융 서비스 확장
|
||||
3. **사용자 이탈**: 초기 열정 이후 지속적 사용 유도의 어려움
|
||||
4. **수익화 어려움**: 무료 서비스 기대로 인한 유료화 전환 어려움
|
||||
5. **개인정보 규제**: 금융 데이터 활용에 대한 규제 강화 가능성
|
||||
|
||||
## 5. 소비자 니즈 분석
|
||||
|
||||
### 주요 불만 사항
|
||||
1. **수동 입력 부담**: 모든 지출을 수동으로 입력해야 하는 번거로움 (68%)
|
||||
2. **실질적 도움 부족**: 단순 기록을 넘어선 실질적 재정 개선 가이드 부족 (62%)
|
||||
3. **지속 사용 동기 부족**: 초기 열정 이후 사용 중단 (57%)
|
||||
4. **개인화 부족**: 개인 상황에 맞는 맞춤형 조언 부족 (53%)
|
||||
5. **복잡한 UI/UX**: 직관적이지 않은 사용자 경험 (48%)
|
||||
|
||||
### 미충족 니즈
|
||||
1. **자동화 니즈**: 자동 거래 분류 및 분석 (76%)
|
||||
2. **맞춤형 절약 전략**: 개인 소비 패턴 기반 실질적 절약 방법 (72%)
|
||||
3. **행동 변화 유도**: 소비 습관 개선을 위한 심리적 접근 (65%)
|
||||
4. **목표 중심 접근**: '적자 탈출'과 같은 구체적 목표 달성 지원 (63%)
|
||||
5. **커뮤니티 지원**: 비슷한 재정 목표를 가진 사용자들과의 정보 공유 (58%)
|
||||
|
||||
## 6. 시장 트렌드
|
||||
|
||||
### 현재 트렌드
|
||||
1. **AI 기반 분석**: 인공지능을 활용한 소비 패턴 분석 및 예측
|
||||
2. **자동화**: 영수증 스캔, 자동 분류, 계좌 연동 등 자동화 기능 강화
|
||||
3. **구독 경제**: 프리미엄 기능을 구독 모델로 제공
|
||||
4. **금융 교육 통합**: 재정 관리 교육 콘텐츠 제공
|
||||
5. **게이미피케이션**: 재정 목표 달성을 게임 요소로 접근
|
||||
|
||||
### 향후 전망
|
||||
1. **초개인화**: 사용자별 완전 맞춤형 재정 관리 서비스
|
||||
2. **예측적 분석**: 미래 재정 상태 예측 및 선제적 조언
|
||||
3. **음성 인터페이스**: 음성 명령을 통한 가계부 기록 및 조회
|
||||
4. **블록체인 활용**: 분산 원장 기술을 활용한 안전한 데이터 관리
|
||||
5. **통합 금융 플랫폼**: 가계부, 투자, 보험, 세금 등 종합 재정 관리
|
||||
|
||||
## 7. 시장 진입 전략 제안
|
||||
|
||||
### 차별화 전략
|
||||
1. **문제 중심 접근**: '적자 탈출'이라는 명확한 목표 제시
|
||||
2. **행동 경제학 활용**: 소비 습관 개선을 위한 심리적 접근법 적용
|
||||
3. **단계적 성공 경험**: 작은 성공 경험을 통한 동기 부여
|
||||
4. **커뮤니티 기반**: 비슷한 목표를 가진 사용자들의 경험 공유
|
||||
5. **실용적 조언**: 이론적 재정 조언이 아닌 실천 가능한 절약 팁 제공
|
||||
|
||||
### 타겟 시장 세분화
|
||||
1. **주 타겟**: 20-30대 직장인 및 대학생 (적자 상태 탈출 희망자)
|
||||
2. **부 타겟**: 30-40대 가정 (가계 재정 개선 희망 가구)
|
||||
3. **틈새 타겟**: 프리랜서 및 자영업자 (불규칙한 수입 관리 필요자)
|
||||
|
||||
### 마케팅 전략
|
||||
1. **콘텐츠 마케팅**: 재정 관리 팁, 성공 사례 등 유용한 콘텐츠 제공
|
||||
2. **인플루언서 협업**: 재테크 인플루언서와의 협업을 통한 신뢰도 구축
|
||||
3. **커뮤니티 마케팅**: 재테크 커뮤니티, 대학생 커뮤니티 등 타겟 접근
|
||||
4. **성공 사례 홍보**: 실제 사용자의 적자 탈출 성공 스토리 공유
|
||||
5. **무료 체험**: 핵심 기능 무료 제공으로 진입장벽 낮추기
|
||||
|
||||
### 수익화 전략
|
||||
1. **프리미엄 구독**: 고급 분석, AI 조언, 다중 기기 동기화 등 프리미엄 기능
|
||||
2. **단계별 요금제**: 사용자 니즈에 따른 다양한 구독 옵션
|
||||
3. **금융 상품 연계**: 저축, 투자 상품 추천 및 중개 수수료
|
||||
4. **기업 파트너십**: 금융 기관, 핀테크 기업과의 제휴 마케팅
|
||||
|
||||
## 8. 결론 및 제언
|
||||
|
||||
### 핵심 발견점
|
||||
1. 가계부 앱 시장은 성장 중이나 차별화된 가치 제안이 필요한 포화 상태
|
||||
2. '적자 탈출'이라는 구체적 문제 해결에 초점을 맞춘 서비스는 틈새 시장 존재
|
||||
3. 사용자들은 단순 기록을 넘어 실질적인 재정 개선 가이드를 원함
|
||||
4. 지속적 사용을 유도하는 동기부여 요소가 성공의 핵심
|
||||
|
||||
### 제언
|
||||
1. **명확한 가치 제안**: '적자 탈출'이라는 구체적 문제 해결에 집중
|
||||
2. **사용자 경험 최우선**: 직관적이고 간편한 UI/UX 설계로 진입장벽 낮추기
|
||||
3. **자동화 강화**: 수동 입력 부담을 최소화하는 자동화 기능 우선 개발
|
||||
4. **행동 변화 유도**: 게이미피케이션, 심리적 접근법을 통한 소비 습관 개선
|
||||
5. **커뮤니티 구축**: 사용자 간 경험 공유 및 동기부여를 위한 커뮤니티 기능 강화
|
||||
6. **단계적 접근**: MVP로 시작하여 사용자 피드백 기반 점진적 기능 확장
|
||||
|
||||
### 성공 지표 제안
|
||||
1. **사용자 성장**: 출시 6개월 내 50,000명 이상의 활성 사용자 확보
|
||||
2. **사용자 참여**: 주 3회 이상 앱 사용 비율 60% 이상
|
||||
3. **재정 개선**: 3개월 이상 사용자의 60%가 지출 감소 또는 저축 증가 보고
|
||||
4. **구독 전환**: 무료 사용자의 8% 이상 유료 구독 전환
|
||||
5. **사용자 유지**: 90일 사용자 유지율 35% 이상
|
||||
|
||||
본 시장 조사 보고서는 '적자 탈출 가계부' 앱의 개발 및 마케팅 전략 수립을 위한 기초 자료로 활용될 수 있습니다. 시장 환경과 소비자 니즈는 지속적으로 변화하므로, 정기적인 시장 모니터링과 사용자 피드백 수집을 통해 전략을 조정해 나가는 것이 중요합니다.
|
||||
202
docs/04_참고자료/Git_이슈_트래킹_시스템.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Git 이슈 트래킹 시스템 설정
|
||||
|
||||
## 개요
|
||||
|
||||
Zellyy Finance 모바일 앱 개발 과정에서 발생하는 다양한 이슈를 체계적으로 관리하기 위해 Gitea 기반의 이슈 트래킹 시스템을 설정했습니다. 이 문서는 이슈 트래킹 시스템의 설정 과정과 사용 방법을 설명합니다.
|
||||
|
||||
## 설정 과정
|
||||
|
||||
### 1. Gitea 저장소 연결
|
||||
|
||||
- 저장소 URL: https://gitea.ism.kr/ZELLYY/Zellyy_Finance.git
|
||||
- 저장소 상태: 정상 연결됨
|
||||
|
||||
### 2. API 토큰 생성
|
||||
|
||||
Gitea API를 사용하여 이슈를 관리하기 위해 API 토큰을 생성했습니다.
|
||||
|
||||
1. Gitea 웹사이트(https://gitea.ism.kr)에 로그인
|
||||
2. 사용자 설정 > 애플리케이션 > 액세스 토큰 생성
|
||||
3. 토큰 이름 입력 및 권한 설정:
|
||||
- repo: 저장소에 대한 전체 접근 권한
|
||||
- issue: 이슈 관리 권한
|
||||
- write:repository: 저장소 쓰기 권한
|
||||
4. 토큰 생성 및 안전한 장소에 저장
|
||||
|
||||
### 3. 이슈 등록
|
||||
|
||||
API를 통해 다음과 같은 이슈들을 등록했습니다:
|
||||
|
||||
1. ConnectivityProvider 클래스의 getter 이름 불일치
|
||||
2. SyncOperationType enum의 switch 문 불완전 처리
|
||||
3. UserModel 생성 시 타입 불일치
|
||||
4. 오프라인 모드 및 테스트 모드 안정화
|
||||
|
||||
## 이슈 목록
|
||||
|
||||
### 이슈 1: ConnectivityProvider 클래스의 getter 이름 불일치
|
||||
|
||||
#### 문제 설명
|
||||
앱 실행 시 `ConnectivityProvider` 클래스의 `isConnected` getter를 찾을 수 없다는 오류가 발생했습니다.
|
||||
|
||||
#### 오류 메시지
|
||||
```
|
||||
Error (Xcode): lib/screens/home_screen.dart:178:50: Error: The getter 'isConnected' isn't defined for the class 'ConnectivityProvider'.
|
||||
```
|
||||
|
||||
#### 원인 분석
|
||||
`ConnectivityProvider` 클래스에는 `isConnected` getter가 없고 대신 `isOnline` getter가 정의되어 있었습니다.
|
||||
|
||||
#### 해결 방법
|
||||
`home_screen.dart`와 `settings_screen.dart` 파일에서 `isConnected` 대신 `isOnline`을 사용하도록 수정했습니다.
|
||||
|
||||
#### 코드 변경
|
||||
```dart
|
||||
// 변경 전
|
||||
final bool isOffline = !connectivityProvider.isConnected;
|
||||
|
||||
// 변경 후
|
||||
final bool isOffline = !connectivityProvider.isOnline;
|
||||
```
|
||||
|
||||
### 이슈 2: SyncOperationType enum의 switch 문 불완전 처리
|
||||
|
||||
#### 문제 설명
|
||||
앱 빌드 시 `SyncOperationType` enum의 모든 케이스를 처리하지 않는다는 오류가 발생했습니다.
|
||||
|
||||
#### 오류 메시지
|
||||
```
|
||||
Error (Xcode): lib/screens/sync_status_screen.dart:294:23: Error: The type 'SyncOperationType' is not exhaustively matched by the switch cases since it doesn't match 'SyncOperationType.register'.
|
||||
```
|
||||
|
||||
#### 원인 분석
|
||||
`SyncOperationType` enum에 `register`와 `login` 타입이 추가되었지만, 여러 파일의 switch 문에서 이 케이스들을 처리하지 않고 있었습니다.
|
||||
|
||||
#### 해결 방법
|
||||
다음 파일들의 switch 문에 `register`와 `login` 케이스를 추가했습니다:
|
||||
- `sync_status_screen.dart`
|
||||
- `api_service.dart`
|
||||
- `sync_status_widget.dart`
|
||||
|
||||
#### 코드 변경
|
||||
```dart
|
||||
// 추가된 케이스
|
||||
case SyncOperationType.register:
|
||||
operationType = '회원가입';
|
||||
break;
|
||||
case SyncOperationType.login:
|
||||
operationType = '로그인';
|
||||
break;
|
||||
```
|
||||
|
||||
### 이슈 3: UserModel 생성 시 타입 불일치
|
||||
|
||||
#### 문제 설명
|
||||
앱 빌드 시 String 타입의 값을 DateTime 타입의 매개변수에 할당하려고 시도하는 오류가 발생했습니다.
|
||||
|
||||
#### 오류 메시지
|
||||
```
|
||||
Error (Xcode): lib/services/auth_service.dart:73:37: Error: The argument type 'String' can't be assigned to the parameter type 'DateTime'.
|
||||
```
|
||||
|
||||
#### 원인 분석
|
||||
`auth_service.dart` 파일에서 `UserModel`을 생성할 때 `createdAt`과 `updatedAt` 필드에 String 타입의 값(`DateTime.now().toIso8601String()`)을 전달하고 있었지만, `UserModel` 클래스에서는 이 필드들이 DateTime 타입으로 정의되어 있었습니다.
|
||||
|
||||
#### 해결 방법
|
||||
`auth_service.dart` 파일에서 `createdAt`과 `updatedAt` 필드를 String 대신 DateTime 객체로 전달하도록 수정했습니다.
|
||||
|
||||
#### 코드 변경
|
||||
```dart
|
||||
// 변경 전
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
updatedAt: DateTime.now().toIso8601String(),
|
||||
|
||||
// 변경 후
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
```
|
||||
|
||||
### 이슈 4: 오프라인 모드 및 테스트 모드 안정화
|
||||
|
||||
#### 기능 설명
|
||||
앱의 오프라인 모드와 테스트 모드 기능을 안정화하여 네트워크 연결 없이도 앱을 사용할 수 있도록 했습니다.
|
||||
|
||||
#### 구현 내용
|
||||
1. 인증 관련 개선:
|
||||
- 회원가입 및 로그인 메서드에 테스트 모드 추가
|
||||
- 오프라인 상태에서도 로그인/회원가입 가능하도록 구현
|
||||
- 서버 오류 발생 시 자동으로 테스트 모드로 전환되는 기능 추가
|
||||
|
||||
2. 로컬 데이터베이스 개선:
|
||||
- 사용자 정보 저장 및 조회 기능 추가
|
||||
- 이메일 기반 사용자 검색 기능 구현
|
||||
- Hive 초기화 과정에 users 박스 등록
|
||||
|
||||
3. 동기화 큐 서비스 개선:
|
||||
- 회원가입 및 로그인 작업을 동기화 큐에 추가하는 기능 구현
|
||||
- 온라인 상태가 되면 자동으로 동기화되는 메커니즘 구현
|
||||
|
||||
4. 모델 클래스 수정:
|
||||
- UserModel의 id 필드 타입을 int에서 String으로 변경하여 테스트 모드 지원
|
||||
- Hive 어댑터 추가 및 등록
|
||||
|
||||
#### 주요 수정 파일
|
||||
- `/mobile/lib/services/api_service.dart`
|
||||
- `/mobile/lib/services/auth_service.dart`
|
||||
- `/mobile/lib/services/local_database_service.dart`
|
||||
- `/mobile/lib/services/sync_queue_service.dart`
|
||||
- `/mobile/lib/models/user_model.dart`
|
||||
- `/mobile/lib/main.dart`
|
||||
|
||||
## API를 통한 이슈 관리 방법
|
||||
|
||||
### 이슈 조회
|
||||
|
||||
```bash
|
||||
curl -X GET "https://gitea.ism.kr/api/v1/repos/ZELLYY/Zellyy_Finance/issues" \
|
||||
-H "Authorization: token YOUR_ACCESS_TOKEN"
|
||||
```
|
||||
|
||||
### 이슈 생성
|
||||
|
||||
```bash
|
||||
curl -X POST "https://gitea.ism.kr/api/v1/repos/ZELLYY/Zellyy_Finance/issues" \
|
||||
-H "Authorization: token YOUR_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"title": "이슈 제목", "body": "이슈 내용"}'
|
||||
```
|
||||
|
||||
### 이슈 수정
|
||||
|
||||
```bash
|
||||
curl -X PATCH "https://gitea.ism.kr/api/v1/repos/ZELLYY/Zellyy_Finance/issues/{issue_id}" \
|
||||
-H "Authorization: token YOUR_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"title": "수정된 이슈 제목", "body": "수정된 이슈 내용", "state": "closed"}'
|
||||
```
|
||||
|
||||
### 이슈 댓글 추가
|
||||
|
||||
```bash
|
||||
curl -X POST "https://gitea.ism.kr/api/v1/repos/ZELLYY/Zellyy_Finance/issues/{issue_id}/comments" \
|
||||
-H "Authorization: token YOUR_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"body": "댓글 내용"}'
|
||||
```
|
||||
|
||||
## 웹 인터페이스를 통한 이슈 관리
|
||||
|
||||
Gitea 웹 인터페이스를 통해 이슈를 관리할 수도 있습니다:
|
||||
|
||||
1. 웹 브라우저에서 https://gitea.ism.kr/ZELLYY/Zellyy_Finance/issues 접속
|
||||
2. 이슈 목록 확인 및 관리
|
||||
3. 이슈에 라벨, 담당자, 마일스톤 설정
|
||||
4. 이슈 상태 변경 (열림/닫힘)
|
||||
5. 이슈에 댓글 추가
|
||||
|
||||
## 향후 계획
|
||||
|
||||
1. 이슈 라벨 체계 구축 (버그, 기능 요청, 개선 등)
|
||||
2. 마일스톤 설정을 통한 릴리스 계획 관리
|
||||
3. 자동화된 이슈 보고 시스템 구축
|
||||
4. 이슈와 커밋 연동을 통한 변경 사항 추적 개선
|
||||
141
docs/README.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# 적자 탈출 가계부 프로젝트 문서
|
||||
|
||||
이 디렉토리는 적자 탈출 가계부 프로젝트의 모든 문서를 체계적으로 정리한 곳입니다. 사용자들이 개인 재정을 효과적으로 관리하고 적자 상태에서 벗어날 수 있도록 도와주는 모바일 앱 개발 프로젝트입니다.
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
'적자 탈출 가계부'는 단순한 수입/지출 기록을 넘어, 사용자의 소비 패턴을 분석하고 맞춤형 절약 전략을 제안하여 재정 건전성을 개선하는 데 중점을 둔 모바일 앱입니다. AI 기술을 활용한 개인화된 재정 관리 경험을 제공하고, 궁극적으로는 사용자들의 재정적 웰빙을 향상시키는 것을 목표로 합니다.
|
||||
|
||||
## 폴더 구조
|
||||
|
||||
### 00_프로젝트_개요
|
||||
프로젝트의 기본 개요와 목표, 사용자 정의에 관한 문서가 포함되어 있습니다.
|
||||
- `01_프로젝트_소개.md` - 프로젝트 개요 및 주요 기능 설명
|
||||
- `02_핵심_문제_정의.md` - 해결하고자 하는 문제 정의 (예정)
|
||||
- `03_사용자_페르소나.md` - 타겟 사용자 프로필 (예정)
|
||||
- `04_사용자_스토리.md` - 사용자 관점의 요구사항 (예정)
|
||||
- `05_비즈니스_모델.md` - 수익 모델 및 사업화 전략 (예정)
|
||||
- `06_법률_규제_검토.md` - 금융 앱 관련 법규 및 규제 검토 (예정)
|
||||
|
||||
### 01_기획_및_설계
|
||||
프로젝트의 기획 및 UI/UX 설계에 관한 문서가 포함되어 있습니다.
|
||||
- `01_요구사항_분석.md` - 사용자 요구사항 및 기능적/비기능적 요구사항 분석
|
||||
- `02_MVP_기능_목록.md` - 최소 기능 제품(MVP)의 기능 목록 (예정)
|
||||
- `03_주요_사용_시나리오.md` - 주요 사용 사례 시나리오 (예정)
|
||||
- `04_UI_와이어프레임.md` - 핵심 화면 와이어프레임 (예정)
|
||||
- `05_사용자_여정_맵.md` - 사용자 경험 흐름도 (예정)
|
||||
- `06_정보_아키텍처.md` - 앱 구조 및 화면 흐름도 (예정)
|
||||
|
||||
### 02_기술_문서
|
||||
프로젝트의 기술적 구현에 관한 문서가 포함되어 있습니다.
|
||||
- `01_시스템_아키텍처.md` - 시스템 아키텍처 설계 문서
|
||||
- `02_데이터_모델_설계.md` - 데이터 모델 설계 문서 (예정)
|
||||
- `03_API_명세서.md` - API 엔드포인트 명세 (예정)
|
||||
- `04_보안_설계.md` - 보안 및 개인정보 보호 설계 (예정)
|
||||
- `05_성능_최적화_전략.md` - 앱 성능 최적화 전략 (예정)
|
||||
- `06_CI_CD_파이프라인.md` - 지속적 통합/배포 전략 (예정)
|
||||
- `07_AI_ML_구현_전략.md` - AI 기반 소비 패턴 분석 구현 방법 (예정)
|
||||
|
||||
### 03_개발_단계
|
||||
프로젝트 개발 단계별 문서가 포함되어 있습니다.
|
||||
- `01_개발_로드맵.md` - 전체 개발 로드맵 및 일정
|
||||
- `02_1단계_개발_계획.md` - 1단계(MVP) 개발 상세 계획 (예정)
|
||||
- `03_테스트_전략.md` - 테스트 방법론 및 계획 (예정)
|
||||
- `04_배포_전략.md` - 배포 및 운영 계획 (예정)
|
||||
- `05_품질_보증_계획.md` - QA 전략 및 테스트 케이스 (예정)
|
||||
- `06_유지보수_전략.md` - 출시 후 유지보수 및 업데이트 계획 (예정)
|
||||
|
||||
### 04_디자인_가이드
|
||||
UI/UX 디자인 관련 문서가 포함되어 있습니다.
|
||||
- `01_디자인_시스템.md` - 디자인 언어 및 컴포넌트 정의 (예정)
|
||||
- `02_색상_팔레트.md` - 앱 색상 가이드라인 (예정)
|
||||
- `03_타이포그래피.md` - 폰트 및 텍스트 스타일 가이드 (예정)
|
||||
- `04_아이콘_및_이미지.md` - 아이콘 디자인 및 사용 가이드 (예정)
|
||||
- `05_애니메이션_가이드.md` - UI 애니메이션 및 트랜지션 (예정)
|
||||
- `06_접근성_지침.md` - 접근성 디자인 원칙 (예정)
|
||||
|
||||
### 05_프로젝트_관리
|
||||
프로젝트 관리 및 협업 관련 문서가 포함되어 있습니다.
|
||||
- `01_팀_구성.md` - 팀 구성원 및 역할 정의 (예정)
|
||||
- `02_의사결정_프로세스.md` - 프로젝트 의사결정 체계 (예정)
|
||||
- `03_커뮤니케이션_계획.md` - 팀 내 소통 방식 및 도구 (예정)
|
||||
- `04_일정_및_마일스톤.md` - 주요 마일스톤 및 납기일 (예정)
|
||||
- `05_위험_관리.md` - 잠재적 위험 요소 및 대응 계획 (예정)
|
||||
|
||||
### 06_참고자료
|
||||
프로젝트 진행에 참고할 수 있는 자료들이 포함되어 있습니다.
|
||||
- `01_시장_조사_보고서.md` - 가계부 앱 시장 조사 보고서
|
||||
- `02_경쟁사_분석.md` - 주요 경쟁 앱 상세 분석 (예정)
|
||||
- `03_사용자_인터뷰.md` - 잠재 사용자 인터뷰 결과 (예정)
|
||||
- `04_참고_리소스.md` - 유용한 참고 자료 및 링크 (예정)
|
||||
- `05_금융_데이터_소스.md` - 재정 관리 데이터 참고 자료 (예정)
|
||||
- `06_관련_연구_자료.md` - 소비 행동 및 금융 심리학 연구 (예정)
|
||||
|
||||
### 07_마케팅_및_성장
|
||||
마케팅 및 사용자 확보 전략 관련 문서가 포함되어 있습니다.
|
||||
- `01_마케팅_전략.md` - 출시 및 사용자 확보 전략 (예정)
|
||||
- `02_ASO_전략.md` - 앱 스토어 최적화 전략 (예정)
|
||||
- `03_콘텐츠_전략.md` - 콘텐츠 마케팅 계획 (예정)
|
||||
- `04_사용자_유지_전략.md` - 사용자 참여 및 유지 방안 (예정)
|
||||
- `05_파트너십_계획.md` - 잠재적 파트너십 및 협업 기회 (예정)
|
||||
|
||||
## 주요 기능
|
||||
|
||||
1. **수입/지출 기록**: 간편한 UI로 일상 재정 활동 기록
|
||||
2. **카테고리 관리**: 사용자 정의 카테고리로 지출 분류
|
||||
3. **예산 설정**: 카테고리별 월간/주간 예산 설정 및 알림
|
||||
4. **지출 분석**: 차트와 그래프로 소비 패턴 시각화
|
||||
5. **AI 기반 분석**: 소비 패턴 분석 및 맞춤형 절약 제안
|
||||
6. **절약 챌린지**: 사용자 맞춤형 절약 목표 설정 및 달성 보상
|
||||
7. **재정 건강 점수**: 사용자의 재정 상태를 점수화하여 개선 동기 부여
|
||||
8. **구독 관리**: 정기 구독 서비스 추적 및 최적화 제안
|
||||
9. **재정 목표 설정**: 단기/중기/장기 저축 목표 설정 및 진행 상황 추적
|
||||
10. **알림 시스템**: 예산 초과, 주요 지출, 절약 기회에 대한 스마트 알림
|
||||
11. **가계부 보고서**: 정기적인 재정 상태 요약 보고서 제공
|
||||
12. **공유 기능**: 가족 또는 파트너와 특정 재정 정보 공유
|
||||
|
||||
## 기술 스택
|
||||
|
||||
- **프론트엔드**: React, Vite, Tailwind CSS, Capacitor
|
||||
- **백엔드**: Node.js, Express, Supabase(PostgreSQL)
|
||||
- **AI/ML**: TensorFlow, Python
|
||||
- **클라우드**: Supabase On-Premise
|
||||
- **데이터 시각화**: D3.js, Chart.js
|
||||
- **인증/보안**: JWT, OAuth 2.0, 데이터 암호화
|
||||
- **테스트**: Jest, Cypress
|
||||
- **CI/CD**: GitHub Actions
|
||||
- **분석**: Supabase Analytics
|
||||
|
||||
## 문서 작성 가이드라인
|
||||
- 모든 문서는 마크다운(.md) 형식으로 작성합니다.
|
||||
- 파일명은 내용을 명확히 나타내는 한글 또는 영문으로 작성합니다.
|
||||
- 이미지나 다이어그램은 가능한 마크다운 내에 포함시킵니다.
|
||||
- 문서 간 연결이 필요한 경우 상대 경로를 사용하여 링크합니다.
|
||||
- 코드 예시는 적절한 구문 강조와 함께 코드 블록으로 포함합니다.
|
||||
- 변경 사항은 문서 하단의 업데이트 이력에 기록합니다.
|
||||
- 중요 결정사항은 의사결정 배경과 함께 기록합니다.
|
||||
|
||||
## 개발 워크플로우
|
||||
1. **기능 기획**: 사용자 스토리 및 요구사항 정의
|
||||
2. **설계**: UI/UX 디자인 및 기술 아키텍처 설계
|
||||
3. **개발**: 기능 구현 및 단위 테스트
|
||||
4. **코드 리뷰**: 팀원 간 코드 품질 검토
|
||||
5. **테스트**: QA 및 사용성 테스트
|
||||
6. **배포**: 스테이징 및 프로덕션 환경 배포
|
||||
7. **모니터링**: 성능 및 사용자 피드백 모니터링
|
||||
8. **반복**: 피드백을 바탕으로 기능 개선
|
||||
|
||||
## 출시 계획
|
||||
- **알파 버전**: 내부 테스트 (2024년 4월 초)
|
||||
- **베타 버전**: 제한적 사용자 테스트 (2024년 4월 중순)
|
||||
- **MVP 출시**: 앱스토어 및 플레이스토어 공개 (2024년 4월 말)
|
||||
- **기능 업데이트**: 사용자 피드백 기반 주요 기능 추가 (2024년 5월 초)
|
||||
- **확장 계획**: 웹 버전 및 추가 기능 확장 (2024년 5월 중순부터)
|
||||
|
||||
## 업데이트 이력
|
||||
- 2024-03-15: 프로젝트 문서 초기 구성 완료
|
||||
- 2024-03-15: 프로젝트 소개, 요구사항 분석, 시스템 아키텍처, 개발 로드맵, 시장 조사 보고서 추가
|
||||
- 2024-04-01: 폴더 구조 개선 및 추가 섹션(디자인 가이드, 프로젝트 관리, 마케팅) 추가
|
||||
- 2024-04-05: 일정 조정 - 모든 개발 계획을 4월 말까지 완료하도록 수정
|
||||
- 2025-03-09: 개발 방법 변경 - Flutter에서 React, Tailwind CSS, Capacitor 기반 웹 앱으로 전환, Lovable UI 컴포넌트 스타일 적용
|
||||
- 2025-03-09: 데이터베이스 변경 - MongoDB에서 Supabase(PostgreSQL) On-Premise로 전환
|
||||
7
docs/build.md
Normal file
@@ -0,0 +1,7 @@
|
||||
```
|
||||
git pull && npx cap sync && cd android && ./gradlew assembleDebug && adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||||
```
|
||||
|
||||
```
|
||||
cd /Users/hansoo./Dev/zellyy-finance && git pull && npx cap sync && cd android && ./gradlew assembleDebug
|
||||
```
|
||||
56
docs/issue.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 예산 동기화 문제 해결 이슈
|
||||
|
||||
## 문제 상황
|
||||
사용자가 예산액을 수정한 후 서버와 동기화를 진행하면, 로컬에서 수정한 예산 데이터가 서버 데이터로 덮어씌워지는 문제가 발생했습니다. 이로 인해 사용자가 설정한 예산 정보가 유지되지 않고 초기화되는 현상이 발생했습니다.
|
||||
|
||||
## 해결 방안
|
||||
수정된 예산 데이터를 추적하는 시스템을 구현하고, 다운로드 및 업로드 로직을 개선하여 로컬에서 수정된 데이터의 무결성을 보장하는 방식으로 문제를 해결했습니다.
|
||||
|
||||
## 구현 내용
|
||||
|
||||
### 1. 수정된 예산 추적 시스템 구현
|
||||
- `modifiedBudgetsTracker.ts` 파일 생성
|
||||
- 로컬 스토리지에 수정된 예산 정보를 타임스탬프와 함께 저장
|
||||
- 일반 예산과 카테고리별 예산 모두 추적 가능
|
||||
- 주요 함수:
|
||||
- `markBudgetAsModified`: 일반 예산 수정 추적
|
||||
- `markSingleCategoryBudgetAsModified`: 단일 카테고리 예산 수정 추적
|
||||
- `getModifiedBudget`, `getModifiedCategoryBudgets`: 수정 정보 조회
|
||||
- `clearModifiedBudget`, `clearModifiedCategoryBudgets`: 수정 정보 초기화
|
||||
|
||||
### 2. 다운로드 로직 개선
|
||||
- `downloadBudget.ts` 파일 수정
|
||||
- 서버 데이터와 로컬 수정 데이터의 타임스탬프 비교
|
||||
- 최신 데이터를 기준으로 병합 로직 구현
|
||||
- 로컬에서 수정된 예산 정보가 있을 경우 우선 적용
|
||||
|
||||
### 3. 업로드 로직 개선
|
||||
- `uploadBudget.ts` 파일 수정
|
||||
- 타임스탬프 관리 개선 (created_at, updated_at 필드 추가)
|
||||
- 업로드 성공 후 수정 추적 정보 초기화 기능 추가
|
||||
|
||||
### 4. UI 컴포넌트 연동
|
||||
- `BudgetInputCard.tsx`: 예산 변경 시 수정 추적 시스템 연동
|
||||
- `CategoryBudgetInputs.tsx`: 카테고리별 예산 변경 시 수정 추적 시스템 연동
|
||||
|
||||
### 5. 코드 품질 개선
|
||||
- ESLint 오류 수정 (any 타입 구체화, let → const 변경)
|
||||
- 함수 인터페이스 개선 및 일관성 유지
|
||||
|
||||
## 작동 방식
|
||||
1. 사용자가 예산 또는 카테고리 예산을 수정하면 해당 정보가 로컬 스토리지에 타임스탬프와 함께 저장됩니다.
|
||||
2. 서버에서 데이터를 다운로드할 때, 로컬에서 수정된 정보와 서버 데이터의 타임스탬프를 비교하여 최신 데이터를 유지합니다.
|
||||
3. 서버에 데이터를 업로드한 후에는 수정 추적 정보를 초기화하여 동기화 상태를 정리합니다.
|
||||
|
||||
## 테스트 시나리오
|
||||
1. **예산 수정 후 동기화**: 사용자가 예산을 수정한 후 동기화를 진행해도 수정 내용이 유지되는지 확인
|
||||
2. **카테고리 예산 수정 후 동기화**: 카테고리별 예산을 수정한 후 동기화를 진행해도 수정 내용이 유지되는지 확인
|
||||
3. **오프라인 상태에서 수정 후 온라인 동기화**: 오프라인 상태에서 예산을 수정한 후 온라인 상태가 되었을 때 동기화가 올바르게 작동하는지 확인
|
||||
|
||||
## 향후 개선 사항
|
||||
1. 예산 수정 충돌 해결 메커니즘 강화
|
||||
2. 동기화 상태 UI 피드백 개선
|
||||
3. 오프라인 모드에서의 예산 관리 기능 강화
|
||||
|
||||
## 결론
|
||||
이번 수정을 통해 예산 데이터의 무결성과 사용자 경험이 크게 향상되었습니다. 사용자가 설정한 예산 정보가 동기화 과정에서도 안전하게 유지되어 앱의 신뢰성이 높아졌습니다.
|
||||
2
docs/keys.md
Normal file
@@ -0,0 +1,2 @@
|
||||
keystore ps / 업계~1#
|
||||
key ps / aplfarm99##
|
||||
41
docs/roadmap.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Zellyy Finance 개발 로드맵
|
||||
|
||||
## 1. 네트워크 및 동기화 개선
|
||||
- [ ] 오프라인 상태에서의 동기화 작업 큐 관리 강화
|
||||
- [ ] 자동 재시도 로직 최적화
|
||||
- [ ] 네트워크 상태 표시기 UI 개선
|
||||
|
||||
## 2. 트랜잭션 관리
|
||||
- [ ] 트랜잭션 삭제 시 앱 먹통 문제 해결
|
||||
- [ ] 대량 트랜잭션 처리 성능 개선
|
||||
- [ ] 트랜잭션 필터링 및 검색 기능 추가
|
||||
|
||||
## 3. 예산 관리
|
||||
- [ ] 카테고리별 예산 설정 기능 강화
|
||||
- [ ] 예산 초과 알림 기능 추가
|
||||
- [ ] 예산 추이 그래프 추가
|
||||
|
||||
## 4. 사용자 경험 개선
|
||||
- [ ] 다크 모드 지원
|
||||
- [ ] 다국어 지원
|
||||
- [ ] 접근성(Accessibility) 개선
|
||||
|
||||
## 5. 테스트 및 품질 관리
|
||||
- [ ] E2E 테스트 코드 추가
|
||||
- [ ] 성능 테스트 및 최적화
|
||||
- [ ] 코드 커버리지 90% 이상 달성
|
||||
|
||||
## 6. 배포 및 유지보수
|
||||
- [ ] CI/CD 파이프라인 구축
|
||||
- [ ] 에러 로깅 및 모니터링 시스템 도입
|
||||
- [ ] 자동 업데이트 기능 추가
|
||||
|
||||
## 7. 보안 강화
|
||||
- [ ] 데이터 암호화 적용
|
||||
- [ ] 2차 인증 기능 추가
|
||||
- [ ] 보안 취약점 정기 점검
|
||||
|
||||
## 8. 문서화
|
||||
- [ ] 개발자 가이드 작성
|
||||
- [ ] API 문서화
|
||||
- [ ] 사용자 매뉴얼 작성
|
||||
1
docs/아이디어.md
Normal file
@@ -0,0 +1 @@
|
||||
* 로그인 화면 (회원 가입)은 프로그램에서 입력된 내용이 10회 이상이 되면 나타나도록 한다.
|
||||
11
docs/적자 탈출 가계부.code-workspace
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "../../../../../Dev/Zellyy_Finance"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
57
docs/한국에서 제일 유명한 가계부 앱은.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "한국에서 제일 유명한 가계부 앱은"
|
||||
source: "https://www.perplexity.ai/search/hangugeseo-jeil-yumyeonghan-ga-7r5.TXbjTpe1Jr.YppHGTg"
|
||||
author:
|
||||
- "[[Perplexity AI]]"
|
||||
published:
|
||||
created: 2025-02-27
|
||||
description: "한국에서 가장 유명한 가계부 앱으로는 편한가계부, 뱅크샐러드, 그리고 위플가계부 등이 꼽힙니다. 각각의 주요 특징은 아래와 같습니다:[특징](pplx://action/followup): 국내 다운로드 1위로, 간편하고 다양한 기능을 제공하며 사용이 편리합니다.[주요..."
|
||||
tags:
|
||||
- "clippings"
|
||||
---
|
||||
한국에서 가장 유명한 가계부 앱으로는 **편한가계부**, **뱅크샐러드**, 그리고 **위플가계부** 등이 꼽힙니다. 각각의 주요 특징은 아래와 같습니다:
|
||||
|
||||
## 1.
|
||||
|
||||
- : 국내 다운로드 1위로, 간편하고 다양한 기능을 제공하며 사용이 편리합니다.
|
||||
- :
|
||||
|
||||
- 카드 사용 문자 자동 입력 및 저장
|
||||
- 영수증 사진 저장
|
||||
- 강력한 필터 및 통계 기능
|
||||
- PC 연동(유료 서비스) 가능
|
||||
- : iOS에서는 자동 입력 기능이 제한적[^1][^3][^4].
|
||||
|
||||
## 2.
|
||||
|
||||
- : 종합 금융 관리 앱으로, 가계부뿐만 아니라 계좌, 카드, 투자 등 다양한 금융 정보를 통합 관리할 수 있습니다.
|
||||
- :
|
||||
|
||||
- 은행/카드사 자동 연동
|
||||
- 지출 내역 자동 분류 및 시각화
|
||||
- 개인 맞춤형 금융상품 추천
|
||||
- : 공인인증서 연동으로 데이터 입력 최소화[^5][^7].
|
||||
|
||||
## 3.
|
||||
|
||||
- : 아이폰 사용자들에게 최적화된 간단하고 쉬운 가계부 앱.
|
||||
- :
|
||||
|
||||
- 초간편 입력 및 작성
|
||||
- 일간/주간/월간 내역 보기
|
||||
- 카테고리별 지출 통계
|
||||
- : 가계부 초보자에게 적합[^1].
|
||||
|
||||
이 외에도 네이버 가계부, 똑똑가계부 등 다양한 앱들이 사용자의 필요에 따라 선택되고 있습니다.
|
||||
|
||||
---
|
||||
|
||||
[^1]: https://tinydreamer.tistory.com/152?category=1347104
|
||||
|
||||
[^3]: https://dgbbang.tistory.com/entry/가계부-어플-추천-BEST-4
|
||||
|
||||
[^4]: https://goyangnews.co.kr/가계부-무료-어플-추천-2025년-최고의-앱-비교-분석/
|
||||
|
||||
[^5]: https://news.androidlist.co.kr/2024/05/02/가계부-앱-추천-best-7/
|
||||
|
||||
[^7]: https://jjtmi.com/entry/2024-부자되기-습관-가계부-어플-추천-BEST-3
|
||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
BIN
images/zellyy-google-banner.png
Normal file
|
After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
@@ -20,6 +20,9 @@ import PaymentMethods from './pages/PaymentMethods';
|
||||
import Settings from './pages/Settings';
|
||||
import { BudgetProvider } from './contexts/BudgetContext';
|
||||
import PrivateRoute from './components/auth/PrivateRoute';
|
||||
import NetworkStatusIndicator from './components/NetworkStatusIndicator';
|
||||
import { initSyncState, startNetworkMonitoring } from './utils/syncUtils';
|
||||
|
||||
// 전역 오류 핸들러
|
||||
const handleError = (error: Error | unknown) => {
|
||||
console.error('앱 오류 발생:', error);
|
||||
@@ -79,6 +82,10 @@ function App() {
|
||||
// 웹뷰 콘텐츠가 완전히 로드되었을 때만 스플래시 화면을 숨김
|
||||
const onAppReady = async () => {
|
||||
try {
|
||||
// 네트워크 모니터링 및 동기화 상태 초기화
|
||||
await initSyncState();
|
||||
console.log('동기화 상태 초기화 완료');
|
||||
|
||||
// 스플래시 화면을 더 빠르게 숨김 (데이터 로딩과 별도로 진행)
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
@@ -145,6 +152,7 @@ function App() {
|
||||
</Routes>
|
||||
</div>
|
||||
<Toaster />
|
||||
<NetworkStatusIndicator />
|
||||
</div>
|
||||
</Router>
|
||||
</BudgetProvider>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Check, ChevronDown, ChevronUp, Wallet } from 'lucide-react';
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
|
||||
import { markBudgetAsModified } from '@/utils/sync/budget/modifiedBudgetsTracker';
|
||||
|
||||
interface BudgetGoalProps {
|
||||
initialBudgets: {
|
||||
@@ -69,6 +69,16 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
|
||||
// 즉시 콜랩시블을 닫아 사용자에게 완료 피드백 제공
|
||||
setIsOpen(false);
|
||||
|
||||
// 월간 예산 변경 시 수정 추적 시스템에 기록
|
||||
if (selectedTab === 'monthly') {
|
||||
try {
|
||||
markBudgetAsModified(amount);
|
||||
console.log(`[예산 추적] 월간 예산 변경 추적: ${amount}원`);
|
||||
} catch (error) {
|
||||
console.error('[예산 추적] 예산 변경 추적 실패:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 예산 저장
|
||||
onSave(selectedTab, amount);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
import React from 'react';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { EXPENSE_CATEGORIES, categoryIcons } from '@/constants/categoryIcons';
|
||||
import { useIsMobile } from '@/hooks/use-mobile';
|
||||
import { markSingleCategoryBudgetAsModified } from '@/utils/sync/budget/modifiedBudgetsTracker';
|
||||
|
||||
interface CategoryBudgetInputsProps {
|
||||
categoryBudgets: Record<string, number>;
|
||||
@@ -27,6 +27,15 @@ const CategoryBudgetInputs: React.FC<CategoryBudgetInputsProps> = ({
|
||||
const numericValue = e.target.value.replace(/[^0-9]/g, '');
|
||||
handleCategoryInputChange(numericValue, category);
|
||||
|
||||
// 수정된 카테고리 예산 추적 시스템에 기록
|
||||
try {
|
||||
const amount = parseInt(numericValue, 10) || 0;
|
||||
markSingleCategoryBudgetAsModified(category, amount);
|
||||
console.log(`[예산 추적] 카테고리 '${category}' 예산 변경 추적: ${amount}원`);
|
||||
} catch (error) {
|
||||
console.error(`[예산 추적] 카테고리 '${category}' 예산 변경 추적 실패:`, error);
|
||||
}
|
||||
|
||||
// 사용자에게 시각적 피드백 제공
|
||||
e.target.classList.add('border-green-500');
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useAuth } from '@/contexts/auth/useAuth';
|
||||
import { toast } from '@/hooks/useToast.wrapper';
|
||||
import { saveTransactionsToStorage } from './storageUtils';
|
||||
import { deleteTransactionFromServer } from '@/utils/sync/transaction/deleteTransaction';
|
||||
import { addToDeletedTransactions } from '@/utils/sync/transaction/deletedTransactionsTracker';
|
||||
|
||||
/**
|
||||
* 안정화된 트랜잭션 삭제 훅 - 완전 재구현 버전
|
||||
@@ -49,6 +50,14 @@ export const useDeleteTransaction = (
|
||||
// 트랜잭션 찾기
|
||||
const updatedTransactions = transactions.filter(t => t.id !== id);
|
||||
|
||||
// 삭제된 트랜잭션 추적 목록에 추가
|
||||
try {
|
||||
addToDeletedTransactions(id);
|
||||
console.log(`[안정화] 삭제된 트랜잭션 추적 추가 (ID: ${id})`);
|
||||
} catch (trackingError) {
|
||||
console.error('[안정화] 삭제 추적 실패:', trackingError);
|
||||
}
|
||||
|
||||
// 로컬 스토리지 저장
|
||||
try {
|
||||
saveTransactionsToStorage(updatedTransactions);
|
||||
@@ -111,8 +120,10 @@ export const useDeleteTransaction = (
|
||||
|
||||
// 컴포넌트 언마운트 시 모든 상태 정리
|
||||
useEffect(() => {
|
||||
// 현재 ref 값을 로컬 변수에 복사하여 클린업 함수에서 사용
|
||||
const pendingDeletion = pendingDeletionRef.current;
|
||||
return () => {
|
||||
pendingDeletionRef.current.clear();
|
||||
pendingDeletion.clear();
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import { isSyncEnabled } from '../syncSettings';
|
||||
import { getModifiedBudget, getModifiedCategoryBudgets } from './modifiedBudgetsTracker';
|
||||
|
||||
/**
|
||||
* 서버에서 예산 데이터 다운로드
|
||||
@@ -107,9 +107,12 @@ async function fetchCategoryBudgetData(userId: string) {
|
||||
/**
|
||||
* 예산 데이터 처리 및 로컬 저장
|
||||
*/
|
||||
async function processBudgetData(budgetData: any, localBudgetDataStr: string | null) {
|
||||
async function processBudgetData(budgetData: Record<string, any>, localBudgetDataStr: string | null) {
|
||||
console.log('서버에서 예산 데이터 수신:', budgetData);
|
||||
|
||||
// 로컬에서 수정된 예산 정보 가져오기
|
||||
const modifiedBudget = getModifiedBudget();
|
||||
|
||||
// 서버 예산이 0이고 로컬 예산이 있으면 로컬 데이터 유지
|
||||
if (budgetData.total_budget === 0 && localBudgetDataStr) {
|
||||
console.log('서버 예산이 0이고 로컬 예산이 있어 로컬 데이터 유지');
|
||||
@@ -117,12 +120,51 @@ async function processBudgetData(budgetData: any, localBudgetDataStr: string | n
|
||||
}
|
||||
|
||||
// 기존 로컬 데이터 가져오기
|
||||
let localBudgetData = localBudgetDataStr ? JSON.parse(localBudgetDataStr) : {
|
||||
const localBudgetData = localBudgetDataStr ? JSON.parse(localBudgetDataStr) : {
|
||||
daily: { targetAmount: 0, spentAmount: 0, remainingAmount: 0 },
|
||||
weekly: { targetAmount: 0, spentAmount: 0, remainingAmount: 0 },
|
||||
monthly: { targetAmount: 0, spentAmount: 0, remainingAmount: 0 }
|
||||
};
|
||||
|
||||
// 로컬에서 수정된 예산이 있고, 서버 데이터보다 최신이면 로컬 데이터 유지
|
||||
if (modifiedBudget && (!budgetData.updated_at || new Date(budgetData.updated_at).getTime() < modifiedBudget.timestamp)) {
|
||||
console.log('로컬에서 수정된 예산이 서버 데이터보다 최신이므로 로컬 데이터 유지');
|
||||
|
||||
// 서버 데이터 대신 로컬에서 수정된 예산 사용
|
||||
const monthlyBudget = modifiedBudget.monthlyAmount;
|
||||
const dailyBudget = Math.round(monthlyBudget / 30); // 월간 예산 / 30일
|
||||
const weeklyBudget = Math.round(monthlyBudget / 4.3); // 월간 예산 / 4.3주
|
||||
|
||||
const updatedBudgetData = {
|
||||
daily: {
|
||||
targetAmount: dailyBudget,
|
||||
spentAmount: localBudgetData.daily.spentAmount,
|
||||
remainingAmount: dailyBudget - localBudgetData.daily.spentAmount
|
||||
},
|
||||
weekly: {
|
||||
targetAmount: weeklyBudget,
|
||||
spentAmount: localBudgetData.weekly.spentAmount,
|
||||
remainingAmount: weeklyBudget - localBudgetData.weekly.spentAmount
|
||||
},
|
||||
monthly: {
|
||||
targetAmount: monthlyBudget,
|
||||
spentAmount: localBudgetData.monthly.spentAmount,
|
||||
remainingAmount: monthlyBudget - localBudgetData.monthly.spentAmount
|
||||
}
|
||||
};
|
||||
|
||||
console.log('로컬 수정 데이터 기반 예산 계산:', updatedBudgetData);
|
||||
|
||||
// 로컬 스토리지에 저장
|
||||
localStorage.setItem('budgetData', JSON.stringify(updatedBudgetData));
|
||||
localStorage.setItem('budgetData_backup', JSON.stringify(updatedBudgetData));
|
||||
console.log('로컬 수정 예산 데이터 유지 완료', updatedBudgetData);
|
||||
|
||||
// 이벤트 발생시켜 UI 업데이트
|
||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 서버 데이터로 업데이트 (지출 금액은 유지)
|
||||
// 수정: 올바른 예산 계산 방식으로 변경
|
||||
const monthlyBudget = budgetData.total_budget;
|
||||
@@ -161,9 +203,12 @@ async function processBudgetData(budgetData: any, localBudgetDataStr: string | n
|
||||
/**
|
||||
* 카테고리 예산 데이터 처리 및 로컬 저장
|
||||
*/
|
||||
async function processCategoryBudgetData(categoryData: any[], localCategoryBudgetsStr: string | null) {
|
||||
async function processCategoryBudgetData(categoryData: Record<string, any>[], localCategoryBudgetsStr: string | null) {
|
||||
console.log(`${categoryData.length}개의 카테고리 예산 수신`);
|
||||
|
||||
// 로컬에서 수정된 카테고리 예산 정보 가져오기
|
||||
const modifiedCategoryBudgets = getModifiedCategoryBudgets();
|
||||
|
||||
// 서버 카테고리 예산 합계 계산
|
||||
const serverTotal = categoryData.reduce((sum, item) => sum + item.amount, 0);
|
||||
|
||||
@@ -173,6 +218,21 @@ async function processCategoryBudgetData(categoryData: any[], localCategoryBudge
|
||||
return;
|
||||
}
|
||||
|
||||
// 로컬에서 수정된 카테고리 예산이 있고, 서버 데이터보다 최신이면 로컬 데이터 유지
|
||||
if (modifiedCategoryBudgets && categoryData.length > 0) {
|
||||
// 서버 데이터 중 가장 최근 업데이트 시간 확인
|
||||
const latestServerUpdate = categoryData.reduce((latest, curr) => {
|
||||
if (!curr.updated_at) return latest;
|
||||
const currTime = new Date(curr.updated_at).getTime();
|
||||
return currTime > latest ? currTime : latest;
|
||||
}, 0);
|
||||
|
||||
if (latestServerUpdate < modifiedCategoryBudgets.timestamp) {
|
||||
console.log('로컬에서 수정된 카테고리 예산이 서버 데이터보다 최신이므로 로컬 데이터 유지');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 카테고리 예산 로컬 형식으로 변환
|
||||
const localCategoryBudgets = categoryData.reduce((acc, curr) => {
|
||||
acc[curr.category] = curr.amount;
|
||||
|
||||
138
src/utils/sync/budget/modifiedBudgetsTracker.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 수정된 예산 데이터를 추적하는 유틸리티
|
||||
* 로컬 스토리지에 수정된 예산 정보를 저장하고 관리합니다.
|
||||
*/
|
||||
|
||||
const MODIFIED_BUDGETS_KEY = 'modified_budgets';
|
||||
const MODIFIED_CATEGORY_BUDGETS_KEY = 'modified_category_budgets';
|
||||
|
||||
interface ModifiedBudget {
|
||||
timestamp: number; // 수정 시간 (밀리초)
|
||||
monthlyAmount: number; // 월간 예산액
|
||||
}
|
||||
|
||||
interface ModifiedCategoryBudgets {
|
||||
timestamp: number; // 수정 시간 (밀리초)
|
||||
categories: Record<string, number>; // 카테고리별 예산액
|
||||
}
|
||||
|
||||
/**
|
||||
* 수정된 예산 정보를 로컬 스토리지에 저장
|
||||
*/
|
||||
export const markBudgetAsModified = (monthlyAmount: number): void => {
|
||||
try {
|
||||
const modifiedBudget: ModifiedBudget = {
|
||||
timestamp: Date.now(),
|
||||
monthlyAmount
|
||||
};
|
||||
|
||||
localStorage.setItem(MODIFIED_BUDGETS_KEY, JSON.stringify(modifiedBudget));
|
||||
console.log(`[예산 추적] 수정된 예산 정보 저장 완료: ${monthlyAmount}원`);
|
||||
} catch (error) {
|
||||
console.error('[예산 추적] 수정된 예산 정보 저장 실패:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 수정된 카테고리 예산 정보를 로컬 스토리지에 저장
|
||||
*/
|
||||
export const markCategoryBudgetsAsModified = (categories: Record<string, number>): void => {
|
||||
try {
|
||||
const modifiedCategoryBudgets: ModifiedCategoryBudgets = {
|
||||
timestamp: Date.now(),
|
||||
categories
|
||||
};
|
||||
|
||||
localStorage.setItem(MODIFIED_CATEGORY_BUDGETS_KEY, JSON.stringify(modifiedCategoryBudgets));
|
||||
console.log(`[예산 추적] 수정된 카테고리 예산 정보 저장 완료: ${Object.keys(categories).length}개 카테고리`);
|
||||
} catch (error) {
|
||||
console.error('[예산 추적] 수정된 카테고리 예산 정보 저장 실패:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 단일 카테고리 예산 정보를 수정된 것으로 표시
|
||||
*/
|
||||
export const markSingleCategoryBudgetAsModified = (category: string, amount: number): void => {
|
||||
try {
|
||||
// 기존 수정 정보 가져오기
|
||||
const existing = getModifiedCategoryBudgets();
|
||||
const categories = existing?.categories || {};
|
||||
|
||||
// 새 카테고리 예산 정보 추가
|
||||
categories[category] = amount;
|
||||
|
||||
// 수정된 정보 저장
|
||||
const modifiedCategoryBudgets: ModifiedCategoryBudgets = {
|
||||
timestamp: Date.now(),
|
||||
categories
|
||||
};
|
||||
|
||||
localStorage.setItem(MODIFIED_CATEGORY_BUDGETS_KEY, JSON.stringify(modifiedCategoryBudgets));
|
||||
console.log(`[예산 추적] 카테고리 '${category}' 예산 정보 저장 완료: ${amount}원`);
|
||||
} catch (error) {
|
||||
console.error(`[예산 추적] 카테고리 '${category}' 예산 정보 저장 실패:`, error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 수정된 예산 정보 가져오기
|
||||
*/
|
||||
export const getModifiedBudget = (): ModifiedBudget | null => {
|
||||
try {
|
||||
const data = localStorage.getItem(MODIFIED_BUDGETS_KEY);
|
||||
if (!data) return null;
|
||||
|
||||
return JSON.parse(data) as ModifiedBudget;
|
||||
} catch (error) {
|
||||
console.error('[예산 추적] 수정된 예산 정보 조회 실패:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 수정된 카테고리 예산 정보 가져오기
|
||||
*/
|
||||
export const getModifiedCategoryBudgets = (): ModifiedCategoryBudgets | null => {
|
||||
try {
|
||||
const data = localStorage.getItem(MODIFIED_CATEGORY_BUDGETS_KEY);
|
||||
if (!data) return null;
|
||||
|
||||
return JSON.parse(data) as ModifiedCategoryBudgets;
|
||||
} catch (error) {
|
||||
console.error('[예산 추적] 수정된 카테고리 예산 정보 조회 실패:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 예산 수정 정보 초기화
|
||||
*/
|
||||
export const clearModifiedBudget = (): void => {
|
||||
try {
|
||||
localStorage.removeItem(MODIFIED_BUDGETS_KEY);
|
||||
console.log('[예산 추적] 수정된 예산 정보 초기화 완료');
|
||||
} catch (error) {
|
||||
console.error('[예산 추적] 수정된 예산 정보 초기화 실패:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 카테고리 예산 수정 정보 초기화
|
||||
*/
|
||||
export const clearModifiedCategoryBudgets = (): void => {
|
||||
try {
|
||||
localStorage.removeItem(MODIFIED_CATEGORY_BUDGETS_KEY);
|
||||
console.log('[예산 추적] 수정된 카테고리 예산 정보 초기화 완료');
|
||||
} catch (error) {
|
||||
console.error('[예산 추적] 수정된 카테고리 예산 정보 초기화 실패:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 모든 수정 정보 초기화
|
||||
*/
|
||||
export const clearAllModifiedBudgets = (): void => {
|
||||
clearModifiedBudget();
|
||||
clearModifiedCategoryBudgets();
|
||||
};
|
||||
@@ -1,6 +1,9 @@
|
||||
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import { isSyncEnabled } from '../syncSettings';
|
||||
import {
|
||||
clearModifiedBudget,
|
||||
clearModifiedCategoryBudgets
|
||||
} from './modifiedBudgetsTracker';
|
||||
|
||||
/**
|
||||
* 예산 데이터를 서버에 업로드
|
||||
@@ -18,6 +21,9 @@ export const uploadBudgets = async (userId: string): Promise<void> => {
|
||||
if (budgetDataStr) {
|
||||
const budgetData = JSON.parse(budgetDataStr);
|
||||
await uploadBudgetData(userId, budgetData);
|
||||
|
||||
// 업로드 성공 후 수정 추적 정보 초기화
|
||||
clearModifiedBudget();
|
||||
} else {
|
||||
console.log('업로드할 예산 데이터가 없음');
|
||||
}
|
||||
@@ -26,6 +32,9 @@ export const uploadBudgets = async (userId: string): Promise<void> => {
|
||||
if (categoryBudgetsStr) {
|
||||
const categoryBudgets = JSON.parse(categoryBudgetsStr);
|
||||
await uploadCategoryBudgets(userId, categoryBudgets);
|
||||
|
||||
// 업로드 성공 후 수정 추적 정보 초기화
|
||||
clearModifiedCategoryBudgets();
|
||||
} else {
|
||||
console.log('업로드할 카테고리 예산이 없음');
|
||||
}
|
||||
@@ -40,7 +49,7 @@ export const uploadBudgets = async (userId: string): Promise<void> => {
|
||||
/**
|
||||
* 일반 예산 데이터 업로드
|
||||
*/
|
||||
async function uploadBudgetData(userId: string, parsedBudgetData: any): Promise<void> {
|
||||
async function uploadBudgetData(userId: string, parsedBudgetData: Record<string, any>): Promise<void> {
|
||||
console.log('예산 데이터 업로드:', parsedBudgetData);
|
||||
|
||||
// 현재 월/년도 가져오기
|
||||
@@ -66,6 +75,9 @@ async function uploadBudgetData(userId: string, parsedBudgetData: any): Promise<
|
||||
|
||||
console.log('업로드할 월간 예산:', monthlyTarget);
|
||||
|
||||
// 현재 타임스탬프
|
||||
const currentTimestamp = new Date().toISOString();
|
||||
|
||||
// 업데이트 또는 삽입 결정
|
||||
if (existingBudgets && existingBudgets.length > 0) {
|
||||
// 기존 데이터 업데이트
|
||||
@@ -73,7 +85,7 @@ async function uploadBudgetData(userId: string, parsedBudgetData: any): Promise<
|
||||
.from('budgets')
|
||||
.update({
|
||||
total_budget: monthlyTarget,
|
||||
updated_at: new Date().toISOString()
|
||||
updated_at: currentTimestamp
|
||||
})
|
||||
.eq('id', existingBudgets[0].id);
|
||||
|
||||
@@ -91,7 +103,9 @@ async function uploadBudgetData(userId: string, parsedBudgetData: any): Promise<
|
||||
user_id: userId,
|
||||
month: currentMonth,
|
||||
year: currentYear,
|
||||
total_budget: monthlyTarget
|
||||
total_budget: monthlyTarget,
|
||||
created_at: currentTimestamp,
|
||||
updated_at: currentTimestamp
|
||||
});
|
||||
|
||||
if (error) {
|
||||
@@ -120,13 +134,18 @@ async function uploadCategoryBudgets(userId: string, parsedCategoryBudgets: Reco
|
||||
// 오류가 나도 계속 진행 (중요 데이터가 아니기 때문)
|
||||
}
|
||||
|
||||
// 현재 타임스탬프
|
||||
const currentTimestamp = new Date().toISOString();
|
||||
|
||||
// 카테고리별 예산 데이터 변환 및 삽입
|
||||
const categoryEntries = Object.entries(parsedCategoryBudgets)
|
||||
.filter(([_, amount]) => amount > 0) // 금액이 0보다 큰 것만 저장
|
||||
.map(([category, amount]) => ({
|
||||
user_id: userId,
|
||||
category,
|
||||
amount
|
||||
amount,
|
||||
created_at: currentTimestamp,
|
||||
updated_at: currentTimestamp
|
||||
}));
|
||||
|
||||
if (categoryEntries.length > 0) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import { isSyncEnabled } from '../syncSettings';
|
||||
import { addToDeletedTransactions } from './deletedTransactionsTracker';
|
||||
|
||||
/**
|
||||
* Supabase 서버에서 트랜잭션을 삭제하는 함수 - 안정성 및 성능 최적화 버전
|
||||
@@ -21,6 +22,9 @@ export const deleteTransactionFromServer = async (userId: string, transactionId:
|
||||
}, 2000);
|
||||
|
||||
try {
|
||||
// 삭제된 트랜잭션 ID 추적 목록에 추가
|
||||
addToDeletedTransactions(transactionId);
|
||||
|
||||
// 서버 요청 실행
|
||||
const { error } = await supabase
|
||||
.from('transactions')
|
||||
|
||||
69
src/utils/sync/transaction/deletedTransactionsTracker.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 삭제된 트랜잭션 ID를 추적하는 유틸리티
|
||||
* 로컬에서 삭제된 트랜잭션이 서버 동기화 후 다시 나타나는 문제를 해결합니다.
|
||||
*/
|
||||
|
||||
// 삭제된 트랜잭션 ID를 저장하는 로컬 스토리지 키
|
||||
const DELETED_TRANSACTIONS_KEY = 'deletedTransactions';
|
||||
|
||||
/**
|
||||
* 삭제된 트랜잭션 ID를 저장
|
||||
* @param id 삭제된 트랜잭션 ID
|
||||
*/
|
||||
export const addToDeletedTransactions = (id: string): void => {
|
||||
try {
|
||||
const deletedIds = getDeletedTransactions();
|
||||
if (!deletedIds.includes(id)) {
|
||||
deletedIds.push(id);
|
||||
localStorage.setItem(DELETED_TRANSACTIONS_KEY, JSON.stringify(deletedIds));
|
||||
console.log(`[삭제 추적] ID 추가됨: ${id}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[삭제 추적] ID 추가 실패:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 삭제된 트랜잭션 ID 목록 가져오기
|
||||
* @returns 삭제된 트랜잭션 ID 배열
|
||||
*/
|
||||
export const getDeletedTransactions = (): string[] => {
|
||||
try {
|
||||
const deletedStr = localStorage.getItem(DELETED_TRANSACTIONS_KEY);
|
||||
const deletedIds = deletedStr ? JSON.parse(deletedStr) : [];
|
||||
return Array.isArray(deletedIds) ? deletedIds : [];
|
||||
} catch (error) {
|
||||
console.error('[삭제 추적] 목록 조회 실패:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 삭제된 트랜잭션 ID 제거 (서버에서 성공적으로 삭제된 경우)
|
||||
* @param id 제거할 트랜잭션 ID
|
||||
*/
|
||||
export const removeFromDeletedTransactions = (id: string): void => {
|
||||
try {
|
||||
const deletedIds = getDeletedTransactions();
|
||||
const updatedIds = deletedIds.filter(deletedId => deletedId !== id);
|
||||
|
||||
if (deletedIds.length !== updatedIds.length) {
|
||||
localStorage.setItem(DELETED_TRANSACTIONS_KEY, JSON.stringify(updatedIds));
|
||||
console.log(`[삭제 추적] ID 제거됨: ${id}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[삭제 추적] ID 제거 실패:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 삭제된 트랜잭션 ID 목록 초기화
|
||||
*/
|
||||
export const clearDeletedTransactions = (): void => {
|
||||
try {
|
||||
localStorage.removeItem(DELETED_TRANSACTIONS_KEY);
|
||||
console.log('[삭제 추적] 목록 초기화됨');
|
||||
} catch (error) {
|
||||
console.error('[삭제 추적] 목록 초기화 실패:', error);
|
||||
}
|
||||
};
|
||||
@@ -3,6 +3,7 @@ import { supabase } from '@/lib/supabase';
|
||||
import { Transaction } from '@/components/TransactionCard';
|
||||
import { isSyncEnabled } from '../syncSettings';
|
||||
import { formatDateForDisplay } from './dateUtils';
|
||||
import { getDeletedTransactions } from './deletedTransactionsTracker';
|
||||
|
||||
/**
|
||||
* Download transaction data from Supabase to local storage
|
||||
@@ -30,40 +31,53 @@ export const downloadTransactions = async (userId: string): Promise<void> => {
|
||||
|
||||
console.log(`서버에서 ${data.length}개의 트랜잭션 다운로드`);
|
||||
|
||||
// 서버 데이터를 로컬 형식으로 변환
|
||||
const serverTransactions = data.map(t => {
|
||||
// 날짜 형식 변환 시 오류 방지 처리
|
||||
let formattedDate = '날짜 없음';
|
||||
try {
|
||||
if (t.date) {
|
||||
// ISO 형식이 아닌 경우 기본 변환 수행
|
||||
if (!t.date.match(/^\d{4}-\d{2}-\d{2}T/)) {
|
||||
console.log(`비표준 날짜 형식 감지: ${t.date}, ID: ${t.transaction_id || t.id}`);
|
||||
// 유효한 Date 객체로 변환 가능한지 확인
|
||||
const testDate = new Date(t.date);
|
||||
if (isNaN(testDate.getTime())) {
|
||||
console.warn(`잘못된 날짜 형식 감지, 현재 날짜 사용: ${t.date}`);
|
||||
t.date = new Date().toISOString(); // 잘못된 날짜는 현재 날짜로 대체
|
||||
}
|
||||
}
|
||||
formattedDate = formatDateForDisplay(t.date);
|
||||
// 삭제된 트랜잭션 ID 목록 가져오기
|
||||
const deletedIds = getDeletedTransactions();
|
||||
console.log(`[동기화] 삭제된 트랜잭션 ${deletedIds.length}개 필터링 적용`);
|
||||
|
||||
// 서버 데이터를 로컬 형식으로 변환 (삭제된 항목 제외)
|
||||
const serverTransactions = data
|
||||
.filter(t => {
|
||||
const transactionId = t.transaction_id || t.id;
|
||||
const isDeleted = deletedIds.includes(transactionId);
|
||||
if (isDeleted) {
|
||||
console.log(`[동기화] 삭제된 트랜잭션 필터링: ${transactionId}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`날짜 변환 오류 (ID: ${t.transaction_id || t.id}):`, err);
|
||||
// 오류 발생 시 기본값 사용
|
||||
formattedDate = new Date().toLocaleString('ko-KR');
|
||||
}
|
||||
|
||||
return {
|
||||
id: t.transaction_id || t.id,
|
||||
title: t.title,
|
||||
amount: t.amount,
|
||||
date: formattedDate,
|
||||
category: t.category,
|
||||
type: t.type,
|
||||
notes: t.notes
|
||||
};
|
||||
});
|
||||
return !isDeleted; // 삭제된 항목 제외
|
||||
})
|
||||
.map(t => {
|
||||
// 날짜 형식 변환 시 오류 방지 처리
|
||||
let formattedDate = '날짜 없음';
|
||||
try {
|
||||
if (t.date) {
|
||||
// ISO 형식이 아닌 경우 기본 변환 수행
|
||||
if (!t.date.match(/^\d{4}-\d{2}-\d{2}T/)) {
|
||||
console.log(`비표준 날짜 형식 감지: ${t.date}, ID: ${t.transaction_id || t.id}`);
|
||||
// 유효한 Date 객체로 변환 가능한지 확인
|
||||
const testDate = new Date(t.date);
|
||||
if (isNaN(testDate.getTime())) {
|
||||
console.warn(`잘못된 날짜 형식 감지, 현재 날짜 사용: ${t.date}`);
|
||||
t.date = new Date().toISOString(); // 잘못된 날짜는 현재 날짜로 대체
|
||||
}
|
||||
}
|
||||
formattedDate = formatDateForDisplay(t.date);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`날짜 변환 오류 (ID: ${t.transaction_id || t.id}):`, err);
|
||||
// 오류 발생 시 기본값 사용
|
||||
formattedDate = new Date().toLocaleString('ko-KR');
|
||||
}
|
||||
|
||||
return {
|
||||
id: t.transaction_id || t.id,
|
||||
title: t.title,
|
||||
amount: t.amount,
|
||||
date: formattedDate,
|
||||
category: t.category,
|
||||
type: t.type,
|
||||
notes: t.notes
|
||||
};
|
||||
});
|
||||
|
||||
// 기존 로컬 데이터 불러오기
|
||||
const localDataStr = localStorage.getItem('transactions');
|
||||
|
||||
BIN
zellyy 512px.jpg
Normal file
|
After Width: | Height: | Size: 68 KiB |