- AuthProvider + ProtectedRoute + AdminRoute (인증 가드) - LoginPage (Google OAuth), PendingPage, DeniedPage - AppLayout (사이드바 + 메인 콘텐츠) - HomePage (퀵링크 카드), GuidePage (섹션 동적 렌더링) - BrowserRouter 라우팅 구성 - API fetch 래퍼 + 메뉴 네비게이션 유틸 - 타입 정의 (User, Role, AuthResponse, NavItem, Issue) - CLAUDE.md 상세화 (별도 세션 작업 가이드)
195 lines
8.1 KiB
Markdown
195 lines
8.1 KiB
Markdown
# gc-guide — 개발자 가이드 사이트 (프론트엔드)
|
|
|
|
## 프로젝트 개요
|
|
GC SI 팀 개발자를 위한 온보딩 가이드 사이트.
|
|
신규 개발자가 개발 환경 설정, Gitea/Nexus 사용법, Git 워크플로우 등을 학습할 수 있도록 안내.
|
|
|
|
## 기술 스택
|
|
- React 19 + TypeScript + Vite 7
|
|
- Tailwind CSS v4 (@tailwindcss/vite 플러그인)
|
|
- React Router v7 (BrowserRouter)
|
|
- @react-oauth/google (Google OAuth2 인증)
|
|
- react-markdown + remark-gfm + rehype-highlight (마크다운 렌더링)
|
|
- highlight.js (코드 블록 구문 강조)
|
|
|
|
## 빌드 & 실행
|
|
|
|
```bash
|
|
npm run dev # 개발 서버 (localhost:5173)
|
|
npm run build # 프로덕션 빌드 (dist/)
|
|
npm run preview # 빌드 프리뷰
|
|
npm run lint # ESLint 검사
|
|
```
|
|
|
|
## 배포
|
|
- 서버: guide.gc-si.dev (Nginx 정적 서빙)
|
|
- main 브랜치 MR 머지 시 자동 배포 (CI/CD, Gitea Actions)
|
|
- 개발 서버 API 프록시: `/api/*` → `localhost:8080` (vite.config.ts)
|
|
- Gitea: https://gitea.gc-si.dev/gc/gc-guide
|
|
|
|
## 의존성 레포지토리
|
|
- npm: https://nexus.gc-si.dev/repository/npm-public/ (.npmrc에 _auth 포함)
|
|
|
|
## 관련 프로젝트
|
|
- gc-guide-api: 백엔드 API (Spring Boot 3.5, JDK 17, PostgreSQL)
|
|
- Gitea: https://gitea.gc-si.dev/gc/gc-guide-api
|
|
|
|
---
|
|
|
|
## 현재 구현 상태
|
|
|
|
### 완료 (scaffold)
|
|
- 프로젝트 초기화 (Vite + React + TypeScript + Tailwind CSS v4)
|
|
- 인증 시스템 뼈대: AuthProvider, useAuth, ProtectedRoute, AdminRoute
|
|
- 페이지 뼈대: LoginPage, PendingPage, DeniedPage, HomePage, GuidePage
|
|
- 레이아웃: AppLayout (좌측 사이드바 + 메인 콘텐츠)
|
|
- 라우팅 구성 (App.tsx): `/login`, `/pending`, `/denied`, `/`, `/dev/:section`, `/admin/*`
|
|
- 유틸: api.ts (fetch 래퍼), navigation.ts (메뉴 + ant-style 패턴 매칭)
|
|
- 타입 정의: User, Role, AuthResponse, NavItem, Issue
|
|
- 빌드 검증: `tsc -b && vite build` 성공
|
|
|
|
### 미구현 (별도 세션에서 작업)
|
|
아래 순서대로 구현 필요:
|
|
|
|
#### 1단계: 공통 컴포넌트
|
|
- `src/components/common/CodeBlock.tsx` — 코드 블록 (highlight.js + 복사 버튼)
|
|
- `src/components/common/Alert.tsx` — 정보/경고/에러 알림 박스
|
|
- `src/components/common/StepGuide.tsx` — 단계별 가이드 UI
|
|
- `src/components/common/CopyButton.tsx` — 클립보드 복사 버튼
|
|
|
|
#### 2단계: 가이드 콘텐츠 (7개 섹션)
|
|
`src/content/` 디렉토리에 TSX 컴포넌트로 작성:
|
|
|
|
| 파일 | URL | 내용 |
|
|
|------|-----|------|
|
|
| DevEnvIntro.tsx | /dev/env-intro | 인프라 구성도, 서비스 카드, 도메인 테이블 |
|
|
| InitialSetup.tsx | /dev/initial-setup | SSH 키, Git 설정, SDKMAN/fnm, Claude Code 설치 |
|
|
| GiteaUsage.tsx | /dev/gitea-usage | Google OAuth 로그인, 리포 브라우징, 이슈/MR |
|
|
| NexusUsage.tsx | /dev/nexus-usage | Maven/Gradle/npm 프록시 설정, 패키지 배포 |
|
|
| GitWorkflow.tsx | /dev/git-workflow | 브랜치 전략, Conventional Commits, 3계층 정책 |
|
|
| ChatBotIntegration.tsx | /dev/chat-bot | 스페이스 생성, 봇 명령어, 알림 유형 |
|
|
| StartingProject.tsx | /dev/starting-project | 템플릿 비교, 리포 생성, /init-project |
|
|
|
|
GuidePage.tsx를 수정하여 section 파라미터에 따라 해당 콘텐츠 컴포넌트를 동적 렌더링.
|
|
|
|
#### 3단계: 관리자 페이지
|
|
- `src/pages/admin/UserManagement.tsx` — 사용자 목록, 승인/거절, 롤 배정
|
|
- `src/pages/admin/RoleManagement.tsx` — 롤 CRUD
|
|
- `src/pages/admin/PermissionManagement.tsx` — 롤별 URL 패턴 CRUD
|
|
- `src/pages/admin/StatsPage.tsx` — 통계 대시보드
|
|
|
|
#### 4단계: 다크모드 + 반응형
|
|
- `src/hooks/useTheme.ts` — 다크/라이트 모드 토글 (localStorage 저장)
|
|
- Header에 토글 버튼 추가
|
|
- 모바일 반응형: 사이드바 접힘 (hamburger 메뉴)
|
|
- `src/hooks/useScrollSpy.ts` — 우측 목차(ToC) 스크롤 추적
|
|
|
|
---
|
|
|
|
## 인증/인가 흐름 (3단계)
|
|
|
|
```
|
|
1단계: Google OAuth (@gcsc.co.kr 필터)
|
|
비인증 → LoginPage → "Google로 로그인"
|
|
→ Google OAuth2 팝업 → ID Token 수신
|
|
→ POST /api/auth/google → 백엔드에서 @gcsc.co.kr 도메인 검증
|
|
→ 신규: status=PENDING으로 등록, JWT 발급
|
|
→ 기존: JWT 발급
|
|
|
|
2단계: 관리자 승인
|
|
PENDING → /pending 페이지 표시 ("승인 대기 중")
|
|
관리자 → /admin/users에서 승인/거절
|
|
승인 → status=ACTIVE, 롤 그룹 배정
|
|
|
|
3단계: 롤 기반 URL 접근 제어
|
|
ACTIVE → 사이드바에 접근 가능한 메뉴만 표시
|
|
라우트 가드: 사용자 롤의 urlPatterns와 현재 경로 매칭
|
|
```
|
|
|
|
- Google OAuth2 Client ID: `295080817934-1uqaqrkup9jnslajkl1ngpee7gm249fv.apps.googleusercontent.com`
|
|
- 사용자 상태: PENDING → ACTIVE / REJECTED / DISABLED
|
|
- 초기 관리자: htlee@gcsc.co.kr (auto-approve, isAdmin=true)
|
|
|
|
## 라우팅 구조
|
|
|
|
```
|
|
/login → LoginPage (공개)
|
|
/pending → PendingPage (PENDING 사용자)
|
|
/denied → DeniedPage (REJECTED/DISABLED)
|
|
/ → HomePage (ACTIVE, 퀵링크 카드)
|
|
/dev/:section → GuidePage → 콘텐츠 컴포넌트 (ACTIVE, 롤 기반)
|
|
/admin/users → UserManagement (ADMIN만)
|
|
/admin/roles → RoleManagement (ADMIN만)
|
|
/admin/permissions → PermissionManagement (ADMIN만)
|
|
/admin/stats → StatsPage (ADMIN만)
|
|
```
|
|
|
|
## 프로젝트 구조
|
|
|
|
```
|
|
src/
|
|
├── auth/
|
|
│ ├── AuthProvider.tsx ✅ (Google OAuth → JWT 인증 컨텍스트)
|
|
│ ├── useAuth.ts ✅ (인증 훅)
|
|
│ ├── ProtectedRoute.tsx ✅ (인증+상태 가드)
|
|
│ └── AdminRoute.tsx ✅ (관리자 가드)
|
|
├── components/
|
|
│ ├── layout/
|
|
│ │ └── AppLayout.tsx ✅ (사이드바 + 메인 콘텐츠)
|
|
│ └── common/ ⬜ (CodeBlock, Alert, StepGuide, CopyButton)
|
|
├── pages/
|
|
│ ├── LoginPage.tsx ✅
|
|
│ ├── PendingPage.tsx ✅
|
|
│ ├── DeniedPage.tsx ✅
|
|
│ ├── HomePage.tsx ✅ (퀵링크 카드)
|
|
│ ├── GuidePage.tsx ✅ (section 기반 동적 렌더링 뼈대)
|
|
│ └── admin/ ⬜ (UserManagement, RoleManagement 등)
|
|
├── content/ ⬜ (7개 가이드 TSX)
|
|
├── hooks/ ⬜ (useTheme, useScrollSpy)
|
|
├── types/index.ts ✅ (User, Role, AuthResponse, NavItem, Issue)
|
|
├── utils/
|
|
│ ├── api.ts ✅ (fetch 래퍼 + 401 자동 리다이렉트)
|
|
│ └── navigation.ts ✅ (메뉴 구성 + ant-style 패턴 매칭)
|
|
├── App.tsx ✅ (BrowserRouter + Routes)
|
|
├── main.tsx ✅
|
|
└── index.css ✅ (Tailwind CSS)
|
|
```
|
|
|
|
## 백엔드 API (gc-guide-api) 엔드포인트
|
|
|
|
프론트엔드에서 호출하는 API 목록:
|
|
|
|
```
|
|
POST /api/auth/google → { idToken } → { token, user }
|
|
GET /api/auth/me → User (JWT Authorization 헤더)
|
|
POST /api/auth/logout → void
|
|
|
|
GET /api/admin/users → User[] (ADMIN만)
|
|
PUT /api/admin/users/:id/approve → User
|
|
PUT /api/admin/users/:id/reject → User
|
|
PUT /api/admin/users/:id/disable → User
|
|
PUT /api/admin/users/:id/roles → { roleIds: number[] } → User
|
|
|
|
GET /api/admin/roles → Role[]
|
|
POST /api/admin/roles → { name, description } → Role
|
|
PUT /api/admin/roles/:id → { name, description } → Role
|
|
DELETE /api/admin/roles/:id → void
|
|
|
|
GET /api/admin/roles/:id/permissions → { urlPatterns: string[] }
|
|
POST /api/admin/roles/:id/permissions → { urlPattern: string }
|
|
DELETE /api/admin/permissions/:id → void
|
|
|
|
GET /api/admin/stats → { totalUsers, activeUsers, ... }
|
|
|
|
POST /api/activity/track → { pagePath } → void
|
|
GET /api/activity/login-history → LoginHistory[]
|
|
```
|
|
|
|
## UI 스타일 가이드
|
|
- Tailwind CSS v4 (index.css에 `@import "tailwindcss"`)
|
|
- 사이드바: 좌측 고정 w-64, 흰색 배경
|
|
- 활성 메뉴: bg-blue-50, text-blue-700
|
|
- 카드: bg-white, border, rounded-xl, hover shadow
|
|
- 반응형: 추후 모바일 대응 (사이드바 접힘)
|
|
- 코드 블록: highlight.js 테마 (atom-one-dark 권장)
|