위치 기반 검색을 위한 content 테이블 공간 데이터(POINT, SRID 4326) 추가 및 동기화 로직 수정 과정 요약
0. 시스템 아키텍처 (System Architecture)
- 프레임워크: Spring Boot 3.x
- 언어: Java 17
- 주요 기술:
- Spring WebFlux (WebClient): 비동기 외부 API 연동
- Spring Data JPA (Hibernate): 데이터베이스 상호작용 및 ORM
- Hibernate Spatial: 공간 데이터(Point) 처리
- MapStruct: DTO <-> Entity 간 객체 매핑
- MySQL (호환 RDBMS): 데이터 저장소
- Lombok: Boilerplate 코드 감소
- SLF4j (Logback): 로깅
- Gradle: 빌드 및 의존성 관리
1. 목표 설정 및 초기 변경:
- 목표: content 테이블에 위치 기반 검색을 위한 공간 데이터 컬럼(location POINT NOT NULL SRID 4326) 추가.
- 변경 사항:
- 데이터베이스 스키마에 location 컬럼 추가 (POINT 타입, NOT NULL, SRID 4326).
- Content JPA 엔티티에 org.locationtech.jts.geom.Point 타입의 location 필드 추가 및 @Column(..., nullable = false, columnDefinition = "POINT SRID 4326") 매핑 설정.
- build.gradle 또는 pom.xml에 org.hibernate.orm:hibernate-spatial 의존성 추가 (버전 6.6.13.Final 사용 확인됨).
- 데이터 동기화 시 API로부터 받은 mapX, mapY (String 타입) 좌표 값을 사용하여 location 필드를 채우도록 로직 수정 필요.
2. 주요 발생 이슈 및 해결 과정:
- 이슈 1: Null Location Field (DataIntegrityViolationException: not-null property references a null...)
- 현상: 동기화 로직 수정 후, Content 엔티티 저장 시 location 필드가 null이어서 데이터베이스의 NOT NULL 제약 조건을 위반하는 오류 발생.
- 원인 추정: 초기 변환 로직 (예: DTO String -> Entity BigDecimal -> @AfterMapping에서 double 변환 -> JTS Point 생성)이 복잡하여, 특정 데이터 처리 중 예외 발생 시 (좌표 변환 실패, NullPointerException 등) location 필드가 최종적으로 null로 남게 되는 문제 발생. 오류 처리 로직에서 기본값을 설정하더라도 효과가 없었을 수 있음.
- 해결 시도: 좌표 변환 및 Point 생성 로직을 MapStruct의 @Named 어노테이션을 이용한 별도 헬퍼 메소드(dtoToPoint)로 분리하고, @Mapping(target = "location", source = "commonDto", qualifiedByName="dtoToPoint")를 통해 매핑 과정에서 직접 호출하도록 구조 변경. 이 메소드는 DTO를 받아 Point 객체를 반환하도록 설계.
- 이슈 2: Invalid Geometry Data (DataTruncation: Cannot get geometry object from data...)
- 현상: location 필드가 null이 되는 문제는 해결되었으나 (항상 Point 객체가 생성됨), 이번에는 데이터베이스가 해당 Point 데이터를 GEOMETRY 필드에 저장할 수 없다는 오류 발생. 즉, 전송된 데이터 형식을 데이터베이스가 공간 객체로 인식하지 못함.
- 원인 분석: 애플리케이션에서 생성된 JTS Point 객체가 데이터베이스가 기대하는 형식(예: WKB - Well-Known Binary)으로 올바르게 직렬화되지 못함. 가장 유력한 원인은 SRID (Spatial Reference ID) 처리 문제. GeometryFactory 생성 시 SRID 4326을 지정했음에도 불구하고, 생성된 Point 객체에 이 SRID 정보가 명시적으로 포함되지 않거나, Hibernate Spatial 또는 MySQL JDBC 드라이버가 이 정보를 데이터베이스에 올바르게 전달하지 못했을 가능성. 데이터베이스 컬럼 자체의 SRID 설정(SRID 0 또는 다른 값)과 애플리케이션에서 보내는 데이터의 SRID(4326) 간의 불일치도 원인이 될 수 있음.
- 최종 해결: dtoToPoint 메소드 내에서 geometryFactory.createPoint(...)로 Point 객체를 생성한 직후, point.setSRID(4326); 코드를 추가하여 JTS Point 객체에 SRID 값을 명시적으로 설정. 이를 통해 Hibernate가 데이터를 직렬화하여 데이터베이스로 전송할 때 SRID 정보(4326)가 명확하게 포함되도록 하여 데이터베이스가 해당 데이터를 올바른 SRID를 가진 유효한 POINT 데이터로 인식하게 함.
3. 결론:
위치 데이터 컬럼 추가 및 관련 동기화 로직 수정 과정에서 NOT NULL 제약 조건 위반 문제와 데이터베이스의 Geometry 타입 인식 오류라는 두 가지 주요 이슈를 겪었습니다. 첫 번째 문제는 좌표 변환 및 Point 생성 로직을 단순화하고 중앙 집중화하여 해결했으며, 두 번째 문제는 JTS Point 객체에 SRID를 명시적으로 설정 (point.setSRID(4326)) 함으로써 Hibernate Spatial과 데이터베이스 간의 공간 데이터 직렬화/해석 문제를 해결하였습니다.
'Project > teamProject1' 카테고리의 다른 글
참고 (0) | 2025.04.06 |
---|---|
[spring boot3]application.properties VS application.yml (0) | 2025.04.05 |