스프링 부트 - 핵심 원리와 활용 - 섹션5. 자동 구성(Auto Configuration)
CS/김영한 스프링 강의

스프링 부트 - 핵심 원리와 활용 - 섹션5. 자동 구성(Auto Configuration)

새 프로젝트로 다시 시작해본다.

 

 

 

데이터베이스랑 연동하는걸 직접 bean으로 등록하며 해보자.

코드 내에서 직접 db관련해서 DataSource, TransactionManager, JDBCTemplate 모두 등록한다. 레퍼지토리에서 이걸 가져와서 쓴다.

 

 

 

 

사실 DbConfig로 작성한 db등록 내용들은 매 프로젝트 생성시마다 해줘야 하는 반복작업이다. 그래서 자동구성이 있다.

일단 테스트를 만들어 자동구성 안하는것과 하는거 차이를 보자.

 

 

내가 만든 @Configure가 실행되서 내가 만든 로그가 뜨는거다. 근데 내가 만든걸 없애도 자동 구성으로 알아서 주입되어있다.

 

 

 

자동 구성은 부트를 쓴다면 왠만하면 있다. 안의 등록 로직은 내가 직접 짠거랑 거의 비슷한 것이 핵심이다.

 

 

@ConditionalOnClass는 if랑 비슷한거다. 이걸 사용해서 내가 직접 등록한것이 bean에 있으면 실행 안하고 하는 조건을 넣어 사용한다. 여기선 데이터소스와 템플릿이 있을 때 이 설정을 사용하라는 방식으로 사용함.

 

@ConditionalOnClass로 만약 내가 bean으로 등록한게 있으면 이걸 실행하지 않고 없다면 실행하여 충돌을 방지한다. 이것도 결국 new JdbcTemplate(dataSource)를 하는게 내가 한거랑 똑같다.

 

스프링이 자동구성 해주는 목록

Auto-configuration Classes (spring.io)

 

Auto-configuration Classes

This appendix contains details of all of the auto-configuration classes provided by Spring Boot, with links to documentation and source code. Remember to also look at the conditions report in your application for more details of which features are switched

docs.spring.io

 

 

임시로 외부 라이브러리를 만들어 bean에 등록 후 사용해보자

 

이러면 사용된다. 이런 외부 라이브러리를 가져오는 것도 자동구성이 있는데 나중에.

 

지금은 @Conditional로 내가 만든 외부 라이브러리를 상황에 따라 다르게 등록해서 실행해보자. 이런 기능이 중요한데, 같은 코드임에도 개발 서버와 운영 서버에서 다르게 동작해야 하기 때문.

 

아까 만든 MemoryConfig에 @Conditional를 추가했다. 그리고 Condition조건 클래스에는 VM option으로 사용한다고 해야 사용 되도록 했다.

 

사용 안했을 경우, match에서 false가 나와 주입이 안되 에러가 뜨는걸 볼수 있다. 반면 VM option으로 넣어줘서 matches가 true가 되면 bean에 주입하여 사용된다.

 

 

 

 

사실 Condition 따로 상속해서 만들고.. 하는걸 이미 만들어놓은 @ConditionalOnProperty가 있다.

이것도 안을 보면 직접 했던것과 같이 어차피 @Conditional을 어노테이션으로 가지고있고 내부적으로 matches를 사용한다.

 

 

 

간단한 라이브러리를 직접 만들어볼건데, 아까 만든 메모리에서 필요한 부분만 때서 새로 프로젝트 만들고 빌드한다.

 

 

이 빌드된 걸 새로운 프로젝트에서 실행하려면, libs 폴더 만든 뒤 이 빌드해서 나온 .jar 파일을 넣고 설정에서 파일로 불러오면 된다.

 

 

 

그 뒤 해줘야 하는게 bean에 등록해야 사용할 수 있다. @AutoConfiguration을 사용하지 않아서 직접 해야함.

 

그럼 내가 따로 url 설정을 해주지 않더라도 이미 컨트롤러를 라이브러리에서 만들어 놓았기 때문에 그냥 된다.

 

 

 

 

아까 라이브러리를 부르고 bean에 등록해야 하는데, 이게 라이브러리 한개라서 그렇지 여러개를 쓰면서 점점 쌓이다보면 또 귀찮다고 부트에서 만든게 @AutoConfiguration이다.

이건 라이브러리를 만드는 사람이 해줘야 한다. 즉, 이걸 사용하는 개발자가 정말 사용하기 쉽게 만들어주는게 목적이다.

 

bean을 주입해주는 곳에 @AutoConfiguration을 넣고 resources/META-INF/spring에 org.springboot... 의 파일 이름을 만들고 자동 주입할 클래스를 입력한다. 그러면 스프링부트가 main에서 스캔할 때 @AutoConfiguration이 있는 것 까지 긁어간다.

 

이렇게 만든걸 똑같이 빌드한다.

 

넣어주고 의존성 주입해준뒤, 라이브러리 만들 때 VM option에서 memory=on인 경우만 하게 했으므로 vm까지 설정해주면 직접 등록 안해도 알아서 해줘서 잘 된다.

이게 어떻게 가능한지를 알아보자.

 

일단 이 라이브러리를 자동으로 불러온 이유는 META-INF/spring에 ...imports 파일을 만들고 여기에 어떤걸 자동으로 가져와야 하는지 정의했기 때문이다.

그리고 이건 다른 라이브러리들도 마찬가지다.

 

긁어오는 이유는 main 시작할 때 사용하는 @SpringBootApplication 어노테이션에 들어가보면, 여기에 자동으로 긁어오는 @EnableAutoConfiguration이 있기 때문이다.

그렇게 쭉쭉 올라가다보면 ImportSelector라는게 나오는데, 일단 이 ImportSelector라는게 뭔지 알아야 어떻게 자동으로 긁어오는지도 이해할 수 있다.

 

원래 @Import(...) 해서 긁어와야 할려면 어노테이션의 매개변수 안은 정적인 클래스여야 한다. 근데 이걸 동적으로 넣어주고 싶다 즉, 특정 조건에 따라 다르게 주고 싶다면 ImportSelector 클래스를 매개변수로 삼는게 가능하고, ImportSelector 클래스의 결과는 동적으로 해주는게 가능해서 결국 동적인게 가능하다.

 

ImportSelector의 selectImports 함수 결과가 문자열 리스트인걸로 보아 저 내용이 META-INF/spring/...imports 파일 안에 들어가는 문자인걸 눈치챘을 수도 있다.

 

이걸 이해했으면 @EnableAutoConfiguration을 이해할 수 있다.

아까 봤던 AutoConfigurationImportSelector. 얘도 결국 아까 해봤듯이 selectImports에서 문자열 결과로 어떤 클래스를 자동으로 가져오는게 좋은지 내놓는 거고 실제 작동도 그렇게 한다.

 

 

 

 

 

 

 

결국 이것도 META-INF/spring/...imports에서 어떤걸 자동으로 생성해야 하는지 싹 긁어모으는걸 알 수 있다.

 

주의할 점은 이 AutoConfiguration자체를 자동등록에 넣지 말것. 자동 등록하고 싶은 것들은 META-INF/spring/...imports에 적어라.

 

근데 직접 라이브러리를 만들일은 매우 드문데 왜 이걸 알아야 할까? 이유는 외부 라이브러리에서 자동으로 주입되다 보니 가끔 이게 어디서 왔는지 확인할 필요가 있기 때문.