From df97719e0fd4194fd46ca628073e22b182826837 Mon Sep 17 00:00:00 2001 From: ttipo Date: Sat, 20 Jun 2026 17:18:14 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=B2=A8=EB=B6=80=20=EB=8B=A4=EC=9A=B4?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EB=A7=81=ED=81=AC=EB=A5=BC=20=EB=B0=B1?= =?UTF-8?q?=EC=97=94=EB=93=9C=20=EC=A0=88=EB=8C=80=20URL=20=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 백엔드가 내려준 루트 상대경로(/api/.../download)를 가 프론트 오리진으로 해석해 404 페이지가 뜨던 문제 수정. useApi 에 toAbsoluteApiUrl 추가, 첨부 매핑에 적용. (dev 프론트 5273 / 백엔드 3100 오리진 분리 환경) Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/composables/useApi.ts | 13 +++++++++++++ frontend/src/stores/task.store.ts | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/frontend/src/composables/useApi.ts b/frontend/src/composables/useApi.ts index 78c26df..4b143c6 100644 --- a/frontend/src/composables/useApi.ts +++ b/frontend/src/composables/useApi.ts @@ -58,6 +58,19 @@ const api: AxiosInstance = axios.create({ withCredentials: true, }) +// 백엔드 오리진 — 다운로드 링크용. axios 와 달리 앵커는 baseURL 을 쓰지 않으므로, +// 백엔드가 내려준 루트 상대 경로('/api/...')에 백엔드 오리진을 붙여 절대 URL 로 만든다. +// (dev 는 프론트 5273 / 백엔드 3100 로 오리진이 달라, 안 붙이면 프론트로 가서 404 페이지가 뜬다) +const API_ORIGIN = new URL( + import.meta.env.VITE_API_BASE_URL || '/api', + window.location.origin, +).origin + +export function toAbsoluteApiUrl(path: string): string { + if (!path || /^https?:\/\//i.test(path)) return path + return `${API_ORIGIN}${path.startsWith('/') ? '' : '/'}${path}` +} + // 요청 인터셉터 — CSRF, 추가 헤더 등 필요 시 확장 api.interceptors.request.use( (config: InternalAxiosRequestConfig) => config, diff --git a/frontend/src/stores/task.store.ts b/frontend/src/stores/task.store.ts index 3d60ab5..363cba4 100644 --- a/frontend/src/stores/task.store.ts +++ b/frontend/src/stores/task.store.ts @@ -1,6 +1,7 @@ import { computed, ref } from 'vue' import { defineStore } from 'pinia' import { useTask } from '@/composables/useTask' +import { toAbsoluteApiUrl } from '@/composables/useApi' import { DEFAULT_PAGE_SIZE } from '@/types/pagination' import { escapeHtml, @@ -75,7 +76,8 @@ function toAttachmentView(a: ApiAttachment): AttachmentView { name: a.name, size: formatBytes(a.size), kind: a.kind, - url: a.url, + // 다운로드 앵커용 절대 URL(백엔드 오리진) — 상대경로면 프론트로 가서 404 페이지가 됨 + url: toAbsoluteApiUrl(a.url), } }