cleanup: remove MariaDB dependencies and files
Some checks failed
Deploy to Vercel / deploy (push) Has been cancelled
Deploy to Railway / deploy (push) Has been cancelled

- Remove MariaDB helper, schema, and initialization script
- Remove mysql2 dependency from package.json
- Update reset-admin.js to use SQLite DatabaseHelper
- Simplify .env.example to remove MariaDB configuration
- Update start-service.sh to use SQLite initialization
- Clean up all MariaDB references across codebase

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-25 14:08:44 +09:00
parent 80f147731e
commit d3d8aa48b6
7 changed files with 21 additions and 466 deletions

View File

@@ -1,238 +0,0 @@
const mysql = require('mysql2/promise');
const { v4: uuidv4 } = require('uuid');
class MariaDBHelper {
constructor() {
this.connection = null;
// 환경별 설정 지원
const isWindows = process.platform === 'win32';
const isNAS = process.env.NODE_ENV === 'production' || process.env.DEPLOY_ENV === 'nas';
if (isWindows) {
// Windows 개발 환경 (NAS MariaDB 원격 접속)
this.config = {
host: process.env.DB_HOST || '119.64.1.86',
port: process.env.DB_PORT || 3306,
user: process.env.DB_USER || 'jaryo_user',
password: process.env.DB_PASSWORD || 'JaryoPass2024!@#',
database: process.env.DB_NAME || 'jaryo',
charset: 'utf8mb4'
};
} else if (isNAS) {
// 시놀로지 NAS 환경 (Unix Socket)
this.config = {
socketPath: '/run/mysqld/mysqld10.sock',
user: 'jaryo_user',
password: 'JaryoPass2024!@#',
database: 'jaryo',
charset: 'utf8mb4'
};
} else {
// 기타 Linux 환경
this.config = {
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 3306,
user: process.env.DB_USER || 'jaryo_user',
password: process.env.DB_PASSWORD || 'JaryoPass2024!@#',
database: process.env.DB_NAME || 'jaryo',
charset: 'utf8mb4'
};
}
}
async connect() {
try {
if (!this.connection || this.connection.connection._closing) {
this.connection = await mysql.createConnection(this.config);
const connectionType = this.config.socketPath ? 'Unix Socket' : `TCP ${this.config.host}:${this.config.port}`;
console.log(`✅ MariaDB 연결 성공 (${connectionType})`);
}
return this.connection;
} catch (error) {
console.error('❌ MariaDB 연결 실패:', error);
console.error('연결 설정:', { ...this.config, password: '***' });
throw error;
}
}
async close() {
if (this.connection) {
await this.connection.end();
this.connection = null;
console.log('📝 MariaDB 연결 종료');
}
}
generateId() {
return uuidv4();
}
// 사용자 관리
async createUser(userData) {
const conn = await this.connect();
const id = this.generateId();
const [result] = await conn.execute(
'INSERT INTO users (id, email, password_hash, name, role) VALUES (?, ?, ?, ?, ?)',
[id, userData.email, userData.password_hash, userData.name, userData.role || 'user']
);
return { id, ...result };
}
async getUserByEmail(email) {
const conn = await this.connect();
const [rows] = await conn.execute(
'SELECT * FROM users WHERE email = ?',
[email]
);
return rows[0] || null;
}
async getUserById(id) {
const conn = await this.connect();
const [rows] = await conn.execute(
'SELECT * FROM users WHERE id = ?',
[id]
);
return rows[0] || null;
}
async updateUserLastLogin(id) {
const conn = await this.connect();
const [result] = await conn.execute(
'UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?',
[id]
);
return result;
}
// 파일 관리
async addFile(fileData) {
const conn = await this.connect();
const [result] = await conn.execute(
'INSERT INTO files (id, title, description, category, tags, user_id) VALUES (?, ?, ?, ?, ?, ?)',
[fileData.id, fileData.title, fileData.description, fileData.category, JSON.stringify(fileData.tags), fileData.user_id]
);
return result;
}
async getAllFiles(limit = 100, offset = 0) {
const conn = await this.connect();
const [rows] = await conn.execute(
'SELECT f.*, u.name as user_name FROM files f LEFT JOIN users u ON f.user_id = u.id ORDER BY f.created_at DESC LIMIT ? OFFSET ?',
[limit, offset]
);
// Parse tags from JSON
return rows.map(row => ({
...row,
tags: row.tags ? JSON.parse(row.tags) : []
}));
}
async searchFiles(searchTerm, category = null, limit = 100) {
const conn = await this.connect();
let query = 'SELECT f.*, u.name as user_name FROM files f LEFT JOIN users u ON f.user_id = u.id WHERE (f.title LIKE ? OR f.description LIKE ?)';
let params = [`%${searchTerm}%`, `%${searchTerm}%`];
if (category) {
query += ' AND f.category = ?';
params.push(category);
}
query += ' ORDER BY f.created_at DESC LIMIT ?';
params.push(limit);
const [rows] = await conn.execute(query, params);
return rows.map(row => ({
...row,
tags: row.tags ? JSON.parse(row.tags) : []
}));
}
async updateFile(id, updates) {
const conn = await this.connect();
const [result] = await conn.execute(
'UPDATE files SET title = ?, description = ?, category = ?, tags = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
[updates.title, updates.description, updates.category, updates.tags, id]
);
return result;
}
async deleteFile(id) {
const conn = await this.connect();
const [result] = await conn.execute('DELETE FROM files WHERE id = ?', [id]);
return result;
}
// 파일 첨부 관리
async addFileAttachment(fileId, attachmentData) {
const conn = await this.connect();
const [result] = await conn.execute(
'INSERT INTO file_attachments (file_id, original_name, file_name, file_path, file_size, mime_type) VALUES (?, ?, ?, ?, ?, ?)',
[fileId, attachmentData.original_name, attachmentData.file_name, attachmentData.file_path, attachmentData.file_size, attachmentData.mime_type]
);
return result;
}
async getFileAttachments(fileId) {
const conn = await this.connect();
const [rows] = await conn.execute(
'SELECT * FROM file_attachments WHERE file_id = ? ORDER BY created_at',
[fileId]
);
return rows;
}
async deleteFileAttachment(attachmentId) {
const conn = await this.connect();
const [result] = await conn.execute('DELETE FROM file_attachments WHERE id = ?', [attachmentId]);
return result;
}
// 카테고리 관리
async getCategories() {
const conn = await this.connect();
const [rows] = await conn.execute('SELECT * FROM categories ORDER BY name');
return rows;
}
async addCategory(name) {
const conn = await this.connect();
const [result] = await conn.execute('INSERT INTO categories (name) VALUES (?)', [name]);
return result;
}
async updateCategory(id, name) {
const conn = await this.connect();
const [result] = await conn.execute('UPDATE categories SET name = ? WHERE id = ?', [name, id]);
return result;
}
async deleteCategory(id) {
const conn = await this.connect();
const [result] = await conn.execute('DELETE FROM categories WHERE id = ?', [id]);
return result;
}
// 통계
async getStats() {
const conn = await this.connect();
const [userCount] = await conn.execute('SELECT COUNT(*) as count FROM users');
const [fileCount] = await conn.execute('SELECT COUNT(*) as count FROM files');
const [categoryCount] = await conn.execute('SELECT COUNT(*) as count FROM categories');
const [attachmentCount] = await conn.execute('SELECT COUNT(*) as count FROM file_attachments');
return {
users: userCount[0].count,
files: fileCount[0].count,
categories: categoryCount[0].count,
attachments: attachmentCount[0].count
};
}
}
module.exports = MariaDBHelper;

View File

@@ -1,87 +0,0 @@
-- 자료실 MariaDB 데이터베이스 스키마
-- 파일: database/mariadb-schema.sql
-- 데이터베이스 생성
CREATE DATABASE IF NOT EXISTS jaryo
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE jaryo;
-- 사용자 테이블
CREATE TABLE IF NOT EXISTS users (
id VARCHAR(36) PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(100) NOT NULL,
role ENUM('admin', 'user') DEFAULT 'user',
is_active TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
last_login TIMESTAMP NULL,
INDEX idx_email (email),
INDEX idx_role (role)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 카테고리 테이블
CREATE TABLE IF NOT EXISTS categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL,
is_default TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_name (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 파일 정보 테이블
CREATE TABLE IF NOT EXISTS files (
id VARCHAR(36) PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
category VARCHAR(100) NOT NULL DEFAULT '기타',
tags JSON,
user_id VARCHAR(36),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_category (category),
INDEX idx_created_at (created_at),
INDEX idx_user_id (user_id),
INDEX idx_title (title),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 파일 첨부 정보 테이블
CREATE TABLE IF NOT EXISTS file_attachments (
id INT AUTO_INCREMENT PRIMARY KEY,
file_id VARCHAR(36) NOT NULL,
original_name VARCHAR(255) NOT NULL,
file_name VARCHAR(255) NOT NULL,
file_path TEXT NOT NULL,
file_size BIGINT DEFAULT 0,
mime_type VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_file_id (file_id),
INDEX idx_original_name (original_name),
FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 세션 테이블 (선택사항)
CREATE TABLE IF NOT EXISTS user_sessions (
id VARCHAR(255) PRIMARY KEY,
user_id VARCHAR(36) NOT NULL,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_expires_at (expires_at),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 기본 카테고리 데이터 삽입
INSERT IGNORE INTO categories (name, is_default) VALUES
('문서', 1),
('이미지', 1),
('동영상', 1),
('프레젠테이션', 1),
('기타', 1);
-- 기본 관리자 계정 생성 (비밀번호: Hee150603!)
-- 실제 해시는 애플리케이션에서 생성됩니다