kintex/_workspace/03_backend_wiring.md
zio a963c69141 feat(impl): M2~M5 배선(501→200) + 프론트 화면 4종
backend: M2 배치/규정검증(PostGIS)·M3 설계·M4 배선/견적·M5 RenderJob + 인증(login/workspaces/accept-invite) 매퍼 배선으로 501 해소. M2 자동배치 3안 생성→선택/병합→규정 재검증. 계약 확장(Violation 좌표·LayoutDto.hall·AutoLayoutOption.booths, additive NON_NULL). 신규 HallMapper·UtilityOrderMapper(기존 테이블). gradlew build 통과.

frontend: SCR-02 대시보드·SCR-06 설계스튜디오(4샷+Before/After)·SCR-07 배선뷰(적/청/녹)·SCR-12 갤러리 + CompareSlider(reroomai)·WiringCanvas. tsc/vite build EXIT 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 18:37:26 +09:00

6.7 KiB
Raw Blame History

킨텍스 백엔드 — M2~M5 매퍼 배선 + 계약 확장 (Phase C, D-4)

작성: kintex-backend-dev · 근거: _workspace/01_backend_contracts.md·_workspace/02_db_schema.md·_workspace/02_frontend_progress.md(계약 공백 5건)·IMPLEMENTATION_BACKLOG C-M2~C-M5 대상: frontend·qa 대조. 이번 회차는 db-engineer가 완성한 MyBatis 매퍼에 ServiceImpl을 배선해 M2~M5·인증의 501(NOT_IMPLEMENTED)을 200으로 전환하고, 프론트가 지적한 계약 공백을 additive(하위호환)로 보강한다. 스키마 마이그레이션·2FA·프론트·build.gradle 미변경. 커밋 없음(파일만).


1. 501 → 200 전환된 엔드포인트

모듈 메서드 엔드포인트 배선 요지
인증 login POST /api/auth/login UserMapper.findAuthByEmail + BCrypt 대조 + findEventRoles→토큰·워크스페이스
인증 listWorkspaces GET /api/auth/workspaces findEventRoles(userId)→WorkspaceDto[]
인증 acceptInvite POST /api/auth/accept-invite 등록업체 검증(findCompanyRegistered)→토큰 재발급. ★초대코드 매핑은 후속(아래 TODO)
M2 getLayout GET …/halls/{hallId}/layout findLayout+findBooths(GeoJSON 파싱)+HallMapper+검증 요약
M2 saveLayout PUT …/layout 폴리곤→WKT upsertLayout+replaceBooths, 저장 후 규정 재검증 반영
M2 validate POST …/layout/validate minAisleWidth·countExitsBlocked+부스 최댓값→룰엔진 M2
M2 autoGenerate POST …/layout/auto-generate 제약 기반 그리드 패킹으로 정확히 optionCount(기본 3)안 + S7 발행
M2 applyOption POST …/layout/apply-option (신규) 선택/병합 부스열→새 버전 저장+규정 재검증
M3 getDesign GET …/booths/{boothId}/design findDesign+spec(jsonb) 역직렬화
M3 saveDesign PUT …/design spec 직렬화 upsertDesign(버전 next), 최신본 반환
M4 computeWiring POST …/utility/wiring isAssumedTrench+단말별 shortestPath(LineString 파싱)·색상 규약
M4 submitOrder POST …/utility/order quote+UtilityOrderMapper.insertOrder(영속)+위치표시도 URL·마감/릴레이 고지
M4 getOrder GET …/utility UtilityOrderMapper.findOrder(부스 최신)
M5 listByBooth GET …/render-jobs RenderJobMapper.findByBooth→갤러리 목록(워터마크 항상 포함)
M5 publish(보강) POST …/render 쿼터 정본을 countSucceededByEvent(DB DONE)로 전환 + insertJob 내구 이력
M5 callback(보강) POST /api/internal/render/callback updateStatus 내구 갱신(쿼터는 DONE 집계에서 자동)

2. 계약 확장 (additive · 하위호환 · 프론트 gap 해소)

모두 @JsonInclude(NON_NULL)기존 필드 불변, 신규 nullable 필드만 추가.

2-1. gap #1 — 위반 오버레이 좌표 (rules.Violation)

  • 추가 필드: boothId(String, nullable) · anchor([x,y] 미터, nullable).
  • 부스 단위 규칙(HEIGHT_MAX·FLOOR_LOAD) 위반에 한해 해당 부스 id + 폴리곤 중심 앵커를 부여. 레이아웃 단위(AISLE_WIDTH_MIN·EXIT_ACCESS)는 null(캔버스에서 목록 핀만).
  • 프론트: violations[].anchor 존재 시 캔버스 핀 위치로 사용, 없으면 기존처럼 목록 핀만.
{ "pin":1, "code":"HEIGHT_MAX", "severity":"block", "measured":"측정 5.4m",
  "boothId":"b-102", "anchor":[3.0,1.5] }

2-2. gap #2 — 홀 치수·트렌치 (m2.dto.LayoutDto.hall = HallInfo)

  • LayoutDtohall 필드 추가(신규 HallInfo). 캔버스 하드코딩(126×90m·트렌치 그리드) 제거 근거.
  • HallInfo: hallId·label·dimsM[w,d]·ceilingM·targetBoothCount·floorLoadTPerM2·assumedTrench·trenches[]·exits[].
  • HallInfo.Trench: {trenchId,x,y,assumed,supplies[power|water|air|network|gas]} · HallInfo.Exit: {x,y,clearanceM}.
  • 원천: 신규 HallMapper(hall·trench·hall_exit read-only). assumedTrench=true면 SCR-07 "가정 트렌치" 배지(PLANNING R4).
"hall": { "hallId":"H7","label":"제2전시장 홀7","dimsM":[126,90],"ceilingM":12,
          "targetBoothCount":510,"floorLoadTPerM2":5.0,"assumedTrench":true,
          "trenches":[{"trenchId":"H7-T-3-3","x":3,"y":3,"assumed":true,"supplies":["power","water","air","network","gas"]}],
          "exits":[{"x":63,"y":0,"clearanceM":3.0}] }

2-3. gap #3 — 자동배치 안의 부스 + 적용 경로 (AutoLayoutOption.booths + apply-option)

  • AutoLayoutOptionbooths(BoothDto[]) 추가 — "이 안으로 편집 시작"/병합 소스.
  • 신규 POST …/layout/apply-option (ORGANIZER): body ApplyOptionRequest {name, booths[]} → 새 버전 저장 + 규정 재검증된 LayoutDto.
  • 3안 흐름 마감: auto-generate(3안+각 booths) → 클라 선택/구역 병합(booths 합성) → apply-option(영속+재검증). 단일 안 적용도 동일 엔드포인트.

3. backend 추가 매퍼 (db-engineer 계약 §3 밖 — 기존 테이블 read/write, 마이그레이션 불변)

db-engineer 인수·정본화 요청. 모두 V2~V5 기존 테이블만 사용.

매퍼 메서드 테이블
m2.mapper.HallMapper findHall·findTrenches·findExits hall·trench·hall_exit (read-only)
m4.mapper.UtilityOrderMapper insertOrder·findOrder utility_order (V3)
auth.mapper.UserMapper(+1) findCompanyRegistered company (read-only)

4. 남은 TODO (경계·후속)

  • 초대코드→행사/부스/역할 매핑: invite 테이블·매퍼 미제공 → acceptInvite는 등록업체 게이트 + 현재 역할 재발급까지만. 역할 upsert는 매핑 매퍼 인수 시 배선(db-engineer).
  • 위치표시도 PDF(M4-3): submitOrder는 신청 영속 + 자산 URL(…/utility/location-diagram)·고지 반환. 실제 PDF 렌더는 문서 큐(후속). 현재 해당 GET 자산은 미구현(URL만).
  • wiring 지오메트리 영속: computeWiring은 산출·반환만. utility_order.wiring(MultiLineString) 저장은 후속.
  • 자동배치 최적화: 현재 결정적 그리드 패킹(3안=통로폭/규격 변주, 무위반 골격). 제약 솔버 고도화는 후속(흐름은 성립).
  • 트렌치 실측(R4): 가정 그리드 유지(is_assumed=true). CAD 추출 교체 시 HallInfo.assumedTrench=false 자동 반영.

5. 검증

  • ./gradlew compileJava · ./gradlew build -x test 통과. 매퍼 id/namespace 정합 확인. PostgreSQL 미기동으로 런타임 왕복은 dev 배포 후.
  • 보안 불변 유지: password_hash/otp 응답 제외, 스택트레이스 미노출(요약 메시지), AI 이미지 워터마크·고지 항상 포함, 워커 에러 요약화.