diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 9853736..5125765 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -39,12 +39,17 @@ "mcp__sequential-thinking__sequentialthinking", "Bash(git commit:*)", "Bash(chmod:*)", - "Bash(./deploy-to-nas.sh:*)" + "Bash(./deploy-to-nas.sh:*)", + "Bash(ssh:*)", + "Bash(scp:*)", + "Bash(cat:*)", + "Bash(./deploy-manual.sh)" ], "deny": [], "ask": [], "additionalDirectories": [ - "C:\\c\\Users\\COMTREE\\claude_code" + "C:\\c\\Users\\COMTREE\\claude_code", + "C:\\Users\\COMTREE\\.ssh" ] }, "default-mode": "plan" diff --git a/deploy-manual.sh b/deploy-manual.sh new file mode 100644 index 0000000..b865fb9 --- /dev/null +++ b/deploy-manual.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# 수동 배포 스크립트 - 각 단계를 개별 실행 +NAS_IP="119.64.1.86" +NAS_USER="vibsin9322" +DEPLOY_DIR="/volume1/web/jaryo" +GITEA_URL="http://119.64.1.86:3000/vibsin9322/jaryo.git" + +echo "==========================================" +echo "🔧 수동 배포 가이드" +echo "==========================================" +echo "다음 명령들을 하나씩 실행하세요:" +echo "" + +echo "1️⃣ SSH 연결 테스트:" +echo "ssh -p 2222 $NAS_USER@$NAS_IP" +echo "" + +echo "2️⃣ 기존 배포 백업 (있는 경우):" +echo "ssh -p 2222 $NAS_USER@$NAS_IP 'sudo cp -r $DEPLOY_DIR ${DEPLOY_DIR}_backup_\$(date +%Y%m%d_%H%M%S) 2>/dev/null || true'" +echo "" + +echo "3️⃣ 배포 디렉토리 준비:" +echo "ssh -p 2222 $NAS_USER@$NAS_IP 'sudo rm -rf $DEPLOY_DIR && sudo mkdir -p $DEPLOY_DIR && sudo chown $NAS_USER:users $DEPLOY_DIR'" +echo "" + +echo "4️⃣ Git 클론:" +echo "ssh -p 2222 $NAS_USER@$NAS_IP 'cd $DEPLOY_DIR && git clone $GITEA_URL .'" +echo "" + +echo "5️⃣ 의존성 설치:" +echo "ssh -p 2222 $NAS_USER@$NAS_IP 'cd $DEPLOY_DIR && npm install'" +echo "" + +echo "6️⃣ 데이터베이스 처리:" +echo "ssh -p 2222 $NAS_USER@$NAS_IP 'cd $DEPLOY_DIR && if [ -f data/database.db ]; then echo \"기존 DB 유지\"; else npm run init-db; fi'" +echo "" + +echo "7️⃣ 서비스 시작:" +echo "ssh -p 2222 $NAS_USER@$NAS_IP 'cd $DEPLOY_DIR && PORT=3005 nohup node server.js > logs/app.log 2>&1 & echo \$! > jaryo.pid'" +echo "" + +echo "8️⃣ 서비스 확인:" +echo "curl http://$NAS_IP:3005" +echo "" +echo "==========================================" \ No newline at end of file diff --git a/deploy-to-nas.sh b/deploy-to-nas.sh index 36eea5f..17aad97 100644 --- a/deploy-to-nas.sh +++ b/deploy-to-nas.sh @@ -1,15 +1,22 @@ #!/bin/bash # 시놀로지 NAS 자료실 배포 스크립트 -# 사용법: ./deploy-to-nas.sh [nas-ip] [project-name] +# 사용법: ./deploy-to-nas.sh [nas-ip] [project-name] [password] +# 예시: ./deploy-to-nas.sh 119.64.1.86 jaryo mypassword +# 환경변수: NAS_PASS=mypassword ./deploy-to-nas.sh # 기본 설정 NAS_IP="${1:-119.64.1.86}" PROJECT_NAME="${2:-jaryo}" +NAS_USER="vibsin9322" +NAS_PASS="${3:-vibsin9322}" # 기본 비밀번호, 환경변수 NAS_PASS로 오버라이드 가능 DEPLOY_DIR="/volume1/web/$PROJECT_NAME" SERVICE_PORT="3005" GITEA_URL="http://$NAS_IP:3000/vibsin9322/jaryo.git" +# SSH 명령어 준비 +SSH_CMD="ssh -p 2222 -o ConnectTimeout=10 -o StrictHostKeyChecking=no $NAS_USER@$NAS_IP" + echo "==========================================" echo "🚀 시놀로지 NAS 자료실 배포 시작" echo "==========================================" @@ -23,9 +30,13 @@ echo "==========================================" # 사전 요구사항 확인 echo "📋 1단계: 사전 요구사항 확인" +# SSH 방식 확인 +echo "🔧 SSH 접속 방식: 비밀번호 프롬프트 방식" +echo "📝 SSH 연결 시 비밀번호 입력이 필요합니다." + # SSH 연결 테스트 (포트 2222) -echo "🔗 SSH 연결 테스트 중... (포트 2222)" -if ! ssh -p 2222 -o ConnectTimeout=5 admin@$NAS_IP "echo 'SSH 연결 성공'" 2>/dev/null; then +echo "🔗 SSH 연결 테스트 중... (사용자: $NAS_USER, 포트: 2222)" +if ! eval "$SSH_CMD 'echo SSH 연결 성공'"; then echo "❌ SSH 연결 실패. 다음을 확인하세요:" echo " - NAS IP 주소: $NAS_IP" echo " - SSH 포트: 2222" @@ -37,27 +48,31 @@ echo "✅ SSH 연결 성공" # Node.js 설치 확인 echo "📦 Node.js 설치 확인 중..." -ssh -p 2222 admin@$NAS_IP "which node" >/dev/null 2>&1 -if [ $? -ne 0 ]; then +NODE_PATH="" +if eval "$SSH_CMD 'test -f /usr/local/bin/node'" 2>/dev/null; then + NODE_PATH="/usr/local/bin" +elif eval "$SSH_CMD 'which node'" >/dev/null 2>&1; then + NODE_PATH=$(eval "$SSH_CMD 'which node'" | dirname) +else echo "❌ Node.js가 설치되지 않았습니다." echo "DSM 패키지 센터에서 Node.js를 설치하세요." exit 1 fi -NODE_VERSION=$(ssh -p 2222 admin@$NAS_IP "node --version") -echo "✅ Node.js 설치됨: $NODE_VERSION" +NODE_VERSION=$(eval "$SSH_CMD '$NODE_PATH/node --version'") +echo "✅ Node.js 설치됨: $NODE_VERSION ($NODE_PATH)" # Git 설치 확인 echo "📦 Git 설치 확인 중..." -ssh -p 2222 admin@$NAS_IP "which git" >/dev/null 2>&1 +eval "$SSH_CMD 'which git'" >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "❌ Git이 설치되지 않았습니다." echo "DSM 패키지 센터에서 Git Server를 설치하거나 다음 명령을 실행하세요:" - echo "ssh -p 2222 admin@$NAS_IP 'sudo apt update && sudo apt install git'" + echo "ssh -p 2222 $NAS_USER@$NAS_IP 'sudo apt update && sudo apt install git'" exit 1 fi -GIT_VERSION=$(ssh -p 2222 admin@$NAS_IP "git --version") +GIT_VERSION=$(eval "$SSH_CMD 'git --version'") echo "✅ Git 설치됨: $GIT_VERSION" # 2단계: 소스 코드 배포 @@ -66,7 +81,7 @@ echo "📂 2단계: 소스 코드 배포" # 기존 배포 디렉토리 확인 echo "🗂️ 배포 디렉토리 확인 중..." -ssh -p 2222 admin@$NAS_IP " +eval "$SSH_CMD ' if [ -d '$DEPLOY_DIR' ]; then echo '⚠️ 기존 배포가 존재합니다: $DEPLOY_DIR' echo '백업 생성 중...' @@ -78,7 +93,7 @@ fi # 배포 디렉토리 생성 echo "📁 배포 디렉토리 생성 중..." -ssh -p 2222 admin@$NAS_IP " +eval "$SSH_CMD ' sudo mkdir -p '$DEPLOY_DIR' sudo chown admin:users '$DEPLOY_DIR' cd '$DEPLOY_DIR' @@ -86,7 +101,7 @@ cd '$DEPLOY_DIR' # Git 클론 echo "📥 Gitea에서 소스 코드 클론 중..." -ssh -p 2222 admin@$NAS_IP " +eval "$SSH_CMD ' cd '$DEPLOY_DIR' git clone '$GITEA_URL' . if [ \$? -ne 0 ]; then @@ -100,7 +115,7 @@ echo '✅ 소스 코드 클론 완료' echo "" echo "🔧 3단계: 의존성 설치 및 빌드" -ssh -p 2222 admin@$NAS_IP " +eval "$SSH_CMD ' cd '$DEPLOY_DIR' # 기존 node_modules 제거 @@ -111,7 +126,8 @@ fi # 의존성 설치 echo '📦 의존성 설치 중...' -npm install +export PATH='$NODE_PATH':\$PATH +'$NODE_PATH'/npm install if [ \$? -ne 0 ]; then echo '❌ npm install 실패' @@ -119,11 +135,27 @@ if [ \$? -ne 0 ]; then fi echo '✅ 의존성 설치 완료' -# 데이터베이스 초기화 +# 데이터베이스 백업 및 초기화 if [ -f 'scripts/init-database.js' ]; then - echo '🗄️ 데이터베이스 초기화 중...' - npm run init-db - echo '✅ 데이터베이스 초기화 완료' + # 기존 데이터베이스 백업 + DB_FILE='data/database.db' + BACKUP_FILE='data/database_backup_$(date +%Y%m%d_%H%M%S).db' + + if [ -f '\$DB_FILE' ]; then + echo '💾 기존 데이터베이스 백업 중...' + cp '\$DB_FILE' '\$BACKUP_FILE' + echo '✅ 백업 완료: \$BACKUP_FILE' + + # 기존 데이터 유지 - 초기화 건너뛰기 + echo 'ℹ️ 기존 데이터베이스 발견 - 초기화 건너뛰기' + echo '💡 새 데이터베이스가 필요하면 수동으로 실행: npm run init-db' + else + # 새 설치 - 데이터베이스 초기화 + echo '🗄️ 새 데이터베이스 초기화 중...' + export PATH='$NODE_PATH':\$PATH + '$NODE_PATH'/npm run init-db + echo '✅ 데이터베이스 초기화 완료' + fi fi " @@ -133,13 +165,14 @@ echo "⚙️ 4단계: 서비스 설정" # 시작 스크립트 생성 echo "📝 시작 스크립트 생성 중..." -ssh -p 2222 admin@$NAS_IP " +eval "$SSH_CMD ' cat > '$DEPLOY_DIR/start-nas-service.sh' << 'EOF' #!/bin/bash # 자료실 NAS 서비스 시작 스크립트 PROJECT_DIR='$DEPLOY_DIR' SERVICE_PORT='$SERVICE_PORT' +NODE_PATH='$NODE_PATH' PID_FILE='\$PROJECT_DIR/jaryo-nas.pid' LOG_FILE='\$PROJECT_DIR/logs/app.log' @@ -168,7 +201,7 @@ fi # 서비스 시작 echo '🚀 자료실 서비스 시작 중...' cd '\$PROJECT_DIR' -PORT='$SERVICE_PORT' nohup node server.js > '\$LOG_FILE' 2>&1 & +PORT='$SERVICE_PORT' nohup \$NODE_PATH/node server.js > '\$LOG_FILE' 2>&1 & echo \$! > '\$PID_FILE' sleep 2 @@ -192,7 +225,7 @@ chmod +x '$DEPLOY_DIR/start-nas-service.sh' # 중지 스크립트 생성 echo "📝 중지 스크립트 생성 중..." -ssh -p 2222 admin@$NAS_IP " +eval "$SSH_CMD ' cat > '$DEPLOY_DIR/stop-nas-service.sh' << 'EOF' #!/bin/bash @@ -233,7 +266,7 @@ chmod +x '$DEPLOY_DIR/stop-nas-service.sh' echo "" echo "🎬 5단계: 서비스 시작" -ssh -p 2222 admin@$NAS_IP "$DEPLOY_DIR/start-nas-service.sh" +eval "$SSH_CMD '$DEPLOY_DIR/start-nas-service.sh" # 6단계: 접속 테스트 echo "" @@ -254,13 +287,13 @@ if curl -s "http://$NAS_IP:$SERVICE_PORT" >/dev/null; then echo "📄 로그 파일: $DEPLOY_DIR/logs/app.log" echo "" echo "🔧 서비스 관리:" - echo " 시작: ssh -p 2222 admin@$NAS_IP '$DEPLOY_DIR/start-nas-service.sh'" - echo " 중지: ssh -p 2222 admin@$NAS_IP '$DEPLOY_DIR/stop-nas-service.sh'" - echo " 로그: ssh -p 2222 admin@$NAS_IP 'tail -f $DEPLOY_DIR/logs/app.log'" + echo " 시작: ssh -p 2222 $NAS_USER@$NAS_IP '$DEPLOY_DIR/start-nas-service.sh'" + echo " 중지: ssh -p 2222 $NAS_USER@$NAS_IP '$DEPLOY_DIR/stop-nas-service.sh'" + echo " 로그: ssh -p 2222 $NAS_USER@$NAS_IP 'tail -f $DEPLOY_DIR/logs/app.log'" echo "" echo "📱 브라우저에서 http://$NAS_IP:$SERVICE_PORT 접속하세요!" else echo "❌ 서비스 접속 실패" echo "로그 확인:" - ssh -p 2222 admin@$NAS_IP "tail -20 $DEPLOY_DIR/logs/app.log" + eval "$SSH_CMD 'tail -20 $DEPLOY_DIR/logs/app.log" fi \ No newline at end of file diff --git a/enhanced-server.js b/enhanced-server.js new file mode 100644 index 0000000..c8d9cc0 --- /dev/null +++ b/enhanced-server.js @@ -0,0 +1,234 @@ +const http = require("http"); +const fs = require("fs"); +const path = require("path"); +const url = require("url"); + +const PORT = 3005; +const DATA_FILE = path.join(__dirname, 'data.json'); +const UPLOAD_DIR = path.join(__dirname, 'uploads'); + +// 데이터 파일 초기화 +function initializeData() { + const defaultData = { + users: [ + { + id: '1', + email: 'admin@jaryo.com', + password: 'admin123', + name: '관리자', + role: 'admin' + } + ], + files: [ + { + id: '1', + title: '샘플 문서', + description: '자료실 테스트용 샘플 파일입니다.', + category: '문서', + tags: ['샘플', '테스트'], + user_id: '1', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + attachments: [] + } + ], + categories: ['문서', '이미지', '동영상', '프레젠테이션', '기타'] + }; + + if (!fs.existsSync(DATA_FILE)) { + fs.writeFileSync(DATA_FILE, JSON.stringify(defaultData, null, 2)); + } + + if (!fs.existsSync(UPLOAD_DIR)) { + fs.mkdirSync(UPLOAD_DIR, { recursive: true }); + } +} + +// 데이터 읽기/쓰기 +function readData() { + try { + const data = fs.readFileSync(DATA_FILE, 'utf8'); + return JSON.parse(data); + } catch (error) { + console.error('데이터 읽기 오류:', error); + return { users: [], files: [], categories: [] }; + } +} + +function writeData(data) { + try { + fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2)); + return true; + } catch (error) { + console.error('데이터 쓰기 오류:', error); + return false; + } +} + +// MIME 타입 +const mimeTypes = { + ".html": "text/html; charset=utf-8", + ".css": "text/css", + ".js": "application/javascript", + ".json": "application/json", + ".png": "image/png", + ".jpg": "image/jpeg" +}; + +// API 요청 처리 +async function handleApiRequest(req, res, pathname, query) { + const data = readData(); + + if (pathname === "/api/files/public" && req.method === "GET") { + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ + success: true, + data: data.files, + total: data.files.length + })); + return; + } + + if (pathname === "/api/files" && req.method === "GET") { + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ + success: true, + data: data.files, + total: data.files.length + })); + return; + } + + if (pathname === "/api/auth/login" && req.method === "POST") { + let body = ''; + req.on('data', chunk => body += chunk); + req.on('end', () => { + try { + const { email, password } = JSON.parse(body); + const user = data.users.find(u => u.email === email && u.password === password); + + if (user) { + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ + success: true, + user: { + id: user.id, + email: user.email, + name: user.name, + role: user.role + } + })); + } else { + res.writeHead(401, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ + success: false, + error: '이메일 또는 비밀번호가 올바르지 않습니다.' + })); + } + } catch (error) { + res.writeHead(400, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ + success: false, + error: '잘못된 요청입니다.' + })); + } + }); + return; + } + + // 기본 응답 + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ + success: true, + message: "자료실 API 서버 실행 중", + timestamp: new Date().toISOString(), + path: pathname + })); +} + +// 정적 파일 서빙 +async function serveStaticFile(req, res, pathname) { + const filePath = path.join(__dirname, pathname); + + fs.readFile(filePath, (err, data) => { + if (err) { + res.writeHead(404, { "Content-Type": "text/html; charset=utf-8" }); + res.end(` + + 404 Not Found + +

404 - 파일을 찾을 수 없습니다

+

요청한 파일: ${pathname}

+

홈으로 돌아가기

+ + + `); + return; + } + + const ext = path.extname(filePath); + const contentType = mimeTypes[ext] || "text/plain"; + + res.writeHead(200, { "Content-Type": contentType }); + res.end(data); + }); +} + +// HTTP 서버 +const server = http.createServer(async (req, res) => { + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); + res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With"); + + if (req.method === "OPTIONS") { + res.writeHead(200); + res.end(); + return; + } + + const parsedUrl = url.parse(req.url, true); + let pathname = parsedUrl.pathname; + const query = parsedUrl.query; + + console.log(`📨 ${req.method} ${pathname}`); + + if (pathname.startsWith("/api/")) { + try { + await handleApiRequest(req, res, pathname, query); + } catch (error) { + console.error('API 처리 오류:', error); + res.writeHead(500, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ + success: false, + error: '서버 내부 오류가 발생했습니다.' + })); + } + return; + } + + if (pathname === "/" || pathname === "/index.html") { + pathname = "/index.html"; + } else if (pathname === "/admin" || pathname === "/admin/") { + pathname = "/admin/index.html"; + } + + await serveStaticFile(req, res, pathname); +}); + +server.listen(PORT, () => { + console.log(`🚀 향상된 자료실 서버가 포트 ${PORT}에서 실행 중입니다`); + console.log(`📍 접속 URL: http://119.64.1.86:${PORT}`); + console.log(`🔧 관리자 URL: http://119.64.1.86:${PORT}/admin`); + console.log(`⏰ 시작 시간: ${new Date().toLocaleString("ko-KR")}`); + + initializeData(); + console.log(`✅ 데이터 파일 초기화 완료`); +}); + +process.on("SIGINT", () => { + console.log("\n🛑 서버를 종료합니다..."); + server.close(() => { + console.log("✅ 서버가 정상적으로 종료되었습니다"); + process.exit(0); + }); +}); \ No newline at end of file diff --git a/ssh-connect.sh b/ssh-connect.sh new file mode 100644 index 0000000..2142941 --- /dev/null +++ b/ssh-connect.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# SSH 연결 헬퍼 스크립트 +NAS_IP="${1:-119.64.1.86}" +NAS_USER="${2:-vibsin9322}" +COMMAND="${3:-echo 'SSH 연결 성공'}" + +# 비밀번호를 입력받아 SSH 연결 +echo "🔑 SSH 연결 시도: $NAS_USER@$NAS_IP:2222" +echo "📝 비밀번호를 입력하세요:" + +ssh -p 2222 -o StrictHostKeyChecking=no "$NAS_USER@$NAS_IP" "$COMMAND" \ No newline at end of file