개인 프로젝트 구조를 현재 진행하고 있는 프로젝트 구조와 비슷하게 하여 진행을 하였는데, 매퍼를 주입받을때 bean 문제가 발생하였다.
이 문제를 해결하면서 bean, di에 대한 개념을 다시 한번 다듬을 수 있었던 계기가 되었기에 배운 내용을 기록하여 남긴다.
내가 자꾸 di에서의 인터페이스 개념과 매퍼 어노테이션을 사용하는 인터페이스 개념을 혼합하다보니까 정리가 안되었던 것 같다.
일단 의존성 주입이라는 것 자체가 인터페이스의 객체를 생성한 상태에서 인터페이스의 구현체를 주입, 언제든지 사용할 수 있는 상태로 만들겠다는 의미이다.
이때 인터페이스를 따로 구현해서 사용할 필요없이, 인터페이스라는 추상체를 활용하여 바로 사용할 수 있다는 것이다.
진짜 쉽게 말하면 인터페이스의 원래 상태로는 이용할 수 없지만, di를 주입받으면 객체 선언 후 사용하는 것처럼 해당 인터페이스 기능을 사용할 수 있다.
이를 지금 문제의 핵심인 매퍼에 녹여내면, 우리는 추상 인터페이스의 기능을 사용하기만 하면 된다는 의미이다. 내부적으로 구현된 sql, CUD 등은 바꿔도 느슨해진 결합도와 di의 힘으로 그대로 사용할 수 있다.
이제 이 이후가 중요하다.
이때 문제는, 내가 일전에 어노테이션의 의미를 공부하면서, 어노테이션은 컴파일과 런타임 모든 관점에서 바라봐야 한다라는 점을 배웠는데, 컴파일에 문제가 없더라도 런타임에서 문제가 발생할 수 있다는 점이다.
매퍼 인터페이스의 경우가 바로 이런 경우이다.
매퍼 인터페이스를 사용하기 위해선 스캔 후 최종적으로 매퍼 빈이 컨테이너에 등록되어야 한다.
대표적인 문제가 빈을 찾을 수 없다는 것인데, 상기 그림처럼 빈을 생성하기 위해선 스프링 컨테이너 생성, 즉 스프링을 실행해야 한다.
이때 config 등을 통해 scan을 진행하게 되는데, 이때 @value에서 설정한 범위 내에서 빈으로 생성할 클래스들을 탐색한다.
따라서 저 value, 즉 scan범위를 잘못 설정해놓으면 애초에 그 클래스를 스캔하지 않아 빈으로 등록이 되지 않는다.
이에 따라 서비스(@service) 등에서 사용한 매퍼 인터페이스는 컴파일은 되었지만 런타임 시점에서 빈으로 등록되지 않은 매퍼를 사용하므로 오류가 발생한다.
이 해결방안은 나와있어도, 원리적으로 접근한 해결방안까지는 못찾았다.
나는 단순히 빈이 없다라는 문제가 아닌, 그 시점과 동작이 더 궁금했기에..알아내느라 너무 애를 썼다.
정리하면 해결방안은 다음과 같다.
매퍼주기 - https://catsbi.oopy.io/3a9e3492-f511-483d-bc65-183bb0c166b3
의존관계주입 - https://code-lab1.tistory.com/m/122
매퍼 어노테이션 - https://codingnojam.tistory.com/27