1.8 XML을 이용한 설정
XML의 도입
오브젝트 사이의 의존 정보는 틀에 박힌 구조를 갖고 있으며, 일일이 자바 코드로 만들어주기 번거롭다. 또, DI 구성이 바뀔 때마다 자바 코드를 수정하고 클래스를 다시 컴파일하기도 귀찮다.
사실 현재에 와서는 스프링 부트 이후 레거시 프로젝트 외에는 XML로 의존관계 설정을 하는 것을 본적은 없다. 지금은 사장된 것 같지만 일단 배워두자. (2021-07-12 작성)
XML의 특징
단순한 텍스트 파일이다.
별도의 빌드 작업이 필요 없다.
사람의 눈으로 이해하기 쉽다.
환경이 바뀌어도 XML의 내용은 바뀔 필요가 없다.
스키마나 DTD를 이용해 정해진 포맷을 따라 작성했는지 쉽게 체크 가능하다.
XML 설정
<beans>
를 루트 엘리먼트로 사용한다. <beans>
내부에는 여러개의 <bean>
을 정의할 수 있다.
자바 애노테이션과 XML의 차이
XML 설정은 @Configuration
, @Bean
애노테이션이 붙은 자바 클래스로 만든 설정 내용과 결국 동일하다.
@Configuration
은<beans>
에 대응된다.@Bean
은<bean>
에 대응된다.
빈의 대표적 DI 정보
빈의 이름: 애노테이션에서는
@Bean
메소드 이름이 빈의 이름이 되었다.빈의 클래스: 빈 오브젝트를 어떤 클래스를 이용해 만들지를 정의한다.
이전
@Bean
애노테이션이 붙은 메소드의new 클래스명
의클래스명
이 될 수 있다.
빈의 의존 오브젝트: 빈의 생성자나 수정자 메소드를 통해 의존 오브젝트를 넣어준다. 의존 오브젝트도 하나의 빈이므로 이름이 있고, 그 이름에 해당하는 메소드를 호출하여 의존 오브젝트를 가져온다. 의존 오브젝트는 하나 이상일 수도 있다.
이전
@Bean
메소드에서도 다른@Bean
메소드를 호출하여 의존 오브젝트를 설정했었다.
connectionMaker() 전환
자바와 XML 비교
빈 설정파일
자바
:@Configuration
XML
:<beans>
빈 이름
자바
:@Bean methodName()
XML
:<bean id="methodName">
빈 클래스
자바
:return new BeanClass();
XML
:class="a.b.c...BeanClass">
반드시 리턴 타입 인터페이스가 아닌 구현체 클래스를 가리켜야 한다. XML에서는 리턴하는 타입을 지정하지 않아도 된다.
IDE는 클래스 이름만으로 빈 클래스를 쉽게
import
할 수 있었는데, XML은 상대적으로 번거롭다.
userDao() 전환
XML로 의존관계 정보를 만들 때는 자바빈의 관례를 따라 수정자 메소드를 프로퍼티로 사용한다. 프로퍼티 이름은 set
을 제외한 나머지 부분을 사용한다.
위에서 정의한 @Bean connectionMaker()
메소드를 이용한 의존성 주입자바코드는 아래와 같다.
XML에서는 의존관계 정보를 줄 때, <bean id="userDao">
내부에 아래와 같이 치환될 것이다.
빈의 이름을 바꾸는 경우 주의사항
properties
내부에 name
과 ref
속성은 문자열 자체는 같지만, 의미가 다르다. name
은 수정자 프로퍼티를 가리키는 것이고, ref
는 주입할 오브젝트를 정의한 빈의 ID이다.
보통 빈의 이름은 바뀔 수 있는 클래스의 이름보다는 인터페이스의 이름을 많이 사용한다. 이로 인해 프로퍼티 이름과 빈의 이름이 같은 경우가 흔하다. 물론 빈의 이름(id
)과 프로퍼티 이름이 달라도 상관없다. 다만, 빈의 이름을 바꿀 때는 해당 빈을 프로퍼티로 쓰는 ref
의 이름도 잘 바꿔주자.
XML은 자바코드에 비해 상대적으로 리팩토링에 주의가 많이 필요하다.
connectionMaker
를 myConnectionMaker
로 바꾸어보았다. 빈의 id
와 프로퍼티의 ref
를 둘 다 변경했다.
같은 인터페이스 타입의 빈을 여러개 정의해놓고 쓰는 경우
위와 같이 dConnectionMaker
, nConnectionMaker
등 여러개의 빈을 정의해놓고 필요한 것을 골라쓸 수도 있다. local
, test
, production
등의 빈을 만들어놓고 테스트하면 용이하다.
DTD와 스키마
DTD
와 스키마
를 활용하면 XML이 미리 정해진 구조를 따라 작성했는지 알 수 있다. 스프링의 XML 설정파일은 이 두가지 방식을 모두 지원한다.
위는 DTD
를 이용한 방식이다.
위는 스키마
를 이용한 방식이다.
스프링은 DI를 위한 기본 태그인 <beans>
, <bean>
이외에도 특별한 목적을 위해 별도의 태그를 사용할 수 있는 방법을 제공한다. 이런 태그를 이용하려면 별개의 스키마 파일을 이용해 독립적인 네임스페이스를 제공해야 해서 DTD
대신 스키마
를 이용하는 것이 바람직하다.
XML을 이용하는 애플리케이션 컨텍스트
GenericXmlApplicationContext
를 이용하여 애플리케이션 컨텍스트를 만들어보자.
Intellij
의 위 메뉴를 이용하면 손쉽게 Spring Config
XML 파일을 생성할 수 있다.
애플리케이션 컨텍스트의 XML 파일 이름은 관례를 따라
applicationContext.xml
으로 지정했다.
java
내부에 만드는 것이 아니라 resources
내부에 만들어야 한다.
기본적인 네임스페이스들은 전부 설정되어 있다.
빈을 추가할 때도 class
애트리뷰트는 앞글자만 입력해도 자동완성된다.
수정자가 없으면 위와 같이 수정자를 만들라는 안내 메세지가 나온다.
정상적으로 수정자가 생성되면 위와 같이 IDE에서 연결된 프로퍼티를 표기해준다.
위와 같이 소스코드를 작성해주고 테스트한 결과 정상적으로 동작한다.
DataSource 인터페이스로 변환하기
DataSource 인터페이스 적용
사실 자바에서는 ConnectionMaker
의 기능을 지원하는 인터페이스가 이미 있다. DataSource
는 DB 커넥션을 가져오는 기능 외에도 여러 개의 메소드를 추가적으로 갖고 있다. 또한 스프링에는 해당 DataSource
를 구현하여 DB 연결, 풀링 등 많은 기능을 갖춘 클래스를 제공한다.
당연히 DB의 종류, 아이디, 비밀번호는 얼마든지 바꾸어도 구현 클래스를 다시 만들지 않아도 되는 정도의 유연성은 제공한다.
스프링에서 제공하는 구현체를 사용하기 위해
implementation group: 'org.springframework', name: 'spring-jdbc', version: '5.3.8'
의존성을 추가해주자.
SimpleDriverDataSoruce 적용
SimpleDriverDataSource
는 스프링에서 제공하는 구현 클래스 중 테스트 환경에서 간단히 사용할 수 있는 DataSource
이다. 이 클래스를 사용하도록 DI를 재구성하자.
자바 코드로 적용
UserDao.java
DaoFactory.java
위와 같이 UserDao
가 의존하는 객체를 DataSource
인터페이스로 바꾼 뒤에 DaoFactory
에서 새로 생성한 SimpleDriverDataSource
오브젝트를 주입하면 된다. SimpleDriverDataSource
는 setter
로 DriverClass
, URL
, Username
, Password
를 삽입할 수 있다.
XML로 적용
applicationContext.xml
위와 같이 작성해주었다. 자바 코드와 같은 내용을 xml
로만 바꾼 것이다.
bean
으로 정의한 것을 프로퍼티로 주입할 때는ref
를 사용하고, 일반 값을 프로퍼티로 주입할 때는value
를 사용한다.
xml 프로퍼티 value 값의 자동 변환
위에 driverClass
를 자바 소스로 적용할 때와는 다르게 ...Driver.class
까지 적어주지 않았는데, 그 이유는 스프링이 프로퍼티의 값을 수정자 메소드 파라미터의 타입을 참조하여 적절하게 변환해주기 때문이다. 스프링은 수정자 메소드의 파라미터 타입이 Class
임을 확인하고 org.postgresql.Driver.class
오브젝트로 자동 변경해준다.
스프링은 value
에 지정한 텍스트 값을 적절한 자바 타입으로 변환해주는데, Integer
, Double
, String
, Boolean
과 같은 기본 타입은 물론이고, Class
, URL
, File
, Charset
같은 오브젝트로 변환이 가능하다. 값이 여러개라면 List
, Map
, Set
, Properties
나 배열로도 주입이 가능하다.
변경 후에 테스트를 돌려본 결과 정상적으로 동작한다. 항상 테스트는 돌려보자.
Last updated