포스트

라이프 다이어리

하루를 10분 단위로 기록하고 태그로 분류해 시간 사용 패턴을 분석하는 Life Diary 프로젝트. 개발 동기, Django 기반 기술 스택, 시스템 아키텍처와 핵심 기능 구현을 정리한다.

라이프 다이어리

프로젝트 이름: Life Diary - 10분 단위 일상 관리 시스템

일상생활을 체계적으로 관리하고 싶지만, 기존의 시간 관리 도구들은 너무 복잡하거나 부담스러웠습니다. Life Diary는 이러한 문제를 해결하기 위해 개발한 웹 애플리케이션입니다. 하루를 10분 단위로 나누어 기록하고, 태그 기반으로 분류하여 시간 사용 패턴을 분석할 수 있게 설계되었습니다.

기술적으로는 Django 5.2.4와 Python을 기반으로 개발되었으며, SQLite를 개발용 데이터베이스로 사용하고 있습니다. 프론트엔드는 Django Templates와 Bootstrap을 활용하여 직관적인 사용자 인터페이스를 구현했습니다.

Life Diary를 왜 만들었나?

대학생 시절부터 시간 관리를 위해 다양한 도구들을 시도해봤지만, 항상 아쉬움이 남았습니다.

  • 너무 세밀한 계획: 30분, 1시간 단위로 계획을 세우면 실제로는 그렇게 되지 않아서 스트레스만 쌓임
  • 복잡한 인터페이스: 많은 기능들이 있지만 실제로는 사용하지 않는 기능들이 대부분
  • 분석 부족: 시간을 기록해도 “그래서 어쩨?”라는 질문에 답을 주지 못함

그러던 중 10분 단위 기록이라는 아이디어가 떠올랐습니다. 10분은 충분히 짧아서 부담스럽지 않으면서도, 하루 144개의 슬롯으로 세밀한 패턴을 파악할 수 있는 단위였습니다.

기술 스택

  • Backend: Django 5.2.4 (Python)
  • Frontend: Django Templates, Bootstrap 5, HTML/CSS/JavaScript
  • Database: SQLite (개발), PostgreSQL (프로덕션)
  • Deployment: Render, Supabase

시스템 아키텍처

1. 프로젝트 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
lifeDiary/
├── apps/                          # Django 앱들
│   ├── core/                      # 핵심 유틸리티
│   │   ├── static/core/           # 공통 정적 파일
│   │   │   ├── css/style.css      # 공통 스타일
│   │   │   ├── js/tag.js          # 태그 관련 JavaScript
│   │   │   └── js/utils.js        # 유틸리티 함수
│   │   └── utils.py               # 공통 유틸리티 함수
│   ├── dashboard/                 # 메인 대시보드
│   │   ├── models.py              # TimeBlock 모델
│   │   ├── views.py               # 대시보드 뷰
│   │   ├── api_urls.py            # API 엔드포인트
│   │   └── templates/dashboard/   # 대시보드 템플릿
│   ├── stats/                     # 통계 및 분석
│   │   ├── views.py               # 통계 뷰
│   │   ├── logic.py               # 통계 계산 로직
│   │   ├── feedback.py            # AI 피드백 생성
│   │   └── templates/stats/       # 통계 템플릿
│   ├── tags/                      # 태그 관리
│   │   ├── models.py              # Tag 모델
│   │   ├── views.py               # 태그 뷰
│   │   ├── api_urls.py            # API 엔드포인트
│   │   └── templates/tags/        # 태그 템플릿
│   └── users/                     # 사용자 관리
│       ├── models.py              # UserGoal, UserNote 모델
│       ├── views.py               # 사용자 뷰
│       ├── forms.py               # 폼 정의
│       └── templates/users/       # 사용자 템플릿
├── lifeDiary/                     # 프로젝트 설정
│   ├── settings/                  # 설정 파일들
│   │   ├── base.py                # 기본 설정
│   │   ├── dev.py                 # 개발 환경 설정
│   │   └── prod.py                # 프로덕션 환경 설정
│   ├── urls.py                    # 메인 URL 설정
│   └── wsgi.py                    # WSGI 설정
└── requirements.txt               # Python 의존성

2. 핵심 컴포넌트

TimeBlock 모델 설계

가장 중요한 설계 결정은 10분 단위 시간 블록을 어떻게 효율적으로 관리할 것인가였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# apps/dashboard/models.py
class TimeBlock(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateField()
    time_slot = models.IntegerField()  # 0-143 (10분 단위)
    tag = models.ForeignKey(Tag, on_delete=models.SET_NULL, null=True, blank=True)
    memo = models.TextField(max_length=500, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ['user', 'date', 'time_slot']
        indexes = [
            models.Index(fields=['user', 'date']),
            models.Index(fields=['user', 'tag']),
        ]

주요 특징:

  • time_slot: 0-143 (하루 144개 10분 슬롯)
  • unique_together: 같은 시간대 중복 방지
  • 인덱스 최적화: 사용자별 날짜, 태그별 조회 성능 향상

태그 시스템

사용자별 개인 태그와 공용 기본 태그를 구분하여 관리합니다.

1
2
3
4
5
6
7
8
9
# apps/tags/models.py
class Tag(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    name = models.CharField(max_length=50)
    color = models.CharField(max_length=7, default='#007bff')  # HEX 색상
    is_default = models.BooleanField(default=False)
    
    class Meta:
        unique_together = ['user', 'name']

설계 포인트

  • 개인 태그: user가 설정된 경우
  • 기본 태그: user가 null이고 is_default=True인 경우
  • 색상 커스터마이징: HEX 색상 코드로 시각적 구분

핵심 기능 구현

1. 시간 블록 관리 시스템

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# apps/dashboard/views.py
class TimeBlock(models.Model):
    """
    10분 단위 시간 블록 관리
    - 하루 24시간 = 144개 슬롯 (0~143)
    - 각 슬롯은 10분 단위
    """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateField()
    slot_index = models.IntegerField(
        validators=[MinValueValidator(0), MaxValueValidator(143)],
        help_text="0: 00:00-00:10, 143: 23:50-24:00"
    )
    tag = models.ForeignKey(Tag, on_delete=models.SET_NULL, null=True)
    memo = models.TextField(blank=True, max_length=500)
    
    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["user", "date", "slot_index"],
                name="unique_user_date_slot"
            )
        ]
        indexes = [
            models.Index(fields=["user", "date"]),
            models.Index(fields=["date", "slot_index"]),
        ]

2. 통계 분석 시스템

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# apps/stats/logic.py
def calculate_tag_statistics(user, start_date, end_date):
    """태그별 시간 사용 통계 계산"""
    timeblocks = TimeBlock.objects.filter(
        user=user,
        date__range=[start_date, end_date],
        tag__isnull=False
    ).select_related('tag')
    
    stats = {}
    for timeblock in timeblocks:
        tag_name = timeblock.tag.name
        if tag_name not in stats:
            stats[tag_name] = {
                'total_minutes': 0,
                'color': timeblock.tag.color,
                'percentage': 0
            }
        stats[tag_name]['total_minutes'] += 10
    
    # 퍼센티지 계산
    total_minutes = sum(stat['total_minutes'] for stat in stats.values())
    for stat in stats.values():
        stat['percentage'] = (stat['total_minutes'] / total_minutes * 100) if total_minutes > 0 else 0
    
    return stats

3. AI 피드백 시스템

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# apps/stats/feedback.py
def generate_ai_feedback(user, stats_data):
    """시간 사용 패턴에 대한 AI 피드백 생성"""
    feedback = []
    
    # 가장 많은 시간을 사용한 태그 분석
    top_tag = max(stats_data.items(), key=lambda x: x[1]['total_minutes'])
    if top_tag[1]['percentage'] > 50:
        feedback.append(f"'{top_tag[0]}'에 하루의 절반 이상을 사용하고 있습니다. "
                       f"다른 활동과의 균형을 고려해보세요.")
    
    # 목표 대비 달성률 분석
    user_goals = UserGoal.objects.filter(user=user)
    for goal in user_goals:
        actual_time = stats_data.get(goal.tag.name, {}).get('total_minutes', 0)
        if actual_time < goal.target_minutes:
            feedback.append(f"'{goal.tag.name}' 목표 달성률: "
                           f"{actual_time/60:.1f}시간 / {goal.target_minutes/60:.1f}시간 "
                           f"({actual_time/goal.target_minutes*100:.1f}%)")
    
    return feedback

데이터 플로우

1
2
3
4
5
6
7
8
9
10
graph TD
    A[사용자 로그인] --> B[대시보드 접속]
    B --> C[날짜 선택]
    C --> D[시간 블록 표시]
    D --> E[태그 할당]
    E --> F[TimeBlock 저장]
    F --> G[통계 페이지]
    G --> H[시간 사용량 계산]
    H --> I[AI 피드백 생성]
    I --> J[결과 시각화]

개발 과정에서의 도전과 해결

1. 10분 단위 시간 관리의 효율성

문제: 144개의 시간 슬롯을 어떻게 직관적으로 표시할 것인가?

해결:

  • 시간대별로 그룹화하여 표시 (아침, 오후, 저녁, 밤)
  • 색상 코딩으로 태그별 구분
  • 드래그 앤 드롭으로 연속 시간 블록 선택

2. 실시간 데이터 동기화

문제: 여러 사용자가 동시에 접근할 때 데이터 일관성

해결:

  • Django ORM의 unique_together 제약 조건 활용
  • AJAX를 통한 비동기 업데이트
  • 낙관적 락킹 패턴 적용

3. 통계 계산 성능 최적화

문제: 대량의 TimeBlock 데이터에서 통계 계산 시 성능 저하

해결:

  • 데이터베이스 인덱스 최적화
  • select_related를 통한 N+1 쿼리 방지
  • 캐싱을 통한 반복 계산 최소화

결과 및 성과

주요 기능

  • 10분 단위 기록: 하루 144개 슬롯으로 세밀한 시간 관리
  • 태그 기반 분류: 사용자 정의 태그로 활동 분류
  • 실시간 통계: 시간 사용 패턴 즉시 분석
  • AI 피드백: 개인화된 시간 관리 조언

사용자 경험 개선

  • 기록 편의성: 클릭 한 번으로 10분 단위 기록
  • 시각적 피드백: 색상 코딩으로 한눈에 파악
  • 인사이트 제공: 시간 사용 패턴 분석 및 개선점 제시

향후 개선 계획

  1. 기능 확장
    • 모바일 앱 개발
    • 팀/그룹 시간 관리 기능
    • 캘린더 연동
  2. AI 기능 강화
    • 머신러닝 기반 시간 사용 패턴 예측
    • 개인화된 생산성 최적화 제안
  3. 데이터 분석
    • 주간/월간 리포트 생성
    • 목표 달성률 추적
    • 생산성 지표 대시보드

마무리

이 프로젝트를 통해 실제 사용자의 일상적 문제를 해결하는 웹 애플리케이션을 만드는 경험을 할 수 있었습니다. 특히 10분 단위라는 독특한 접근 방식으로 시간 관리의 새로운 패러다임을 제시할 수 있었다는 점이 가장 보람찼습니다.

가장 중요한 학습은 사용자 중심의 설계가 얼마나 중요한지 깨달은 것입니다. 복잡한 기능보다는 사용자가 실제로 필요로 하는 핵심 기능에 집중하는 것이 더 가치 있다는 것을 배웠습니다.


관련 링크


이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.