fix(setup): 설치 스크립트 3가지 오류 예방 수정 + workspace 자동분석 워크플로우 추가

[설치 스크립트 수정사항]
- PYTHONIOENCODING=utf-8 systemd/NSSM 서비스 환경변수 추가 (Windows cp949 오류 예방)
- db_init.py 헬퍼 추가: 스키마 불일치 자동 감지 → 백업 → 재초기화
- 포트 8001 충돌 감지 및 기존 프로세스 자동 종료 로직 추가
- --test 검증 항목 강화: HTTP 응답 + 로그인 API + UTF-8 인코딩 포함
- setup_ubuntu/centos/rhel: PYTHONUNBUFFERED=1 추가

[workspace 자동분석 워크플로우]
- workspace/ 디렉토리 생성 (소스코드 투입 위치)
- .claude/skills/workspace-analyzer/SKILL.md 스킬 생성
  Phase 0~6: 탐색→스택탐지→심층분석→리포트→개발환경가이드→하네스생성→CLAUDE.md
- CLAUDE.md에 workspace 워크플로우 안내 등록

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
DESKTOP-TKLFCPR\ython 2026-05-29 18:40:20 +09:00
parent 77a0bfb8c8
commit 09ea775a18
8 changed files with 553 additions and 62 deletions

View File

@ -0,0 +1,276 @@
---
name: workspace-analyzer
description: >
워크스페이스에 소스코드를 넣으면 자동으로 분석·하네스 적용·개발환경 가이드를 제공하는 스킬.
다음 상황에서 반드시 사용:
(1) "workspace 폴더에 소스 넣었어", "소스 분석해줘", "하네스 적용해줘" 요청;
(2) workspace/ 하위 폴더에 새 프로젝트가 있을 때;
(3) "개발환경 가이드", "이 소스 어떻게 돌려?", "의존성 뭐야?" 질문;
(4) "프로젝트 분석", "코드베이스 파악", "기술스택 알려줘" 요청;
(5) 처음 보는 레포지토리를 분석해야 할 때.
workspace/ 폴더에 소스가 없을 때도 분석 요청이 오면 이 스킬을 먼저 실행하라.
---
# Workspace 소스 자동분석 + 하네스 적용 + 개발환경 가이드
소스코드를 `workspace/<프로젝트명>/` 에 넣으면 자동으로 3단계를 수행한다.
---
## Phase 0: 워크스페이스 탐색
```
1. Glob("workspace/**") 으로 프로젝트 폴더 목록 확인
2. 분석 대상 폴더 결정:
- 사용자가 폴더명을 명시한 경우 → 해당 폴더
- 명시 없으면 가장 최근 수정된 폴더 (수정 시간 기준)
- 폴더가 없으면 → "workspace/<프로젝트명>/ 폴더를 만들고 소스를 넣어주세요." 안내
```
---
## Phase 1: 기술스택 자동 탐지
아래 파일 존재 여부로 스택을 판별한다.
| 파일 | 스택 |
|------|------|
| `pom.xml` / `build.gradle` | Java (Maven/Gradle) |
| `package.json` | Node.js / React / Vue / Next.js |
| `requirements.txt` / `pyproject.toml` / `setup.py` | Python |
| `composer.json` | PHP |
| `Gemfile` | Ruby on Rails |
| `go.mod` | Go |
| `Cargo.toml` | Rust |
| `*.csproj` / `*.sln` | .NET / C# |
| `Dockerfile` / `docker-compose.yml` | 컨테이너 |
| `.env.example` / `application.yml` | 설정 파일 |
**탐지 순서:**
1. Glob으로 루트 파일 목록 확인
2. 없으면 1~2 depth 하위까지 탐색
3. 여러 스택 감지 시 → 멀티스택으로 처리
---
## Phase 2: 심층 분석 (스택별)
### Java 프로젝트
```
필독 파일: pom.xml 또는 build.gradle (의존성), src/main/resources/application*.yml (설정)
분석 항목:
- Spring Boot 버전, JDK 버전
- 주요 의존성 (JPA, Security, MyBatis, Redis 등)
- DB 설정 (datasource)
- 포트 (server.port, 기본 8080)
- 프로파일 구조 (dev/stg/prd)
- 테스트 프레임워크 (JUnit 5, Mockito)
```
### Python 프로젝트
```
필독 파일: requirements.txt 또는 pyproject.toml, .env.example
분석 항목:
- FastAPI/Django/Flask/Flask 버전
- Python 버전 (.python-version, runtime.txt)
- DB ORM (SQLAlchemy, Django ORM, Tortoise)
- 주요 패키지 (celery, redis, boto3 등)
- 실행 진입점 (main.py, app.py, manage.py, wsgi.py)
```
### Node.js 프로젝트
```
필독 파일: package.json, .env.example, next.config.js
분석 항목:
- 프레임워크 (Next.js, Express, Nest.js, React 순수)
- Node 버전 (.nvmrc, engines 필드)
- 주요 의존성 (ORM, auth, 상태관리 등)
- scripts 명령어 (start, build, dev, test)
- 빌드 도구 (webpack, vite, turbopack)
```
### PHP 프로젝트
```
필독 파일: composer.json, .env.example
분석 항목:
- 프레임워크 (Laravel, Symfony, CodeIgniter, 순수 PHP)
- PHP 버전 (require 필드)
- DB (Eloquent, Doctrine, mysqli)
- 아티즌 명령어 (Laravel일 때)
```
---
## Phase 3: 분석 결과 리포트
다음 형식으로 사용자에게 보고한다:
```markdown
## 소스 분석 결과: {프로젝트명}
### 기술 스택
- 언어: {언어 및 버전}
- 프레임워크: {프레임워크 및 버전}
- DB: {DB 종류}
- 기타: {주요 라이브러리}
### 프로젝트 구조
{핵심 폴더/파일 트리 — 5~10개}
### 진입점
- 실행 명령: `{실행 명령어}`
- 기본 포트: {포트번호}
- 설정 파일: `{설정 파일 경로}`
```
---
## Phase 4: 개발환경 가이드 생성
스택에 맞는 설치 명령어와 실행 방법을 단계별로 제공한다.
### Java (Spring Boot)
```bash
# 1. JDK 설치 확인
java -version # JDK 17+ 필요 (pom.xml java.version 확인)
# 2. 빌드 (Maven)
./mvnw clean package -DskipTests
# 3. DB 설정 (application-local.yml 생성)
# spring.datasource.url, username, password 설정
# 4. 실행
./mvnw spring-boot:run -Dspring-boot.run.profiles=local
# 또는
java -jar target/{artifact}.jar --spring.profiles.active=local
```
### Python (FastAPI/Django)
```bash
# 1. 가상환경
python3.11 -m venv venv && source venv/bin/activate # Linux/Mac
python -m venv venv && venv\Scripts\activate # Windows
# 2. 의존성 설치
pip install -r requirements.txt
# 3. 환경변수 설정
cp .env.example .env # .env 편집 후 DB URL, SECRET_KEY 설정
# 4. DB 초기화 (있으면)
alembic upgrade head # 또는 python manage.py migrate
# 5. 실행
uvicorn main:app --reload --port 8000 # FastAPI
python manage.py runserver 0:8000 # Django
```
### Node.js
```bash
# 1. Node.js 버전 확인 (.nvmrc 있으면 nvm use)
node --version
# 2. 의존성 설치
npm install # 또는 yarn install / pnpm install
# 3. 환경변수
cp .env.example .env
# 4. DB 마이그레이션 (있으면)
npx prisma migrate dev # Prisma
npm run typeorm:migration:run # TypeORM
# 5. 실행
npm run dev # 개발
npm run build && npm start # 빌드 후 실행
```
---
## Phase 5: 하네스 적용
프로젝트 유형에 따라 `.claude/` 하네스를 자동 생성한다.
### 하네스 생성 원칙
- `workspace/{project}/.claude/agents/` 에 에이전트 생성
- `workspace/{project}/.claude/skills/` 에 스킬 생성
- 프레임워크 특성에 맞는 전문 에이전트 구성
### Java Spring Boot 하네스 구성
| 에이전트 | 역할 |
|---------|------|
| `java-dev` | 기능 개발, 테스트 작성 |
| `db-migrator` | 엔티티/마이그레이션 관리 |
| `api-reviewer` | REST API 설계 검토 |
스킬: `run-tests`, `build-check`, `api-spec`
### Python FastAPI 하네스 구성
| 에이전트 | 역할 |
|---------|------|
| `py-dev` | 기능 개발, 의존성 관리 |
| `db-migrator` | Alembic 마이그레이션 |
| `test-runner` | pytest 실행 및 커버리지 |
스킬: `run-tests`, `lint-check`, `type-check`
### Node.js 하네스 구성
| 에이전트 | 역할 |
|---------|------|
| `frontend-dev` | 컴포넌트/페이지 개발 |
| `backend-dev` | API 라우터 개발 |
| `test-runner` | Jest/Vitest 실행 |
스킬: `lint`, `type-check`, `build-check`
### 범용 에이전트 (모든 프로젝트 공통)
| 에이전트 | 역할 |
|---------|------|
| `code-reviewer` | PR 리뷰, 보안 검토 |
| `doc-writer` | README, API 문서 생성 |
---
## Phase 6: CLAUDE.md 자동 생성
`workspace/{project}/CLAUDE.md` 를 자동 생성한다. 포함 내용:
- 프로젝트 개요 및 기술스택
- 디렉토리 구조 (핵심 경로만)
- 실행 명령어 (개발/빌드/테스트)
- 환경변수 목록
- 보안 주의사항 (있으면)
- 하네스 트리거 규칙
---
## 실행 흐름 요약
```
사용자가 소스를 workspace/<proj>/에 넣음
Phase 0: workspace/ 탐색
Phase 1: 기술스택 파일 탐지 (Glob)
Phase 2: 핵심 파일 읽기 (Read)
Phase 3: 분석 리포트 출력
Phase 4: 개발환경 가이드 출력
Phase 5: .claude/ 하네스 생성 (에이전트 + 스킬)
Phase 6: CLAUDE.md 생성
사용자 확인 → 추가 분석 or 개발 시작
```
---
## 주의사항
- **보안**: 소스 내 `.env`, `secrets.yml`, 비밀번호 패턴 발견 시 즉시 경고
- **외부 API 금지**: 분석 중 외부 서비스 호출 금지 (Ollama만 허용)
- **파일 무결성**: workspace/ 소스를 수정하지 않는다 — 분석과 가이드만
- **대용량 파일**: 10,000줄 이상 파일은 헤더/핵심 섹션만 읽는다

View File

@ -108,6 +108,21 @@ C:\GUARDiA\
--- ---
## Workspace 소스 분석 워크플로우
**사용법:**
1. `C:\GUARDiA\workspace\<프로젝트명>\` 폴더에 소스코드를 넣는다
2. Claude에게 "workspace에 소스 넣었어" 또는 "분석해줘" 라고 말한다
3. `workspace-analyzer` 스킬이 자동으로:
- 기술스택 탐지 (Java/Python/Node.js/PHP 등)
- 개발환경 설치 가이드 제공
- `.claude/` 하네스 자동 생성 (에이전트 + 스킬)
- `CLAUDE.md` 자동 생성
**트리거:** `workspace-analyzer` 스킬을 사용하라 — "소스 분석", "workspace", "개발환경 가이드", "하네스 적용" 요청 시.
---
## 하네스: GUARDiA ITSM ## 하네스: GUARDiA ITSM
**목표:** SR 접수·배포·코드리뷰·SLA·인시던트·RCA·보안패치 등 ITSM 운영 전반 자동화 **목표:** SR 접수·배포·코드리뷰·SLA·인시던트·RCA·보안패치 등 ITSM 운영 전반 자동화

116
itsm/tools/db_init.py Normal file
View File

@ -0,0 +1,116 @@
#!/usr/bin/env python3
"""
GUARDiA ITSM DB 초기화 헬퍼 (설치 스크립트용)
스키마 불일치 감지 자동 백업 재초기화.
설치·업그레이드 setup 스크립트에서 호출한다.
사용법:
python tools/db_init.py [--force]
--force: 기존 DB 강제 삭제 재초기화 (신규 설치)
"""
import asyncio
import os
import shutil
import sys
from datetime import datetime
from pathlib import Path
# itsm/ 디렉토리를 Python 경로에 추가
ITSM_DIR = Path(__file__).parent.parent
sys.path.insert(0, str(ITSM_DIR))
os.chdir(str(ITSM_DIR))
# .env 로드 (있으면)
try:
from dotenv import load_dotenv
load_dotenv(".env")
except ImportError:
pass
FORCE = "--force" in sys.argv
DB_PATH = Path(os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./guardia_itsm.db")
.replace("sqlite+aiosqlite:///", "").replace("./", ""))
def _backup_db():
if DB_PATH.exists():
backup = DB_PATH.with_suffix(
f".backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}.db"
)
shutil.copy2(DB_PATH, backup)
print(f"[BACKUP] {DB_PATH}{backup}")
return backup
return None
async def _verify_schema(max_retries: int = 1) -> bool:
"""
현재 DB 스키마가 모델과 일치하는지 확인.
주요 테이블의 컬럼 존재 여부를 점검한다.
"""
from database import SessionLocal
from models import User
from sqlalchemy import select, text
for attempt in range(max_retries + 1):
try:
async with SessionLocal() as db:
# User 테이블 전체 컬럼 조회 (가장 자주 변경되는 테이블)
await db.execute(select(User).limit(1))
return True
except Exception as e:
if attempt == 0:
print(f"[SCHEMA] 스키마 불일치 감지: {e}")
return False
return False
async def main():
from database import init_db, engine
from core.seed import seed_all
from database import SessionLocal
db_is_sqlite = not os.getenv("DATABASE_URL", "").startswith("postgresql")
# ── 신규 설치 모드 --force ──────────────────────────────────────────────
if FORCE and db_is_sqlite and DB_PATH.exists():
print("[FORCE] 기존 DB 삭제 후 재초기화...")
_backup_db()
DB_PATH.unlink()
# ── DB 존재 시 스키마 검증 ──────────────────────────────────────────────
if db_is_sqlite and DB_PATH.exists():
print(f"[CHECK] 기존 DB 스키마 검증: {DB_PATH}")
schema_ok = await _verify_schema()
if not schema_ok:
print("[MIGRATE] 스키마 불일치 — 백업 후 재초기화합니다.")
_backup_db()
DB_PATH.unlink()
print("[INFO] 새 스키마로 DB를 생성합니다.")
else:
print("[OK] 스키마 정상")
# ── 테이블 생성 ────────────────────────────────────────────────────────
try:
await init_db()
print("[OK] DB 테이블 초기화 완료")
except Exception as e:
print(f"[ERROR] DB 초기화 실패: {e}")
sys.exit(1)
# ── 시드 데이터 삽입 ──────────────────────────────────────────────────
try:
async with SessionLocal() as db:
await seed_all(db)
print("[OK] 시드 데이터 삽입 완료")
except Exception as e:
print(f"[WARN] 시드 데이터 삽입 오류 (무시): {e}")
await engine.dispose()
print("[OK] DB 초기화 완료")
if __name__ == "__main__":
asyncio.run(main())

View File

@ -140,23 +140,25 @@ ENVEOF
warn ".env 생성됨 — SECRET_KEY를 변경하세요" warn ".env 생성됨 — SECRET_KEY를 변경하세요"
fi fi
# ── 6. DB 초기화 ──────────────────────────────────────────── # ── 6. DB 초기화 (스키마 불일치 자동 감지·복구) ─────────────────────────
echo "" echo ""
echo "[6/8] DB 초기화..." echo "[6/8] DB 초기화..."
cd "$GUARDIA_ROOT/itsm" cd "$GUARDIA_ROOT/itsm"
source /opt/guardia/venv/bin/activate source /opt/guardia/venv/bin/activate
python -c "
import asyncio, sys if ss -tlnp 2>/dev/null | grep -q ':8001'; then
sys.path.insert(0, '.') warn "포트 8001 사용 중 — 기존 프로세스 종료..."
from dotenv import load_dotenv; load_dotenv('.env') fuser -k 8001/tcp 2>/dev/null || true; sleep 2
from database import init_db fi
asyncio.run(init_db())
print('DB OK') PYTHONIOENCODING=utf-8 python tools/db_init.py --force \
" && ok "DB 초기화 완료" && ok "DB 초기화 완료" || fail "DB 초기화 실패"
# ── 7. systemd 서비스 ─────────────────────────────────────── # ── 7. systemd 서비스 ───────────────────────────────────────
echo "" echo ""
echo "[7/8] systemd 서비스..." echo "[7/8] systemd 서비스..."
systemctl stop guardia-itsm 2>/dev/null || true
cat > /etc/systemd/system/guardia-itsm.service << SVCEOF cat > /etc/systemd/system/guardia-itsm.service << SVCEOF
[Unit] [Unit]
Description=GUARDiA ITSM Server Description=GUARDiA ITSM Server
@ -167,6 +169,8 @@ Type=exec
User=nginx User=nginx
WorkingDirectory=$GUARDIA_ROOT/itsm WorkingDirectory=$GUARDIA_ROOT/itsm
Environment="PATH=/opt/guardia/venv/bin" Environment="PATH=/opt/guardia/venv/bin"
Environment="PYTHONIOENCODING=utf-8"
Environment="PYTHONUNBUFFERED=1"
EnvironmentFile=$GUARDIA_ROOT/itsm/.env EnvironmentFile=$GUARDIA_ROOT/itsm/.env
ExecStart=/opt/guardia/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8001 --workers 4 ExecStart=/opt/guardia/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8001 --workers 4
Restart=always Restart=always

View File

@ -139,23 +139,25 @@ ENVEOF
warn ".env 생성됨 — SECRET_KEY 필수 변경: $ENV_FILE" warn ".env 생성됨 — SECRET_KEY 필수 변경: $ENV_FILE"
fi fi
# ── 7. DB 초기화 ──────────────────────────────────────────── # ── 7. DB 초기화 (스키마 불일치 자동 감지·복구) ─────────────────────────
echo "" echo ""
echo "[7/9] DB 초기화..." echo "[7/9] DB 초기화..."
cd "$GUARDIA_ROOT/itsm" cd "$GUARDIA_ROOT/itsm"
source /opt/guardia/venv/bin/activate source /opt/guardia/venv/bin/activate
python -c "
import asyncio, sys if ss -tlnp 2>/dev/null | grep -q ':8001'; then
sys.path.insert(0, '.') warn "포트 8001 사용 중 — 기존 프로세스 종료..."
from dotenv import load_dotenv; load_dotenv('.env') fuser -k 8001/tcp 2>/dev/null || true; sleep 2
from database import init_db fi
asyncio.run(init_db())
print('DB OK') PYTHONIOENCODING=utf-8 python tools/db_init.py --force \
" && ok "DB 초기화 완료" && ok "DB 초기화 완료" || fail "DB 초기화 실패"
# ── 8. systemd ────────────────────────────────────────────── # ── 8. systemd ──────────────────────────────────────────────
echo "" echo ""
echo "[8/9] systemd 서비스..." echo "[8/9] systemd 서비스..."
systemctl stop guardia-itsm 2>/dev/null || true
cat > /etc/systemd/system/guardia-itsm.service << SVCEOF cat > /etc/systemd/system/guardia-itsm.service << SVCEOF
[Unit] [Unit]
Description=GUARDiA ITSM Server Description=GUARDiA ITSM Server
@ -166,6 +168,8 @@ Type=exec
User=nginx User=nginx
WorkingDirectory=$GUARDIA_ROOT/itsm WorkingDirectory=$GUARDIA_ROOT/itsm
Environment="PATH=/opt/guardia/venv/bin" Environment="PATH=/opt/guardia/venv/bin"
Environment="PYTHONIOENCODING=utf-8"
Environment="PYTHONUNBUFFERED=1"
EnvironmentFile=$GUARDIA_ROOT/itsm/.env EnvironmentFile=$GUARDIA_ROOT/itsm/.env
ExecStart=/opt/guardia/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8001 --workers 4 ExecStart=/opt/guardia/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8001 --workers 4
Restart=always Restart=always

View File

@ -45,13 +45,15 @@ if [[ "$TEST_MODE" == "--test" ]]; then
} }
fail_cnt() { echo -e "${RED}[FAIL]${NC} $*"; } fail_cnt() { echo -e "${RED}[FAIL]${NC} $*"; }
check "Python 3.11+" python3.11 --version check "Python 3.11+" python3.11 --version
check "pip 설치" python3.11 -m pip --version check "pip 설치" python3.11 -m pip --version
check "PostgreSQL" pg_isready -q check "PostgreSQL" pg_isready -q
check "Redis" redis-cli ping check "Redis" redis-cli ping
check "GUARDiA 포트 8001" bash -c 'curl -sf http://localhost:8001/api/dashboard/overview -o /dev/null' check "GUARDiA 서버 기동" systemctl is-active guardia-itsm
check "Nginx 실행" nginx -t check "GUARDiA HTTP 응답" bash -c 'curl -sf http://localhost:8001/ -o /dev/null'
check "systemd 서비스" systemctl is-active guardia-itsm check "GUARDiA 로그인 API" bash -c 'curl -sf -X POST http://localhost:8001/api/auth/login -H "Content-Type: application/json" -d "{\"username\":\"admin\",\"password\":\"1111\"}" -o /dev/null'
check "Nginx 설정" nginx -t
check "Python UTF-8 인코딩" bash -c 'PYTHONIOENCODING=utf-8 python3.11 -c "print(\"OK\")" > /dev/null'
echo "" echo ""
echo "검증 결과: 성공 $PASS / 실패 $FAIL" echo "검증 결과: 성공 $PASS / 실패 $FAIL"
@ -130,24 +132,28 @@ else
info ".env 파일 이미 존재 — 건너뜀" info ".env 파일 이미 존재 — 건너뜀"
fi fi
# ── 5. DB 초기화 ────────────────────────────────────────── # ── 5. DB 초기화 (스키마 불일치 자동 감지·복구) ─────────────────────────
echo "" echo ""
echo "[5/8] DB 초기화..." echo "[5/8] DB 초기화..."
cd "$GUARDIA_ROOT/itsm" cd "$GUARDIA_ROOT/itsm"
source /opt/guardia/venv/bin/activate source /opt/guardia/venv/bin/activate
python -c "
import asyncio, os, sys # 포트 8001 기존 프로세스 종료 (업그레이드 시 충돌 방지)
sys.path.insert(0, '.') if ss -tlnp 2>/dev/null | grep -q ':8001'; then
from dotenv import load_dotenv warn "포트 8001 사용 중 — 기존 프로세스 종료..."
load_dotenv('.env') fuser -k 8001/tcp 2>/dev/null || true
from database import init_db sleep 2
asyncio.run(init_db()) fi
print('DB 초기화 완료')
" && ok "DB 초기화 완료" PYTHONIOENCODING=utf-8 python tools/db_init.py --force \
&& ok "DB 초기화 완료" || fail "DB 초기화 실패 — 로그를 확인하세요"
# ── 6. systemd 서비스 등록 ─────────────────────────────── # ── 6. systemd 서비스 등록 ───────────────────────────────
echo "" echo ""
echo "[6/8] systemd 서비스 등록..." echo "[6/8] systemd 서비스 등록..."
# 기존 서비스 중지 (재설치/업그레이드)
systemctl stop guardia-itsm 2>/dev/null || true
cat > /etc/systemd/system/guardia-itsm.service << SVCEOF cat > /etc/systemd/system/guardia-itsm.service << SVCEOF
[Unit] [Unit]
Description=GUARDiA ITSM Server Description=GUARDiA ITSM Server
@ -158,6 +164,8 @@ Type=exec
User=www-data User=www-data
WorkingDirectory=$GUARDIA_ROOT/itsm WorkingDirectory=$GUARDIA_ROOT/itsm
Environment="PATH=/opt/guardia/venv/bin" Environment="PATH=/opt/guardia/venv/bin"
Environment="PYTHONIOENCODING=utf-8"
Environment="PYTHONUNBUFFERED=1"
EnvironmentFile=$GUARDIA_ROOT/itsm/.env EnvironmentFile=$GUARDIA_ROOT/itsm/.env
ExecStart=/opt/guardia/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8001 --workers 4 ExecStart=/opt/guardia/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8001 --workers 4
Restart=always Restart=always

View File

@ -42,15 +42,30 @@ if ($Test) {
} }
} }
Check-Item "Python 3.11+" { python --version 2>&1 | Select-String "3\.(1[1-9]|[2-9]\d)" } Check-Item "Python 3.11+" { python --version 2>&1 | Select-String "3\.(1[1-9]|[2-9]\d)" }
Check-Item "PostgreSQL" { pg_isready -q } Check-Item "PostgreSQL 응답" { pg_isready -q }
Check-Item "Redis" { redis-cli ping } Check-Item "Redis 응답" { redis-cli ping }
Check-Item "GUARDiA 포트 8001" { Check-Item "NSSM 서비스 등록" { Get-Service "guardia-itsm" -ErrorAction Stop }
$r = Invoke-WebRequest "http://localhost:8001/api/dashboard/overview" -UseBasicParsing -TimeoutSec 5 Check-Item "GUARDiA 서비스 실행" {
if ($r.StatusCode -ne 200) { throw "API 응답 오류" } $s = Get-Service "guardia-itsm"
if ($s.Status -ne "Running") { throw "서비스 상태: $($s.Status)" }
} }
Check-Item "NSSM 서비스" { Get-Service "guardia-itsm" -ErrorAction Stop } Check-Item "GUARDiA HTTP 응답" {
Check-Item "Nginx" { nginx -t 2>&1 } $r = Invoke-WebRequest "http://localhost:8001/" -UseBasicParsing -TimeoutSec 10
if ($r.StatusCode -ne 200) { throw "HTTP $($r.StatusCode)" }
}
Check-Item "GUARDiA 로그인 API" {
$body = '{"username":"admin","password":"1111"}'
$r = Invoke-WebRequest "http://localhost:8001/api/auth/login" -Method POST `
-ContentType "application/json" -Body $body -UseBasicParsing -TimeoutSec 10
if ($r.StatusCode -ne 200) { throw "로그인 실패 ($($r.StatusCode))" }
}
Check-Item "Python UTF-8 인코딩" {
$env:PYTHONIOENCODING = "utf-8"
$out = & python -c "print('OK')" 2>&1
if ("$out" -notmatch "OK") { throw "인코딩 오류: $out" }
}
Check-Item "Nginx 설정" { nginx -t 2>&1 }
Write-Host "" Write-Host ""
Write-Host "검증 결과: 성공 $pass / 실패 $fail" Write-Host "검증 결과: 성공 $pass / 실패 $fail"
@ -158,19 +173,26 @@ MESSENGER_OPS_ROOM=ops
Write-Warn ".env 생성됨 — SECRET_KEY를 변경하세요: $envFile" Write-Warn ".env 생성됨 — SECRET_KEY를 변경하세요: $envFile"
} }
# ── 6. DB 초기화 ──────────────────────────────────────────── # ── 6. DB 초기화 (스키마 불일치 자동 감지·복구) ────────────────────────
Write-Host "" Write-Host ""
Write-Host "[7/8] DB 초기화..." Write-Host "[7/8] DB 초기화..."
# 포트 8001 기존 프로세스 종료 (업그레이드 시 충돌 방지)
$portProc = Get-NetTCPConnection -LocalPort 8001 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
if ($portProc) {
Write-Warn "포트 8001 사용 중 (PID $($portProc.OwningProcess)) — 종료..."
Stop-Process -Id $portProc.OwningProcess -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
}
Push-Location "$GuardiaRoot\itsm" Push-Location "$GuardiaRoot\itsm"
& "$venvPath\Scripts\python.exe" -c @" $env:PYTHONIOENCODING = "utf-8"
import asyncio, sys, os $env:PYTHONUNBUFFERED = "1"
sys.path.insert(0, '.') $dbResult = & "$venvPath\Scripts\python.exe" tools\db_init.py --force 2>&1
os.chdir(r'$GuardiaRoot\itsm') $dbResult | ForEach-Object { Write-Host " $_" }
from dotenv import load_dotenv; load_dotenv('.env') if ($LASTEXITCODE -ne 0) {
from database import init_db Write-Fail "DB 초기화 실패 — 로그를 확인하세요"
asyncio.run(init_db()) }
print('DB OK')
"@
Pop-Location Pop-Location
Write-OK "DB 초기화 완료" Write-OK "DB 초기화 완료"
@ -181,17 +203,18 @@ Write-Host "[8/8] Windows 서비스 등록 (NSSM)..."
$uvicorn = "$venvPath\Scripts\uvicorn.exe" $uvicorn = "$venvPath\Scripts\uvicorn.exe"
$svcName = "guardia-itsm" $svcName = "guardia-itsm"
# 기존 서비스 제거 후 재등록 # 기존 서비스 중지 및 제거 (업그레이드)
nssm stop $svcName 2>$null try { nssm stop $svcName 2>$null; Start-Sleep -Seconds 2 } catch {}
nssm remove $svcName confirm 2>$null try { nssm remove $svcName confirm 2>$null } catch {}
nssm install $svcName $uvicorn nssm install $svcName $uvicorn
nssm set $svcName AppParameters "main:app --host 0.0.0.0 --port 8001 --workers 4" nssm set $svcName AppParameters "main:app --host 0.0.0.0 --port 8001 --workers 4"
nssm set $svcName AppDirectory "$GuardiaRoot\itsm" nssm set $svcName AppDirectory "$GuardiaRoot\itsm"
nssm set $svcName AppEnvironmentExtra "PATH=$venvPath\Scripts;$env:PATH" # PYTHONIOENCODING=utf-8 필수 — Windows 기본 cp949에서 한글 print 오류 방지
nssm set $svcName Start SERVICE_AUTO_START nssm set $svcName AppEnvironmentExtra "PATH=$venvPath\Scripts;$env:PATH PYTHONIOENCODING=utf-8 PYTHONUNBUFFERED=1"
nssm set $svcName AppStdout "C:\guardia\logs\guardia-itsm.log" nssm set $svcName Start SERVICE_AUTO_START
nssm set $svcName AppStderr "C:\guardia\logs\guardia-itsm-err.log" nssm set $svcName AppStdout "C:\guardia\logs\guardia-itsm.log"
nssm set $svcName AppStderr "C:\guardia\logs\guardia-itsm-err.log"
New-Item -ItemType Directory -Force "C:\guardia\logs" | Out-Null New-Item -ItemType Directory -Force "C:\guardia\logs" | Out-Null
nssm start $svcName nssm start $svcName

45
workspace/README.md Normal file
View File

@ -0,0 +1,45 @@
# GUARDiA Workspace
이 폴더에 분석할 프로젝트 소스코드를 넣으세요.
## 사용 방법
1. **소스 배치**
```
workspace/
└── 프로젝트명/ ← 여기에 소스를 넣으세요
├── src/
├── pom.xml (Java)
├── requirements.txt (Python)
├── package.json (Node.js)
└── ...
```
2. **분석 요청**
- `"workspace에 소스 넣었어. 분석해줘."`
- `"<프로젝트명> 소스 분석하고 개발환경 가이드 해줘."`
- `"이 프로젝트에 하네스 적용해줘."`
3. **자동 수행 내용**
- 기술스택 탐지 (Java/Spring, Python/FastAPI, Node.js, PHP 등)
- 의존성 및 설정 파일 분석
- 개발환경 설치 단계별 가이드
- `.claude/` 하네스 자동 생성 (프로젝트에 맞는 에이전트 + 스킬)
- `CLAUDE.md` 자동 생성
## 지원 스택
| 스택 | 감지 파일 |
|------|---------|
| Java (Spring/Gradle/Maven) | `pom.xml`, `build.gradle` |
| Python (FastAPI/Django/Flask) | `requirements.txt`, `pyproject.toml` |
| Node.js (React/Next.js/Express) | `package.json` |
| PHP (Laravel/Symfony) | `composer.json` |
| Go | `go.mod` |
| .NET / C# | `*.csproj`, `*.sln` |
## 보안 주의
- `.env` 파일에 실제 비밀번호를 포함하지 마세요
- 고객사 실제 운영 DB 자격증명이 포함된 파일은 배제하세요
- `.gitignore` 에 workspace/를 추가하는 것을 권장합니다