그누보드5 → Laravel 레시피
# 그누보드5 - Laravel 레시피
## 프로젝트 개요
그누보드5를 Laravel 13.x 기반으로 완전히 재구축하는 프로젝트입니다. 기존 그누보드5 DB 스키마를 100% 유지하면서, Laravel의 Eloquent ORM, Blade 템플릿, 라우팅, 미들웨어 등 모던 PHP 프레임워크의 장점을 활용합니다. 기존 그누보드5 사이트의 DB를 그대로 연결하면 즉시 사용 가능한 것이 핵심입니다.
---
## 그누보드5 분석
### 핵심 DB 테이블 구조
| 테이블 | 용도 | 특이사항 |
|--------|------|----------|
| `g5_config` | 사이트 전체 설정 | 단일 레코드, cf_* 필드 수백 개 |
| `g5_member` | 회원 테이블 | Laravel users 대체, mb_id가 PK 역할 |
| `g5_group` | 게시판 그룹 | gr_id(string) PK |
| `g5_board` | 게시판 설정 | bo_table(string) PK, 권한/포인트/스킨 등 |
| `g5_write_{bo_table}` | 게시글/댓글 | **게시판마다 동적 테이블 생성** |
| `g5_board_file` | 첨부파일 | (bo_table, wr_id, bf_no) 복합 PK |
| `g5_point` | 포인트 내역 | 포인트 적립/차감 로그 |
| `g5_memo` | 쪽지 | 회원 간 1:1 메시지 |
| `g5_scrap` | 스크랩 | 게시글 스크랩 |
| `g5_board_good` | 추천/비추천 | 중복 추천 방지 |
| `g5_board_new` | 새글 알림 | 최근 게시글 목록 |
| `g5_login` | 로그인 기록 | 접속 통계 |
| `g5_visit` | 방문자 통계 | 일별 방문자 |
| `g5_popular` | 인기 검색어 | 검색어 통계 |
| `g5_auth` | 관리 권한 | 개별 게시판 관리 권한 |
| `g5_uniqid` | 고유 ID | 세션/토큰 관리 |
| `g5_cert_history` | 본인인증 이력 | 휴대폰/아이핀 인증 |
| `g5_faq_master` | FAQ 분류 | FAQ 카테고리 |
| `g5_faq` | FAQ 내용 | 질문/답변 |
| `g5_content` | 내용 관리 | 정적 페이지 (이용약관 등) |
| `g5_mail` | 메일 발송 | 회원 대상 메일 |
| `g5_poll` | 설문조사 | 투표 기능 |
| `g5_poll_etc` | 설문 기타 | 기타 의견 |
### 그누보드5 핵심 메커니즘
#### 1. 동적 게시판 테이블 (`g5_write_{bo_table}`)
```
게시판 생성 시 → CREATE TABLE g5_write_{bo_table} (...)
게시판 삭제 시 → DROP TABLE g5_write_{bo_table}
```
- 게시판마다 독립 테이블 생성 (수백 개 가능)
- 게시글(wr_is_comment=0)과 댓글(wr_is_comment=1)이 같은 테이블
- wr_1 ~ wr_10 여분 필드 (사용자 확장용)
#### 2. 답글 체인 구조
```
원글: wr_num=-100, wr_reply=''
├─ 답글1: wr_num=-100, wr_reply='A'
│ └─ 답답글: wr_num=-100, wr_reply='AA'
├─ 답글2: wr_num=-100, wr_reply='B'
```
- `wr_num`: 음수, 같은 스레드는 같은 번호
- `wr_reply`: A-Z 문자열, 깊이마다 1글자 추가 (최대 10단계)
- 정렬: `ORDER BY wr_num, wr_reply` (시간 역순 + 답글 순서)
#### 3. 댓글 구조
```
게시글: wr_id=1, wr_is_comment=0, wr_parent=1
├─ 댓글1: wr_id=2, wr_is_comment=1, wr_parent=1, wr_comment=1
│ └─ 대댓글: wr_id=3, wr_is_comment=1, wr_parent=1, wr_comment=1, wr_comment_reply='A'
├─ 댓글2: wr_id=4, wr_is_comment=1, wr_parent=1, wr_comment=2
```
#### 4. 권한 시스템
```
회원 레벨: mb_level (1~10, 10=최고관리자)
게시판별 권한: bo_list_level, bo_read_level, bo_write_level, bo_reply_level, bo_comment_level
게시판별 업/다운로드: bo_upload_level, bo_download_level
비회원 허용: level 1 (비로그인도 가능)
```
#### 5. 포인트 시스템
```
게시글 작성: +bo_write_point
댓글 작성: +bo_comment_point
글 읽기: -bo_read_point (읽는 사람이 차감)
파일 다운로드: -bo_download_point
```
#### 6. 비밀번호 해싱 (4가지 호환)
```
- sha256:iterations:salt:hash (PBKDF2, 그누보드5 최신)
- bcrypt ($2y$, $2a$)
- MySQL PASSWORD() (41자, * 시작)
- md5 (32자 hex, 그누보드4 호환)
```
---
## 필수 기능
### 프론트엔드
- **회원 시스템**: 가입/로그인/로그아웃/정보수정/비밀번호변경
- **게시판 목록**: 글 목록, 페이지네이션, 카테고리, 검색
- **게시판 읽기**: 글 보기, 조회수, 추천/비추천, 첨부파일 다운로드
- **게시판 쓰기**: 글쓰기/수정/삭제, 답글, WYSIWYG 에디터, 파일첨부
- **댓글**: 댓글/대댓글 작성/수정/삭제
- **쪽지**: 발신/수신/읽기/삭제
- **스크랩**: 게시글 스크랩/해제
- **포인트**: 자동 적립/차감, 포인트 내역 조회
- **새글 알림**: 새 게시글 표시
### 관리자 패널
- **대시보드**: 통계 (회원수, 게시글수, 방문자수, 포인트)
- **사이트 설정**: g5_config 전체 필드 관리 (탭 방식)
- **회원 관리**: 목록/검색/수정/삭제/레벨변경/차단
- **게시판 관리**: 생성/수정/삭제/복사, 동적 테이블 생성
- **그룹 관리**: 게시판 그룹 CRUD
- **포인트 관리**: 포인트 내역 조회/수동 지급
- **FAQ 관리**: FAQ 분류 및 내용 CRUD
- **내용 관리**: 정적 페이지 (이용약관, 개인정보처리방침 등)
- **방문자 통계**: 일별/월별 방문자 현황
- **인기 검색어**: 검색어 통계
- **메일 발송**: 회원 대상 일괄 메일
### 보너스 기능
- 소셜 로그인 (카카오, 네이버, 구글)
- 본인인증 (휴대폰, 아이핀)
- 1:1 문의 게시판
- 다크 모드 지원
- SEO 최적화 (wr_seo_title 활용)
- 이미지 리사이즈 및 썸네일 생성
- 스팸 방지 (캡차, 글쓰기 간격 제한)
- 실시간 알림 (WebSocket)
- PWA 지원
---
## 기술 스택
| 영역 | 기술 |
|------|------|
| **Backend** | Laravel 13.x, PHP 8.3+ |
| **Database** | MySQL 8.0+ / MariaDB 10.3+ (utf8mb3) |
| **Frontend** | Blade + Tailwind CSS 4.0 + DaisyUI 5.x |
| **빌드 도구** | Vite |
| **에디터** | CKEditor 5 |
| **인증** | Custom Auth Provider (g5_member 호환) |
| **캐싱** | Laravel Cache (Redis/File) |
| **테스트** | PHPUnit / Pest |
---
## 제약 조건
- 그누보드5 DB 스키마 100% 호환 (기존 DB 연결 시 즉시 사용)
- `g5_member` 테이블을 Laravel `users` 대신 사용
- 비밀번호 4종 해싱 호환 (PBKDF2, bcrypt, PASSWORD(), md5)
- charset: utf8mb3, collation: utf8mb3_uca1400_ai_ci
- wr_1~wr_10 여분 필드를 하드코딩하지 않음
- 에디터 업로드 파일은 `data/` 디렉토리에 저장, 라우트로 서빙
- basic 테마만 수정 (flowbite 테마 수정 금지)
- 게시판 스킨은 basic만 수정
- RESTful 라우팅: `/boards/{bo_table}/{wr_id}`
- Service Layer 패턴 적용
- N+1 쿼리 방지 (Eager Loading)
- Laravel Pint 코드 스타일
---
## 프롬프트 레시피 (12단계)
---
### Step 1: 프로젝트 초기 설정 및 DB 연결
**목표**: Laravel 프로젝트 생성, 그누보드5 DB 연결, 기본 설정
**프롬프트**:
```
Laravel 13.x 프로젝트를 생성하고 그누보드5 데이터베이스에 연결하는 초기 설정을 해줘.
요구사항:
1. Laravel 프로젝트 생성 (composer create-project)
2. .env 설정:
- DB_CONNECTION=mysql
- DB_CHARSET=utf8mb3
- DB_COLLATION=utf8mb3_uca1400_ai_ci
- APP_THEME=basic (커스텀 환경변수)
3. config/database.php에서 charset/collation을 env()로 읽도록 수정
4. Laravel 기본 마이그레이션 실행 (sessions, cache, jobs 테이블만)
- users 테이블 마이그레이션은 삭제 (g5_member 사용)
5. Tailwind CSS 4.0 + DaisyUI 5.x + Vite 설정
6. package.json에 concurrently 추가 (dev 스크립트)
7. CLAUDE.md 파일 생성 (프로젝트 규칙 정의)
제약사항:
- 그누보드5 기존 테이블에 대한 마이그레이션은 만들지 않음
- 기존 DB를 그대로 사용하는 것이 원칙
```
---
### Step 2: Eloquent 모델 및 인증 시스템
**목표**: 그누보드5 테이블에 대응하는 Eloquent 모델 생성, 커스텀 인증
**프롬프트**:
```
그누보드5 DB 테이블에 대응하는 Eloquent 모델과 커스텀 인증 시스템을 구현해줘.
모델 목록 (app/Models/G5/ 디렉토리):
1. Config.php - g5_config 테이블
- cf_id PK, 단일 레코드
- 캐시: Cache::remember('g5_config', 300, ...)
- 정적 메서드: instance(), val(key, default), clearCache()
2. Member.php - g5_member 테이블 (extends Authenticatable)
- mb_no PK (auto_increment), mb_id (unique, 인증 식별자)
- isAdmin() → mb_level >= 10
- isBanned() → mb_intercept_date 확인
- isLeft() → mb_leave_date 확인
3. Group.php - g5_group 테이블
- gr_id(string) PK
- hasMany(Board)
4. Board.php - g5_board 테이블
- bo_table(string) PK
- belongsTo(Group), 동적 write 테이블 접근
- getWriteTableName() → 'g5_write_{bo_table}'
5. Write.php - g5_write_{bo_table} 동적 테이블
- 핵심: setBoTable(), forBoard() 팩토리 메서드
- Scopes: posts(), commentsOf($wrId), ordered()
- isPost(), isComment(), isReply(), isSecret()
6. BoardFile.php - g5_board_file 테이블
- 복합키: (bo_table, wr_id, bf_no)
7. Point.php - g5_point 테이블
8. Memo.php - g5_memo 테이블
9. Scrap.php - g5_scrap 테이블
10. BoardGood.php - g5_board_good 테이블
11. BoardNew.php - g5_board_new 테이블
인증 시스템:
1. G5PasswordService.php - 4종 해싱 호환
- check(password, hash): sha256/bcrypt/PASSWORD()/md5 자동 감지
- hash(password): PBKDF2 SHA256 (iterations:12000)
2. G5UserProvider.php - Laravel UserProvider 구현
- retrieveById → mb_id로 조회
- validateCredentials → G5PasswordService 사용
3. config/auth.php 설정
- provider: g5_members (driver: g5)
4. AppServiceProvider에서 Auth::provider('g5', ...) 등록
제약사항:
- timestamps = false (그누보드5는 *_datetime 필드 직접 관리)
- incrementing 설정 주의 (bo_table, gr_id는 string PK)
- Write 모델은 테이블명이 동적이므로 특별 처리 필요
```
---
### Step 3: 테마 시스템 및 레이아웃
**목표**: 테마 전환 시스템, 기본 레이아웃, 네비게이션
**프롬프트**:
```
그누보드5 스타일의 테마 시스템과 basic 테마의 기본 레이아웃을 구현해줘.
테마 시스템:
1. AppServiceProvider에서 테마 뷰 경로 설정
- config('app.theme') 또는 env('APP_THEME', 'basic')
- View::prependNamespace로 테마 경로 우선
- 폴백: basic 테마
2. View Composer로 전체 레이아웃에 게시판 목록 공유
디렉토리 구조:
resources/views/themes/basic/
├── layouts/
│ └── app.blade.php # 메인 레이아웃
├── home.blade.php # 홈페이지
├── auth/
│ ├── login.blade.php
│ └── register.blade.php
└── boards/
└── basic/ # 기본 게시판 스킨
├── index.blade.php
├── show.blade.php
└── create.blade.php
레이아웃 요구사항 (DaisyUI 기반):
1. app.blade.php:
- 반응형 네비게이션 바 (navbar 컴포넌트)
- 사이드바 또는 드롭다운으로 게시판 목록
- 로그인/회원가입 또는 회원정보/로그아웃 표시
- 다크모드 토글 (data-theme)
- Flash 메시지 표시 (toast)
- 푸터
2. home.blade.php:
- 게시판 그리드 (card 컴포넌트)
- 각 게시판 최신글 미리보기
스타일링:
- Tailwind CSS 4.0 + DaisyUI 5.x
- 모바일 퍼스트 반응형
- 접근성 고려 (ARIA 라벨)
```
---
### Step 4: 회원 기능 (가입/로그인/정보수정)
**목표**: 회원가입, 로그인, 로그아웃, 회원정보 수정, 비밀번호 변경
**프롬프트**:
```
그누보드5 호환 회원 시스템의 프론트엔드 기능을 구현해줘.
라우트:
GET /login → AuthController@loginForm
POST /login → AuthController@login
GET /register → AuthController@registerForm
POST /register → AuthController@register
POST /logout → AuthController@logout
GET /member/profile → MemberController@profile
PUT /member/profile → MemberController@updateProfile
GET /member/password → MemberController@passwordForm
PUT /member/password → MemberController@updatePassword
회원가입 (AuthController@register):
1. 유효성 검사:
- mb_id: 3~20자, 영문+숫자+밑줄, unique in g5_member
- mb_nick: 2~20자, unique, mb_nick_date 체크 (닉네임 변경 제한)
- mb_email: 이메일 형식, unique
- mb_password: 최소 4자, 확인 일치
2. G5PasswordService::hash()로 비밀번호 해싱
3. mb_level = 2 (기본 회원), mb_datetime = now()
4. 자동 로그인 후 리다이렉트
로그인 (AuthController@login):
1. mb_id + mb_password로 인증
2. 차단 회원(mb_intercept_date) 체크
3. 탈퇴 회원(mb_leave_date) 체크
4. mb_today_login, mb_login_ip 업데이트
5. 세션 재생성
회원정보 수정 (MemberController@updateProfile):
1. 수정 가능: mb_nick, mb_email, mb_homepage, mb_tel, mb_hp, mb_zip*, mb_addr*, mb_signature
2. mb_nick 변경 시 mb_nick_date 체크 (일정 기간 제한)
3. mb_open (정보공개 여부)
비밀번호 변경 (MemberController@updatePassword):
1. 현재 비밀번호 확인 (G5PasswordService::check)
2. 새 비밀번호 해싱 후 저장
뷰:
- DaisyUI form 컴포넌트 사용
- 실시간 유효성 검사 (Alpine.js 또는 Blade)
- 에러 메시지 한글화
```
---
### Step 5: 게시판 핵심 기능 (목록/읽기/쓰기)
**목표**: 게시판 CRUD의 핵심 기능 구현
**프롬프트**:
```
그누보드5 호환 게시판의 핵심 CRUD 기능을 구현해줘.
라우트:
GET /boards/{boTable} → BoardController@index (목록)
GET /boards/{boTable}/write → BoardController@create (글쓰기 폼)
POST /boards/{boTable}/write → BoardController@store (글 저장)
GET /boards/{boTable}/{wrId} → BoardController@show (글 보기)
GET /boards/{boTable}/{wrId}/edit → BoardController@edit (수정 폼)
PUT /boards/{boTable}/{wrId} → BoardController@update (글 수정)
DELETE /boards/{boTable}/{wrId} → BoardController@destroy (글 삭제)
목록 (index):
1. 권한 체크: bo_list_level vs mb_level
2. Write::forBoard($boTable)->posts()->ordered()->paginate(bo_page_rows)
3. 공지사항: bo_notice (쉼표 구분 wr_id) 상단 고정
4. 카테고리: bo_use_category=1이면 bo_category_list (파이프 구분) 필터
5. 검색: wr_subject, wr_content, wr_name, mb_id 검색
6. 글번호 계산: bo_count_write - (page-1)*per_page - index (역순 표시)
7. 비밀글 표시: wr_option에 'secret' 포함 시 제목 마스킹
글보기 (show):
1. 권한 체크: bo_read_level vs mb_level
2. 비밀글 체크: 작성자/관리자만 열람
3. 조회수 증가: 세션 기반 중복 방지 (session key: 'board_{bo_table}_read_{wr_id}')
4. 이전글/다음글 링크
5. 첨부파일 목록 (BoardFile)
6. 댓글 목록
7. 추천/비추천 버튼
글쓰기/수정 (create/edit → store/update):
1. 권한 체크: bo_write_level (신규), 작성자/관리자 (수정)
2. 유효성: wr_subject(필수), wr_content(필수), 글자수 제한(bo_write_min/max)
3. CKEditor 5 WYSIWYG 에디터
4. wr_option: html1 체크박스 (HTML 사용)
5. 카테고리 선택 (bo_use_category=1)
6. 링크 입력 (wr_link1, wr_link2)
7. 비밀글 체크 (bo_use_secret)
8. 파일 첨부 (bo_upload_count만큼 슬롯)
글 저장 로직 (store):
1. wr_num: MIN(wr_num) - 1 (음수, 최신글이 가장 작은 음수)
2. wr_parent: 자기 자신의 wr_id
3. mb_id, wr_name, wr_email, wr_ip 자동 설정
4. wr_datetime, wr_last = now()
5. bo_count_write 증가
글 삭제 로직 (destroy):
1. 권한: 작성자 또는 관리자
2. 답글 전체 삭제 (wr_reply LIKE '{parent_reply}%')
3. 댓글 전체 삭제 (wr_is_comment=1 AND wr_parent=wr_id)
4. 첨부파일 물리 삭제 + DB 삭제
5. bo_count_write, bo_count_comment 감소
스킨 시스템:
- BoardController에서 skinView() 헬퍼로 스킨별 뷰 로드
- Board.bo_skin → resources/views/themes/basic/boards/{skin}/
- 폴백: basic 스킨
```
---
### Step 6: 답글/댓글 및 파일 첨부
**목표**: 답글, 댓글/대댓글, 파일 업로드/다운로드
**프롬프트**:
```
게시판의 답글, 댓글, 파일 첨부 기능을 구현해줘.
답글 시스템:
라우트: GET /boards/{boTable}/write?wr_id={parentId} (답글 쓰기)
1. 원글의 wr_num 공유 (같은 스레드)
2. wr_reply 계산:
- 부모의 wr_reply + 다음 문자 (A → B → ... → Z)
- 같은 부모의 마지막 답글 wr_reply를 찾아서 +1
- 이미 Z이면 더 이상 답글 불가 (깊이/수 제한)
3. wr_parent는 원글의 wr_id
4. 답글 권한: bo_reply_level
댓글/대댓글 시스템:
라우트:
POST /boards/{boTable}/{wrId}/comment → 댓글 작성
PUT /boards/{boTable}/{wrId}/comment/{cmtId} → 댓글 수정
DELETE /boards/{boTable}/{wrId}/comment/{cmtId} → 댓글 삭제
1. 댓글 저장:
- wr_is_comment = 1
- wr_parent = 원글 wr_id
- wr_comment = 순번 (기존 최대값 + 1)
- wr_num = 원글의 wr_num
- bo_comment_min/max 글자수 체크
- 비밀댓글: wr_option = 'secret'
2. 대댓글:
- wr_comment_reply로 깊이 표현 (A, AA, AB...)
- 부모 댓글의 wr_comment 공유
3. 댓글 삭제: 대댓글 존재 시 내용만 삭제 ("삭제된 댓글입니다")
4. 포인트: bo_comment_point 적립/차감
파일 첨부:
라우트:
POST /ckeditor/upload → 에디터 이미지 업로드
POST /ckeditor/upload-drop → 드래그 앤 드롭 업로드
GET /data/{path} → 파일 서빙
GET /boards/{boTable}/{wrId}/download/{bfNo} → 파일 다운로드
1. 게시판 첨부파일:
- bo_upload_count만큼 파일 슬롯
- bo_upload_size 제한
- 저장 경로: data/file/{boTable}/{timestamp}_{random}.ext
- g5_board_file 레코드 생성 (bo_table, wr_id, bf_no)
- 이미지: bf_type=1, bf_width/bf_height 자동 감지
- 파일 삭제/교체: bf_delete[] 배열 처리
- 파일 순서: bf_order[] 배열 처리
2. 에디터 이미지:
- 저장 경로: data/editor/{YYYYMM}/{timestamp}_{random}.ext
- 이미지만 허용 (jpeg, png, gif, svg, webp)
- CKEditor JSON 응답: {uploaded:1, url:'...'}
3. 파일 서빙:
- data/ 디렉토리 파일을 라우트로 서빙
- 경로 탐색(path traversal) 보안 체크
4. 다운로드:
- bf_download 카운터 증가
- bo_download_level 권한 체크
- bo_download_point 포인트 차감
```
---
### Step 7: 추천/비추천, 스크랩, 새글
**목표**: 추천/비추천 중복 방지, 스크랩, 새글 알림
**프롬프트**:
```
추천/비추천, 스크랩, 새글 알림 기능을 구현해줘.
추천/비추천 (BoardGood 모델):
라우트:
POST /boards/{boTable}/{wrId}/good → 추천
POST /boards/{boTable}/{wrId}/nogood → 비추천
1. g5_board_good 테이블로 중복 체크:
- bo_table + wr_id + mb_id 조합이 존재하면 "이미 추천/비추천 했습니다"
- bg_flag: 'good' 또는 'nogood'
2. 본인 글 추천 방지
3. bo_use_good, bo_use_nogood 설정 체크
4. Write의 wr_good, wr_nogood 카운터 증가
5. AJAX 응답 (JSON): {count: 새로운 추천수}
스크랩 (Scrap 모델):
라우트:
POST /boards/{boTable}/{wrId}/scrap → 스크랩 추가
DELETE /member/scrap/{scId} → 스크랩 삭제
GET /member/scrap → 스크랩 목록
1. g5_scrap 테이블:
- mb_id, bo_table, wr_id, sc_datetime
2. 중복 스크랩 방지
3. 스크랩 목록: 게시글 제목, 게시판명, 날짜
새글 알림 (BoardNew 모델):
1. g5_board_new 테이블:
- bo_table, wr_id, wr_parent, bn_datetime, mb_id
2. 게시글/댓글 작성 시 자동 등록
3. 네비게이션에 새글 카운트 표시
4. 새글 목록 페이지:
GET /member/new → 최근 새글 목록 (24시간 이내)
5. 읽음 처리: 글 조회 시 해당 레코드 삭제
```
---
### Step 8: 포인트 시스템
**목표**: 포인트 자동 적립/차감, 내역 조회, 관리
**프롬프트**:
```
그누보드5 호환 포인트 시스템을 구현해줘.
PointService (app/Services/PointService.php):
1. insert(mb_id, point, content, rel_table, rel_id, rel_action):
- g5_point 레코드 생성
- g5_member.mb_point 업데이트
- 이미 지급된 포인트 중복 체크 (rel_table + rel_id + rel_action)
- 음수 포인트 시 잔액 체크 (cf_use_point 설정에 따라)
2. delete(mb_id, rel_table, rel_id, rel_action):
- 기존 포인트 레코드 찾아서 반대 포인트 지급
- 글 삭제 시 기존 적립 포인트 회수
자동 적용 시점:
- 글 작성: +bo_write_point (rel_action: 'write')
- 댓글 작성: +bo_comment_point (rel_action: 'comment')
- 글 읽기: -bo_read_point (rel_action: 'read', 읽는 사람에게)
- 파일 다운로드: -bo_download_point (rel_action: 'download')
- 회원가입: +cf_register_point
- 로그인: +cf_login_point (1일 1회)
- 글/댓글 삭제: 기존 포인트 회수
포인트 내역 조회:
라우트: GET /member/point → 포인트 내역 목록
- 페이지네이션
- 적립/차감 구분 표시
- 잔액 표시
관리자 포인트 관리:
라우트: GET /admin/points → 전체 포인트 내역
- 회원별 검색
- 수동 포인트 지급/차감
```
---
### Step 9: 쪽지 및 부가 기능
**목표**: 쪽지 시스템, FAQ, 내용 관리(정적 페이지)
**프롬프트**:
```
쪽지, FAQ, 내용 관리 기능을 구현해줘.
쪽지 (Memo 모델):
라우트:
GET /member/memo → 받은쪽지 목록
GET /member/memo/sent → 보낸쪽지 목록
GET /member/memo/{meNo} → 쪽지 읽기
GET /member/memo/write → 쪽지 쓰기 폼
POST /member/memo/write → 쪽지 발송
DELETE /member/memo/{meNo} → 쪽지 삭제
1. g5_memo 테이블:
- me_no PK, me_recv_mb_id, me_send_mb_id
- me_memo (내용), me_send_datetime, me_read_datetime
- me_type: recv(수신), send(발신)
2. 발송 시 recv, send 2개 레코드 생성
3. 읽음 처리: me_read_datetime 업데이트
4. 네비게이션에 안읽은 쪽지 수 표시
FAQ (FaqMaster + Faq 모델):
라우트:
GET /faq → FAQ 목록 (카테고리별)
GET /faq/{fmId} → FAQ 상세 (아코디언)
관리자:
GET /admin/faq → FAQ 분류 목록
POST /admin/faq → FAQ 분류 생성
PUT /admin/faq/{fmId} → FAQ 분류 수정
DELETE /admin/faq/{fmId} → FAQ 분류 삭제
POST /admin/faq/{fmId}/item → FAQ 항목 추가
PUT /admin/faq/item/{faId} → FAQ 항목 수정
DELETE /admin/faq/item/{faId} → FAQ 항목 삭제
내용 관리 (Content 모델):
라우트:
GET /content/{coId} → 내용 페이지 표시
관리자:
GET /admin/content → 내용 목록
POST /admin/content → 내용 생성
GET /admin/content/{coId}/edit → 내용 수정 폼
PUT /admin/content/{coId} → 내용 저장
DELETE /admin/content/{coId} → 내용 삭제
1. g5_content 테이블:
- co_id(string) PK: 'company', 'privacy', 'provision' 등
- co_html: 0(텍스트), 1(HTML), 2(PHP - 미지원)
- co_subject, co_content, co_mobile_content
2. 기본 내용: 이용약관(provision), 개인정보처리방침(privacy), 회사소개(company)
3. CKEditor로 내용 편집
```
---
### Step 10: 관리자 패널
**목표**: 대시보드, 사이트 설정, 회원/게시판/그룹 관리
**프롬프트**:
```
그누보드5 호환 관리자 패널을 구현해줘.
미들웨어:
- AdminMiddleware: auth 체크 + mb_level >= 10
레이아웃:
- resources/views/admin/layout.blade.php
- DaisyUI drawer + sidebar 네비게이션
- 메뉴: 대시보드, 환경설정, 회원관리, 게시판관리, 그룹관리, 포인트관리, FAQ관리, 내용관리, 방문자통계
대시보드 (Admin\DashboardController):
GET /admin
- 통계 카드: 오늘 가입자, 전체 회원수, 전체 게시판수, 오늘 게시글수
- 최근 가입 회원 5명
- 최근 게시글 10개
- 방문자 차트 (최근 7일)
사이트 설정 (Admin\ConfigController):
GET /admin/config?tab=basic
PUT /admin/config
- 탭 구성:
- 기본: cf_title, cf_admin, cf_admin_email, cf_use_point, cf_page_rows 등
- 게시판: cf_editor, cf_image_extension, cf_flash_extension, cf_write_pages 등
- 회원: cf_use_email_certify, cf_register_level, cf_register_point, cf_login_point 등
- 메일: cf_email_use, cf_email_ho, cf_admin_email_name 등
- 토글 필드는 0/1로 변환
- 저장 후 캐시 무효화
회원 관리 (Admin\MemberController):
GET /admin/members → 회원 목록 (검색, 레벨 필터, 페이지네이션)
GET /admin/members/{mbId}/edit → 회원 수정 폼
PUT /admin/members/{mbId} → 회원 정보 수정 (레벨, 차단, 포인트 등)
DELETE /admin/members/{mbId} → 회원 삭제 (mb_leave_date 설정)
게시판 관리 (Admin\BoardAdminController):
GET /admin/boards → 게시판 목록
GET /admin/boards/create → 게시판 생성 폼
POST /admin/boards → 게시판 생성
GET /admin/boards/{boTable}/edit → 게시판 수정 폼
PUT /admin/boards/{boTable} → 게시판 수정
DELETE /admin/boards/{boTable} → 게시판 삭제 (테이블 DROP)
POST /admin/boards/{boTable}/recount → 게시물 수 재계산
게시판 생성 시:
1. g5_board 레코드 생성
2. g5_write_{bo_table} 테이블 동적 생성:
- Schema::create로 전체 필드 (wr_id ~ wr_10)
- charset: utf8mb3
- 인덱스: (wr_num, wr_reply), (wr_is_comment, wr_id)
게시판 수정 폼 필드:
- 기본: bo_subject, gr_id, bo_skin, bo_mobile_skin
- 권한: bo_list/read/write/reply/comment/upload/download_level
- 포인트: bo_read/write/comment/download_point
- 기능: bo_use_category, bo_category_list, bo_use_secret, bo_use_good, bo_use_nogood
- 제한: bo_page_rows, bo_upload_size, bo_upload_count, bo_write_min/max, bo_comment_min/max
- 공지: bo_notice
그룹 관리 (Admin\GroupController):
GET /admin/groups → 그룹 목록
POST /admin/groups → 그룹 생성
PUT /admin/groups/{grId} → 그룹 수정
DELETE /admin/groups/{grId} → 그룹 삭제 (하위 게시판 존재 시 불가)
```
---
### Step 11: 방문자 통계, 인기검색어, 검색
**목표**: 방문자 추적, 인기 검색어, 통합 검색
**프롬프트**:
```
방문자 통계, 인기검색어, 통합 검색 기능을 구현해줘.
방문자 통계 (Visit 모델 + Login 모델):
미들웨어: VisitMiddleware (모든 요청에 적용)
1. g5_visit 테이블:
- vi_id, vi_ip, vi_date, vi_time, vi_referer, vi_agent
- IP + 날짜 기준 중복 방지
2. g5_login 테이블 (로그인 회원):
- lo_id, mb_id, lo_ip, lo_datetime, lo_location, lo_url
관리자 통계 페이지:
GET /admin/visits
- 일별 방문자수 차트 (최근 30일)
- 월별 방문자수 테이블
- 오늘 방문자 목록
인기검색어 (Popular 모델):
1. g5_popular 테이블:
- pp_id, pp_word, pp_date
- 검색 시 자동 기록
2. 홈페이지/사이드바에 인기검색어 TOP 10 표시
3. 관리자: GET /admin/popular → 인기검색어 관리 (삭제)
통합 검색:
라우트: GET /search?q={keyword}&bo_table={optional}
1. 전체 게시판 또는 특정 게시판 검색
2. 검색 대상: wr_subject, wr_content, wr_name
3. 검색 결과: 게시판별 그룹화, 각 3~5건 미리보기
4. 검색어 g5_popular에 기록
5. 검색 필터: 기간, 게시판, 검색 대상 (제목/내용/작성자)
```
---
### Step 12: 테스트, 보안, 최적화 및 최종 완성
**목표**: 테스트 작성, 보안 점검, 성능 최적화, UI 마무리
**프롬프트**:
```
테스트, 보안 강화, 성능 최적화, UI 마무리를 진행해줘.
테스트 (PHPUnit / Pest):
1. Unit Tests:
- G5PasswordService: 4종 해싱 검증
- Write 모델: forBoard(), scopes
- PointService: 포인트 적립/차감/중복 체크
2. Feature Tests:
- 회원가입/로그인/로그아웃 흐름
- 게시판 CRUD (권한별)
- 댓글 작성/삭제
- 파일 업로드/다운로드
- 추천/비추천 중복 방지
- 관리자 접근 권한
3. 테스트 DB: SQLite in-memory 또는 별도 MySQL DB
보안:
1. XSS 방지: Blade {{ }} 자동 이스케이프, 에디터 콘텐츠는 {!! !!}로 표시하되 HTMLPurifier 적용
2. CSRF: Laravel 기본 @csrf
3. SQL Injection: Eloquent/Query Builder 사용 (raw query 지양)
4. 파일 업로드: MIME 타입 검증, 실행 파일 차단, 경로 탐색 방지
5. 비밀번호: PBKDF2 SHA256 (12000 iterations)
6. Rate Limiting: 로그인 시도 제한, 글쓰기 간격 제한 (bo_write_min)
7. 관리자 라우트: AdminMiddleware 보호
8. 비밀글: 작성자/관리자만 접근
성능 최적화:
1. N+1 방지: with() Eager Loading (boards.group, write.files 등)
2. Config 캐시: 300초 Cache::remember
3. 게시글 수 캐시: bo_count_write, bo_count_comment 활용
4. 인덱스 활용: wr_num+wr_reply 복합 인덱스
5. 페이지네이션: cursor pagination 검토 (대용량 게시판)
6. 이미지 최적화: 썸네일 생성, lazy loading
7. Vite 빌드 최적화: 코드 분할, 트리 쉐이킹
UI 마무리:
1. DaisyUI 컴포넌트 일관성 유지
2. 모바일 반응형 완벽 대응
3. 로딩 상태 표시 (스피너)
4. Toast 알림 (성공/에러)
5. 빈 상태 표시 (게시글 없음, 검색 결과 없음)
6. 접근성: ARIA 라벨, 키보드 네비게이션
7. SEO: meta tags, wr_seo_title, sitemap
8. Laravel Pint 코드 스타일 통일
```
---
## 그누보드5 → Laravel 매핑 참고표
| 그누보드5 파일 | Laravel 대응 |
|----------------------|-------------|
| `common.php` (전역 설정) | `AppServiceProvider`, `config/*.php` |
| `head.php` / `tail.php` | `layouts/app.blade.php` |
| `bbs/board.php` | `BoardController@index` |
| `bbs/write.php` | `BoardController@create/store` |
| `bbs/view.php` | `BoardController@show` |
| `bbs/delete.php` | `BoardController@destroy` |
| `bbs/comment_update.php` | `BoardController@commentStore` |
| `bbs/good.php` | `BoardController@good/nogood` |
| `bbs/download.php` | `BoardController@download` |
| `bbs/write_update.php` | `BoardController@store/update` |
| `adm/board_form.php` | `Admin\BoardAdminController` |
| `adm/config_form.php` | `Admin\ConfigController` |
| `adm/member_form.php` | `Admin\MemberController` |
| `lib/common.lib.php` | 각 Service 클래스 |
| `lib/board.lib.php` | `BoardService` (추후) |
| `lib/member.lib.php` | `Member` 모델 메서드 |
| `lib/point.lib.php` | `PointService` |
| `lib/get_data.lib.php` | Eloquent Query (View Composer) |
| `lib/thumbnail.lib.php` | 이미지 처리 서비스 |
| `skin/board/basic/` | `views/themes/basic/boards/basic/` |
| `theme/basic/` | `views/themes/basic/` |
| `g5_member` 직접 쿼리 | `Member::where(...)` |
| `sql_query()` | `DB::table()` / Eloquent |
| `$g5['path']` | `config()`, `env()` |
| `$config` (전역) | `Config::val('key')` |
| `$board` (전역) | Controller에서 `Board::find()` |
| `$member` (전역) | `auth()->user()` |
| `$is_admin` | `auth()->user()->isAdmin()` |
---
## 예상 소요 시간
| 단계 | 예상 시간 | 난이도 |
|------|----------|--------|
| Step 1: 프로젝트 초기 설정 | 30분 | ⭐ |
| Step 2: 모델 및 인증 | 1시간 | ⭐⭐⭐ |
| Step 3: 테마 및 레이아웃 | 45분 | ⭐⭐ |
| Step 4: 회원 기능 | 1시간 | ⭐⭐ |
| Step 5: 게시판 핵심 | 2시간 | ⭐⭐⭐⭐ |
| Step 6: 답글/댓글/파일 | 2시간 | ⭐⭐⭐⭐ |
| Step 7: 추천/스크랩/새글 | 1시간 | ⭐⭐ |
| Step 8: 포인트 시스템 | 1시간 | ⭐⭐⭐ |
| Step 9: 쪽지/FAQ/내용관리 | 1.5시간 | ⭐⭐ |
| Step 10: 관리자 패널 | 2시간 | ⭐⭐⭐ |
| Step 11: 통계/검색 | 1시간 | ⭐⭐ |
| Step 12: 테스트/보안/최적화 | 2시간 | ⭐⭐⭐ |
| **총합** | **약 16시간** | **고급** |
---
## 도구
- **AI 코딩**: Claude Code, Cursor, Windsurf
- **프레임워크**: Laravel 13.x
- **스타일링**: Tailwind CSS 4.0 + DaisyUI 5.x
- **에디터**: CKEditor 5
- **DB**: MySQL 8.0+ / MariaDB 10.3+
- **난이도**: 고급 PHP Laravel
---
## 핵심 주의사항
1. **기존 DB 100% 호환**: 그누보드5 DB를 그대로 연결하면 즉시 동작해야 함
2. **동적 테이블**: `g5_write_{bo_table}`은 게시판마다 별도 테이블 → Write 모델의 `setBoTable()` 필수
3. **비밀번호 호환**: 4종 해싱 자동 감지 (기존 회원 로그인 보장)
4. **charset**: utf8mb3 (utf8mb4 아님!) → 그누보드5 호환
5. **여분 필드**: wr_1~wr_10은 하드코딩 금지, 동적 처리
6. **wr_num 음수**: 최신글이 가장 작은 음수값 (정렬 핵심)
7. **wr_reply 문자열**: A-Z 순서 답글 체인 (그누보드5 고유 방식)
8. **포인트 중복 방지**: rel_table + rel_id + rel_action 조합으로 체크
9. **누락 테이블 대응**: 그누보드5 설치 상태에 따라 `g5_visit`, `g5_popular`, `g5_memo`, `g5_board_good`, `g5_board_new`, `g5_scrap`, `g5_faq_master`, `g5_faq`, `g5_content` 등이 없을 수 있음. 미들웨어·서비스에서 DB 오류 시 try/catch로 무시 처리하여 사이트가 멈추지 않도록 할 것. 필요하면 마이그레이션으로 테이블을 자동 생성하는 방식도 고려
이 레시피 대로 되는지 한번 해보겠습니다
댓글 3개
아래는 20% 작업중에 찍어본겁니다