diff --git a/HANDOFF.md b/HANDOFF.md index 34a33a4..1142ffa 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -4,7 +4,7 @@ - 프로젝트명: 10 Minute Planner 웹 UI - 기술 스택: Vue 3 + Vite + TailwindCSS + JavaScript -- 현재 기준 버전: `v0.1.24` 준비 중 +- 현재 기준 버전: `v0.1.25` 준비 중 - Git 원격 저장소: `https://git.sori.studio/zenn/planner.sori.studio.git` ## 기준 디자인 @@ -162,6 +162,7 @@ - 배포용 `docker-compose.yml`과 별도로 개발용 `docker-compose.dev.yml`을 추가했다. - 개발용 compose는 프론트 `5173`, 백엔드 `3001`, PostgreSQL `5432`를 열고, 소스 마운트 + Vite HMR + Node watch 기반으로 자동 반영된다. - 개발/배포 실행 방법은 루트 `README.md`에 먼저 적고, `HANDOFF.md`에는 변경 이유와 주의사항 위주로 남긴다. +- API 클라이언트는 body가 없는 `GET`, `DELETE` 요청에 `Content-Type: application/json`을 붙이지 않도록 수정했다. 날짜 선택 시 발생하던 `Body cannot be empty...` 오류는 이 문제였다. - 비로그인 랜딩 카드는 상단 고정이 아니라 화면 중앙에 오도록 정렬을 수정했다. - 현재 환경에서는 Docker 데몬이 꺼져 있어서 `docker compose build` 실검증은 하지 못했고, 데몬 시작 후 다시 확인이 필요하다. - 이미지 저장 기능은 추후 `print-only` 또는 별도 export 전용 레이아웃을 기준으로 구현하면 화면/인쇄/공유 결과를 맞추기 쉽다. diff --git a/package-lock.json b/package-lock.json index b5ecbbf..469ca7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ten-minute-planner", - "version": "0.1.24", + "version": "0.1.25", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ten-minute-planner", - "version": "0.1.24", + "version": "0.1.25", "dependencies": { "vue": "^3.5.13" }, diff --git a/package.json b/package.json index 6a7dd45..276008d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ten-minute-planner", "private": true, - "version": "0.1.24", + "version": "0.1.25", "type": "module", "scripts": { "dev": "vite", diff --git a/src/lib/authClient.js b/src/lib/authClient.js index 5bcb924..5b7dc7c 100644 --- a/src/lib/authClient.js +++ b/src/lib/authClient.js @@ -1,19 +1,20 @@ const AUTH_STORAGE_KEY = 'ten-minute-planner-auth' import { buildApiUrl, toUserFacingApiError } from './apiBase' -function buildHeaders(token, extraHeaders = {}) { +function buildHeaders(token, hasBody, extraHeaders = {}) { return { - 'Content-Type': 'application/json', + ...(hasBody ? { 'Content-Type': 'application/json' } : {}), ...(token ? { Authorization: `Bearer ${token}` } : {}), ...extraHeaders, } } async function request(path, { method = 'GET', token, body } = {}) { + const hasBody = body !== undefined const response = await fetch(buildApiUrl(path), { method, - headers: buildHeaders(token), - body: body ? JSON.stringify(body) : undefined, + headers: buildHeaders(token, hasBody), + body: hasBody ? JSON.stringify(body) : undefined, }) const data = await response.json().catch(() => ({})) diff --git a/src/lib/goalsApi.js b/src/lib/goalsApi.js index 4f617a8..06d960c 100644 --- a/src/lib/goalsApi.js +++ b/src/lib/goalsApi.js @@ -1,17 +1,18 @@ import { buildApiUrl, toUserFacingApiError } from './apiBase' -function buildHeaders(token) { +function buildHeaders(token, hasBody) { return { - 'Content-Type': 'application/json', - Authorization: `Bearer ${token}`, + ...(hasBody ? { 'Content-Type': 'application/json' } : {}), + ...(token ? { Authorization: `Bearer ${token}` } : {}), } } async function request(path, { method = 'GET', token, body } = {}) { + const hasBody = body !== undefined const response = await fetch(buildApiUrl(path), { method, - headers: buildHeaders(token), - body: body ? JSON.stringify(body) : undefined, + headers: buildHeaders(token, hasBody), + body: hasBody ? JSON.stringify(body) : undefined, }) const data = await response.json().catch(() => ({})) diff --git a/src/lib/plannerApi.js b/src/lib/plannerApi.js index 34b3baf..6ac781f 100644 --- a/src/lib/plannerApi.js +++ b/src/lib/plannerApi.js @@ -1,17 +1,18 @@ import { buildApiUrl, toUserFacingApiError } from './apiBase' -function buildHeaders(token) { +function buildHeaders(token, hasBody) { return { - 'Content-Type': 'application/json', - Authorization: `Bearer ${token}`, + ...(hasBody ? { 'Content-Type': 'application/json' } : {}), + ...(token ? { Authorization: `Bearer ${token}` } : {}), } } async function request(path, { method = 'GET', token, body } = {}) { + const hasBody = body !== undefined const response = await fetch(buildApiUrl(path), { method, - headers: buildHeaders(token), - body: body ? JSON.stringify(body) : undefined, + headers: buildHeaders(token, hasBody), + body: hasBody ? JSON.stringify(body) : undefined, }) const data = await response.json().catch(() => ({}))