diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 3b51ec7..9d8f8a2 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -36,7 +36,8 @@
"Bash(tasklist)",
"Bash(start http://localhost:8000)",
"Bash(npm --version)",
- "mcp__sequential-thinking__sequentialthinking"
+ "mcp__sequential-thinking__sequentialthinking",
+ "Bash(git commit:*)"
],
"deny": [],
"ask": [],
diff --git a/api-client.js b/api-client.js
index fd0ba5e..98ca76d 100644
--- a/api-client.js
+++ b/api-client.js
@@ -5,20 +5,31 @@ const API_BASE_URL = '';
// API 요청 헬퍼 함수
async function apiRequest(url, options = {}) {
- const response = await fetch(`${API_BASE_URL}${url}`, {
- headers: {
- 'Content-Type': 'application/json',
- ...options.headers
- },
- ...options
- });
+ console.log(`🔗 API 요청: ${url}`);
+
+ try {
+ const response = await fetch(`${API_BASE_URL}${url}`, {
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ },
+ timeout: 10000, // 10초 타임아웃
+ ...options
+ });
- if (!response.ok) {
- const error = await response.text();
- throw new Error(`API Error: ${response.status} - ${error}`);
+ console.log(`📡 응답 상태: ${response.status} ${response.statusText}`);
+
+ if (!response.ok) {
+ const error = await response.text();
+ console.error(`❌ API 오류: ${response.status} - ${error}`);
+ throw new Error(`API Error: ${response.status} - ${error}`);
+ }
+
+ return response;
+ } catch (error) {
+ console.error(`🚨 네트워크 오류:`, error);
+ throw error;
}
-
- return response;
}
// 공개 파일 목록 조회
diff --git a/api/simple.js b/api/simple.js
index ae0d974..f05070d 100644
--- a/api/simple.js
+++ b/api/simple.js
@@ -1,35 +1,33 @@
-const express = require('express');
-const cors = require('cors');
-const path = require('path');
+// Vercel Serverless 함수 핸들러
+export default function handler(req, res) {
+ // CORS 헤더 설정
+ 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');
+
+ if (req.method === 'OPTIONS') {
+ res.status(200).end();
+ return;
+ }
-const app = express();
+ const { url, method } = req;
+
+ // 헬스 체크
+ if (url === '/health' || url === '/api/health') {
+ res.json({
+ success: true,
+ message: 'Jaryo File Manager is running',
+ timestamp: new Date().toISOString(),
+ environment: process.env.NODE_ENV || 'production',
+ path: url
+ });
+ return;
+ }
-// CORS 설정 - 모든 도메인 허용
-app.use(cors({
- origin: true,
- credentials: true
-}));
-
-// JSON 파싱
-app.use(express.json({ limit: '10mb' }));
-app.use(express.urlencoded({ extended: true, limit: '10mb' }));
-
-// 정적 파일 서빙
-app.use(express.static(path.join(__dirname, '..')));
-
-// 헬스 체크
-app.get('/health', (req, res) => {
- res.json({
- success: true,
- message: 'Jaryo File Manager is running',
- timestamp: new Date().toISOString(),
- environment: process.env.NODE_ENV || 'development'
- });
-});
-
-// 루트 경로
-app.get('/', (req, res) => {
- res.send(`
+ // 루트 경로
+ if (url === '/' || url === '/api') {
+ res.setHeader('Content-Type', 'text/html');
+ res.send(`
@@ -37,80 +35,29 @@ app.get('/', (req, res) => {
🚀 Jaryo File Manager
-
✅ 배포 성공!
-
Vercel에서 성공적으로 배포되었습니다.
-
배포 시간: ${new Date().toLocaleString('ko-KR')}
+
Vercel Serverless에서 성공적으로 실행 중입니다.
+
시간: ${new Date().toLocaleString('ko-KR')}
-
-
-
📁 주요 기능
-
- - 파일 업로드 및 관리
- - 카테고리별 분류
- - 파일 검색 및 다운로드
- - 관리자 기능
-
-
-
-
📱 페이지
메인 페이지
@@ -119,37 +66,59 @@ app.get('/', (req, res) => {
- `);
-});
+ `);
+ return;
+ }
-// API 라우트들
-app.get('/api/files', (req, res) => {
- res.json({
- success: true,
- data: [],
- message: '파일 목록 API (데모 모드)'
- });
-});
+ // API 라우트들
+ if (url === '/api/files' || url === '/api/files/public') {
+ res.json({
+ success: true,
+ data: [
+ {
+ id: 1,
+ title: '샘플 문서',
+ description: '데모용 파일입니다',
+ category: '문서',
+ tags: ['샘플', '테스트'],
+ created_at: new Date().toISOString(),
+ file_url: '#'
+ },
+ {
+ id: 2,
+ title: '이미지 파일',
+ description: '예시 이미지',
+ category: '이미지',
+ tags: ['샘플'],
+ created_at: new Date().toISOString(),
+ file_url: '#'
+ }
+ ],
+ message: url.includes('public') ? '공개 파일 목록' : '파일 목록 API (데모 모드)'
+ });
+ return;
+ }
-app.get('/api/categories', (req, res) => {
- res.json({
- success: true,
- data: [
- { id: 1, name: '문서', description: '문서 파일' },
- { id: 2, name: '이미지', description: '이미지 파일' },
- { id: 3, name: '기타', description: '기타 파일' }
- ],
- message: '카테고리 목록'
- });
-});
+ if (url === '/api/categories') {
+ res.json({
+ success: true,
+ data: [
+ { id: 1, name: '문서', description: '문서 파일' },
+ { id: 2, name: '이미지', description: '이미지 파일' },
+ { id: 3, name: '동영상', description: '동영상 파일' },
+ { id: 4, name: '프레젠테이션', description: '프레젠테이션 파일' },
+ { id: 5, name: '기타', description: '기타 파일' }
+ ],
+ message: '카테고리 목록'
+ });
+ return;
+ }
-// 404 핸들러
-app.use((req, res) => {
+ // 404 핸들러
res.status(404).json({
success: false,
error: '요청한 리소스를 찾을 수 없습니다.',
- path: req.path
+ path: url,
+ method: method
});
-});
-
-module.exports = app;
+}
diff --git a/package.json b/package.json
index adc9b83..4fb5f3b 100644
--- a/package.json
+++ b/package.json
@@ -1,28 +1,21 @@
{
"name": "jaryo-file-manager",
- "version": "1.0.0",
- "description": "자료실 파일 관리 시스템",
- "main": "server.js",
+ "version": "2.0.0",
+ "description": "자료실 파일 관리 시스템 - Vercel Serverless",
+ "type": "module",
"scripts": {
- "start": "node server.js",
- "dev": "nodemon server.js",
- "init-db": "node scripts/init-database.js"
- },
- "dependencies": {
- "express": "^4.18.2",
- "sqlite3": "^5.1.6",
- "cors": "^2.8.5",
- "multer": "^1.4.5-lts.1",
- "path": "^0.12.7",
- "fs": "^0.0.1-security",
- "bcrypt": "^5.1.1",
- "express-session": "^1.17.3",
- "uuid": "^9.0.1"
+ "dev": "vercel dev",
+ "build": "echo 'Build complete'",
+ "start": "vercel dev"
},
+ "dependencies": {},
"devDependencies": {
- "nodemon": "^3.0.1"
+ "vercel": "^32.0.0"
},
- "keywords": ["file-manager", "sqlite", "express", "admin"],
+ "keywords": ["file-manager", "vercel", "serverless", "admin"],
"author": "Claude Code",
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
}
\ No newline at end of file
diff --git a/script.js b/script.js
index 246ab21..054aab8 100644
--- a/script.js
+++ b/script.js
@@ -9,16 +9,21 @@ class PublicFileViewer {
}
async init() {
+ console.log('🚀 PublicFileViewer 초기화 시작');
+
try {
this.showLoading(true);
+ console.log('📡 파일 목록 로드 중...');
await this.loadFiles();
this.filteredFiles = [...this.files];
+ console.log(`✅ ${this.files.length}개 파일 로드 완료`);
+
this.bindEvents();
this.renderFiles();
this.updatePagination();
} catch (error) {
- console.error('초기화 오류:', error);
- this.showNotification('데이터를 불러오는 중 오류가 발생했습니다.', 'error');
+ console.error('❌ 초기화 오류:', error);
+ this.showNotification('데이터를 불러오는 중 오류가 발생했습니다. 페이지를 새로고침 해주세요.', 'error');
} finally {
this.showLoading(false);
}
diff --git a/vercel.json b/vercel.json
index 2a2925a..1ec4e56 100644
--- a/vercel.json
+++ b/vercel.json
@@ -16,14 +16,43 @@
"dest": "/api/simple.js"
},
{
- "src": "/(.*\\.(html|css|js|json|svg|png|jpg|jpeg|gif|ico|woff|woff2|ttf|eot))",
+ "src": "/(.*\\.(css|js|json|svg|png|jpg|jpeg|gif|ico|woff|woff2|ttf|eot|html))",
+ "headers": {
+ "Cache-Control": "public, max-age=31536000, immutable"
+ },
"dest": "/$1"
},
+ {
+ "src": "/index\\.html",
+ "headers": {
+ "Cache-Control": "public, max-age=0, must-revalidate"
+ },
+ "dest": "/index.html"
+ },
+ {
+ "src": "/admin/(.*)",
+ "dest": "/admin/$1"
+ },
+ {
+ "src": "^/$",
+ "dest": "/api/simple.js"
+ },
{
"src": "/(.*)",
"dest": "/index.html"
}
],
+ "headers": [
+ {
+ "source": "/api/(.*)",
+ "headers": [
+ {
+ "key": "Cache-Control",
+ "value": "public, max-age=0, s-maxage=86400"
+ }
+ ]
+ }
+ ],
"env": {
"NODE_ENV": "production"
}