From 2163d0f31151cce094c2d05124c06b18269b7a85 Mon Sep 17 00:00:00 2001 From: tolelom <98kimsungmin@naver.com> Date: Tue, 24 Feb 2026 22:34:45 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EA=B4=80=EB=A6=AC=EC=9E=90=20=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=EB=A1=9C=EB=93=9C=20=ED=8F=BC=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=94=BC=EB=93=9C=EB=B0=B1=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?nginx=20HTML=20=EC=BA=90=EC=8B=B1=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 저장 실패 시 에러 메시지 표시 - nginx index.html Cache-Control: no-store 설정 Co-Authored-By: Claude Sonnet 4.6 --- nginx.conf | 6 ++++++ src/components/admin/AdminCommon.css | 6 ++++++ src/components/admin/DownloadAdmin.jsx | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/nginx.conf b/nginx.conf index 2a12dc8..2f7415a 100644 --- a/nginx.conf +++ b/nginx.conf @@ -3,6 +3,12 @@ server { root /usr/share/nginx/html; index index.html; + # index.html은 캐싱 금지 (배포 후 즉시 반영) + location = /index.html { + try_files $uri =404; + add_header Cache-Control "no-store, no-cache, must-revalidate"; + } + # SPA fallback (react-router 사용 시 필요) location / { try_files $uri $uri/ /index.html; diff --git a/src/components/admin/AdminCommon.css b/src/components/admin/AdminCommon.css index 1d0ef75..8a0bf0d 100644 --- a/src/components/admin/AdminCommon.css +++ b/src/components/admin/AdminCommon.css @@ -67,6 +67,12 @@ border-color: rgba(186, 205, 176, 0.5); } +.admin-error { + font-size: 0.85rem; + color: rgba(229, 115, 115, 0.9); + margin: 0; +} + .admin-form-actions { display: flex; gap: 8px; diff --git a/src/components/admin/DownloadAdmin.jsx b/src/components/admin/DownloadAdmin.jsx index 415478c..103169d 100644 --- a/src/components/admin/DownloadAdmin.jsx +++ b/src/components/admin/DownloadAdmin.jsx @@ -7,6 +7,7 @@ export default function DownloadAdmin() { const [form, setForm] = useState({ url: '', version: '', fileName: '', fileSize: '', fileHash: '' }); const [loading, setLoading] = useState(false); const [saved, setSaved] = useState(false); + const [error, setError] = useState(''); useEffect(() => { getDownloadInfo() @@ -23,6 +24,7 @@ export default function DownloadAdmin() { const handleSubmit = async (e) => { e.preventDefault(); setLoading(true); + setError(''); try { await apiFetch('/api/download/info', { method: 'PUT', @@ -30,6 +32,8 @@ export default function DownloadAdmin() { }); setSaved(true); setTimeout(() => setSaved(false), 2000); + } catch (err) { + setError(err.message || '저장에 실패했습니다.'); } finally { setLoading(false); } @@ -56,6 +60,7 @@ export default function DownloadAdmin() { {field('파일명', 'fileName', 'A301_Launcher.zip')} {field('파일 크기', 'fileSize', '1.2 GB')} {field('A301.exe SHA256 해시', 'fileHash', 'sha256 해시값 (certutil -hashfile A301.exe SHA256)')} + {error &&

{error}

}