# 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) 동시 실행 ```