v0.1.22 - 로그인 오류 문구와 비로그인 화면 정리

This commit is contained in:
2026-04-22 11:05:46 +09:00
parent bc2e981577
commit b972209c2f
8 changed files with 73 additions and 17 deletions

46
src/lib/apiBase.js Normal file
View File

@@ -0,0 +1,46 @@
const DEFAULT_API_BASE_URL = 'http://localhost:3001'
function normalizeBaseUrl(baseUrl) {
return (baseUrl || DEFAULT_API_BASE_URL).replace(/\/+$/, '')
}
function normalizePath(path) {
return path.startsWith('/') ? path : `/${path}`
}
export function buildApiUrl(path) {
const baseUrl = normalizeBaseUrl(import.meta.env.VITE_API_BASE_URL)
const normalizedPath = normalizePath(path)
if (baseUrl.endsWith('/api') && normalizedPath.startsWith('/api/')) {
return `${baseUrl}${normalizedPath.slice(4)}`
}
return `${baseUrl}${normalizedPath}`
}
export function toUserFacingApiError(error, fallbackMessage) {
const rawMessage = `${error?.message ?? ''}`.trim()
if (!rawMessage) {
return fallbackMessage
}
if (
rawMessage.includes('Failed to fetch') ||
rawMessage.includes('NetworkError') ||
rawMessage.includes('Load failed')
) {
return '서버에 연결하지 못했습니다. 잠시 후 다시 시도해 주세요.'
}
if (
rawMessage.includes('Route ') ||
rawMessage.includes('not found') ||
rawMessage.includes('/api/')
) {
return '로그인 요청을 처리하지 못했습니다. 잠시 후 다시 시도해 주세요.'
}
return rawMessage
}

View File

@@ -1,5 +1,5 @@
const AUTH_STORAGE_KEY = 'ten-minute-planner-auth'
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3001'
import { buildApiUrl, toUserFacingApiError } from './apiBase'
function buildHeaders(token, extraHeaders = {}) {
return {
@@ -10,7 +10,7 @@ function buildHeaders(token, extraHeaders = {}) {
}
async function request(path, { method = 'GET', token, body } = {}) {
const response = await fetch(`${API_BASE_URL}${path}`, {
const response = await fetch(buildApiUrl(path), {
method,
headers: buildHeaders(token),
body: body ? JSON.stringify(body) : undefined,
@@ -19,7 +19,7 @@ async function request(path, { method = 'GET', token, body } = {}) {
const data = await response.json().catch(() => ({}))
if (!response.ok) {
throw new Error(data.message || '요청 처리 중 문제가 발생했습니다.')
throw new Error(toUserFacingApiError(data, '요청 처리 중 문제가 발생했습니다.'))
}
return data

View File

@@ -1,4 +1,4 @@
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3001'
import { buildApiUrl, toUserFacingApiError } from './apiBase'
function buildHeaders(token) {
return {
@@ -8,7 +8,7 @@ function buildHeaders(token) {
}
async function request(path, { method = 'GET', token, body } = {}) {
const response = await fetch(`${API_BASE_URL}${path}`, {
const response = await fetch(buildApiUrl(path), {
method,
headers: buildHeaders(token),
body: body ? JSON.stringify(body) : undefined,
@@ -17,7 +17,7 @@ async function request(path, { method = 'GET', token, body } = {}) {
const data = await response.json().catch(() => ({}))
if (!response.ok) {
throw new Error(data.message || '목표 데이터를 처리하지 못했습니다.')
throw new Error(toUserFacingApiError(data, '목표 데이터를 처리하지 못했습니다.'))
}
return data

View File

@@ -1,4 +1,4 @@
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3001'
import { buildApiUrl, toUserFacingApiError } from './apiBase'
function buildHeaders(token) {
return {
@@ -8,7 +8,7 @@ function buildHeaders(token) {
}
async function request(path, { method = 'GET', token, body } = {}) {
const response = await fetch(`${API_BASE_URL}${path}`, {
const response = await fetch(buildApiUrl(path), {
method,
headers: buildHeaders(token),
body: body ? JSON.stringify(body) : undefined,
@@ -17,7 +17,7 @@ async function request(path, { method = 'GET', token, body } = {}) {
const data = await response.json().catch(() => ({}))
if (!response.ok) {
throw new Error(data.message || '플래너 데이터를 처리하지 못했습니다.')
throw new Error(toUserFacingApiError(data, '플래너 데이터를 처리하지 못했습니다.'))
}
return data