01
Requirements
기능 요구 사항
REQ-01
기본 프로세스 상에서 특정 버튼 클릭으로 사용자가 PDF 문서를 업로드한다.
REQ-02
Gemini API 로 해당 문서의 내용 중 평면도를 분석한다.
REQ-03
분석 내용을 응답으로 전달받고 현재 프로세스(캔버스)로 전달한다.
REQ-04
분석이 성공적으로 마무리되면 업로드한 파일은 폐기 처리한다.
02
Decisions
결정사항
워크트리
현재 워크트리
lucid-shaw-91e51f 에서 진행캔버스 반영 형태
외곽선 폴리곤 좌표(JSON)
버튼 위치
floor-plan 상단 툴바
API 호출 위치
서버 라우트
/api/gemini/floor-planGemini 모델
gemini-3.1-pro-preview좌표 단위
mm툴바 아이콘
신규 PDF 아이콘 추가
03
End-to-end Flow
전체 흐름
Client · UI
툴바 버튼 클릭
Client · Modal
PdfImportModal — 파일 선택 및 업로드
Server · Route
POST /api/gemini/floor-plan (multipart)
Gemini · File API
PDF 업로드 → fileUri 획득
Gemini · gemini-3.1-pro-preview
외곽선 좌표 JSON 응답 (mm 단위)
Server · finally
Gemini 파일 삭제 (성공 / 실패 무관)
Client · Canvas
좌표 검증 → outerLinePointsState + QLine / QPolygon 생성
∗ 클라이언트는 서버 라우트만 호출하며 Gemini API 키와 직접 통신하지 않는다.
04
Files
핵심 파일 (수정 / 신규)
영역
경로
변경 내용
구분
서버 라우트
src/app/api/gemini/floor-plan/route.js
multipart 수신 + Gemini 호출 + finally 폐기
신규
환경설정
src/config/config.*.js
GEMINI_API_KEY, GEMINI_MODEL 추가수정
의존성
package.json
@google/generative-ai 추가수정
메뉴 등록
src/store/menuAtom.js (menusState)
{ type: 'pdf-import', name, icon } 항목수정
툴바 분기
src/components/floor-plan/CanvasMenu.jsx (onClickNav)
case 'pdf-import' 추가수정
업로드 모달
src/components/floor-plan/modal/pdfImport/PdfImportModal.jsx
파일 선택 / 진행 / 에러 상태머신
신규
캔버스 반영 hook
src/hooks/pdf-import/usePdfImport.js
좌표 검증 + 단위 변환 + 캔버스 반영
신규
다국어 메시지
메시지 키 추가 — pdf.import.*
ja / ko 양쪽
수정
아이콘
public/ 또는 기존 아이콘 디렉토리
PDF 임포트용 SVG 추가
신규
05
Server Route · /api/gemini/floor-plan
서버 라우트 설계
5 · 1
입력 (Input)
- Content-Type ·
multipart/form-data - file · PDF (≤ 20MB, MIME
application/pdf) - unitHint (옵션) ·
mm·auto
5 · 2
처리 (Pipeline)
formData.get('file')→ 사이즈 / MIME 검증GoogleGenerativeAI(GEMINI_API_KEY)클라이언트 생성- Gemini File API 업로드 →
fileUri획득 gemini-3.1-pro-preview호출 · 외곽선 추출 프롬프트 + JSON 강제- 응답 JSON 파싱 + 좌표 검증 (vertex ≥ 3, 자기교차 / 0면적 거부)
- finally ·
genai.files.delete(uploadedFile.name)
5 · 3
출력 (Output)
- 성공 ·
{ outerline:[{x,y},…], unit:'mm', confidence } - 실패 ·
{ error:{ code, message } } - 응답 스키마:
{ outerline, unit:'mm', scale?, confidence:0..1, notes? } response_mime_type=application/json·response_schema강제
5 · 4
보안 / 운영 (Ops)
GEMINI_API_KEY는 서버 env 만 사용 · 클라이언트 노출 금지- S3 등 영구 저장소에 절대 저장하지 않음 (REQ-04 폐기)
- 로깅은
src/util/logger.js만 사용 - raw 응답 출력은
NEXT_PUBLIC_ENABLE_LOGGING=true일 때만
06
Client Flow
클라이언트 흐름
6 · 1모달 PdfImportModal
- 상태머신 ·
idle → uploading → analyzing → success | error - 호출 ·
fetch('/api/gemini/floor-plan', { method:'POST', body: formData }) - 성공 시
usePdfImport.applyOuterline(points, unit)호출 후 모달 닫기 - 실패 시
useSwal로 에러 메시지 표시
6 · 2캔버스 반영 hook usePdfImport
- 단위 변환 ·
unit === 'mm'→ canvas px/mm 비율로 변환 - 정규화 · 시계방향 정렬 + bounding box 중앙 정렬(translate)
- 기존 외곽선 존재 시
useSwalconfirm — 덮어쓰기 분기 - 점 →
name === 'outerLine'QLine 객체 add setOuterLinePoints(points)후addPolygonByLines(lines)재사용canvas.renderAll()
07
Edge Cases
검증 / 엣지 케이스
PDF 가 아닌 파일
라우트에서 MIME 거부
평면도가 아닌 PDF
모델이 빈 outerline 반환 → 친화적 메시지
좌표 ≤ 2개 / 자기교차 / 0면적
라우트에서 거부 (
SizeSetting 가드와 일관)모델 JSON 파싱 실패
retry 1회 후 실패 메시지
Gemini 호출 실패
finally 에서 File API 삭제 보장
캔버스 기존 외곽선 존재
confirm 후 덮어쓰기
응답이 거대한 폴리곤(> 500 vertex)
Douglas–Peucker 단순화 또는 거부
업로드 파일 크기 초과
클라이언트 / 서버 양쪽 가드
네트워크 실패
모달에 재시도 버튼 + 파일 폐기 보장
08
Conventions · Ops
컨벤션 / 운영
Formatting
- Prettier · single quote · no semicolons
tabWidth: 2·printWidth: 150- 경로 alias
@/...우선 (상대경로 체이닝 지양)
Messaging / I18n
- 모든 알림 · 다이얼로그는
useSwal+useMessage - raw
alert()금지 - 다국어 키
pdf.import.*ja / ko 양쪽 추가
Logging
console.log직접 사용 금지src/util/logger.js·NEXT_PUBLIC_ENABLE_LOGGING게이트- Gemini raw 응답은 로깅 플래그 ON 시에만 출력
Verification
- 마지막에 lint / type / build subagent 점검
- dev 에서 실제 평면도 PDF 1~2건 manual test
[xxxx] feat(api) — Gemini 평면도 분석 라우트 신설
[xxxx] feat(floor-plan) — PDF 임포트 모달 / 툴바 진입
[xxxx] feat(floor-plan) — 분석 결과 외곽선 캔버스 반영
[xxxx] chore — 다국어 메시지 / lint 정리
09
Work Order
작업 순서
@google/generative-ai 의존성 추가GEMINI_API_KEY · GEMINI_MODEL env / config 매핑서버 라우트
src/app/api/gemini/floor-plan/route.js 작성Gemini 호출 + 파일 폐기 (try / finally)
menusState 에 pdf-import 항목 + PDF 아이콘 SVG 추가기존 menusState 아이콘 컨벤션에 맞춤
CanvasMenu.jsx onClickNav switch 에 케이스 추가modalAtom 으로 PdfImportModal 오픈PdfImportModal.jsx 작성idle → uploading → analyzing → success / error 상태머신
usePdfImport.js 작성단위 / 방향 정규화 · 외곽선 덮어쓰기 분기 · QLine / QPolygon 반영
다국어 메시지 키 추가
pdf.import.* · ja / ko 양쪽yarn lint + dev 환경 manual test실제 평면도 PDF 1~2건으로 회귀 확인
의미 단위로 커밋
§ 8 의 commit 단위 표 참고