prepare app for public app store distribution
- rebrand from 습관 트래커 to 해빗랩 across templates, manifest, service worker - add HTTPS redirect middleware for reverse-proxied deployments - add public landing page (/) and privacy policy page with real data handling disclosures - add in-app account deletion (Apple review requirement) - add Android TWA Digital Asset Links support (/.well-known/assetlinks.json) - add SFTP deployment script for the Synology-hosted server Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}페이지를 찾을 수 없어요 · 습관 트래커{% endblock %}
|
||||
{% block title %}페이지를 찾을 수 없어요 · 해빗랩{% endblock %}
|
||||
{% block content %}
|
||||
<div style="min-height: 60vh; display:flex; align-items:center; justify-content:center; text-align:center;">
|
||||
<div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}오류가 발생했어요 · 습관 트래커{% endblock %}
|
||||
{% block title %}오류가 발생했어요 · 해빗랩{% endblock %}
|
||||
{% block content %}
|
||||
<div style="min-height: 60vh; display:flex; align-items:center; justify-content:center; text-align:center;">
|
||||
<div>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}계정 · 해빗랩{% endblock %}
|
||||
{% block content %}
|
||||
<h1>계정</h1>
|
||||
|
||||
<div class="card">
|
||||
<p><strong>이메일</strong><br />{{ current_user.email }}</p>
|
||||
{% if current_user.name %}<p><strong>이름</strong><br />{{ current_user.name }}</p>{% endif %}
|
||||
<p><strong>가입일</strong><br />{{ current_user.created_at.strftime('%Y-%m-%d') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>계정 삭제</h2>
|
||||
<p>
|
||||
계정을 삭제하면 등록한 모든 습관, 체크 기록, 알림 구독 정보가 즉시 영구적으로 삭제되며 되돌릴 수 없습니다.
|
||||
</p>
|
||||
{% if delete_error %}<p style="color: var(--color-danger);">{{ delete_error }}</p>{% endif %}
|
||||
<form method="post" action="/account/delete">
|
||||
<label for="confirm_email">확인을 위해 본인 이메일({{ current_user.email }})을 입력하세요</label>
|
||||
<input type="text" id="confirm_email" name="confirm_email" autocomplete="off" />
|
||||
<button type="submit" class="btn btn-danger-ghost btn-block" style="margin-top: var(--space-2);">계정 영구 삭제</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -3,14 +3,14 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||
<title>{% block title %}습관 트래커{% endblock %}</title>
|
||||
<title>{% block title %}해빗랩{% endblock %}</title>
|
||||
|
||||
<link rel="manifest" href="/static/manifest.json" />
|
||||
<meta name="theme-color" content="#d97757" media="(prefers-color-scheme: light)" />
|
||||
<meta name="theme-color" content="#e08962" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||
<meta name="apple-mobile-web-app-title" content="습관 트래커" />
|
||||
<meta name="apple-mobile-web-app-title" content="해빗랩" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/icons/icon-apple-180.png" />
|
||||
<link rel="apple-touch-icon" href="/static/icons/icon-192.png" />
|
||||
<link rel="icon" href="/static/icons/icon-192.png" />
|
||||
@@ -31,7 +31,7 @@
|
||||
<button type="button" onclick="dismissIosInstallBanner()" aria-label="닫기">×</button>
|
||||
</div>
|
||||
<nav class="top-nav">
|
||||
<span class="brand">습관 트래커</span>
|
||||
<span class="brand">해빗랩</span>
|
||||
<div class="nav-links">
|
||||
<a href="/today" class="{% block nav_today %}{% endblock %}">오늘</a>
|
||||
<a href="/habits" class="{% block nav_habits %}{% endblock %}">습관 관리</a>
|
||||
@@ -40,7 +40,7 @@
|
||||
{% if current_user %}
|
||||
<div class="nav-user">
|
||||
{% if account_level %}<span class="nav-level-pill">Lv.{{ account_level.level }}</span>{% endif %}
|
||||
<span>{{ current_user.name or current_user.email }}</span>
|
||||
<a href="/account">{{ current_user.name or current_user.email }}</a>
|
||||
<form method="post" action="/auth/logout">
|
||||
<button type="submit" class="btn-link">로그아웃</button>
|
||||
</form>
|
||||
@@ -63,6 +63,9 @@
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% block content %}{% endblock %}
|
||||
<footer class="app-footer">
|
||||
<a href="/privacy">개인정보처리방침</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}습관 관리 · 습관 트래커{% endblock %}
|
||||
{% block title %}습관 관리 · 해빗랩{% endblock %}
|
||||
{% block nav_habits %}active{% endblock %}
|
||||
{% block content %}
|
||||
<h1>습관 관리</h1>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}기록 · 습관 트래커{% endblock %}
|
||||
{% block title %}기록 · 해빗랩{% endblock %}
|
||||
{% block nav_history %}active{% endblock %}
|
||||
{% block shell_class %} wide{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}해빗랩 · 습관이 만들어지는 진짜 시간{% endblock %}
|
||||
{% block content %}
|
||||
<div class="landing">
|
||||
<div class="landing-hero">
|
||||
<div class="landing-brand"><img src="/static/icons/icon-192.png" alt="" /> 해빗랩</div>
|
||||
<h1>습관이 만들어지는<br />진짜 시간</h1>
|
||||
<p class="landing-tagline">21일의 법칙 대신, 습관마다 다른 진짜 목표 기간을 알려드려요</p>
|
||||
|
||||
<div class="landing-streak" aria-hidden="true">
|
||||
<div class="landing-day done">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5 9-9" /></svg>
|
||||
</div>
|
||||
<div class="landing-day done">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5 9-9" /></svg>
|
||||
</div>
|
||||
<div class="landing-day done">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5 9-9" /></svg>
|
||||
</div>
|
||||
<div class="landing-day done">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5 9-9" /></svg>
|
||||
</div>
|
||||
<div class="landing-day done">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l5 5 9-9" /></svg>
|
||||
</div>
|
||||
<div class="landing-day">토</div>
|
||||
<div class="landing-day">일</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="landing-copy">
|
||||
<p>
|
||||
"습관은 21일이면 만들어진다"는 말, 많이 들어보셨을 거예요. 사실 근거가 약한 통설이에요.
|
||||
실증 연구(<strong>Lally et al., 2010, UCL</strong>)에 따르면 습관이 몸에 붙기까지 걸리는 시간은
|
||||
사람마다, 습관마다 달라서 짧게는 3주, 길게는 8개월 넘게 걸리기도 해요.
|
||||
</p>
|
||||
<p>
|
||||
<strong>해빗랩</strong>은 여러분이 만들고 싶은 습관도, 멈추고 싶은 습관도 함께 만들어가는 동반자예요.
|
||||
검증된 연구를 시스템에 그대로 담아 목표 기간과 진행 상황을 짚어드리고, 그 여정을 끝까지 응원할게요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="landing-features">
|
||||
<div class="landing-feature">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9" /><circle cx="12" cy="12" r="5" /><circle cx="12" cy="12" r="1" /></svg>
|
||||
<p><strong>연구 기반 목표 기간</strong>속설이 아니라 실제 연구값(21·66·254일)으로 목표를 잡아요</p>
|
||||
</div>
|
||||
<div class="landing-feature">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="12" r="6" /><line x1="8" y1="9" x2="8" y2="15" /><line x1="5" y1="12" x2="11" y2="12" /><circle cx="17" cy="12" r="6" /><line x1="14" y1="12" x2="20" y2="12" /></svg>
|
||||
<p><strong>만들기와 끊기, 동시에</strong>새 습관을 만드는 것과 나쁜 습관을 끊는 것을 똑같은 무게로 다뤄요</p>
|
||||
</div>
|
||||
<div class="landing-feature">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9" /><line x1="6" y1="6" x2="18" y2="18" /></svg>
|
||||
<p><strong>광고·구독 없음</strong>습관관리에만 집중해요, 그 외엔 아무것도 없어요</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="/auth/google/login" class="btn btn-primary btn-block">Google로 시작하기</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,9 +1,10 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}로그인 · 습관 트래커{% endblock %}
|
||||
{% block title %}로그인 · 해빗랩{% endblock %}
|
||||
{% block content %}
|
||||
<div style="min-height: 70vh; display: flex; align-items: center; justify-content: center;">
|
||||
<div class="card" style="width: 100%; max-width: 320px;">
|
||||
<h1 style="text-align:center;">습관 트래커</h1>
|
||||
<h1 style="text-align:center;">해빗랩</h1>
|
||||
{% if deleted %}<p style="text-align:center; color: var(--color-success);">계정이 삭제되었습니다.</p>{% endif %}
|
||||
<p style="text-align:center;">구글 계정으로 로그인하세요</p>
|
||||
<a href="/auth/google/login" class="btn btn-primary btn-block">Google로 로그인</a>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}개인정보처리방침 · 해빗랩{% endblock %}
|
||||
{% block content %}
|
||||
<div style="max-width: 640px; margin: 0 auto; padding: 24px 16px 48px;">
|
||||
<div class="card">
|
||||
<h1>개인정보처리방침</h1>
|
||||
<p>시행일자: 2026년 7월 22일</p>
|
||||
|
||||
<p>해빗랩(이하 "서비스")는 이용자의 개인정보를 소중히 다루며, 아래와 같이 개인정보를 수집·이용·보관합니다.</p>
|
||||
|
||||
<h2>1. 수집하는 개인정보 항목</h2>
|
||||
<p><strong>가. 구글 로그인 시 (필수)</strong><br />
|
||||
이메일 주소, 이름, 프로필 사진 URL, 구글 계정 고유 식별자(sub). 서비스는 구글 계정 정보를 이용해 자동으로 계정을 생성하며, 비밀번호는 별도로 수집·저장하지 않습니다.</p>
|
||||
<p><strong>나. 서비스 이용 중 직접 입력하는 정보</strong><br />
|
||||
등록한 습관의 이름, 유형(만들기/끊기), 요일 스케줄, 목표 난이도, 달성 조건, 알림 시각, 날짜별 체크·실패 기록.</p>
|
||||
<p><strong>다. 알림(Web Push)을 켠 경우에만</strong><br />
|
||||
브라우저가 발급하는 푸시 구독 정보(endpoint, 암호화 키)와 브라우저 종류(User-Agent). 알림 중복 발송을 막기 위한 발송 이력도 함께 기록됩니다.</p>
|
||||
<p><strong>라. 자동 수집 정보</strong><br />
|
||||
로그인 유지를 위한 서명된 세션 쿠키. 별도의 광고·분석·트래킹 쿠키는 사용하지 않습니다.</p>
|
||||
|
||||
<h2>2. 개인정보의 수집 및 이용 목적</h2>
|
||||
<p>구글 계정 인증 및 로그인 유지, 습관 등록·체크·통계(완료율, 연속 달성일 등) 제공, 설정한 시각에 맞춘 습관 알림(Web Push) 발송을 위해서만 이용합니다. 광고, 마케팅, 프로필링 목적으로는 이용하지 않습니다.</p>
|
||||
|
||||
<h2>3. 개인정보의 보유 및 이용 기간</h2>
|
||||
<p>회원 탈퇴 시까지 보관하며, 탈퇴 시 계정 정보와 습관·체크 기록, 푸시 구독 정보를 지체 없이 삭제합니다. 관계 법령에 따라 보존이 필요한 경우가 아니면 별도 보관하지 않습니다.</p>
|
||||
|
||||
<h2>4. 개인정보의 제3자 제공</h2>
|
||||
<p>서비스는 이용자의 개인정보를 원칙적으로 외부에 제공하지 않습니다. 다만 구글 로그인 인증 과정에서 구글(Google LLC)과 통신이 발생하며, 이는 이용자 인증을 위한 목적에 한정됩니다.</p>
|
||||
|
||||
<h2>5. 이용자의 권리와 행사 방법</h2>
|
||||
<p>이용자는 언제든지 자신의 개인정보 열람·정정·삭제를 요청할 수 있습니다. 로그인 후 <a href="/account">계정</a> 페이지에서 본인 이메일 확인 후 즉시 계정과 모든 데이터를 직접 삭제할 수 있으며, 앱을 이용하기 어려운 경우 아래 문의처로 요청하셔도 확인 후 지체 없이 처리해드립니다.</p>
|
||||
|
||||
<h2>6. 보안을 위한 조치</h2>
|
||||
<p>비밀번호를 직접 저장하지 않는 구글 OAuth 인증 방식을 사용하며, 로그인 세션은 서명된 쿠키로 관리합니다. 모든 통신은 HTTPS로 암호화되며, 각 이용자의 데이터는 계정 단위로 분리되어 다른 이용자가 접근할 수 없습니다.</p>
|
||||
|
||||
<h2>7. 문의처</h2>
|
||||
<p>개인정보 관련 문의, 열람·정정·삭제 요청은 아래로 연락해주세요.</p>
|
||||
<p>해빗랩 운영자<br />
|
||||
이메일: <a href="mailto:shinalok357@gmail.com">shinalok357@gmail.com</a></p>
|
||||
|
||||
<h2>8. 고지의 의무</h2>
|
||||
<p>이 개인정보처리방침은 법령이나 서비스 변경사항을 반영하기 위해 수정될 수 있으며, 변경 시 이 페이지를 통해 고지합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}오늘 · 습관 트래커{% endblock %}
|
||||
{% block title %}오늘 · 해빗랩{% endblock %}
|
||||
{% block nav_today %}active{% endblock %}
|
||||
{% block content %}
|
||||
<div id="today-content">
|
||||
|
||||
Reference in New Issue
Block a user