Laravel PackageManifest 는 bootstrap/cache/packages.php 가 있으면 stale 여부를 검사하지 않고 그대로 읽어 등재된 provider 를 new 한다. 코어 업데이트는 Step 6/8 에서 vendor 를 --no-dev 로 교체하지만 그 파일은 Step 11 까지 이전 설치본의 것이 남으므로, 옵션 없는 `composer install` 로 깔린 사이트에서는 Step 10 spawn 자식이 새 vendor 에 없는 provider 를 찾다 부팅 단계에서 죽는다. 부팅 전이라 앱 로그에 흔적이 없고 부모에게는 자식의 비정상 종료로만 보여, 운영자에게는 「Class ... not found」 와 수동 재개 안내만 남는다. (sir.kr 커뮤니티 제보, 7.0.9 → 7.0.10) 3계층으로 막는다. 1. 부모 — spawn 직전 PackageManifestCacheHelper::clear 2. 자식 — bootstrap/app.php 가 G7_UPDATE_IN_PROGRESS 를 보고 스스로 정리한다. 이미 배포된 7.0.9·7.0.10 부모는 고칠 수 없으므로 그 아래에서 도는 신버전 자식의 유일한 방어다. App\ 클래스를 참조하지 않고 실패는 무시한다. 3. 범위 — CoreVersionChecker 의 env APP_VERSION 우선을 CoreUpdateContext 트리 안으로 축소한다. 업데이트 전에 뜬 artisan serve·큐 워커가 옛 값을 물고 확장을 incompatible_core 로 끄던 경로를 닫는다(관리자 템플릿이 대상이면 복구 UI 자체에 도달할 수 없다). 업데이트 트리 판정은 App\Support\CoreUpdateContext 가 단독 소유하고 CoreServiceProvider::isCoreUpdateInProgress 는 위임으로 남는다. bootstrap/app.php 의 복제본은 부팅 전이라 불가피한 예외이며, 두 조건의 동형성을 테스트가 단언한다. 실측 중 드러난 결함 2건을 함께 고쳤다. - ConfigCacheHelper::withPreservedContainer 가 파사드 애플리케이션을 되돌리지 않아 Step 11 이 `Target class [command.tinker] does not exist` 로 실패·롤백했다. - updateVersionInEnv 가 프로세스 환경을 갱신하지 않아 config 캐시에 이전 버전이 구워졌다 (Laravel env 저장소가 불변이라 재부팅으로도 덮이지 않는다). 인스톨러는 재사용 vendor 의 개발용 패키지를 installed.json 으로 감지해 설치 환경 확인 카드·설치 로그로 알리되 설치를 차단하지 않고( 결정 D1), 재사용 경로에서도 컴파일 캐시를 정리한다. 실행되는 명령만이 아니라 실패 시 안내하는 수동 명령까지 --no-dev 로 맞췄다. 코어 업데이트 완료·핸드오프·단독 재개 사후 단계에서 queue:restart 신호를 보낸다(D3). 코어 7.0.10 → 7.0.11.
696 lines
30 KiB
Markdown
696 lines
30 KiB
Markdown
# 그누보드7 설치 가이드
|
|
|
|
그누보드7(G7)을 설치하는 방법을 안내합니다.
|
|
|
|
---
|
|
|
|
## 시스템 요구사항
|
|
|
|
| 항목 | 요구사항 |
|
|
|------|---------|
|
|
| **PHP** | 8.2 이상 (필수 확장 16개 포함 — 기능별 선택 확장은 별도) |
|
|
| **데이터베이스** | MySQL 8.0+ 또는 MariaDB 10.3+ (utf8mb4) |
|
|
| **Composer** | 2.x |
|
|
| **Redis** | 6.0+ (프로덕션 권장, 선택) |
|
|
|
|
> 상세 요구사항은 [docs/requirements.md](docs/requirements.md)를 참조하세요.
|
|
|
|
---
|
|
|
|
## 방법 1: 웹 서버에서 바로 구동
|
|
|
|
Apache, Nginx 등 웹 서버가 이미 구동 중인 환경에서 설치합니다.
|
|
|
|
### 1단계: 소스 코드 다운로드
|
|
|
|
웹 서버의 루트 디렉토리(또는 원하는 위치)에서 실행합니다.
|
|
|
|
```bash
|
|
git clone https://github.com/gnuboard/g7.git
|
|
```
|
|
|
|
### 2단계: 웹 서버 설정
|
|
|
|
웹 서버의 DocumentRoot(또는 Virtual Host)를 `g7/public` 디렉토리로 설정합니다.
|
|
|
|
**Apache 예시** (Virtual Host):
|
|
|
|
```apache
|
|
<VirtualHost *:80>
|
|
ServerName example.com
|
|
DocumentRoot /var/www/g7/public
|
|
|
|
<Directory /var/www/g7/public>
|
|
AllowOverride All
|
|
Require all granted
|
|
</Directory>
|
|
</VirtualHost>
|
|
```
|
|
|
|
**Apache + mod_fcgid 환경 추가 설정** (PHP 8.5 NTS Windows 등 mod_php 미제공 빌드):
|
|
|
|
`fcgid.conf` 에 다음 1줄을 추가 후 Apache 재시작. 미설정 시 mod_fcgid 의 default 64KB 출력 버퍼가 인스톨러 SSE 스트림과 폴링 응답을 스크립트 종료 시점까지 보관하여 설치 진행 상황이 화면에 실시간 반영되지 않는다.
|
|
|
|
```apache
|
|
FcgidOutputBufferSize 0
|
|
```
|
|
|
|
**Nginx 예시**:
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name example.com;
|
|
root /var/www/g7/public;
|
|
|
|
index index.php;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.php?$query_string;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
|
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
|
include fastcgi_params;
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 정적 파일 최적화 블록을 함께 쓰는 경우
|
|
|
|
아래처럼 확장자로 캐시 규칙을 거는 블록(aaPanel · CyberPanel · Plesk 기본 템플릿에
|
|
포함되어 있습니다)을 함께 사용한다면 주의가 필요합니다.
|
|
|
|
```nginx
|
|
location ~* \.(js|css|json|png|jpg|svg|woff2?)$ {
|
|
expires max;
|
|
access_log off;
|
|
}
|
|
```
|
|
|
|
nginx 는 **정규식 location 을 프리픽스 location(`location /`)보다 먼저** 매칭합니다.
|
|
G7 은 일부 동적 엔드포인트에 `.js` · `.css` · `.json` 확장자를 쓰므로, 위 블록 안에
|
|
PHP 핸들러가 없으면 그 요청들이 `try_files ... /index.php` 폴백에 닿지 못하고
|
|
nginx 가 직접 파일을 찾다가 404 를 반환합니다. 증상은 **모든 페이지가 백지**입니다.
|
|
|
|
해결 방법은 두 가지이며, 아무것도 하지 않아도 G7 이 스스로 복구합니다.
|
|
|
|
1. **그대로 두기** — 브라우저가 자산 로드 실패를 감지하면 확장자 없는 주소로 자동
|
|
전환합니다. 설치 마법사도 설치 시점에 이를 감지해 설정에 반영합니다.
|
|
설치 후 확정하려면 `php artisan g7:asset-url-mode extensionless` 를 실행하거나
|
|
관리자 > 환경설정 > 일반에서 "자산 파일 주소 방식" 을 변경하세요.
|
|
(검색엔진 봇은 JavaScript 를 실행하지 않으므로, SEO 를 쓴다면 이 확정을 권장합니다.)
|
|
|
|
2. **`/api/` 를 정규식 블록보다 우선시키기** — `^~` 는 정규식 location 보다 우선하므로
|
|
아래 블록을 추가하면 `/api/` 요청이 항상 PHP 로 갑니다. 확장자 기반 캐시 최적화를
|
|
정적 파일에만 그대로 유지할 수 있습니다.
|
|
|
|
```nginx
|
|
location ^~ /api/ {
|
|
try_files $uri $uri/ /index.php?$query_string;
|
|
}
|
|
```
|
|
|
|
서버가 동적 응답을 가로채는지는 아래 두 요청을 비교해 확인할 수 있습니다.
|
|
첫 번째만 실패하면 가로채는 것입니다.
|
|
|
|
```bash
|
|
curl -i https://example.com/api/system/asset-probe.js
|
|
curl -i https://example.com/api/system/asset-probe
|
|
```
|
|
|
|
### 3단계: 설치 마법사 실행
|
|
|
|
브라우저에서 접속합니다.
|
|
|
|
```
|
|
http://도메인/install
|
|
```
|
|
|
|
설치 마법사의 안내에 따라 DB 정보 입력 및 관리자 계정을 생성합니다.
|
|
|
|
---
|
|
|
|
## 방법 2: 로컬 개발 서버 (PHP 내장 서버)
|
|
|
|
로컬 환경에서 개발/테스트 목적으로 빠르게 구동합니다.
|
|
|
|
### 1단계: 소스 코드 다운로드
|
|
|
|
```bash
|
|
git clone https://github.com/gnuboard/g7.git
|
|
```
|
|
|
|
### 2단계: 프로젝트 디렉토리로 이동
|
|
|
|
```bash
|
|
cd g7
|
|
```
|
|
|
|
### 3단계: Composer 의존성 설치 (선택)
|
|
|
|
```bash
|
|
composer install --no-dev --optimize-autoloader
|
|
```
|
|
|
|
> 이 단계는 생략해도 됩니다 — `vendor/` 가 없으면 설치 마법사가 운영용 구성(`--no-dev`)으로 자동 설치합니다.
|
|
>
|
|
> 개발용 패키지가 포함되는 `composer install`(옵션 없음)의 결과를 운영 사이트에 그대로 쓰지 마세요. 이미 그렇게 설치했다면 위 명령을 한 번 더 실행하면 개발용 패키지만 제거됩니다.
|
|
|
|
### 4단계: 환경 설정 파일 생성
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
### 5단계: 개발 서버 실행
|
|
|
|
```bash
|
|
php artisan serve
|
|
```
|
|
|
|
### 6단계: 설치 마법사 실행
|
|
|
|
브라우저에서 접속합니다.
|
|
|
|
```
|
|
http://localhost:8000/install
|
|
```
|
|
|
|
설치 마법사의 안내에 따라 DB 정보 입력 및 관리자 계정을 생성합니다.
|
|
|
|
---
|
|
|
|
## 방법 3: ZIP 파일 다운로드
|
|
|
|
Git이 설치되지 않은 환경에서 설치합니다.
|
|
|
|
### 1단계: GitHub 접속
|
|
|
|
브라우저에서 아래 주소로 접속합니다.
|
|
|
|
```
|
|
https://github.com/gnuboard/g7
|
|
```
|
|
|
|
### 2단계: 릴리스 다운로드
|
|
|
|
1. 페이지 우측의 **Releases** 섹션을 클릭합니다.
|
|
2. 최신 릴리스를 선택합니다.
|
|
3. 하단의 **Source code (zip)** 을 다운로드합니다.
|
|
|
|
### 3단계: 압축 해제
|
|
|
|
다운로드한 ZIP 파일을 원하는 위치에 압축 해제합니다.
|
|
|
|
### 4단계: Composer 의존성 설치 (선택)
|
|
|
|
터미널에서 압축 해제된 디렉토리로 이동한 후 실행합니다. 이 단계는 생략해도 됩니다 — `vendor/` 가 없으면 설치 마법사가 운영용 구성(`--no-dev`)으로 자동 설치합니다.
|
|
|
|
```bash
|
|
cd g7-버전명
|
|
composer install --no-dev --optimize-autoloader
|
|
```
|
|
|
|
> 개발용 패키지가 포함되는 `composer install`(옵션 없음)의 결과를 운영 사이트에 그대로 쓰지 마세요. 이미 그렇게 설치했다면 위 명령을 한 번 더 실행하면 개발용 패키지만 제거됩니다.
|
|
|
|
### 5단계: 환경 설정 파일 생성
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
### 6단계: 설치 진행
|
|
|
|
환경에 따라 선택합니다.
|
|
|
|
**웹 서버가 있는 경우:**
|
|
|
|
- DocumentRoot를 `public` 디렉토리로 설정한 후 브라우저에서 `http://도메인/install` 접속
|
|
|
|
**로컬에서 구동하는 경우:**
|
|
|
|
```bash
|
|
php artisan serve
|
|
```
|
|
|
|
브라우저에서 `http://localhost:8000/install` 접속
|
|
|
|
설치 마법사의 안내에 따라 DB 정보 입력 및 관리자 계정을 생성합니다.
|
|
|
|
---
|
|
|
|
## 방법 4: 공유 호스팅
|
|
|
|
Composer 실행이 불가능한 공유 호스팅 환경에서의 설치 방법입니다. SSH + PHP CLI 사용이 가능한 요금제를 전제로 하며, [Vendor 번들 시스템](docs/extension/vendor-bundle.md)을 통해 Composer 없이 의존성을 배치합니다.
|
|
|
|
### Cafe24
|
|
|
|
#### 검증 환경
|
|
|
|
본 가이드는 Cafe24 [**뉴아우토반 호스팅 절약형**](https://hosting.cafe24.com/?controller=new_product_page&page=newautobahn) 요금제에서 검증되었습니다. 동일 계열(일반형/비즈니스형 등) 요금제는 더 넉넉한 리소스를 제공하므로 그대로 적용 가능합니다.
|
|
|
|
| 항목 | 절약형 사양 |
|
|
|------|-------------|
|
|
| 월 요금 | 500원 (1년 약정 시 450원) |
|
|
| 웹 용량 | 700MB (FullSSD) |
|
|
| 트래픽 | 1.6GB/일 |
|
|
| DB | MariaDB 10.x (InnoDB), 서버 공간 내 무제한 |
|
|
| PHP | 8.4 / 8.2 / 7.4 (Rocky OS 기준) |
|
|
| 접속 | FTP / SFTP / SSH 지원 |
|
|
|
|
> 웹 용량 700MB는 G7 코어 + 기본 확장 설치에 충분하지만, 업로드 파일이 많아질 경우 **일반형(1.4GB) 이상**을 권장합니다.
|
|
|
|
#### 사전 준비
|
|
|
|
- SSH 접속이 허용된 Cafe24 호스팅 계정 (절약형 이상)
|
|
- SFTP 클라이언트 (FileZilla, WinSCP, Cyberduck 등)
|
|
- Cafe24 관리자 페이지에서 PHP 버전을 **8.2 또는 8.4**로 설정
|
|
- Cafe24 관리자 페이지에서 생성한 MariaDB DB (utf8mb4)
|
|
|
|
#### 1단계: GitHub Release에서 배포 패키지 다운로드
|
|
|
|
[https://github.com/gnuboard/g7/releases](https://github.com/gnuboard/g7/releases) 접속하여 최신 릴리스의 **Assets** 섹션에서 배포 패키지를 다운로드합니다.
|
|
|
|
#### 2단계: SFTP로 ZIP 파일 업로드
|
|
|
|
다운로드한 ZIP 파일을 SFTP로 홈 디렉토리 바로 아래에 업로드합니다.
|
|
|
|
```text
|
|
~/ ← Cafe24 계정의 홈 디렉토리
|
|
├── www ← 기존 심볼릭 링크 또는 디렉토리 (4단계에서 갱신)
|
|
└── g7-release.zip ← 업로드한 ZIP 파일
|
|
```
|
|
|
|
#### 3단계: SSH 접속 후 압축 해제 및 심볼릭 링크 갱신
|
|
|
|
SSH 접속 후 홈 디렉토리에서 ZIP 압축 해제와 웹 루트 심볼릭 링크 갱신을 함께 진행합니다.
|
|
|
|
```bash
|
|
cd ~
|
|
|
|
# 업로드한 ZIP 압축 해제 (파일명은 실제 다운로드한 이름으로 교체)
|
|
unzip g7-release.zip
|
|
|
|
# 압축 해제 결과 확인 — 루트 디렉토리가 g7이 아니면 이름 변경
|
|
ls -la
|
|
# (필요 시) mv g7-7.0.11 g7
|
|
|
|
# ZIP 파일 정리 (선택)
|
|
rm g7-release.zip
|
|
```
|
|
|
|
압축 해제 후 디렉토리 구조는 다음과 같아야 합니다.
|
|
|
|
```text
|
|
~/
|
|
├── www ← 아래에서 갱신할 심볼릭 링크
|
|
└── g7/
|
|
├── app/
|
|
├── bootstrap/
|
|
├── public/
|
|
├── storage/
|
|
├── vendor-bundle.zip
|
|
├── .env.example
|
|
└── ...
|
|
```
|
|
|
|
Cafe24의 웹 루트는 홈 디렉토리 아래 `www`(심볼릭 링크 또는 디렉토리)이며, 이를 `g7/public/`으로 연결해야 합니다.
|
|
|
|
```bash
|
|
# 기존 www 상태 확인
|
|
ls -la www
|
|
|
|
# 기존 www 삭제 후 재생성
|
|
rm www
|
|
ln -s g7/public www
|
|
|
|
# 결과 확인 (아래와 같은 형태여야 합니다)
|
|
ls -la www
|
|
# lrwxrwxrwx 1 user user 9 ... www -> g7/public/
|
|
```
|
|
|
|
기존 `www` 안에 운영 중인 사이트가 있다면, 먼저 SFTP로 백업 다운로드하거나 `mv www www.bak`으로 이름 변경한 뒤 새 심볼릭 링크를 생성하세요.
|
|
|
|
> 본 가이드의 모든 쉘 명령은 `cd ~` 또는 `cd ~/g7` 컨텍스트 진입 후 `./` 상대경로로 실행하므로, Cafe24 계정의 홈 디렉토리 절대경로를 몰라도 됩니다.
|
|
|
|
#### 4단계: 웹 인스톨러 실행
|
|
|
|
브라우저에서 도메인으로 접속합니다.
|
|
|
|
```text
|
|
http://도메인/install
|
|
```
|
|
|
|
설치 마법사의 각 단계를 진행합니다.
|
|
|
|
| Step | 작업 |
|
|
|------|------|
|
|
| 0. 환영 | 언어 선택 및 `storage` 권한 검증 — 권한 부족 시 인스톨러가 상대경로 기반 명령을 자동 안내 |
|
|
| 1. 라이선스 | 동의 |
|
|
| 2. 요구사항 | PHP 8.2+ 및 필수 확장 확인 + 권장 항목(OPcache · Composer 의존성 구성) 안내 |
|
|
| 3. 환경 설정 | DB 정보 + 관리자 계정 + **Vendor 설치 방식** 선택 |
|
|
| 4. 확장 선택 | 템플릿/모듈/플러그인 선택 (의존성 자동 해결) |
|
|
| 5. 설치 실행 | "설치 시작" 버튼 클릭 후 진행 상황 모니터링 |
|
|
|
|
`.env` 파일 생성과 `storage` / `bootstrap/cache` / `public/build` 쓰기 권한 부여는 인스톨러가 환경(소유자 일치 여부 등)에 맞춰 Step 0 및 이후 단계에서 자동 안내하므로, 사전 SSH 작업으로 수행할 필요 없습니다.
|
|
|
|
**Step 2 — Composer 의존성 구성 (선택 항목):**
|
|
|
|
이미 `vendor/` 가 준비되어 있으면 설치 마법사는 그것을 그대로 씁니다. 이때 그 `vendor/` 가 개발용 패키지까지 포함한 설치(`composer install`, 옵션 없음)인지 확인해 알려 줍니다.
|
|
|
|
- **운영용 구성 (개발용 패키지 없음)**: 권장 상태입니다. 조치가 필요 없습니다.
|
|
- **개발용 패키지 N개 포함**: 설치는 그대로 진행됩니다. 운영에 사용할 서버라면 설치를 마친 뒤 프로젝트 루트에서 `composer install --no-dev --optimize-autoloader` 를 한 번 실행하세요. 그대로 두면 이후 코어 업데이트가 `vendor/` 를 교체할 때 이전 패키지 목록 캐시와 어긋나 업데이트가 중단될 수 있습니다.
|
|
- **vendor 없음**: 설치 마법사가 운영용 구성으로 자동 설치하므로 조치가 필요 없습니다.
|
|
|
|
이 항목은 설치를 차단하지 않습니다.
|
|
|
|
**Step 3 — Vendor 설치 방식 선택:**
|
|
|
|
- **자동 (권장)**: 환경을 자동 감지하여 번들 모드로 폴백합니다.
|
|
- **번들 Vendor 사용**: `vendor-bundle.zip`을 명시적으로 선택합니다 (Cafe24 권장).
|
|
|
|
#### Cafe24 환경 체크리스트
|
|
|
|
설치 중 문제가 발생하면 아래 항목을 확인합니다.
|
|
|
|
- [ ] `php -v` 출력이 8.2 이상인가? (Cafe24 관리자에서 PHP 버전 변경 가능)
|
|
- [ ] `php -m` 출력에 `pdo_mysql`, `mbstring`, `openssl`, `zip`이 포함되어 있는가?
|
|
- [ ] `~/www`가 `g7/public/`를 올바르게 가리키는가? (`ls -la ~/www` 확인)
|
|
- [ ] `vendor-bundle.zip`이 `~/g7/` 디렉토리에 존재하는가?
|
|
- [ ] 웹 인스톨러 Step 3에서 "Vendor 설치 방식"을 **번들 Vendor 사용** 또는 **자동**으로 선택했는가?
|
|
- [ ] DB 접속 정보(호스트/포트/계정)가 Cafe24 관리자 정보와 일치하는가?
|
|
|
|
---
|
|
|
|
## 설치 트러블슈팅
|
|
|
|
### 2단계에서 "Unexpected end of JSON input" 오류가 표시되는 경우
|
|
|
|
**증상**: 설치 마법사 2단계(설치 환경 확인)에서 요구사항 카드가 표시되지 않고
|
|
`요구사항 검증 실패: ... Unexpected end of JSON input` 이 표시됩니다.
|
|
서버 로그에는 아무 오류도 남지 않습니다.
|
|
|
|
**원인**: Windows 사용자 계정 이름에 한글(또는 서버가 쓰는 문자 인코딩 밖의 문자)이
|
|
포함되어 있으면, 설치 마법사가 계정 이름을 조회하는 과정에서 응답을 만들지 못합니다.
|
|
|
|
**해결**:
|
|
|
|
- **7.0.10 이상**: 수정되었습니다. 별도 조치가 필요하지 않습니다.
|
|
- **7.0.9 이하**: 계정 이름이 영문인 Windows 계정으로 웹 서버를 실행하거나,
|
|
코어를 7.0.10 이상으로 올린 뒤 설치를 진행하세요.
|
|
|
|
설치 과정에서 문자 인코딩 관련 조치가 있었다면 `storage/logs/installation.log` 에
|
|
`[env] whoami output was not UTF-8 — normalized` 형태로 기록됩니다.
|
|
|
|
---
|
|
|
|
## 설치 후 확인
|
|
|
|
설치가 완료되면 아래 페이지에 접근할 수 있습니다.
|
|
|
|
| 페이지 | URL | 비고 |
|
|
|--------|-----|------|
|
|
| **관리자 페이지** | `http://도메인/admin` | |
|
|
| **사용자 페이지** | `http://도메인/` | 사용자 템플릿 설치 필수 |
|
|
|
|
> 사용자 페이지는 사용자 템플릿이 설치되어 있어야 접근할 수 있습니다. 인스톨러에서 사용자 템플릿을 함께 설치하거나, 관리자 페이지에서 템플릿을 먼저 설치해 주세요.
|
|
|
|
### 파일 권한 (설치 후 확인)
|
|
|
|
POSIX 권한 모델 (Linux/macOS/BSD) 환경에서 웹 서버 실행 계정이 쓸 수 있어야 하는 위치는 다음과 같습니다. Windows 환경에서는 해당하지 않습니다.
|
|
|
|
| 위치 | 필요한 이유 |
|
|
|------|------------|
|
|
| `storage/` · `bootstrap/cache` | 애플리케이션 동작에 항상 필요 (로그·캐시·세션·업로드·런타임 캐시) |
|
|
| `modules/` · `plugins/` · `templates/` · `public/build` | 관리자 화면에서 확장(모듈/플러그인/템플릿)을 설치·업데이트·삭제할 때 필요 |
|
|
|
|
```bash
|
|
sudo chown -R www-data:www-data storage bootstrap/cache modules plugins templates public/build
|
|
```
|
|
|
|
**`vendor/` 에는 쓰기 권한이 필요하지 않습니다.** 확장의 `vendor/` 는 설치·업데이트 시점에만 기록되며, 애플리케이션이 동작하면서 만드는 런타임 캐시는 모두 `storage/` 아래에 기록됩니다. 명령줄로 설치·업데이트를 수행한다면 그 계정만 쓸 수 있으면 됩니다.
|
|
|
|
전체 권한 모델(그룹 공유 방식 A / 소유자 통일 방식 B / ACL 방식 C 와 umask 운영)은 [docs/requirements.md](docs/requirements.md) "파일 권한 및 umask 운영 방식" 절을 참고하세요.
|
|
|
|
### 명령줄·cron 실행 계정
|
|
|
|
`php artisan` 명령과 cron 은 **웹 서버 실행 계정으로** 실행합니다 (예: `sudo -u www-data php artisan …`, 또는 `crontab -u www-data -e` 로 등록). 대부분의 명령이 캐시·병합 번들·임시 파일을 만드는데, root 나 다른 계정으로 실행하면 그 산출물이 그 계정 소유로 남아 이후 웹 요청이 같은 자리에 쓰려는 순간 `Permission denied` 로 500 을 낼 수 있습니다. 이 문제는 특정 명령의 결함이 아니라 캐시를 건드리는 모든 명령에 공통이므로, 계정을 맞추는 것이 유일한 해법입니다.
|
|
|
|
예외는 코어 업데이트(`php artisan core:update`)입니다. 이 명령은 `.env` 등 웹 계정이 쓸 수 없는 파일까지 고치므로 `sudo` 를 권장하며, 실행이 끝날 때 자기가 만든 파일의 소유권을 되돌리는 절차가 내장되어 있습니다.
|
|
|
|
---
|
|
|
|
## 업그레이드
|
|
|
|
이미 운영 중인 그누보드7을 새 버전으로 업그레이드할 때의 절차입니다. 신버전 ZIP 또는 git pull 로 파일만 덮어쓰면 **데이터베이스 마이그레이션, 데이터 시드, 확장(모듈/플러그인/템플릿) 재동기화가 함께 수행되지 않아** 게시판/회원/상품 데이터 누락이나 부정합 부팅 실패가 발생합니다. 반드시 아래 절차를 따라주세요.
|
|
|
|
### 개요
|
|
|
|
그누보드7 업그레이드의 SSoT(Single Source of Truth)는 Artisan 커맨드입니다.
|
|
|
|
```bash
|
|
sudo php artisan core:update
|
|
```
|
|
|
|
이 커맨드 1회 실행으로 다음 작업이 자동 수행됩니다.
|
|
|
|
- 신버전 다운로드 및 압축 해제 (GitHub Release 또는 지정 ZIP)
|
|
- 자동 백업 생성 (실패 시 자동 롤백)
|
|
- 유지보수 모드 자동 진입
|
|
- 데이터베이스 마이그레이션 실행
|
|
- 업그레이드 스텝 실행 (버전별 데이터 보정)
|
|
- 번들 확장 자동 재동기화
|
|
- 캐시 정리 및 유지보수 모드 해제
|
|
|
|
### 업그레이드 사전 준비
|
|
|
|
업그레이드 전 다음을 확인하세요.
|
|
|
|
1. **데이터베이스 백업** (필수)
|
|
|
|
```bash
|
|
mysqldump -u DB사용자 -p DB이름 > backup-$(date +%Y%m%d).sql
|
|
```
|
|
|
|
2. **활성 디렉토리 백업 권장** — 직접 수정한 코드나 외부 확장(`_bundled` 에 포함되지 않은 GitHub install 확장) 이 있다면 다음 4개 디렉토리를 별도 위치로 백업하세요.
|
|
|
|
```bash
|
|
tar -czf extensions-backup-$(date +%Y%m%d).tar.gz modules plugins templates lang-packs
|
|
```
|
|
|
|
3. **SSH/CLI 접근 확보** — 코어 업그레이드는 보안상 웹 UI 에서 실행할 수 없으며, 반드시 서버 터미널(SSH) 에서 직접 실행해야 합니다.
|
|
|
|
### 방법 1: 관리자 UI 에서 업데이트 확인 (권장 동선 시작점)
|
|
|
|
운영자가 새 버전 출시 여부를 가장 빠르게 알 수 있는 동선입니다.
|
|
|
|
1. 관리자 페이지 로그인 → **환경설정 > 정보** 탭 이동
|
|
2. "**업데이트 확인**" 버튼 클릭 → 최신 버전과 변경사항 모달 표시
|
|
3. 신버전이 감지되면 "**변경사항 보기**" 로 changelog 확인 → "**업데이트 방법**" 버튼 클릭
|
|
4. 모달이 권장 명령어와 본 가이드 링크를 안내하므로 그 안내에 따라 **서버 터미널에서 직접 실행**
|
|
|
|
> 모달은 안내 전용입니다. 보안상 UI 에서 코어 업그레이드를 직접 실행하지 않으며, 운영자가 권한 일치를 확인한 후 CLI 에서 실행해야 합니다.
|
|
|
|
### 방법 2: CLI 자동 업그레이드 (표준 절차)
|
|
|
|
대다수 환경에서 권장되는 절차입니다.
|
|
|
|
```bash
|
|
sudo php artisan core:update
|
|
```
|
|
|
|
#### `sudo` 가 권장되는 이유
|
|
|
|
업그레이드는 다음 파일들을 수정·생성하므로, 운영 환경에서 일반 사용자 권한으로 모두 접근 가능한 경우가 드뭅니다.
|
|
|
|
- `.env` — `APP_VERSION` 갱신 (보안상 `0600` 또는 `0640` 권한, 소유자는 보통 웹 서버 사용자 `www-data` · `nginx` · `apache` 등)
|
|
- `bootstrap/cache/` — 설정·라우트·서비스 캐시 갱신
|
|
- `storage/framework/`, `storage/logs/` — 캐시·로그 파일 생성
|
|
- `modules/`, `plugins/`, `templates/`, `lang-packs/` — 확장 재동기화
|
|
|
|
`sudo` 로 root 권한을 위임받으면 위 파일들의 소유자가 누구든(웹 서버 사용자 또는 별도 배포 사용자) 권한 충돌 없이 한 번에 처리할 수 있습니다. 업그레이드 도중 `.env` 머지 단계는 기존 소유자·그룹을 그대로 보존하므로, root 로 실행해도 파일 권한이 임의로 변경되지 않습니다.
|
|
|
|
#### `sudo` 없이 실행해도 되는 환경
|
|
|
|
- 소유자가 명령줄 사용자와 일치하는 **단일 사용자 호스팅** (Cafe24 등 공유 호스팅, 개인 VPS 의 사용자 계정 운영) — 그냥 `php artisan core:update` 실행
|
|
- **Windows (XAMPP/Laragon 등)** — 관리자 권한 PowerShell 에서 `php artisan core:update` 실행
|
|
|
|
> 자신의 환경이 어느 쪽인지 확인하려면 `ls -l .env` 의 소유자(세 번째 컬럼) 가 명령줄 로그인 사용자와 일치하는지 보세요. 일치하면 `sudo` 없이 실행 가능합니다.
|
|
|
|
### 방법 3: 수동 ZIP 업그레이드 (PHP zip 확장 미설치 환경)
|
|
|
|
PHP `zip` 확장 또는 시스템 `unzip` 명령이 없는 서버에서는 GitHub Release ZIP 을 직접 다운로드한 뒤 압축 해제 경로를 지정해 업그레이드합니다.
|
|
|
|
```bash
|
|
# 1. GitHub 릴리스 페이지에서 ZIP 다운로드 후 서버에 압축 해제
|
|
wget https://github.com/gnuboard/g7/releases/download/<버전>/<파일명>.zip
|
|
unzip <파일명>.zip -d /tmp/g7-new
|
|
|
|
# 2. 압축 해제된 경로를 지정하여 업데이트 실행
|
|
sudo php artisan core:update --source=/tmp/g7-new
|
|
```
|
|
|
|
`--source=` 옵션은 다운로드 단계를 건너뛰고 지정 경로의 파일을 신버전으로 간주합니다.
|
|
|
|
### 사용자군별 단계적 업그레이드
|
|
|
|
여러 베타 버전을 건너뛰고 한 번에 최신 버전으로 올리는 것은 권장하지 않습니다. 중간 버전의 업그레이드 스텝이 이전 버전 메모리에 없는 신규 코드에 의존하여 부팅 실패 위험이 있습니다.
|
|
|
|
| 현재 버전 | 권장 경로 |
|
|
|----------|----------|
|
|
| **beta.5 이상** | `sudo php artisan core:update` 1회로 최신 버전까지 자동 처리 |
|
|
| **beta.3 / beta.4** | beta.5 → 최신 순서로 2회 분할 실행. 각 단계 후 `.env` `APP_VERSION` 이 자동 갱신되므로 같은 명령을 반복 실행 |
|
|
| **beta.1 / beta.2** | beta.2 → beta.3 → beta.4 → beta.5 → 최신 순으로 단계별 진행 |
|
|
| **beta.4 도중 fatal 후 중단** | `.env` `APP_VERSION` 을 변경하지 말고 `php artisan core:update --force` 재실행. 새 자식 프로세스가 신버전 메모리로 부팅되어 남은 스텝이 멱등 적용됨 |
|
|
|
|
특정 베타 버전으로의 단계 업그레이드는 `--source=` 또는 `--zip=` 옵션으로 해당 버전 릴리스 ZIP 을 지정하여 진행합니다.
|
|
|
|
> 사용자군별 상세 분기는 [CHANGELOG.md](CHANGELOG.md) 의 해당 버전 "Upgrade Notice" 섹션을 참고하세요.
|
|
|
|
### 권한/캐시 트러블슈팅
|
|
|
|
업그레이드 도중 또는 직후 사이트가 응답하지 않는 경우, 다음을 확인합니다. 본 절의 `chmod`/`chown`/`chgrp` 명령은 POSIX 권한 모델 (Linux/macOS/BSD) 환경 전용이며, Windows 환경에서는 해당하지 않습니다.
|
|
|
|
#### `.env` 읽기 실패 (`Permission denied`)
|
|
|
|
```bash
|
|
ls -l .env
|
|
# -rw------- 1 www-data www-data ... .env ← 세 번째 컬럼이 소유자
|
|
```
|
|
|
|
대부분의 경우 `sudo php artisan core:update` 로 재실행하면 root 권한으로 소유자에 관계없이 접근됩니다. 권한 보안을 강화하려면 본 문서 [`.env` 권한 강화 (선택)](#env-권한-강화-선택) 섹션의 `0600` / `0640` 가이드를 참고하세요. 명령줄 사용자와 웹 서버 사용자가 다른 환경에서는 `0640` + 웹 서버 그룹 부여가 안전한 절충안입니다.
|
|
|
|
#### `bootstrap/cache` 쓰기 실패
|
|
|
|
```bash
|
|
sudo chown -R www-data:www-data bootstrap/cache storage
|
|
```
|
|
|
|
소유자를 웹 서버 사용자로 일괄 정렬한 뒤 업그레이드를 재실행합니다.
|
|
|
|
#### 업그레이드 도중 자동 롤백 후 부팅 실패
|
|
|
|
beta.6 이상에서는 자동 롤백 후 잔존 파일을 추가 진단하는 `hotfix:rollback-stale-files` 커맨드가 제공됩니다.
|
|
|
|
```bash
|
|
# 진단 모드 (실제 삭제 없음)
|
|
sudo php artisan hotfix:rollback-stale-files
|
|
|
|
# 운영자 확인 후 실제 정리
|
|
sudo php artisan hotfix:rollback-stale-files --prune
|
|
```
|
|
|
|
### 업그레이드 후 확인
|
|
|
|
업그레이드가 끝나면 다음을 점검합니다.
|
|
|
|
1. 관리자 페이지 > **환경설정 > 정보** 에서 G7 버전이 갱신되었는지 확인
|
|
2. **확장 > 모듈/플러그인/템플릿** 목록이 모두 정상 표시되는지 확인
|
|
3. 사용자 페이지 진입하여 기존 콘텐츠(게시판/상품/페이지) 가 정상 노출되는지 확인
|
|
4. `storage/logs/laravel.log` 에 신규 에러가 누적되지 않는지 확인
|
|
|
|
---
|
|
|
|
## 프로덕션 환경 추가 설정
|
|
|
|
프로덕션 환경에서는 아래 항목을 추가로 설정하는 것을 권장합니다.
|
|
|
|
### HTTPS 설정
|
|
|
|
프로덕션 환경에서는 HTTPS를 사용해야 합니다. `.env` 파일에서 `APP_URL`을 `https://`로 설정하세요.
|
|
|
|
`APP_URL` 은 명령줄 실행·큐 워커·메일 발송처럼 **요청이 없는 맥락**에서 절대 URL 을 만들 때의
|
|
기준입니다. 웹 요청에서 만들어지는 절대 URL(화면 자산, 콜백 주소 등)은 `APP_URL` 이 아니라
|
|
**요청 자체의 스킴과 호스트**를 따릅니다.
|
|
|
|
따라서 TLS 를 앞단에서 처리하고 사이트에는 HTTP 로 전달하는 구성(AWS ALB, CloudFront,
|
|
Cloudflare, nginx 리버스 프록시, ngrok)에서는 `APP_URL` 만 `https://` 로 두어서는 부족합니다.
|
|
사이트가 접속 주소와 방문자 IP 를 올바르게 인식하려면 `.env` 에 `TRUSTED_PROXIES` 를 함께
|
|
지정해야 합니다.
|
|
|
|
```dotenv
|
|
# 프록시 뒤에서 구동하는 경우에만 지정합니다 (미설정이 기본값).
|
|
TRUSTED_PROXIES=*
|
|
```
|
|
|
|
지정하지 않으면 화면이 표시되지 않거나(혼합 콘텐츠 차단), 결제 통보가 수신되지 않고, 모든
|
|
방문자가 같은 IP 로 기록됩니다. 값 선택 기준과 도입 시 후속 조치는
|
|
[docs/backend/reverse-proxy.md](docs/backend/reverse-proxy.md) 를 참고하세요.
|
|
|
|
### `.env` 를 운영 기준값으로 삼기 (선택)
|
|
|
|
기본 설계에서 **관리자 환경설정 화면이 운영 기준**입니다. 설치가 끝나면 메일·드라이버·디버그
|
|
같은 항목은 화면에서 관리하며, 그 값이 `.env` 의 같은 항목보다 우선합니다. 설치 마법사가
|
|
초기값을 저장하므로 **설치 직후부터** 그 우선순위가 적용됩니다.
|
|
|
|
컨테이너·구성 관리 도구·다중 서버처럼 `.env` 를 배포 기준값으로 관리하는 환경에서는 이
|
|
우선순위를 뒤집을 수 있습니다. `.env` 에 다음 한 줄을 추가하세요.
|
|
|
|
```dotenv
|
|
G7_ENV_PRIORITY=true
|
|
```
|
|
|
|
켜면 **`.env` 에 값이 적혀 있는 항목만** 화면 저장값의 영향을 받지 않습니다. 그 항목들은
|
|
관리자 화면에서 편집 불가로 표시되고, 화면에는 실제로 적용 중인 값이 나타납니다. 값이 비어
|
|
있거나 줄이 없는 항목은 종전대로 화면에서 관리합니다.
|
|
|
|
주의할 점:
|
|
|
|
- `.env.example` 은 `APP_NAME`, `LOG_LEVEL`, `G7_UPDATE_GITHUB_URL` 등에 값을 채워 배포합니다.
|
|
그 파일을 복사해 쓰고 있다면 스위치를 켜는 즉시 **그 항목들도 함께 잠깁니다.** 화면에서
|
|
관리하고 싶은 항목은 값을 비우거나(`KEY=`) 줄을 지우세요.
|
|
- `.env` 에 `BROADCAST_CONNECTION` 이나 `REVERB_*` 를 적으면 웹소켓 사용 여부까지 `.env` 가
|
|
결정합니다. 관리자 화면의 웹소켓 토글은 그 설치에서 동작하지 않습니다.
|
|
- `.env` 만 고친 경우에는 `php artisan config:cache` 를 다시 실행해야 반영됩니다. 관리자
|
|
화면에서 저장하는 경우에는 자동으로 처리됩니다.
|
|
- 비밀번호·시크릿·토큰 같은 값은 잠금 표시만 되고 화면에 나타나지 않습니다.
|
|
|
|
스위치를 넣지 않으면 아무 것도 달라지지 않습니다(기존 설치 무영향).
|
|
|
|
### `.env` 권한 강화 (선택)
|
|
|
|
`.env` 는 DB 비밀번호와 `APP_KEY` 등 평문 자격증명을 포함합니다. 인스톨러는 설치 직후 `.env` 의 권한을 임의로 변경하지 않으므로, 운영자가 환경에 맞춰 직접 강화 권한을 적용할 수 있습니다.
|
|
|
|
- 가장 안전한 권한은 `0600` (소유자만 읽기·쓰기) 입니다. 다만 `0600` 적용 전에 **`.env` 의 소유자가 웹 서버 실행 사용자와 동일해야** 합니다. 소유자가 다른데 `0600` 으로 변경하면 웹 서버가 `.env` 를 읽지 못해 사이트가 응답하지 않습니다.
|
|
|
|
- **단일 사용자 환경** (예: 카페24 등 명령줄 사용자와 웹 서버 사용자가 같은 경우):
|
|
|
|
```bash
|
|
sudo chown www-data:www-data .env
|
|
sudo chmod 600 .env
|
|
```
|
|
|
|
- **자체 구축 서버** (명령줄 사용자 `jjh` 등과 웹 서버 사용자 `www-data` 가 다른 경우):
|
|
|
|
```bash
|
|
sudo chgrp www-data .env
|
|
sudo chmod 640 .env
|
|
```
|
|
|
|
웹 서버는 그룹 멤버로 읽기만 허용되고, 명령줄 사용자는 직접 수정할 수 있는 절충안입니다.
|
|
|
|
인스톨러 Step 5 완료 화면은 현재 `.env` 권한이 `0600` 이 아닐 경우 위 두 명령 예시를 조건부로 표시합니다.
|
|
|
|
### 데몬 프로세스
|
|
|
|
상시 실행이 필요한 프로세스입니다. Supervisor 등을 사용하여 관리합니다.
|
|
|
|
| 프로세스 | 명령어 | 용도 |
|
|
|---------|--------|------|
|
|
| 큐 워커 | `php artisan queue:work` | 비동기 작업 처리 |
|
|
| WebSocket | `php artisan reverb:start` | 실시간 알림 |
|
|
|
|
### 스케줄러
|
|
|
|
cron에 아래 항목을 등록합니다.
|
|
|
|
```bash
|
|
* * * * * cd /path/to/g7 && sudo -u www-data php artisan schedule:run >> /dev/null 2>&1
|
|
```
|
|
|
|
웹 서버 계정(`www-data` · `nginx` · `apache` 등)으로 실행해야 합니다 — root 의 crontab 에 그대로 등록하면 매분 캐시 파일이 root 소유로 만들어져 웹 요청이 실패할 수 있습니다. `crontab -u www-data -e` 로 그 계정의 crontab 에 등록하면 `sudo -u` 없이 같은 줄을 씁니다. 「명령줄·cron 실행 계정」 절을 참고하세요.
|
|
|
|
> 상세 내용은 [docs/requirements.md](docs/requirements.md)를 참조하세요.
|