feat: Toast 알림 시스템 + 어드민 UX 개선
All checks were successful
Client CI/CD / deploy (push) Successful in 29s
All checks were successful
Client CI/CD / deploy (push) Successful in 29s
- Toast 알림 컴포넌트 추가 (success/error/warn/info) - AnnouncementAdmin 초기 로딩 상태 + 에러 표시 - DownloadAdmin 로딩 상태 추가 - UserAdmin/AnnouncementAdmin에 Toast 피드백 적용 - API client 5xx/네트워크 에러 자동 재시도 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,9 +52,20 @@ async function parseResponse(res) {
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function apiFetch(path, options = {}) {
|
||||
export async function apiFetch(path, options = {}, _retryCount = 0) {
|
||||
const token = localStorage.getItem('token');
|
||||
const res = await doFetch(path, options, token);
|
||||
let res;
|
||||
|
||||
try {
|
||||
res = await doFetch(path, options, token);
|
||||
} catch (e) {
|
||||
// 네트워크 에러 (오프라인 등) — 재시도
|
||||
if (_retryCount < 2) {
|
||||
await delay(1000 * (_retryCount + 1));
|
||||
return apiFetch(path, options, _retryCount + 1);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (res.status === 401) {
|
||||
try {
|
||||
@@ -79,6 +90,16 @@ export async function apiFetch(path, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
// 5xx 서버 에러 — 최대 2회 재시도 (exponential backoff)
|
||||
if (res.status >= 500 && _retryCount < 2) {
|
||||
await delay(1000 * (_retryCount + 1));
|
||||
return apiFetch(path, options, _retryCount + 1);
|
||||
}
|
||||
|
||||
if (!res.ok) throw await parseError(res);
|
||||
return parseResponse(res);
|
||||
}
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user