본문 바로가기

삽질

Reflection API와 JPA, Spring Bean

Reflection API에 관한 글을 작성하고 공부하면서, 글에서 담지 못한 궁금증과 알게된 점에 대해 정리한 글이다.

틀린 내용이 포함되어 있을 수 있다.😅


Reflection API는 프레임워크나 라이브러리에서 주로 사용한다.

내가 쓴 글 내용 중 아래와 같은 내용이 있다.

Spring Framework에서도 Reflection API를 사용하는데 대표적으로 Spring Container의 BeanFactory가 있다. Bean은 애플리케이션이 실행한 후 런타임에 객체가 호출될 때 동적으로 객체의 인스턴스를 생성하는데 이때 Spring Container의 BeanFactory에서 리플렉션을 사용한다.

이해가 잘 된다. Reflection은 동적으로 객체를 생성할 수 있는 API니까 가능하다.

Spring Data JPA 에서 Entity에 기본 생성자가 필요한 이유도 동적으로 객체 생성 시 Reflection API를 활용하기 때문이다. Reflection API로 가져올 수 없는 정보 중 하나가 생성자의 인자 정보이다. 그래서 기본 생성자가 반드시 있어야 객체를 생성할 수 있는 것이다. 기본 생성자로 객체를 생성만 하면 필드 값 등은 Reflection API로 넣어줄 수 있다.

여기서 궁금한 점이 생겼다. JPA에서는 Reflection API를 활용해서 동적으로 Entity 객체를 생성하기 때문에 Entity 객체에 기본 생성자를 항상 만들어줬었다. Reflection API에서는 생성자의 인자 정보를 가져올 수 없으니까 기본 생성자를 만들어줘야 객체를 생성하고 필드값을 넣어주고 할 수 있다.

근데 생각해보면 Spring에서 Bean 등록한 객체에 기본 생성자를 일부러 만든 적은 없다. BeanFactory에서도 객체를 동적으로 생성하려면 해당 Bean 객체에 기본 생성자가 있어야 하는 거 아닌가?

빈을 등록하는 xml 코드를 보고 의문이 해소할 수 있었다.

<bean id="demoService" class="com.example.demo.DemoService">
    <property name="repository" ref="demoRepository"/>
    <property name="count" value="42"/>
</bean>

Bean 객체의 위치, 클래스 이름과 함께
property 태그로 생성자의 인자 정보를 작성해준 모습을 볼 수 있다.

Reflection API에서 가져올 수 없는 정보인 생성자의 인자 정보를 빈 등록할 때 작성해주는 것이다.

Component Scan을 통해 자동으로 bean 등록을 할 때도 생성자 주입이면 생성자의 정보가 등록될 것이고 필드 주입이면 @Autowired가 붙은 필드 정보가 등록될 것이다.

생성자 중 한 개가 자동으로 꼭 연결되어 있어야 한다. 아닌 경우엔 기본 생성자로 객체 생성을 시도하고 @Autowired가 붙은 필드들의 의존성을 주입할 것이다. 생성자가 여러개라면 컴파일이 안될 것이다.

이번 학습으로 RestAssured와 기본 생성자에 관련된 삽질에서 완벽히 이해하지 못했던 부분도 일정 부분 깨달을 수 있었다.

RestAssured나, Spring Framework에서 사용하는 jackson 라이브러리도 결국에 Reflection API를 사용한다. 때문에 위에서 얘기했던 것처럼 생성자에 대한 인자 정보를 얻어올 수 없어서 기본 생성자가 필요했던 것이고 SpringBoot에서는 SpringBoot에 포함되어있는 모듈인 ParameterNamesModule로 생성자 인자 정보를 얻어오는 것 같다.

jackson 라이브러리의 @JsonCreator, @JsonProperty 등등 어노테이션들도 결국엔 생성자를 연결시키거나 생성자의 인자정보를 얻어오기 위한 어노테이션이였던 것 같다.

물론 틀릴 수도 있다.😅

참고 자료