Files
zellyy-finance/docs/02_기술_문서/데이터베이스_스키마_구현.md
2025-03-21 16:08:43 +09:00

11 KiB

적자 탈출 가계부 - 데이터베이스 스키마 구현

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) 테이블

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) 테이블

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) 테이블

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) 테이블

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) 테이블

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) 테이블

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) 테이블

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) 테이블

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) 테이블

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 정책 패턴:

-- 테이블에 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_iddate 조합)

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. 마이그레이션 실행 방법

마이그레이션 파일을 실행하기 위한 스크립트가 제공됩니다:

# 실행 권한 부여
chmod +x run_migrations.sh

# 스크립트 실행
./run_migrations.sh

환경 변수를 통해 데이터베이스 연결 정보를 설정할 수 있습니다:

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)이 자동으로 기록됩니다.