- database/schema/ 14개 DDL 파일 신규 생성 (운영 DB pg_dump 기반) - database/seed/ 14개 초기 데이터 파일 분리 - database/_deprecated/로 구 init.sql, auth_init.sql 이동 - database/README.md 신규 작성 (DB 아키텍처, 설치 절차) - docs/ 6개 가이드 문서 wing_auth→auth 스키마 구조로 수정 - README.md, CLAUDE.md wing 단일 DB 구조 반영 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
732 lines
22 KiB
Markdown
Executable File
732 lines
22 KiB
Markdown
Executable File
# WING-OPS 설치 매뉴얼
|
|
|
|
## 목차
|
|
|
|
1. [시스템 요구사항](#1-시스템-요구사항)
|
|
2. [프로젝트 구조](#2-프로젝트-구조)
|
|
3. [온라인 설치](#3-온라인-설치)
|
|
4. [오프라인 설치](#4-오프라인-설치)
|
|
5. [DB 초기화 및 마이그레이션](#5-db-초기화-및-마이그레이션)
|
|
6. [개발 서버 실행](#6-개발-서버-실행)
|
|
7. [운영 서버 배포](#7-운영-서버-배포)
|
|
8. [CI/CD 자동 배포](#8-cicd-자동-배포)
|
|
9. [접속 정보 요약](#9-접속-정보-요약)
|
|
10. [트러블슈팅](#10-트러블슈팅)
|
|
|
|
---
|
|
|
|
## 1. 시스템 요구사항
|
|
|
|
### 필수 소프트웨어
|
|
|
|
| 소프트웨어 | 최소 버전 | 권장 버전 | 용도 |
|
|
|-----------|----------|----------|------|
|
|
| Node.js | v20 | v20 LTS | Frontend/Backend 실행 |
|
|
| npm | v10 | v10+ | 패키지 관리 (Node.js 포함) |
|
|
| PostgreSQL | v15 | v16 | 운영 DB (wing 단일 DB) |
|
|
| PostGIS | v3.3 | v3.4 | 공간 데이터 처리 |
|
|
| Git | v2.30 | v2.40+ | 소스 코드 관리 |
|
|
|
|
### 하드웨어 권장 사양
|
|
|
|
| 항목 | 개발 환경 | 운영 환경 |
|
|
|------|----------|----------|
|
|
| CPU | 2 Core | 4 Core |
|
|
| RAM | 4 GB | 8 GB |
|
|
| Disk | 10 GB | 50 GB |
|
|
| OS | macOS / Linux / Windows | Rocky Linux 9 / CentOS 9 |
|
|
|
|
### Node.js 설치 (fnm 권장)
|
|
|
|
fnm(Fast Node Manager)으로 Node.js 버전을 관리한다. 프로젝트 루트의 `.node-version` 파일에 `20`이 지정되어 있다.
|
|
|
|
**macOS / Linux:**
|
|
|
|
```bash
|
|
# fnm 설치
|
|
curl -fsSL https://fnm.vercel.app/install | bash
|
|
|
|
# 셸 재시작 후
|
|
fnm install 20
|
|
fnm use 20
|
|
|
|
# 확인
|
|
node -v # v20.x.x
|
|
npm -v # v10.x.x
|
|
```
|
|
|
|
**수동 설치 (fnm 없이):**
|
|
|
|
https://nodejs.org 에서 Node.js 20 LTS를 다운로드하여 설치한다.
|
|
|
|
---
|
|
|
|
## 2. 프로젝트 구조
|
|
|
|
```
|
|
wing/
|
|
├── frontend/ React 19 + Vite 7 + TypeScript 5.9 + Tailwind CSS 3
|
|
│ ├── src/
|
|
│ │ ├── App.tsx 메인 (탭 라우팅, 감사 로그 자동 기록)
|
|
│ │ ├── common/ 공통 모듈 (@common/ alias)
|
|
│ │ │ ├── components/ auth/, layer/, layout/, map/, ui/
|
|
│ │ │ ├── hooks/ useLayers, useSubMenu, useAuth
|
|
│ │ │ ├── services/ api.ts (Axios), authApi.ts, layerService.ts
|
|
│ │ │ ├── store/ authStore, menuStore (Zustand)
|
|
│ │ │ ├── types/ backtrack, boomLine, hns, navigation
|
|
│ │ │ └── utils/ coordinates, geo, sanitize
|
|
│ │ └── tabs/ 탭 단위 패키지 (11개)
|
|
│ │ ├── prediction/ 확산 예측
|
|
│ │ ├── hns/ HNS 분석
|
|
│ │ ├── rescue/ 구조 시나리오
|
|
│ │ ├── aerial/ 항공 방제
|
|
│ │ ├── weather/ 해양 기상
|
|
│ │ ├── incidents/ 사건/사고 관리
|
|
│ │ ├── board/ 게시판
|
|
│ │ ├── reports/ 보고서
|
|
│ │ ├── assets/ 자산 관리
|
|
│ │ ├── scat/ Pre-SCAT 조사
|
|
│ │ └── admin/ 관리자
|
|
│ ├── package.json
|
|
│ └── vite.config.ts
|
|
├── backend/ Express 4 + TypeScript + PostgreSQL
|
|
│ ├── src/
|
|
│ │ ├── server.ts 진입점 (보안 미들웨어 + 라우터 등록)
|
|
│ │ ├── auth/ 인증 (JWT, Google OAuth)
|
|
│ │ ├── users/ 사용자 관리
|
|
│ │ ├── roles/ 역할/권한 (RBAC 2차원 권한)
|
|
│ │ ├── db/ DB Pool (wingDb, authDb — re-export), seed
|
|
│ │ ├── middleware/ 보안 (입력 살균, rate-limit)
|
|
│ │ └── {도메인}/ 도메인별 모듈 (Router + Service)
|
|
│ ├── package.json
|
|
│ └── tsconfig.json
|
|
├── database/ SQL 스크립트
|
|
│ ├── schema/ DDL (스키마 정의)
|
|
│ │ ├── 00_init.sql wing DB 생성, PostGIS, 스키마 설정
|
|
│ │ └── 01_auth_tables.sql auth 스키마 테이블 (사용자, 역할, 권한 등)
|
|
│ ├── seed/ 초기 데이터 (01~06)
|
|
│ ├── migration/ 마이그레이션 (001 ~ 016)
|
|
│ └── _deprecated/ 사용 중단 파일 (auth_init.sql 등)
|
|
├── docs/ 개발 문서
|
|
├── .githooks/ Git Hooks (pre-commit, commit-msg)
|
|
├── .gitea/workflows/ CI/CD (Gitea Actions)
|
|
├── .node-version Node.js 20
|
|
└── .npmrc npm 레지스트리 (Nexus 프록시)
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 온라인 설치
|
|
|
|
인터넷이 가능한 환경에서의 설치 절차.
|
|
|
|
### 3-1. 소스 코드 클론
|
|
|
|
```bash
|
|
git clone https://gitea.gc-si.dev/gc/wing-ops.git wing
|
|
cd wing
|
|
```
|
|
|
|
### 3-2. Git Hooks 설정
|
|
|
|
```bash
|
|
# pre-commit (TypeScript + ESLint 검증), commit-msg (Conventional Commits 검증)
|
|
git config core.hooksPath .githooks
|
|
chmod +x .githooks/pre-commit .githooks/commit-msg
|
|
```
|
|
|
|
### 3-3. 의존성 설치
|
|
|
|
npm 레지스트리는 프로젝트 루트의 `.npmrc`에 Nexus 프록시로 설정되어 있다.
|
|
|
|
```bash
|
|
# Frontend
|
|
cd frontend
|
|
npm install
|
|
|
|
# Backend
|
|
cd ../backend
|
|
npm install
|
|
```
|
|
|
|
### 3-4. 환경변수 설정
|
|
|
|
#### Backend (`backend/.env`)
|
|
|
|
```bash
|
|
# ===========================================
|
|
# 서버 설정
|
|
# ===========================================
|
|
PORT=3001
|
|
NODE_ENV=development
|
|
|
|
# ===========================================
|
|
# wing DB (운영 데이터 - PostgreSQL + PostGIS)
|
|
# ===========================================
|
|
WING_DB_HOST=211.208.115.83
|
|
WING_DB_PORT=5432
|
|
WING_DB_USER=wing
|
|
WING_DB_PASS=<비밀번호>
|
|
WING_DB_NAME=wing
|
|
|
|
# ===========================================
|
|
# JWT 인증
|
|
# ===========================================
|
|
JWT_SECRET=<랜덤 시크릿 문자열>
|
|
JWT_EXPIRES_IN=24h
|
|
|
|
# ===========================================
|
|
# CORS (프론트엔드 출처)
|
|
# ===========================================
|
|
FRONTEND_URL=http://localhost:5173
|
|
|
|
# ===========================================
|
|
# Google OAuth (선택)
|
|
# ===========================================
|
|
GOOGLE_CLIENT_ID=<Google OAuth 클라이언트 ID>
|
|
```
|
|
|
|
#### Frontend (`frontend/.env`)
|
|
|
|
```bash
|
|
# 백엔드 API URL
|
|
VITE_API_URL=http://localhost:3001/api
|
|
|
|
# Google OAuth (선택)
|
|
VITE_GOOGLE_CLIENT_ID=<Google OAuth 클라이언트 ID>
|
|
|
|
# 공공데이터 API 키 (해양기상, 선택)
|
|
VITE_DATA_GO_KR_API_KEY=<data.go.kr API 키>
|
|
VITE_WEATHER_API_KEY=<기상 API 키>
|
|
```
|
|
|
|
> `.env` 파일은 `.gitignore`에 포함된다. 실제 값은 팀 내부에서 공유한다.
|
|
|
|
### 3-5. 실행
|
|
|
|
```bash
|
|
# 터미널 1: 백엔드
|
|
cd backend
|
|
npm run dev
|
|
# 출력: 서버가 포트 3001에서 실행 중입니다.
|
|
|
|
# 터미널 2: 프론트엔드
|
|
cd frontend
|
|
npm run dev
|
|
# 출력: VITE vX.X.X ready in XXXms
|
|
# -> Local: http://localhost:5173/
|
|
```
|
|
|
|
브라우저에서 http://localhost:5173 접속하여 확인한다.
|
|
|
|
---
|
|
|
|
## 4. 오프라인 설치
|
|
|
|
인터넷이 불가능한 폐쇄망 환경에서의 설치 절차.
|
|
|
|
### 4-1. 온라인 환경에서 패키지 준비
|
|
|
|
인터넷이 되는 PC에서 다음을 실행한다:
|
|
|
|
```bash
|
|
# 1. 프로젝트 클론 및 의존성 설치
|
|
git clone https://gitea.gc-si.dev/gc/wing-ops.git wing
|
|
cd wing/frontend && npm install
|
|
cd ../backend && npm install
|
|
|
|
# 2. 전체 프로젝트 압축 (node_modules 포함)
|
|
cd ../..
|
|
tar -czf wing_full.tar.gz wing/
|
|
```
|
|
|
|
### 4-2. Node.js 오프라인 설치 파일 준비
|
|
|
|
대상 OS에 맞는 설치 파일을 다운로드한다:
|
|
|
|
| OS | 파일 | 다운로드 |
|
|
|----|------|---------|
|
|
| Linux (x64) | `node-v20.x.x-linux-x64.tar.xz` | https://nodejs.org/dist/v20.x.x/ |
|
|
| macOS (arm64) | `node-v20.x.x-darwin-arm64.tar.gz` | https://nodejs.org/dist/v20.x.x/ |
|
|
| macOS (x64) | `node-v20.x.x-darwin-x64.tar.gz` | https://nodejs.org/dist/v20.x.x/ |
|
|
| Windows | `node-v20.x.x-x64.msi` | https://nodejs.org/dist/v20.x.x/ |
|
|
|
|
### 4-3. 대상 서버에 설치
|
|
|
|
```bash
|
|
# 1. Node.js 설치 (Linux 예시)
|
|
tar -xJf node-v20.x.x-linux-x64.tar.xz
|
|
export PATH=$PWD/node-v20.x.x-linux-x64/bin:$PATH
|
|
# .bashrc 또는 .profile에 PATH 영구 등록
|
|
|
|
# 2. 프로젝트 압축 해제
|
|
tar -xzf wing_full.tar.gz
|
|
cd wing
|
|
|
|
# 3. 환경변수 설정 (3-4 참조)
|
|
vi backend/.env
|
|
vi frontend/.env
|
|
|
|
# 4. 실행 (node_modules가 이미 포함되어 있으므로 npm install 불필요)
|
|
cd backend && npm run dev # 터미널 1
|
|
cd frontend && npm run dev # 터미널 2
|
|
```
|
|
|
|
### 4-4. 오프라인 환경 주의사항
|
|
|
|
- `npm install` 불가하므로 패키지 추가 시 온라인 환경에서 설치 후 재배포해야 한다.
|
|
- DB는 대상 환경에서 접근 가능한 PostgreSQL을 사용해야 한다.
|
|
- 공공데이터 API (기상, 해양) 키가 필요한 기능은 외부 네트워크 접근이 필요하다.
|
|
|
|
---
|
|
|
|
## 5. DB 초기화 및 마이그레이션
|
|
|
|
### 5-1. DB 구성
|
|
|
|
프로젝트는 단일 PostgreSQL 데이터베이스(wing)에 3개의 스키마를 사용한다:
|
|
|
|
| 스키마 | 용도 | 주요 테이블 |
|
|
|--------|------|------------|
|
|
| `public` | 운영 데이터 (사고, 예측, 자산 등) | PostGIS 확장 포함 |
|
|
| `auth` | 인증/권한 (사용자, 역할, 메뉴, 감사로그) | AUTH_USER, AUTH_ROLE, AUTH_PERM 등 |
|
|
| `wing` | 기타 도메인 테이블 | 레이어, 시뮬레이션 등 |
|
|
|
|
백엔드는 `search_path = wing, auth, public`으로 접속하므로 스키마 접두사 없이 테이블을 참조할 수 있다.
|
|
|
|
### 5-2. 신규 DB 초기화
|
|
|
|
PostgreSQL에 최초 설치 시 아래 순서로 실행한다.
|
|
|
|
```bash
|
|
# 1. wing DB 및 스키마 초기화 (PostgreSQL superuser로 실행)
|
|
psql -U postgres -f database/schema/00_init.sql
|
|
|
|
# 2. auth 스키마 테이블 생성
|
|
psql -U postgres -d wing -f database/schema/01_auth_tables.sql
|
|
|
|
# 3. 초기 데이터 적재 (01~06 순서대로)
|
|
psql -U postgres -d wing -f database/seed/01_common_code.sql
|
|
psql -U postgres -d wing -f database/seed/02_org.sql
|
|
psql -U postgres -d wing -f database/seed/03_role.sql
|
|
psql -U postgres -d wing -f database/seed/04_perm_tree.sql
|
|
psql -U postgres -d wing -f database/seed/05_menu.sql
|
|
psql -U postgres -d wing -f database/seed/06_admin_user.sql
|
|
```
|
|
|
|
`database/schema/00_init.sql`에 포함된 내용:
|
|
- 사용자(wing) 및 데이터베이스(wing) 생성
|
|
- PostGIS, uuid-ossp, pgcrypto 확장 설치
|
|
- public, auth, wing 스키마 생성 및 search_path 설정
|
|
- 공통코드, 시뮬레이션, 사고, 예측 등 핵심 테이블 생성
|
|
|
|
`database/schema/01_auth_tables.sql`에 포함된 내용:
|
|
- auth 스키마 내 조직, 역할, 사용자, 권한, 메뉴, 설정, 감사로그 테이블 생성
|
|
|
|
### 5-3. 마이그레이션 적용
|
|
|
|
초기 스키마 이후 추가된 변경 사항은 `database/migration/` 디렉토리에 순번대로 관리된다.
|
|
|
|
```
|
|
database/migration/
|
|
├── 001_layer_table.sql 레이어 테이블
|
|
├── 002_hns_substance.sql HNS 물질 데이터
|
|
├── 003_perm_tree.sql 권한 트리
|
|
├── 004_oper_cd.sql 오퍼레이션 코드
|
|
├── 005_db_consolidation.sql DB 통합
|
|
├── 006_board.sql 게시판
|
|
├── 007_reports.sql 보고서
|
|
├── 008_assets.sql 자산
|
|
├── 008_assets_seed.sql 자산 시드 데이터
|
|
├── 009_incidents.sql 사건/사고
|
|
├── 010_postgis_geom.sql PostGIS 지오메트리
|
|
├── 011_scat.sql SCAT 조사
|
|
├── 012_board_ext.sql 게시판 확장
|
|
├── 013_hns_analysis.sql HNS 분석
|
|
├── 014_prediction.sql 확산 예측
|
|
├── 015_aerial.sql 항공 방제
|
|
└── 016_rescue.sql 구조 시나리오
|
|
```
|
|
|
|
**마이그레이션 실행 (수동):**
|
|
|
|
```bash
|
|
# wing DB에 순번대로 적용
|
|
psql -h <호스트> -p 5432 -U wing -d wing -f database/migration/001_layer_table.sql
|
|
psql -h <호스트> -p 5432 -U wing -d wing -f database/migration/002_hns_substance.sql
|
|
# ... 순번대로 계속
|
|
```
|
|
|
|
> 이미 적용된 마이그레이션을 다시 실행해도 대부분 `IF NOT EXISTS` 조건이 포함되어 있어 안전하다.
|
|
|
|
### 5-4. 시드 데이터
|
|
|
|
초기 데이터(관리자 계정, 공통코드 등)를 입력한다:
|
|
|
|
```bash
|
|
cd backend
|
|
npm run db:seed
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 개발 서버 실행
|
|
|
|
### 6-1. 명령어 요약
|
|
|
|
**Frontend:**
|
|
|
|
| 명령어 | 설명 |
|
|
|--------|------|
|
|
| `npm run dev` | Vite 개발 서버 (localhost:5173, HMR 지원) |
|
|
| `npm run build` | 프로덕션 빌드 (`tsc -b && vite build` -> `dist/`) |
|
|
| `npm run lint` | ESLint 검증 |
|
|
| `npm run preview` | 빌드 결과 미리보기 |
|
|
|
|
**Backend:**
|
|
|
|
| 명령어 | 설명 |
|
|
|--------|------|
|
|
| `npm run dev` | tsx watch 개발 서버 (localhost:3001, 파일 변경 시 자동 재시작) |
|
|
| `npm run build` | TypeScript 컴파일 (`tsc` -> `dist/`) |
|
|
| `npm start` | 프로덕션 실행 (`node dist/server.js`) |
|
|
| `npm run db:seed` | DB 시드 데이터 입력 |
|
|
|
|
### 6-2. 개발 서버 시작
|
|
|
|
```bash
|
|
# 터미널 1: 백엔드 (먼저 실행)
|
|
cd backend
|
|
npm run dev
|
|
# 서버가 포트 3001에서 실행 중입니다.
|
|
# wing DB 연결 성공 (211.208.115.83:5432/wing)
|
|
|
|
# 터미널 2: 프론트엔드
|
|
cd frontend
|
|
npm run dev
|
|
# VITE v7.x.x ready in XXXms
|
|
# -> Local: http://localhost:5173/
|
|
```
|
|
|
|
### 6-3. 검증 명령어
|
|
|
|
```bash
|
|
# TypeScript 타입 체크
|
|
cd frontend && npx tsc --noEmit
|
|
cd backend && npx tsc --noEmit
|
|
|
|
# ESLint
|
|
cd frontend && npx eslint src/
|
|
|
|
# Prettier
|
|
cd frontend && npx prettier --check src/
|
|
cd frontend && npx prettier --write src/ # 자동 수정
|
|
```
|
|
|
|
---
|
|
|
|
## 7. 운영 서버 배포
|
|
|
|
### 7-1. 서버 환경 준비
|
|
|
|
운영 서버(Rocky Linux 9 기준)에 다음을 설치한다:
|
|
|
|
```bash
|
|
# Node.js 20 설치 (fnm 또는 직접 설치)
|
|
curl -fsSL https://fnm.vercel.app/install | bash
|
|
source ~/.bashrc
|
|
fnm install 20
|
|
fnm use 20
|
|
|
|
# PostgreSQL 16 + PostGIS 설치 (dnf 또는 직접 설치)
|
|
# 이미 설치된 경우 생략
|
|
```
|
|
|
|
### 7-2. 수동 배포 절차
|
|
|
|
#### Frontend
|
|
|
|
```bash
|
|
cd frontend
|
|
|
|
# 의존성 설치
|
|
npm ci
|
|
|
|
# 환경변수 설정 (빌드 시 Vite가 주입)
|
|
export VITE_API_URL=/api
|
|
export VITE_GOOGLE_CLIENT_ID=<클라이언트ID>
|
|
export VITE_DATA_GO_KR_API_KEY=<키>
|
|
export VITE_WEATHER_API_KEY=<키>
|
|
|
|
# 프로덕션 빌드
|
|
npx vite build
|
|
|
|
# 빌드 결과를 웹 서버 디렉토리로 복사
|
|
cp -r dist/* /deploy/wing-demo/
|
|
```
|
|
|
|
#### Backend
|
|
|
|
```bash
|
|
cd backend
|
|
|
|
# 의존성 설치
|
|
npm ci
|
|
|
|
# TypeScript 컴파일
|
|
npx tsc
|
|
|
|
# 프로덕션 의존성만 유지 (devDependencies 제거)
|
|
npm prune --omit=dev
|
|
|
|
# 배포 디렉토리로 복사
|
|
mkdir -p /deploy/wing-demo-backend/dist
|
|
cp -r dist/* /deploy/wing-demo-backend/dist/
|
|
cp -r node_modules /deploy/wing-demo-backend/
|
|
cp package.json /deploy/wing-demo-backend/
|
|
```
|
|
|
|
### 7-3. systemd 서비스 등록
|
|
|
|
Backend를 systemd 서비스로 등록하여 자동 시작/재시작을 설정한다.
|
|
|
|
**서비스 파일 생성** (`/etc/systemd/system/wing-demo-api.service`):
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=WING-OPS Backend API
|
|
After=network.target postgresql.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=deploy
|
|
WorkingDirectory=/deploy/wing-demo-backend
|
|
ExecStart=/home/deploy/.local/share/fnm/aliases/default/bin/node dist/server.js
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
# 환경변수
|
|
Environment=NODE_ENV=production
|
|
Environment=PORT=3001
|
|
Environment=WING_DB_HOST=211.208.115.83
|
|
Environment=WING_DB_PORT=5432
|
|
Environment=WING_DB_USER=wing
|
|
Environment=WING_DB_PASS=<비밀번호>
|
|
Environment=WING_DB_NAME=wing
|
|
Environment=JWT_SECRET=<시크릿>
|
|
Environment=JWT_EXPIRES_IN=24h
|
|
Environment=FRONTEND_URL=https://wing-demo.gc-si.dev
|
|
Environment=GOOGLE_CLIENT_ID=<클라이언트ID>
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
**서비스 등록 및 시작:**
|
|
|
|
```bash
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable wing-demo-api
|
|
sudo systemctl start wing-demo-api
|
|
|
|
# 상태 확인
|
|
sudo systemctl status wing-demo-api
|
|
|
|
# 로그 확인
|
|
sudo journalctl -u wing-demo-api -f
|
|
```
|
|
|
|
### 7-4. 리버스 프록시 (Nginx)
|
|
|
|
Frontend 정적 파일과 Backend API를 하나의 도메인으로 서비스한다.
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl;
|
|
server_name wing-demo.gc-si.dev;
|
|
|
|
ssl_certificate /etc/ssl/certs/wing-demo.crt;
|
|
ssl_certificate_key /etc/ssl/private/wing-demo.key;
|
|
|
|
# Frontend 정적 파일
|
|
root /deploy/wing-demo;
|
|
index index.html;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
# Backend API 프록시
|
|
location /api/ {
|
|
proxy_pass http://127.0.0.1:3001/api/;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
# 헬스 체크
|
|
location /health {
|
|
proxy_pass http://127.0.0.1:3001/health;
|
|
}
|
|
}
|
|
|
|
# HTTP -> HTTPS 리다이렉트
|
|
server {
|
|
listen 80;
|
|
server_name wing-demo.gc-si.dev;
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 8. CI/CD 자동 배포
|
|
|
|
### 8-1. Gitea Actions 파이프라인
|
|
|
|
main 브랜치에 push(머지)되면 `.gitea/workflows/deploy.yml`이 자동 실행된다.
|
|
|
|
```
|
|
main 브랜치 push
|
|
|
|
|
[Checkout] 소스 코드 체크아웃
|
|
|
|
|
[Setup Node.js] Node.js 24 설정
|
|
|
|
|
[Configure npm] Nexus 프록시 레지스트리 설정
|
|
|
|
|
[Frontend Build] npm ci -> vite build -> /deploy/wing-demo/
|
|
|
|
|
[Backend Build] npm ci -> tsc -> npm prune --omit=dev
|
|
| -> /deploy/wing-demo-backend/
|
|
|
|
|
[Deploy Trigger] .deploy-trigger 파일 생성
|
|
-> cron/watchdog이 감지 -> 서비스 재시작
|
|
```
|
|
|
|
### 8-2. Gitea Secrets 설정
|
|
|
|
CI/CD에서 사용하는 시크릿을 Gitea에 등록해야 한다:
|
|
|
|
**등록 경로:** Settings -> Actions -> Secrets -> Add Secret
|
|
|
|
| Secret 이름 | 용도 |
|
|
|-------------|------|
|
|
| `NEXUS_NPM_AUTH` | npm Nexus 프록시 인증 토큰 |
|
|
| `GOOGLE_CLIENT_ID` | Google OAuth 클라이언트 ID |
|
|
| `DATA_GO_KR_API_KEY` | 공공데이터 API 키 |
|
|
| `WEATHER_API_KEY` | 기상 API 키 |
|
|
|
|
### 8-3. 배포 확인
|
|
|
|
```bash
|
|
# 프론트엔드 응답 확인
|
|
curl -s -o /dev/null -w '%{http_code}' https://wing-demo.gc-si.dev/
|
|
# 기대: 200
|
|
|
|
# 백엔드 헬스 체크
|
|
curl -s https://wing-demo.gc-si.dev/api/health
|
|
# 기대: {"status":"ok"}
|
|
|
|
# 백엔드 API 정보
|
|
curl -s https://wing-demo.gc-si.dev/api/
|
|
# 기대: {"name":"WING Backend API","version":"1.0.0","status":"running"}
|
|
```
|
|
|
|
---
|
|
|
|
## 9. 접속 정보 요약
|
|
|
|
### 개발 환경
|
|
|
|
| 서비스 | URL | 포트 |
|
|
|--------|-----|------|
|
|
| Frontend (Vite dev) | http://localhost:5173 | 5173 |
|
|
| Backend API | http://localhost:3001 | 3001 |
|
|
| Backend 헬스 체크 | http://localhost:3001/health | 3001 |
|
|
| PostgreSQL (wing) | 211.208.115.83:5432/wing | 5432 |
|
|
|
|
### 운영 환경
|
|
|
|
| 서비스 | URL |
|
|
|--------|-----|
|
|
| Frontend | https://wing-demo.gc-si.dev |
|
|
| Backend API | https://wing-demo.gc-si.dev/api/ |
|
|
| 헬스 체크 | https://wing-demo.gc-si.dev/api/health |
|
|
| Gitea | https://gitea.gc-si.dev/gc/wing-ops |
|
|
|
|
### API 엔드포인트
|
|
|
|
| 경로 | 용도 |
|
|
|------|------|
|
|
| `GET /` | API 정보 |
|
|
| `GET /health` | 헬스 체크 |
|
|
| `POST /api/auth/login` | 로그인 |
|
|
| `POST /api/auth/logout` | 로그아웃 |
|
|
| `GET /api/auth/me` | 현재 사용자 |
|
|
| `GET /api/users` | 사용자 목록 |
|
|
| `GET /api/roles` | 역할 목록 |
|
|
| `GET /api/menus` | 메뉴 목록 |
|
|
| `GET /api/settings` | 시스템 설정 |
|
|
| `GET /api/audit` | 감사 로그 |
|
|
| `GET /api/board` | 게시판 |
|
|
| `GET /api/layers` | 레이어 |
|
|
| `GET /api/simulation` | 시뮬레이션 |
|
|
| `GET /api/hns` | HNS 물질 |
|
|
| `GET /api/reports` | 보고서 |
|
|
| `GET /api/assets` | 자산 |
|
|
| `GET /api/incidents` | 사건/사고 |
|
|
| `GET /api/scat` | SCAT 조사 |
|
|
| `GET /api/prediction` | 확산 예측 |
|
|
| `GET /api/aerial` | 항공 방제 |
|
|
| `GET /api/rescue` | 구조 시나리오 |
|
|
|
|
---
|
|
|
|
## 10. 트러블슈팅
|
|
|
|
### 의존성 설치
|
|
|
|
| 증상 | 원인 | 해결 |
|
|
|------|------|------|
|
|
| `npm install` 실패 (ENETUNREACH) | Nexus 프록시 접근 불가 | `.npmrc`의 registry URL 확인, VPN/네트워크 상태 확인 |
|
|
| `npm install` 실패 (EAUTH) | Nexus 인증 토큰 만료 | `.npmrc`의 `_auth` 값 갱신 |
|
|
| `npm install` 실패 (peer dependency) | 패키지 버전 충돌 | `npm install --legacy-peer-deps` 시도 |
|
|
| `MODULE_NOT_FOUND` | node_modules 누락/손상 | `rm -rf node_modules package-lock.json && npm install` |
|
|
|
|
### 서버 실행
|
|
|
|
| 증상 | 원인 | 해결 |
|
|
|------|------|------|
|
|
| 포트 5173/3001 충돌 | 이미 다른 프로세스가 사용 중 | `lsof -i :5173` 또는 `lsof -i :3001`로 PID 확인 후 `kill -9 <PID>` |
|
|
| 백엔드 시작 시 DB 연결 실패 | DB 접속 정보 오류 또는 네트워크 | `backend/.env`의 DB 호스트/포트/사용자/비밀번호 확인, `nc -zv <호스트> 5432`로 네트워크 확인 |
|
|
| 프론트엔드에서 API 호출 CORS 에러 | 백엔드 CORS 설정 불일치 | `backend/.env`의 `FRONTEND_URL`이 프론트엔드 URL과 일치하는지 확인 |
|
|
| `env: tsx: No such file or directory` | tsx 미설치 | `cd backend && npm install` 재실행 |
|
|
|
|
### DB
|
|
|
|
| 증상 | 원인 | 해결 |
|
|
|------|------|------|
|
|
| `relation "XXX" does not exist` | 테이블 미생성 | `database/schema/*.sql` 또는 해당 마이그레이션 SQL 실행 |
|
|
| PostGIS 함수 에러 | PostGIS 확장 미설치 | `psql -U postgres -d wing -c "CREATE EXTENSION IF NOT EXISTS postgis"` |
|
|
| 인코딩 문제 (한글 깨짐) | DB 인코딩 설정 | DB 생성 시 `ENCODING='UTF8' LC_COLLATE='ko_KR.UTF-8'` 지정 |
|
|
| seed 실패 | 이미 데이터 존재 또는 FK 제약 | 에러 메시지 확인 후 해당 테이블 데이터 정리 |
|
|
|
|
### Git Hooks
|
|
|
|
| 증상 | 원인 | 해결 |
|
|
|------|------|------|
|
|
| pre-commit이 실행되지 않음 | hooksPath 미설정 | `git config core.hooksPath .githooks` |
|
|
| pre-commit permission denied | 실행 권한 없음 | `chmod +x .githooks/pre-commit .githooks/commit-msg` |
|
|
| TypeScript 에러로 커밋 차단 | 타입 에러 존재 | `npx tsc --noEmit`으로 에러 확인 후 수정 |
|
|
| commit-msg 형식 오류 | Conventional Commits 미준수 | `type(scope): subject` 형식 준수 (type: feat, fix, docs 등) |
|
|
|
|
### 빌드
|
|
|
|
| 증상 | 원인 | 해결 |
|
|
|------|------|------|
|
|
| `vite build` 메모리 부족 | Node.js 힙 메모리 부족 | `export NODE_OPTIONS=--max-old-space-size=4096` 후 재시도 |
|
|
| `tsc` 타입 에러 | TypeScript strict 모드 위반 | `npx tsc --noEmit`으로 에러 목록 확인 후 수정 |
|
|
| 빌드 후 라우팅 404 | SPA 서버 설정 누락 | Nginx `try_files $uri $uri/ /index.html` 설정 확인 |
|