diff --git a/HANDOFF.md b/HANDOFF.md index a957e99..05e022a 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -4,7 +4,7 @@ - 프로젝트명: 10 Minute Planner 웹 UI - 기술 스택: Vue 3 + Vite + TailwindCSS + JavaScript -- 현재 기준 버전: `v0.1.45` 준비 중 +- 현재 기준 버전: `v0.1.46` 준비 중 - Git 원격 저장소: `https://git.sori.studio/zenn/planner.sori.studio.git` ## 기준 디자인 @@ -196,7 +196,7 @@ - 모바일 대응 이후 인쇄에서 `TIME TABLE`이 사라지던 문제를 막기 위해, print 시에는 `PlannerPage` 내부 레이아웃을 다시 가로 배치로 고정하고 타임테이블 오버플로를 해제하도록 보정했다. - 인쇄 레이아웃은 추가로 미세 조정해 `COMMENT` 영역이 잘리지 않도록 textarea 높이/행간을 print 전용으로 풀고, `1-UP` / `2-UP` 배율도 프레임 실측 기준으로 다시 계산했다. - `TODO.md`는 중복 체크 항목을 정리했고, 인증 확장을 위해 `이메일 인증 / 비밀번호 재설정 / rate limit / 메일 인프라` 작업을 별도 항목으로 추가했다. -- Resend 무료 플랜은 도메인 1개 제약이 있어 현재 프로젝트 인증 메일에는 바로 쓰기 어렵다. 다음 단계에서는 AWS SES 또는 범용 SMTP 공급자 기준으로 메일 발송 추상화를 붙이는 쪽이 적합하다. +- 메일 발송은 현재 Resend 기준으로 운영한다. 도메인 정책이나 플랜 조건이 실제 운영과 어긋나는 시점이 오면 그때 대체 수단을 재검토한다. - 현재 인증 메일/재설정 메일은 실제 발송 대신 개발용 `previewUrl`을 응답으로 돌려주는 단계다. 프론트 UI 연결과 실제 메일러 연결은 다음 단계에서 마무리하면 된다. - 미니 달력 날짜 버튼은 원형 비율이 흔들리지 않도록 고정 `width/height` 기준으로 다시 맞췄다. - 플래너 본문 D-DAY 텍스트는 3줄까지만 보이고, 넘치면 말줄임 처리되도록 정리했다. @@ -223,6 +223,7 @@ - 왼쪽 사이드바의 인쇄 영역은 `PRINT` 버튼 하나로 줄이고, 클릭 시 모달에서 시작일/종료일과 `1페이지씩` 또는 `2페이지씩` 출력 방식을 선택한다. 인쇄 전용 렌더링은 선택 기간의 날짜를 순서대로 여러 장 생성하며, 2페이지씩 출력에서 홀수 날짜가 남으면 오른쪽은 빈 페이지 프레임으로 둔다. - 회원가입과 프로필 수정 시 이메일뿐 아니라 닉네임 중복도 서버에서 409로 막는다. 비밀번호 재설정 API는 로그인 모달의 `비밀번호 찾기` 흐름과 연결되어 있고, `/reset-password?token=...` URL로 들어오면 새 비밀번호 설정 모드가 열린다. 실제 메일 발송 전까지는 백엔드 응답의 `resetPreviewUrl`을 개발용 링크로 표시한다. - Resend 메일러가 추가되었다. `RESEND_API_KEY`, `MAIL_FROM_EMAIL`, `MAIL_FROM_NAME`, `APP_BASE_URL` 환경변수를 설정하면 이메일 인증과 비밀번호 재설정 메일을 실제로 발송한다. API 키는 저장소에 커밋하지 말고 루트 `.env`/`.env.dev`에만 넣는다. +- 메일 발송 인프라는 현재 Resend 기준으로 확정했다. 자동 로그아웃 옵션은 플래너를 오래 띄워두는 사용 흐름과 맞지 않아 TODO 대상에서 제외했다. - 인증/비밀번호 재설정 개발용 링크는 `AUTH_PREVIEW_LINKS=true`일 때만 API 응답에 포함된다. 운영 `.env`는 반드시 `AUTH_PREVIEW_LINKS=false`로 두어야 하며, 현재 예시 파일도 false가 기본값이다. - 회원가입은 이제 자동 로그인되지 않는다. 인증 메일 발송 후 `이메일 인증 후 로그인` 안내만 보여주고, 일반 사용자는 이메일 인증 전까지 로그인할 수 없다. - 기존에 발급된 세션이라도 일반 사용자 이메일 인증이 안 되어 있으면 `/api/auth/me` 단계에서 세션을 즉시 폐기한다. 운영 중 인증 정책을 켠 뒤에도 미인증 세션이 남지 않게 하기 위한 장치다. @@ -241,7 +242,7 @@ - 날짜에 적용되는 목표가 새로 생기면 D-DAY는 기본 표시된다. 사용자가 해당 날짜에서 직접 `D-DAY 사용`을 끈 경우에만 로컬 숨김 목록에 저장해 다시 숨긴다. - 비로그인 랜딩은 모바일에서 `카드 안 카드`처럼 보이지 않도록 기능 설명 카드를 얇은 리스트로 단순화했고, `LOGIN` / `SIGN UP` 버튼은 같은 너비와 높이로 맞췄다. 로그인/회원가입 모달도 하단 전환 영역을 별도 카드 대신 구분선 형태로 정리했다. - 로그인 모달에 `로그인 유지` 체크박스를 추가했다. 기본값은 OFF이며, OFF 상태에서는 인증 토큰을 `sessionStorage`에 저장해 브라우저 세션이 끝나면 사라지고, ON 상태에서만 `localStorage`에 저장한다. -- 현재 로그아웃은 프론트 저장 토큰을 지우는 수준이다. 개인 기록 서비스 성격을 고려하면 다음 단계에서 서버 세션 폐기 API와 미사용 자동 로그아웃 옵션을 추가하는 편이 좋다. +- 현재 로그아웃은 `/api/auth/logout`으로 서버 세션까지 함께 폐기한다. 자동 로그아웃 옵션은 플래너를 오래 열어두는 사용 흐름과 맞지 않아 추가 대상에서 제외했다. - 비로그인 랜딩에 `DEMO VIEW`를 추가했다. 데모는 실제 저장/로그인 상태와 분리된 읽기 전용 샘플이며, 어제/오늘/내일 3일치 플래너를 전환해서 제품 감각을 먼저 볼 수 있다. - 플래너 본문 `MEMO`와 `TIME TABLE` 하단 높이를 맞추기 위해 TASK/MEMO 리스트 간격과 행 높이를 조정했다. TASK 드래그 선택 피드백은 레이아웃 흔들림을 줄이도록 ring 대신 배경색만 사용한다. - 이월된 할 일은 `carryoverFrom` 날짜를 가진다. TASK 본문에는 `이월` 배지를 표시하고, 클릭하면 오른쪽 `READ NEXT` 영역에 원래 시작 날짜를 안내한다. diff --git a/TODO.md b/TODO.md index 199ce42..8370697 100644 --- a/TODO.md +++ b/TODO.md @@ -98,11 +98,9 @@ - [x] 비밀번호 찾기 / 재설정 토큰 흐름을 추가한다. - [ ] 로그인 및 인증 관련 rate limit / 잠금 정책을 추가한다. - [x] 로그인 유지 여부를 사용자가 선택할 수 있게 한다. -- [ ] 일정 시간 미사용 시 자동 로그아웃 옵션을 추가한다. - [x] 설정 화면에서 현재 기기 로그인 상태와 저장 방식을 안내한다. - [x] 서버 세션을 명시적으로 폐기하는 로그아웃 API를 추가한다. -- [ ] 메일 발송 인프라와 발신 도메인 정책을 확정한다. -- [ ] Resend 무료 플랜 대체 수단으로 SES 또는 일반 SMTP 연동 방식을 확정한다. +- [x] 메일 발송 인프라와 발신 도메인 정책을 Resend 기준으로 확정한다. - [ ] 관리자 페이지에서 계정 비활성화 / 강제 로그아웃 / 삭제 기능을 추가한다. - [ ] 관리자 페이지에서 사용자별 문서 상세 조회 기능을 추가한다. - [ ] 관리자 페이지에서 검색 / 정렬 / 필터 UX를 추가한다. @@ -135,6 +133,6 @@ - 앱을 새로 열면 마지막 열람 날짜가 아니라 항상 오늘 날짜부터 시작하고, Docker/NAS 컨테이너 시간대는 `Asia/Seoul` 기준으로 맞춘다. - TASK LABELS는 버튼 묶음 대신 동일한 토글 패턴으로 단순화했다. - 구현할 때마다 완료된 항목은 체크하고, 큰 결정사항은 `HANDOFF.md`에도 함께 반영한다. -- Resend 무료 플랜은 도메인 수 제약이 있으므로, 실제 인증 메일은 AWS SES 또는 별도 SMTP 서비스 전환을 전제로 설계하는 편이 안전하다. +- 메일 발송은 현재 Resend 기준으로 운영한다. 무료 플랜/도메인 제약이 바뀌는 시점에만 별도 대체 수단을 다시 검토한다. - 관리자 기능은 읽기 전용 대시보드부터 시작하고, 실제 정리 액션은 권한/감사 로그 정책을 정한 뒤 추가하는 편이 안전하다. - 관리자 아이디/비밀번호는 README나 HANDOFF에 실제 값으로 남기지 않고, Docker 배포용 비공개 `.env`에서만 관리한다. diff --git a/package-lock.json b/package-lock.json index 2f39197..323daf0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ten-minute-planner", - "version": "0.1.45", + "version": "0.1.46", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ten-minute-planner", - "version": "0.1.45", + "version": "0.1.46", "dependencies": { "vue": "^3.5.13" }, diff --git a/package.json b/package.json index 299394b..7dce18a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ten-minute-planner", "private": true, - "version": "0.1.45", + "version": "0.1.46", "type": "module", "scripts": { "dev": "vite",