개발환경
JDK 1.8
MySQL
스프링부트 version 2.4.5
발단
JPA를 사용하는 사내 스프링부트 프로젝트를 진행하며 내가 만든 엔티티가 데이터베이스에 반영되지 않는 현상이 발견되었다. 사내 프로젝트는 Mybatis와 JPA를 혼용해 사용하기 때문에 ddl-auto 옵션을 update로 설정해두고 개발을 진행하고 있었는데도 엔티티가 데이터베이스에 반영되지 않았다. 컴파일러가 실행되며 애플리케이션이 구동될 때 어떠한 에러도 발견되지 않았고 서버도 정상적으로 실행되는데... 왜 엔티티가 반영되지 않는거지? 마치... 내가 만든 엔티티가 단 한순간도 존재하지 않았던 것처럼 스프링 프로젝트가 내가 만든 엔티티를 철저히 무시하고 있다는 생각이 들었다.
원인
당시에는 원인을 몰라 정말 많은 시도(라 쓰고 삽질이라 읽는다)를 해 보았는데 원인을 찾고 나니 정말 간단한 문제였다. 스프링이 마치 내 엔티티를 무시하고 있는 것 같다는 느낌을 받았었는데, 정말로 스프링이 내 엔티티를 인식하지 못하고 있었던 것이었다.
위의 예제처럼 당시 프로젝트는 rootLocation이라고 불리는 메인 프로젝트 패키지 외에 anotherLocation이라고 불리는 별도의 커스텀 패키지를 두고 작업을 진행하고 있었다.
문제는 스프링 프로젝트가 애플리케이션이 실행되는 실행되는 실행 파일을 기준으로 빈을 스캔해 등록한다는 것. 즉, rootLocation 경로에 존재하는 스프링 실행 파일인 RootLocationApplication을 기준으로 그 이하의 경로에 있는 빈만을 등록하기 때문에 anotherLocation 이하에 있는 엔티티는 스프링 입장에서 존재하는지 알 수 없는 파일이었던 것이었다. 그러니 당연히 엔티티는 등록되지 않았고, 스프링에서는 어떠한 오류도 없이 프로젝트가 실행되었던 것.
- 스프링 프로젝트는 애플리케이션 실행 파일을 기준으로 그 이하의 빈들을 컨테이너에 등록함.
- 애플리케이션 실행 파일의 스캔 경로에 해당하지 않는 파일은 빈으로 등록되지 않기 때문에 스프링에 의해 관리되지 않음.
이런 간단한 부분을 모르고 수 시간동안 시간을 허비했다는 사실이 조금 부끄러워지기는 했지만 원인을 파악한 이상 해결은 시간 문제였다.
해결
rootLocation과 anotherLocation 패키지 아래에 스캔을 시작할 포인트인 빈 인터페이스를 두개 만들고, 스프링 실행파일에서 엔티티의 스캔 범위를 재설정 해 주었다.
스프링 실행 파일에 @EntityScan 애노테이션을 등록해주고, 스캔의 시작 범위를 설정해주었다. @EntityScan에서 스캔 범위를 지정하는 방법은 두 가지로 basePackages 위치를 지정해 스캔 시작 '패키지'를 지정하는 것, 그리고 basePackageClasses 위치를 지정해 스캔 시작 '클래스'를 지정해 주는 것. basePackageClasses를 사용하면 그 클래스 이하의 경로로 스캔을 진행한다.
+ 추가 (Repository 인식 안됨)
같은 이유로 애플리케이션의 스캔 범위와 JPA 레포지토리 파일이 있을 경우 스캔이 되지 않는다. 그 때는 아래처럼
괴롭던 이슈가 해결되는 후련함을 경험할 수 있다. (후련)
'메모 & 삽질기록보관소' 카테고리의 다른 글
[데이터베이스] MySQL과 MariaDB의 차이점? (0) | 2022.11.17 |
---|---|
[strapi] NginX 리버스 프록싱 관련 이슈 (0) | 2022.07.07 |
[윈도우 11?] Mybatis - Password Not Matched!!! (0) | 2022.03.18 |
[jqeury] ajax에서의 parse error | 스프링과 자바스크립트의 부조화 (0) | 2022.03.13 |
[메모] 배포 관련 리눅스 명령어 (0) | 2022.01.19 |