From 6457817e70a26771d9e20c455d262a78a054de3f Mon Sep 17 00:00:00 2001 From: sangwook yoo Date: Wed, 24 Jun 2026 15:18:23 +0900 Subject: [PATCH] =?UTF-8?q?feat(roof-shape):=20=EC=A7=80=EB=B6=95=ED=98=95?= =?UTF-8?q?=EC=83=81=20=EC=9E=90=EB=8F=99=ED=8C=90=EB=8F=85=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EB=A1=9C=EA=B9=85=20=EC=B6=94=EA=B0=80=20=E2=80=94?= =?UTF-8?q?=20=EC=88=98=EB=8F=99=20QA=20=EB=B3=B4=EC=A1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [작업내용] : - route.js: Gemini roofShape 원본+정규화 결과 logger.debug (서버 콘솔) - useRoofShapeSetting: descriptor→매칭 shapeNum+패턴명 logger.info (브라우저 콘솔, pre-select 시점) - raw console.log 대신 logger 사용(NEXT_PUBLIC_ENABLE_LOGGING=true 시 출력, 프로덕션 무음) Co-Authored-By: Claude Opus 4.8 --- src/app/api/gemini/floor-plan/route.js | 6 +++++- src/hooks/roofcover/useRoofShapeSetting.js | 11 ++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/app/api/gemini/floor-plan/route.js b/src/app/api/gemini/floor-plan/route.js index 6e132d9e..7b42072e 100644 --- a/src/app/api/gemini/floor-plan/route.js +++ b/src/app/api/gemini/floor-plan/route.js @@ -343,6 +343,10 @@ export async function POST(req) { return NextResponse.json({ error: { code: validation.code, message: validation.message } }, { status: 422 }) } + const roofShape = normalizeRoofShape(parsed.roofShape) + // 수동 QA 용 — Gemini 가 판독한 지붕형상 원본과 정규화 결과를 함께 남긴다(NEXT_PUBLIC_ENABLE_LOGGING=true 시). + logger.debug('[gemini/floor-plan] roofShape 판독', { raw: parsed.roofShape ?? null, normalized: roofShape }) + return NextResponse.json({ outerline: parsed.outerline, unit: parsed.unit || 'mm', @@ -350,7 +354,7 @@ export async function POST(req) { confidence: parsed.confidence ?? null, notes: parsed.notes ?? null, selectedDrawingType: parsed.selectedDrawingType ?? null, - roofShape: normalizeRoofShape(parsed.roofShape), + roofShape, empty: validation.empty, }) } catch (error) { diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 5d4936b9..7b1ae75e 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -7,7 +7,8 @@ import { usePolygon } from '@/hooks/usePolygon' import { useMode } from '@/hooks/useMode' import { useLine } from '@/hooks/useLine' import { outerLineFixState, pdfRoofShapeDescriptorState } from '@/store/outerLineAtom' -import { matchRoofShapePattern } from '@/common/roofShapePattern' +import { matchRoofShapePattern, getRoofShapePatternByShapeNum } from '@/common/roofShapePattern' +import { logger } from '@/util/logger' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util' @@ -94,6 +95,14 @@ export function useRoofShapeSetting(id) { // PDF 분석 지붕형상 descriptor 가 있으면 매칭 버튼을 pre-select 한다(자동 선택만 — handleSave 는 사용자 [적용]). if (pdfRoofShapeDescriptor) { const matched = matchRoofShapePattern(pdfRoofShapeDescriptor) + const pattern = matched != null ? getRoofShapePatternByShapeNum(matched) : null + // 수동 QA 용 — Gemini 가 판독한 지붕형상과 자동 선택된 버튼을 콘솔에 남긴다(NEXT_PUBLIC_ENABLE_LOGGING=true 시). + logger.info('[지붕형상 자동판독]', { + descriptor: pdfRoofShapeDescriptor, + matchedShapeNum: matched, + pattern: pattern ? `${pattern.shapeNum}:${pattern.key}(${pattern.note})` : null, + result: matched != null ? 'pre-select(사용자 [적용] 대기)' : '매칭 실패 → 수동 선택(기본값 유지)', + }) if (matched != null) setShapeNum(matched) resetPdfRoofShapeDescriptor() // consume-once: 비-PDF 재진입 시 stale 적용 방지 }