Skip to content

Latest commit

 

History

31 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nestly-api

nestly 백엔드 — 이사 전 가구 배치를 미리 확인하는 인테리어 시뮬레이터의 API 서버

평면도 이미지 + 보유 가구 + 자연어 요구를 받아, AI가 배치안을 제안하고 코드가 제약(충돌·무타공·치수)을 검증해 실현 가능한 안만 남깁니다. 프론트엔드는 nestly-web(React 19).

Spring Boot 3.5 · Java 21 · PostgreSQL 16 · Flyway · Spring Security(OAuth2) · WebFlux


핵심 아키텍처 — "AI는 제안, 판정은 코드"

flowchart LR
    A[평면도 이미지] -->|VLM 인식| B[방·문·창 구조]
    F[보유 가구 + 자연어 요구] --> G[Generator: 배치안 N개 제안]
    B --> G
    G -->|후보 좌표 JSON| V[Verifier]
    V -->|위반 재현 시 피드백| G
    V -->|통과안만| R[사용자에게 표시]
    subgraph det [결정론 코어]
      V
    end
Loading
  • 판정은 LLM을 신뢰하지 않는다. Verifier는 LLM 응답의 "합격/불합격" 문구를 무시하고, 코드가 위반 3종(collisions 충돌 / no_drilling_violations 무타공 / size_mismatches 치수)을 직접 세어 상태를 확정합니다 — 모두 0이면 passed, 하나라도 있으면 fallback. LLM이 모순된 판정을 내도 일관성이 코드로 보장됩니다.
  • AI 백엔드는 교체 가능하다. VLM·Generator·Verifier·이미지 생성·SMS를 모두 인터페이스로 추상화했습니다. 평면도 인식(VLM)은 NVIDIA 호스팅 모델을 쓰고 실패 시 로컬 7B로 폴백, Verifier/Generator는 로컬 Ollama — 품질·비용에 따라 구현체만 갈아끼웁니다.
  • 실패 정책을 층별로 다르게. 검증 실패 = 결과 미저장(검증의 본질이 깨졌으므로) / 가구 사진 정규화 실패 = 사진은 저장하고 치수만 비움(보조 기능이므로).

도메인 모델 · 스키마

엔티티 11개 — Space(공간·평면도) · Furniture/FurnitureItem/FurnitureCatalog(가구) · Intent(요구·제약) · Layout(배치안 + 검증 로그) · Placement(편집기 배치, 공간당 1행) · GalleryLayout(공개 갤러리) · User/Favorite/Consent.

  • 유연한 결과(인식 초안·검증 로그·배치 스냅샷)는 JSONB(@JdbcTypeCode(SqlTypes.JSON)), PostgreSQL enum은 PostgreSQLEnumJdbcType로 매핑.
  • 스키마는 Flyway 마이그레이션 24개(V1~V24) 가 단일 출처. forward-only(ADD COLUMN/CREATE TABLE), 운영은 ddl-auto: none / 테스트는 validate로 코드-스키마 정합을 강제.

판정 위치가 두 종류로 갈립니다 — 위저드 배치안 검증(passed/fallback)은 위처럼 백엔드가 확정하고, 편집기의 초록/노랑/빨강 판정은 프론트엔드가 기하로 계산합니다(백엔드는 좌표만 보관, judgment_snapshot은 표시용 선택 저장).


API 개요

도메인별 REST 컨트롤러. /api/me/**와 갤러리 쓰기는 인증 필수, 그 외 permitAll.

영역 대표 엔드포인트
인증·계정 POST /api/auth/{register,login}, POST /api/auth/phone/{send,verify}(SMS OTP), OAuth2(카카오·구글), GET/PATCH/DELETE /api/me
공간·인식 POST /api/spaces, POST /api/spaces/{id}/recognize(VLM), PUT /api/spaces/{id}/intent, POST/GET /api/spaces/{id}/layouts(비동기 생성·폴링)
가구 POST /api/spaces/{id}/furniture, .../furniture/photo(사진 인식), /api/me/furniture(라이브러리 CRUD), /api/furniture-catalog
내 공간 POST /api/me/spaces/{id}/claim(익명 공간 귀속), PUT .../base·.../placement·PATCH .../calibration
갤러리 GET /api/gallery(필터), POST/PATCH/DELETE /api/gallery/{id}, .../favorite(찜)

돋보이는 엔지니어링

  • 테스트 445개 — 통합 38개(@SpringBootTest + Testcontainers PG16 + Flyway 전체 적용) · JPA 슬라이스 10개(@DataJpaTest + 실 PG로 enum·ON DELETE CASCADE 검증) · 서비스/DTO 단위.
  • Testcontainers singleton 패턴 — static 블록에서 컨테이너를 1회만 띄우고 JVM 수명 공유(withReuse(true)). 클래스마다 재시작해 포트가 바뀌며 나던 ConnectException flaky를 근본 제거했습니다.
  • N+1 회귀를 테스트로 차단 — Hibernate generate_statistics로 발행 SQL 횟수를 단언해, 연관 로딩이 N+1로 퇴화하면 테스트가 깨지게 했습니다.
  • 0원 운영 제약 설계 — 유료 가구 DB·알림톡 없이 운영자 큐레이션 카탈로그 + 개인 발신번호 SMS OTP(dev/test는 고정코드 Stub, @ConditionalOnProperty)로 대체.

로컬 실행

# 1. DB (PostgreSQL 16)
docker compose up -d nestly-db

# 2. Backend
./gradlew bootRun          # → http://localhost:8081
./gradlew test             # 통합·단위 (Testcontainers, macOS는 Colima)

프로파일 — dev(로컬 Postgres) / prod(접속정보 환경변수) / secret(AI·OAuth 키; application-secret.yml은 .gitignore, 미설정 시 더미 폴백으로 기동).

About

nestly backend (Spring Boot, Java 21, PostgreSQL)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages