Merge branch 'restore-work-20251013'

This commit is contained in:
koreacomp5
2025-10-13 04:48:26 +09:00
12 changed files with 221 additions and 120 deletions

View File

@@ -0,0 +1,3 @@
### 메인페이지구성
[] 1. https://mabinogimobile.nexon.com/Main를 브라우저로 열기
[] 2. 1번 링크를 참조해서 기존 src/app/layout.tsx과 src/app/page.tsx파일에 큰 레이아웃 클론 css는 tailwind로

102
.cursor/.prompt/todolist.md Normal file
View File

@@ -0,0 +1,102 @@
### 백엔드/API
[x] 1.1 Prisma 스키마 최종 확정(모델/관계/index/unique)
[x] 1.2 마이그레이션 생성 및 적용(prisma migrate dev)
[x] 1.3 Prisma Client 재생성 및 dev DB 초기화
[x] 1.4 시드 스크립트 분리(역할/기본 관리자/샘플 게시판)
[x] 1.5 서비스/리포지토리 계층 뼈대 생성(트랜잭션 유틸 포함)
### 권한/역할(RBAC)
[x] 2.1 역할·권한 시드(admin/editor/user) 추가
[x] 2.2 권한 enum/매핑 정의(리소스/액션)
[x] 2.3 서버 권한 미들웨어 적용(API 보호 라우트 지정)
[x] 2.4 페이지/컴포넌트 가드 훅 구현(usePermission)
[x] 2.5 권한 기반 UI 노출 제어(빠른 액션/관리자 메뉴)
### 로그인/인증
[x] 3.1 로그인/가입 폼 검증(Zod) 및 오류 UX
[x] 3.2 비밀번호 해시/검증 로직(bcrypt) 적용
[x] 3.3 세션/쿠키(HttpOnly/SameSite/Secure) 및 토큰 저장 전략
[x] 3.4 비밀번호 재설정 토큰 발급/검증/만료
[x] 3.5 보호 라우팅 미들웨어 및 인증 가드
[x] 3.6 로그인 시도 레이트리밋(정책은 보안/정책 참조)
### 상태관리/데이터
[x] 4.1 React Query 설치 및 Provider 구성
[x] 4.2 공통 fetcher/에러 형식/재시도·백오프 설정
[x] 4.3 캐시 키/무효화 전략 수립 및 적용
[x] 4.4 낙관적 업데이트 패턴 적용(작성/수정)
### 공통/레이아웃
[x] 5.1 앱 레이아웃/헤더/푸터/사이드바 구성
[x] 5.2 공통 컴포넌트(버튼/입력/모달/토스트) 제작
[x] 5.3 글로벌 로딩/스켈레톤/에러 경계 패턴 정립
[x] 5.4 테마/다크모드 및 반응형 설정
### 메인 화면
[x] 6.1 Hero/공지 배너 컴포넌트(자동/수동 슬라이드)
[x] 6.2 최근/인기 글 리스트 및 무한스크롤 연동
[x] 6.3 권한 기반 빠른 액션 노출 제어
[x] 6.4 검색 바 및 결과 페이지 라우팅
[x] 6.5 개인화 위젯(최근 본 글/알림 요약)
### 게시판/컨텐츠
[x] 7.1 게시글 CRUD API 및 페이지 연동
[x] 7.2 목록 페이징/정렬/검색(제목/태그/작성자/기간)
[x] 7.3 태그/카테고리 모델 및 UI
[x] 7.4 첨부 업로드 및 본문 삽입
[x] 7.5 추천/신고, 조회수 카운트
[x] 7.6 익명/비밀댓글/비댓 해시 처리
[x] 7.7 신고→알림→블라인드 자동화 훅
[x] 7.8 일반 게시판 공용 폼/라우트 템플릿 생성
[x] 7.9 일반 카테고리 설정 매핑(공지/가입인사/버그건의/이벤트/소통방/자유/무엇이든/마사지꿀팁/관리사찾아요/청와대/방문후기[승인])
[x] 7.10 제휴업소 일반(사진) 카테고리 전용 이미지 첨부/미리보기 규칙
### 특수 페이지(카테고리)
[x] 8.1 출석부: 데일리 체크인/중복 방지/포인트 지급/누적 통계
[x] 8.2 포인트안내: 정책 안내 페이지(에디터 연동/버전 이력)
[x] 8.3 회원랭킹: 기간별 랭킹 집계/캐싱/페이지네이션/정렬 옵션
[x] 8.4 무료쿠폰: 쿠폰 등록/재고/사용 처리/만료/1인 제한/로그
[x] 8.5 월간집계: 월별 지표 산출 배치/차트/다운로드(CSV)
[x] 8.6 주변 제휴업체: 위치 기반 목록/지도/필터(거리/카테고리)
[x] 8.7 제휴문의: 접수 폼/관리자 승인 워크플로우/알림
[x] 8.8 제휴업소 요청: 요청 생성/승인/상태 관리/이력
### 에디터/업로드
[x] 9.1 에디터(Tiptap/Quill 중 택1) 통합
[x] 9.2 이미지/파일 업로드 서버 처리 및 검증
[x] 9.3 리사이즈/웹포맷 최적화 및 용량 제한
[x] 9.4 붙여넣기/드래그 삽입, 캡션/대체텍스트
[x] 9.5 사진 중심 카테고리 프리셋(해상도/비율/워터마크 옵션)
### 관리자(Admin)
[x] 10.1 대시보드 핵심 지표 위젯
[x] 10.2 게시판 스키마/설정 관리 UI
[x] 10.3 사용자 검색/정지/권한 변경
[x] 10.4 공지/배너 등록 및 노출 설정
[x] 10.5 감사 이력/신고 내역/열람 로그
[x] 10.6 카테고리 유형/설정 관리(일반/특수/승인/레벨/익명/태그)
### 테스트/품질
[ ] 11.1 유닛 테스트(서비스/리포지토리)
[ ] 11.2 통합 테스트(API 핵심 플로우)
[ ] 11.3 E2E 테스트(인증/게시글 작성/검색)
[ ] 11.4 린트/포맷/프리커밋 훅, 타입 엄격화
### 보안/정책
[ ] 12.1 레이트리밋 파라미터 확정 및 적용
[ ] 12.2 CSRF 방어 전략 및 토큰 처리
[ ] 12.3 XSS 콘텐츠 정제 규칙 정의/적용
[ ] 12.4 비밀번호 정책/자동 로그아웃/감사 로그 설정
[ ] 12.5 금칙어 정책/DB 운영 절차 수립
### 배포/운영
[ ] 13.1 환경변수 파일 체계 및 비밀키 전략
[ ] 13.2 CI 파이프라인 구성(테스트/빌드/린트)
[ ] 13.3 배포 설정 및 헬스체크 엔드포인트
[ ] 13.4 모니터링/알림(Sentry 등) 연동
[ ] 13.5 백업/복구 전략 수립
### 14 배포용 상태 적용
[ ] 14.1 패스워드찾기 정상화
[ ] 14.2 에디터 정상화

3
.cursor/commands/ck.md Normal file
View File

@@ -0,0 +1,3 @@
#check
Mark the checklist as done once completed

3
.cursor/commands/cm.md Normal file
View File

@@ -0,0 +1,3 @@
# Commit with message
Set an appropriate message for the recent changes, then commit.

2
.cursor/commands/n.md Normal file
View File

@@ -0,0 +1,2 @@
### next work
Do the next task.

36
src/app/_layout.tsxbk Normal file
View File

@@ -0,0 +1,36 @@
import type { Metadata } from "next";
import "./globals.css";
import QueryProvider from "@/app/QueryProvider";
import { AppHeader } from "@/app/components/AppHeader";
import { AppSidebar } from "@/app/components/AppSidebar";
import { AppFooter } from "@/app/components/AppFooter";
import { ToastProvider } from "@/app/components/ui/ToastProvider";
export const metadata: Metadata = {
title: "msg App",
description: "msg App",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
<QueryProvider>
<ToastProvider>
<AppHeader />
<div style={{ display: "flex", minHeight: "80vh" }}>
<AppSidebar />
<main style={{ flex: 1, padding: 16 }}>{children}</main>
</div>
<AppFooter />
</ToastProvider>
</QueryProvider>
</body>
</html>
);
}

17
src/app/_page.tsx.bk Normal file
View File

@@ -0,0 +1,17 @@
import Image from "next/image";
import { QuickActions } from "@/app/components/QuickActions";
import { HeroBanner } from "@/app/components/HeroBanner";
import { PostList } from "@/app/components/PostList";
import { PersonalWidgets } from "@/app/components/PersonalWidgets";
export default function Home({ searchParams }: { searchParams?: { sort?: "recent" | "popular" } }) {
const sort = searchParams?.sort ?? "recent";
return (
<div className="">
<HeroBanner />
<QuickActions />
<PostList sort={sort} />
<PersonalWidgets />
</div>
);
}

View File

@@ -22,5 +22,8 @@
body { body {
background: var(--background); background: var(--background);
color: var(--foreground); color: var(--foreground);
font-family: Arial, Helvetica, sans-serif; font-family: var(--font-sans), Arial, Helvetica, sans-serif;
} }
/* 유틸: 카드 스켈레톤 색상 헬퍼 (타깃 사이트 톤 유사) */
.bg-neutral-100 { background-color: #f5f5f7; }

View File

@@ -2,7 +2,6 @@ import type { Metadata } from "next";
import "./globals.css"; import "./globals.css";
import QueryProvider from "@/app/QueryProvider"; import QueryProvider from "@/app/QueryProvider";
import { AppHeader } from "@/app/components/AppHeader"; import { AppHeader } from "@/app/components/AppHeader";
import { AppSidebar } from "@/app/components/AppSidebar";
import { AppFooter } from "@/app/components/AppFooter"; import { AppFooter } from "@/app/components/AppFooter";
import { ToastProvider } from "@/app/components/ui/ToastProvider"; import { ToastProvider } from "@/app/components/ui/ToastProvider";
@@ -18,16 +17,27 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}>) { }>) {
return ( return (
<html lang="en"> <html lang="ko">
<body> <body className="min-h-screen bg-background text-foreground antialiased">
<QueryProvider> <QueryProvider>
<ToastProvider> <ToastProvider>
<div className="min-h-screen flex flex-col">
<div className="sticky top-0 z-50 border-b bg-white/80 backdrop-blur">
<div className="max-w-7xl mx-auto px-4">
<AppHeader /> <AppHeader />
<div style={{ display: "flex", minHeight: "80vh" }}>
<AppSidebar />
<main style={{ flex: 1, padding: 16 }}>{children}</main>
</div> </div>
</div>
<main className="flex-1">
<div className="max-w-7xl mx-auto px-4 py-6">
{children}
</div>
</main>
<div className="border-t">
<div className="max-w-7xl mx-auto px-4">
<AppFooter /> <AppFooter />
</div>
</div>
</div>
</ToastProvider> </ToastProvider>
</QueryProvider> </QueryProvider>
</body> </body>

View File

@@ -1,17 +1,41 @@
import Image from "next/image";
import { QuickActions } from "@/app/components/QuickActions";
import { HeroBanner } from "@/app/components/HeroBanner"; import { HeroBanner } from "@/app/components/HeroBanner";
import { PostList } from "@/app/components/PostList";
import { PersonalWidgets } from "@/app/components/PersonalWidgets";
export default function Home({ searchParams }: { searchParams?: { sort?: "recent" | "popular" } }) { export default function Home({ searchParams }: { searchParams?: { sort?: "recent" | "popular" } }) {
const sort = searchParams?.sort ?? "recent"; const sort = searchParams?.sort ?? "recent";
return ( return (
<div className=""> <div className="space-y-8">
{/* 히어로 섹션: 상단 대형 비주얼 영역 */}
<section>
<HeroBanner /> <HeroBanner />
<QuickActions /> </section>
<PostList sort={sort} />
<PersonalWidgets /> {/* 메인 그리드: 좌 대형 카드, 우 2열 카드 등 타깃 사이트 구조를 단순화한 12그리드 */}
<section className="grid grid-cols-1 md:grid-cols-12 gap-4">
<div className="md:col-span-8 grid grid-cols-1 gap-4">
<div className="aspect-[16/9] rounded-xl bg-neutral-100 overflow-hidden" />
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="h-40 rounded-xl bg-neutral-100" />
<div className="h-40 rounded-xl bg-neutral-100" />
</div>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div className="h-28 rounded-lg bg-neutral-100" />
<div className="h-28 rounded-lg bg-neutral-100" />
<div className="h-28 rounded-lg bg-neutral-100" />
</div>
</div>
<aside className="md:col-span-4 space-y-4">
<div className="h-40 rounded-xl bg-neutral-100" />
<div className="h-40 rounded-xl bg-neutral-100" />
<div className="h-40 rounded-xl bg-neutral-100" />
</aside>
</section>
{/* 하단 롤링 배너/뉴스 영역 유사 섹션 */}
<section className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="h-28 rounded-lg bg-neutral-100" />
<div className="h-28 rounded-lg bg-neutral-100" />
<div className="h-28 rounded-lg bg-neutral-100" />
</section>
</div> </div>
); );
} }

View File

@@ -1,102 +0,0 @@
[백엔드/API]
1.1 Prisma 스키마 최종 확정(모델/관계/index/unique) o
1.2 마이그레이션 생성 및 적용(prisma migrate dev) o
1.3 Prisma Client 재생성 및 dev DB 초기화 o
1.4 시드 스크립트 분리(역할/기본 관리자/샘플 게시판) o
1.5 서비스/리포지토리 계층 뼈대 생성(트랜잭션 유틸 포함) o
[권한/역할(RBAC)]
2.1 역할·권한 시드(admin/editor/user) 추가 o
2.2 권한 enum/매핑 정의(리소스/액션) o
2.3 서버 권한 미들웨어 적용(API 보호 라우트 지정) o
2.4 페이지/컴포넌트 가드 훅 구현(usePermission) o
2.5 권한 기반 UI 노출 제어(빠른 액션/관리자 메뉴) o
[로그인/인증]
3.1 로그인/가입 폼 검증(Zod) 및 오류 UX o
3.2 비밀번호 해시/검증 로직(bcrypt) 적용 o
3.3 세션/쿠키(HttpOnly/SameSite/Secure) 및 토큰 저장 전략 o
3.4 비밀번호 재설정 토큰 발급/검증/만료 o
3.5 보호 라우팅 미들웨어 및 인증 가드 o
3.6 로그인 시도 레이트리밋(정책은 보안/정책 참조) o
[상태관리/데이터]
4.1 React Query 설치 및 Provider 구성 o
4.2 공통 fetcher/에러 형식/재시도·백오프 설정 o
4.3 캐시 키/무효화 전략 수립 및 적용 o
4.4 낙관적 업데이트 패턴 적용(작성/수정) o
[공통/레이아웃]
5.1 앱 레이아웃/헤더/푸터/사이드바 구성 o
5.2 공통 컴포넌트(버튼/입력/모달/토스트) 제작 o
5.3 글로벌 로딩/스켈레톤/에러 경계 패턴 정립 o
5.4 테마/다크모드 및 반응형 설정 o
[메인 화면]
6.1 Hero/공지 배너 컴포넌트(자동/수동 슬라이드) o
6.2 최근/인기 글 리스트 및 무한스크롤 연동 o
6.3 권한 기반 빠른 액션 노출 제어 o
6.4 검색 바 및 결과 페이지 라우팅 o
6.5 개인화 위젯(최근 본 글/알림 요약) o
[게시판/컨텐츠]
7.1 게시글 CRUD API 및 페이지 연동 o
7.2 목록 페이징/정렬/검색(제목/태그/작성자/기간) o
7.3 태그/카테고리 모델 및 UI o
7.4 첨부 업로드 및 본문 삽입 o
7.5 추천/신고, 조회수 카운트 o
7.6 익명/비밀댓글/비댓 해시 처리 o
7.7 신고→알림→블라인드 자동화 훅 o
7.8 일반 게시판 공용 폼/라우트 템플릿 생성 o
7.9 일반 카테고리 설정 매핑(공지/가입인사/버그건의/이벤트/소통방/자유/무엇이든/마사지꿀팁/관리사찾아요/청와대/방문후기[승인]) o
7.10 제휴업소 일반(사진) 카테고리 전용 이미지 첨부/미리보기 규칙 o
[특수 페이지(카테고리)]
8.1 출석부: 데일리 체크인/중복 방지/포인트 지급/누적 통계 o
8.2 포인트안내: 정책 안내 페이지(에디터 연동/버전 이력) o
8.3 회원랭킹: 기간별 랭킹 집계/캐싱/페이지네이션/정렬 옵션 o
8.4 무료쿠폰: 쿠폰 등록/재고/사용 처리/만료/1인 제한/로그 o
8.5 월간집계: 월별 지표 산출 배치/차트/다운로드(CSV) o
8.6 주변 제휴업체: 위치 기반 목록/지도/필터(거리/카테고리) o
8.7 제휴문의: 접수 폼/관리자 승인 워크플로우/알림 o
8.8 제휴업소 요청: 요청 생성/승인/상태 관리/이력 o
[에디터/업로드]
9.1 에디터(Tiptap/Quill 중 택1) 통합 o
9.2 이미지/파일 업로드 서버 처리 및 검증 o
9.3 리사이즈/웹포맷 최적화 및 용량 제한 o
9.4 붙여넣기/드래그 삽입, 캡션/대체텍스트 o
9.5 사진 중심 카테고리 프리셋(해상도/비율/워터마크 옵션) o
[관리자(Admin)]
10.1 대시보드 핵심 지표 위젯 o
10.2 게시판 스키마/설정 관리 UI o
10.3 사용자 검색/정지/권한 변경 o
10.4 공지/배너 등록 및 노출 설정 o
10.5 감사 이력/신고 내역/열람 로그 o
10.6 카테고리 유형/설정 관리(일반/특수/승인/레벨/익명/태그) o
[테스트/품질]
11.1 유닛 테스트(서비스/리포지토리)
11.2 통합 테스트(API 핵심 플로우)
11.3 E2E 테스트(인증/게시글 작성/검색)
11.4 린트/포맷/프리커밋 훅, 타입 엄격화
[보안/정책]
12.1 레이트리밋 파라미터 확정 및 적용
12.2 CSRF 방어 전략 및 토큰 처리
12.3 XSS 콘텐츠 정제 규칙 정의/적용
12.4 비밀번호 정책/자동 로그아웃/감사 로그 설정
12.5 금칙어 정책/DB 운영 절차 수립
[배포/운영]
13.1 환경변수 파일 체계 및 비밀키 전략
13.2 CI 파이프라인 구성(테스트/빌드/린트)
13.3 배포 설정 및 헬스체크 엔드포인트
13.4 모니터링/알림(Sentry 등) 연동
13.5 백업/복구 전략 수립
14 배포용 상태 적용
14.1 패스워드찾기 정상화
14.2 에디터 정상화