Files
slot/docs/05-local-dev-setup.md
T
chpark 980d7d905d Add Next.js + PostgreSQL rewrite scaffold with 4-theme system
Stack
- Next.js 15 (App Router) + TypeScript + Drizzle ORM + postgres-js
- Node scrypt for password hashing; PBKDF2 verifier for legacy gnuboard5 hashes
- pnpm workspace monorepo: apps/web + packages/{db,auth,themes,...}

Themes (admin-selectable at /admin/themes)
- basic     : 그누보드 default reproduction (light, blue accent)
- eyoom     : eb4_maga_005 매거진 reproduction (dark, orange accent, ranking sidebar)
- amina     : Aminam Builder reproduction (light, violet gradient, card grid)
- youngcart : 영카트 shop reproduction (red accent, search bar, category nav)

DB
- New schema (12 tables) pushed to PG via drizzle-kit: members, sessions, boards,
  posts, point_ledger, app_settings, bacara_*, lottery_tickets, roulette_spins,
  game_points, board_groups
- Legacy data still readable from inspection2 schema via @slot/db/legacy

Verified end-to-end against the migrated DB on localhost:3000:
- Home renders with active theme tokens injected as CSS variables
- /free lists 442K real posts from inspection2.g5_write_free
- Login (testlogin/test1234) issues session cookie, header switches to
  "테스트님 환영합니다 / 로그아웃"
- Switching app_settings.theme.global from eyoom → amina swaps colors,
  layout, and Korean nav labels site-wide on next request

Migration docs added: 03-migration-plan, 04-theme-architecture,
05-local-dev-setup, 06-feature-inventory.
2026-04-27 18:51:32 +09:00

195 lines
7.2 KiB
Markdown

# Local Development Setup
## 0. 사전조건
- macOS / Linux
- **Docker Desktop** 실행 중
- **Homebrew** (PostgreSQL, pgloader 용)
- **Node.js 20+**, **pnpm** (신규 시스템 작업 시)
## 1. 원본 PHP 사이트 로컬 가동
```bash
# 0) 사전: Docker 데스크톱 실행 / 5432 PostgreSQL 사용 가능 / 33306 미사용
brew install postgresql@17 pgloader
brew services start postgresql@17
# 1) (한 번만) MariaDB 임시 컨테이너 띄우기
docker network create slot-net 2>/dev/null
docker run -d --name slot-mariadb \
--network slot-net \
-e MARIADB_ROOT_PASSWORD=rootpass \
-p 33306:3306 \
-v slot-mariadb-data:/var/lib/mysql \
--restart unless-stopped \
mariadb:10.5 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci \
--max-allowed-packet=512M \
--innodb-buffer-pool-size=1G
# 2) DB dump 복원 (db/inspection2.sql.gz, db/inspection.sql.gz 있어야 함)
docker cp db/inspection2.sql.gz slot-mariadb:/tmp/
docker cp db/inspection.sql.gz slot-mariadb:/tmp/
docker exec slot-mariadb sh -c "mariadb -uroot -prootpass -e 'CREATE DATABASE inspection2 DEFAULT CHARACTER SET utf8mb4; CREATE DATABASE inspection DEFAULT CHARACTER SET utf8mb4;'"
docker exec slot-mariadb sh -c "gunzip -c /tmp/inspection2.sql.gz | mariadb -uroot -prootpass --default-character-set=utf8mb4 inspection2"
docker exec slot-mariadb sh -c "gunzip -c /tmp/inspection.sql.gz | mariadb -uroot -prootpass --default-character-set=utf8mb4 inspection"
# 3) PHP + Apache + Redis 컨테이너 가동
cd docker && docker compose up -d
# 첫 실행 시 entrypoint 가 ~5분 정도 걸린다 (apt-get + composer install).
# 진행 상태: docker logs -f slot-php
# 4) 사이트 접속
open http://localhost:8088/
open http://localhost:8088/adm/ # 관리자 (admin 계정 OTP 필요)
```
### 1.1 테스트 계정 (로컬에서만 사용)
원본 dump 의 admin 비밀번호는 알 수 없으므로 로컬 검증용 계정을 만들어 사용:
```bash
# PBKDF2 해시 생성
docker exec slot-php php -r '
define("_GNUBOARD_", true);
include_once("/var/www/html/lib/pbkdf2.compat.php");
echo create_hash("test1234"); echo PHP_EOL;'
# 위 출력 해시를 변수에 담아 회원 추가 (level 10 = 일반회원, 12 = 최고관리자)
HASH='<위에서 출력된 해시>'
docker exec slot-mariadb mariadb -uroot -prootpass inspection2 -e "
INSERT IGNORE INTO g5_member
(mb_id, mb_password, mb_name, mb_nick, mb_email, mb_level, mb_datetime, mb_today_login, mb_open)
VALUES
('testlogin', '$HASH', '테스트', '테스트', 'test@local.test', 10, NOW(), NOW(), 1);"
```
이제 `testlogin` / `test1234` 로 로그인 가능. 관리자는 admin 계정 비밀번호를 PBKDF2 해시로 직접 update 후 로그인 (운영 OTP 가 활성화되어 있어 OTP 단계 통과 필요).
## 2. PostgreSQL 마이그레이션 (재실행)
```bash
# 빈 DB 생성
psql -h localhost -d postgres -c "
DROP DATABASE IF EXISTS slot;
CREATE DATABASE slot WITH ENCODING='UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE=template0;
DROP DATABASE IF EXISTS slot_legacy;
CREATE DATABASE slot_legacy WITH ENCODING='UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE=template0;"
# pgloader 실행
cd db
pgloader migrate_inspection2.load # ~6분, 165 테이블
pgloader migrate_inspection.load # ~10초
# 검증
psql -h localhost -d slot -c "
SELECT count(*) AS pg_tables, COALESCE(SUM(reltuples)::bigint,0) AS approx_rows
FROM pg_class c JOIN pg_namespace n ON c.relnamespace=n.oid
WHERE n.nspname='inspection2' AND c.relkind='r';"
```
## 3. 운영 서버에서 새 DB dump 가져오기 (옵션)
`scripts/refresh-db.sh` (예시):
```bash
#!/bin/bash
# 1) 원격에서 dump 생성
sshpass -p "$SSH_PASS" ssh -p 21693 root@103.31.14.207 'bash -s' < db/remote_dump.sh
# 2) 로컬로 복사
sshpass -p "$SSH_PASS" rsync -az -e 'ssh -p 21693' root@103.31.14.207:/tmp/slot_dbdump/ db/
# 3) 로컬 MariaDB 로 재복원 (위 1.2 단계 반복)
```
운영 서버 SSH 패스워드는 환경변수 `SSH_PASS` 로만 주입하고 저장소에는 두지 말 것.
## 4. 자주 쓰는 명령
```bash
# PHP 컨테이너 셸
docker exec -it slot-php bash
# Apache 에러 로그
docker logs slot-php 2>&1 | grep -iE "error|warn|fatal" | tail -30
# (php_errors.log 는 컨테이너 안 /var/log/apache2/php_errors.log 에 저장됨)
docker exec slot-php tail -f /var/log/apache2/php_errors.log
# MariaDB 셸
docker exec -it slot-mariadb mariadb -uroot -prootpass inspection2
# PostgreSQL 셸
psql -h localhost -d slot
# 데이터는 schema 'inspection2' 안:
# slot=> SET search_path TO inspection2; SELECT count(*) FROM g5_member;
# Redis 셸
docker exec -it slot-redis redis-cli
# 전체 스택 종료
cd docker && docker compose down
# 전체 스택 재시작 + 재초기화 (entrypoint 다시 실행)
cd docker && docker compose down && docker compose up -d
docker logs -f slot-php
```
## 5. 알려진 경고 (정상 동작과 무관)
| 메시지 | 원인 | 해결 |
|--------|------|------|
| `Notice: Undefined index HTTP_X_FORWARDED_FOR` | common.php:2 의 부주의한 헤더 접근 | `display_errors=Off` 로 숨김 (현재 적용됨) |
| `Class 'Redis' not found` | php-redis 익스텐션 누락 | entrypoint 가 `pecl install redis` 자동 실행 |
| `Headers already sent ...` | display_errors 가 On 이고 PHP notice 출력 | display_errors Off (현재 적용됨) |
| `apache2: Could not reliably determine ...` | ServerName 미설정 (cosmetic) | 무시 |
| `pdo (pdo.so) is already loaded!` | Debian 기본 PHP 에 pdo 가 빌트인이라 두 번 로드 | 무시 |
## 6. 운영 서버 / 로컬 차이점 요약
| 항목 | 운영 | 로컬 |
|------|------|------|
| URL | https://slot-ss.com | http://localhost:8088 |
| `G5_DOMAIN` | https://slot-ss.com (config.php) | env `G5_DOMAIN_OVERRIDE` |
| DB 호스트 | localhost | docker network "slot-net" / `slot-mariadb` |
| DB 비밀번호 | `iiOii5*^^*` (운영) | `rootpass` (로컬) |
| Redis | (운영 서버 redis) | `slot-redis` 컨테이너 |
| 첨부파일 | `/var/www/slot-ss.com/data/file/...`, `data/editor/...` | 로컬 src/data 는 빈 디렉토리 (실파일 없음) |
| 사용자 업로드 | 운영 그대로 | **없음** — 다운받지 않음 |
## 7. 트러블슈팅
### 7.1 컨테이너가 unhealthy 또는 재시작 반복
```bash
docker logs slot-php 2>&1 | tail -50
# pecl install redis 가 빌드 의존성 문제로 실패할 수 있음 → entrypoint 가 || true 로 무시
# 그래도 실패 시:
docker exec slot-php bash -lc 'apt-get update && apt-get install -y libssl-dev && pecl install redis && docker-php-ext-enable redis && apache2ctl restart'
```
### 7.2 사이트 500
```bash
# php_errors.log 확인 (display_errors 는 Off 이므로 화면엔 안 뜸)
docker exec slot-php tail -50 /var/log/apache2/php_errors.log
```
### 7.3 DB 연결 실패
```bash
# slot-mariadb 가 같은 네트워크에 있는지 확인
docker network inspect slot-net
# 없으면:
docker network connect slot-net slot-mariadb
```
### 7.4 포트 충돌
- 8088 사용 중이면 `docker/docker-compose.yml``ports: "8088:80"` 을 다른 포트로 변경
- 33306 사용 중이면 위와 마찬가지
## 8. 신규 시스템 (Next.js) 개발 셋업
(추후 M1 단계에서 추가 예정)
```bash
# 모노레포 루트
pnpm install
pnpm db:migrate
pnpm dev # apps/web (3000) + apps/admin (3001) + apps/api (4000) 동시 실행
```