Files
ai-dev-portal/PLANS.md
Hyemin Lee e6928a8d61 docs: PLANS 진행상황 갱신 (Phase 4·5 완료 체크)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 17:27:09 +09:00

9.1 KiB

PLANS.md — 디자인·기능 전격 개편

목표: design-refs/AI DEV 포털.dc.html 의 디자인/기능을 거의 그대로 살려서 현재 포털을 개편한다. 단, 제약은 유지 — 빌드 없음 · React 없음 · 서버 렌더링(EJS) + 단일 CSS(public/style.css) + 가벼운 바닐라 JS(public/app.js).

기준: 디자인이 기획(PRD)보다 앞섰으므로 디자인을 정답으로 본다. PRD에 빠진 항목은 PRD에 보강한다(Phase 6).

확정된 설계 결정 (사용자 합의)

  • 반응 2종 유지: ❤️ 좋아요(heart) + 즐겨찾기(star) 둘 다. 인기순 정렬·즐겨찾기 필터 포함.
  • 부가 요소 전부 유지: 다크모드 토글, 토스트, 헤더 검색, 이스터에그(로고 흔들기·👍🚀·LGTM 스탬프).
  • 공개/비공개(visibility) 도입: 내 프로젝트는 공개/비공개 전환 가능, 비공개는 피드 미노출.
  • 관리자 판별은 실제 Keycloak role 로. (디자인의 "관리자 보기" 데모 토글은 제거하고 role 기반으로 대체)
  • 상세는 모달 + 비-JS 폴백용 /projects/:id 단독 페이지도 유지.
  • 반응/댓글은 점진적 향상(progressive enhancement): JS 없으면 폼 POST→리다이렉트, JS 있으면 fetch 로 즉시 반영.
  • 폐쇄망: 폰트/아이콘은 외부 CDN 의존 최소화(시스템 폰트 폴백 + 인라인 SVG/이모지).

Phase 0 — DB 스키마 & db.js (db:init 실행만 남음)

  • schema.sql: projectsis_public boolean NOT NULL DEFAULT true, lang text DEFAULT '' 컬럼 추가(멱등 ADD COLUMN IF NOT EXISTS).
  • schema.sql: commentsparent_id bigint REFERENCES comments(id) ON DELETE CASCADE 추가(대댓글 1뎁스).
  • schema.sql: ❤️ 좋아요용 hearts(project_id, sabun, created_at, PK) 테이블 추가. (기존 stars = 즐겨찾기 유지)
  • db.js: listProjects(viewer) — heart_count·star_count·comment_count·owner_name·is_public·lang + viewer hearted/starred. 공개 + 본인 비공개만 반환(남의 비공개 미노출).
  • db.js: getProject(id, viewer) — 단일 조회 + 카운트 + viewer 반응 여부.
  • db.js: listComments(projectId) — parent_id 포함, 작성자 이름.
  • db.js: addProject({owner,title,description,repoUrl,appUrl,tags,isPublic,lang}).
  • db.js: addComment({projectId,author,body,parentId}) — 부모가 같은 프로젝트의 최상위일 때만(1뎁스 강제), 새 행 반환.
  • db.js: deleteComment({id, sabun}) — 본인만, 자식 댓글까지 cascade.
  • db.js: toggleHeart(❤️) / toggleStar() — {on,count} 반환(AJAX 즉시 반영용).
  • db.js: setVisibility({id, sabun, isPublic}) — 본인 프로젝트만.
  • db.js: deleteProject({id, sabun}) — 본인만.
  • npm run db:init 재실행해 적용 — 로컬에 .project-env(DATABASE_URL)가 없어 미실행. 실제 DB 환경에서 사용자가 실행 필요.

Phase 1 — 설정 · 권한 · 사이트 카탈로그

  • auth.js: 콜백 claims 에서 role 추출(realm_access.roles + 클라이언트 role), roles + isAdmin 반환 → 세션 저장.
  • config.js: 도구 URL 8종 환경변수화(기본값 유지). 관리자 role 이름(ADMIN_ROLE, 기본 admin) 추가.
  • sites.js: 디자인 도구 목록으로 재구성 — 개발(Coder·Gitea·Kubero·Harbor) + 인프라(OpenEverest·MinIO·Keycloak·LiteLLM, adminOnly:true). SSO 플래그·이모지 아이콘·toolsForUser(isAdmin) 헬퍼.
  • .project-env.example: ADMIN_ROLE + 도구 URL 항목 추가.
  • 참고: server.js 는 아직 siteGroups(구 export)를 import → Phase 4 에서 재작성 전까지 부팅 불가 (의도된 중간 상태).

Phase 2 — 공통 레이아웃 · CSS · 클라이언트 JS

  • public/style.css: CSS 변수 시스템(라이트+다크 html[data-aidev-theme="dark"]) 전면 도입. 헤더/도구 그리드/내 프로젝트 패널/피드 그리드/카드/배지/버튼/모달/공유모달/댓글 스레드/토스트/플라이어/푸터/로그인/단독페이지/키프레임/반응형 — 단일 파일. 반응 아이콘 채움↔외곽선 토글 규칙 포함.
  • views/_header.ejs: 스티키 다크 헤더(로고+이스터에그 훅, 검색창, 테마 토글, 관리자 배지, 사용자 메뉴 드롭다운+로그아웃). 데모 관리자 토글 제거→실제 role. FOUC 방지 테마 초기화 인라인 스크립트.
  • 아이콘: views/_icons.ejs 대신 src/helpers.jsicon(name,{size,fill}) 헬퍼로 구현(Octicon 22종). 더불어 identicon(seed,size)(서버 SVG 아바타)·langColor·langFromTags 도 제공 → Phase 4 에서 res.locals 로 노출.
  • public/app.js(바닐라): 테마 토글·localStorage, 사용자 메뉴, 상세 모달 열기/닫기(Esc·오버레이), 검색·정렬(최신/인기)·즐겨찾기 필터(피드, 클라이언트), 내 프로젝트 필터(전체/공개/비공개), 댓글 답글 타깃·Enter 등록·삭제 확인, 공유 모달·공개범위 토글, 반응 fetch 즉시 반영, 토스트, 이스터에그(로고 흔들기·👍🚀·콘솔 아트), body 데이터속성 시작 신호(data-toast/data-egg/data-open-modal).
  • 참고: 대시보드/모달 마크업은 app.js 의 DOM 계약(data- 속성)* 에 맞춰 Phase 3/5 에서 렌더.

Phase 3 — 대시보드(/)

  • views/dashboard.ejs ① 개발 도구 섹션: role 필터된 카드 그리드(a target=_blank), SSO 배지, 관리자 전용 카드 스타일(보라) + "관리자 도구 표시 중" 배지.
  • ② 내 프로젝트 섹션: 좌측 액센트 바 패널, 전체/공개/비공개 필터 탭+카운트, "새 프로젝트" 버튼, 카드(가시성 배지·언어 점·❤️//💬 카운트·공개↔비공개 폼 토글), 새 프로젝트 추가 카드, 빈 상태.
  • ③ 공유 피드 섹션: 2열 카드 그리드, 인라인 ❤️/ 반응 버튼(채움/외곽선 토글), 작성자 아바타·날짜, 바로가기 링크, 최신/인기 탭 + 즐겨찾기 필터, 검색 빈 상태 요소.
  • 검색/정렬/필터용 data-* 속성(data-search/data-created/data-pop/data-starred/data-vis) 부여 → app.js 가 클라이언트 처리.
  • 모의 데이터로 EJS 렌더 검증 통과(헤더 include 포함). 모달/공유모달/상세저장소는 Phase 5.

Phase 4 — 라우트(server.js)

  • 공통: res.locals 에 icon/identicon/langColor 노출, isAjax/safeBack 헬퍼.
  • GET /listProjects(me) → 내 프로젝트/피드 분리, 도구 role 필터. ?open/?toast/?egg → body 신호.
  • POST /projects — 태그 정리·lang 추론·visibility 반영 후 toast 리다이렉트.
  • POST /projects/:id/heart · /star — 토글. AJAX 면 JSON {on,count}, 아니면 Referer 복귀.
  • POST /projects/:id/visibility — 공개/비공개 전환(본인).
  • POST /projects/:id/delete — 본인 프로젝트 삭제.
  • POST /projects/:id/comments — 댓글/대댓글(parent_id), LGTM/🚀 egg 신호, return_to 복귀.
  • POST /comments/:id/delete — 본인 댓글 삭제.
  • GET /projects/:id — 단독 페이지(비공개는 본인만). _header body 신호용 typeof 가드 추가.
  • 크로스 모듈 import/export 해석 검증 통과(서버 부팅 가능 상태 복구).

Phase 5 — 상세 모달 · 공유 모달 · 단독 페이지

  • views/_project_detail.ejs 신설 — 헤더(제목·가시성·작성자·날짜·언어)·태그·설명·❤️//바로가기/저장소·소유자 삭제·댓글 스레드(대댓글 들여쓰기·LGTM 스탬프·답글/삭제)·댓글 입력(Enter 등록). 모달/단독 페이지 공용(modal 플래그).
  • 대시보드: #detailModal 오버레이 + #detailStore(프로젝트별 <template>) + 공유 모달(제목*·설명·태그·저장소/배포 URL·공개범위 토글+안내).
  • 서버: listCommentsByProjects 로 댓글 일괄 조회 → commentsByProject 전달. allProjects 로 저장소 렌더.
  • app.js 가 template 내용을 .modal 에 주입해 모달 구성(이미 Phase 2 에서 구현).
  • views/project.ejs(단독) · views/login.ejs 새 디자인으로 재작성.
  • 세 뷰 모의 렌더 검증 통과(저장소 3개·공유모달·body 신호·백링크·알림).

Phase 6 — 문서 · 마무리 · 점검

  • ai-dev-portal-prd.md 보강: 반응 2종(heart/star), 공개/비공개, lang, 댓글 parent_id, 추가 라우트, 다크모드/검색/토스트 등 디자인 확정 사항 반영.
  • CLAUDE.md 구조 맵 갱신(public/app.js, _icons.ejs, hearts 테이블 등) 필요 시.
  • Pretendard 폰트: 시스템 폰트 폴백 확정. (선택) public/ 에 woff2 로컬 호스팅 태스크 별도.
  • 로컬 구동 점검: npm run dev → 로그인/도구/내프로젝트/피드/모달/공유/반응/댓글/대댓글/삭제/테마/검색 수동 확인.
  • 미인증·관리자/일반 분기·비공개 노출 규칙 점검.

진행 메모

  • (작업하며 결정·이슈를 여기에 누적)