스프링 3.1에 도입된 런타임 환경 추상화는 프로파일과 프로퍼티 소스로 구성되어있다. 스프링 설정 파일 외부에 설정용 프로퍼티 값을 두고 관리하는 방법을 사용하려면 프로퍼티 파일(.proerties, .xml)에 값을 넣고 XML에서 ${} 프로퍼티 치환자를 사용하거나 SpEL을 이용해서 <util:properties/>로 정의된 프로퍼티 빈의 값을 끌어오는 방법뿐이었다. 참. 스프링이 ApplicationContext나 BeanFactory처럼 기본으로 @Resource 해주는 systemProperties와 systemEnvironment 빈을 이용하는 방법도 있긴하다. 아참. 웹이라면 컨트롤러 등에서 서블릿 컨텍스트를 가져와서 애트리뷰트나 컨텍스트 파라미터를 읽어도 되겠지. 아차차. <jee:jndi-lookup>으로 JNDI에 설정해둔 값을 가져오는 방법도 가능하게다. 이런. 빈 초기화 하는 즈음에 DB에 넣어둔 프로퍼티 값을 읽거나 RestTemplate으로 다른 서버에서 끌어오는 방법도 가능하겠네.

애플리케이션의 구성 정보를 담은 XML설정파일 말고 주로 런타임 환경과 관련이 있는 속성은 이렇게 다양한 위치에 넣어두고 다양한 방법으로 가져와서 사용할 수 있다. 그런데 이 모든 방법이 대부분 “키와 값의 쌍으로 이루어진 애플리케이션 외부에 정의된 프로퍼티 값을 가져온다”는 공동점이 있으니 추상화를 하면 좋겠다.

그래서 스프링 3.1은 앞에서 말한 다양한 방법(환경변수, 시스템 프로퍼티, JNDI, 서블릿 컨텍스트 파라미터 , 서블릿 콘픽 파라미터, DB나 서버에서 끌어오기 같은 기타 등등)으로 정의된 프로퍼티를 ProperySource라는 개념으로 추상화하고, 이를 PropertyResolver에서 일관된 방법으로 가져올 수 있도록 만들었는데, 환경 추상화 API인 Environment가 바로 이 PropertyResolver의 서브 인터페이스다.

스프링은 고맙게도 프로퍼티 소스로 추상화 했다고 옛정을 버리지는 않았다. 원한다면 이전에 쓰던 placeholder configurer를 그대로 사용할 수 있다. <context:property-placeholder>와 ${}를 그대로 사용할 수 있다는 뜻이다. 대신 내부에선 프로퍼티 소스 추상화를 이용해 통합된 프로퍼티 정보에 접근하는 방법을 사용하도록 변경됐다.

자세한 내용은 올 봄에 나올지도(-_-;;) 모르는 토스3 개정판에서…

그런데 얼마전에 권남님의 http://kwon37xi.egloos.com/4665590 를 읽어보니

properties-placeholder는 부모 자식 관계에 있는 Application Context XML 설정파일들의 경우에도 동일한 properties 파일임에도 모든 Bean 설정 파일에 property-placeholder를 명시해줘야 하는 문제가 있다.

는 얘기가 나온다. 그래서 빈으로 프로퍼티를 정의하고 SpEL로 끌어오는 방법을 추천한다는.

부모-자식 관계의 컨텍스트 구조는 웹 환경에서 루트와 서블릿 컨텍스트가 분리되는 경우가 대표적인데, 루트에 <context:property-placeholder>를 넣어도 서블릿 컨텍스트의 ${}에는 안 먹는다는 얘기인 것 같다. 당연하다. 왜냐하면 기존 <c:pp>는 빈 팩토리의 ${}등이 들어있는 메타 정보(프로퍼티 값)를 가공하는 방식이다. pull이 아니라 push개념인 셈인데, 루트에 정의된 <c:pp>에서 아직 만들어지지도 않은 서블릿 컨텍스트의 메터 정보를 가공한다는 것은 불가능하기 때문이다. 반면에 SpEL은 다른 빈의 값을 끌어오는 pull 방식이라 컨텍스트 생성 시점에 이미 루트 컨텍스트를 부모 컨텍스트로 주입받은 서블릿 컨텍스트 입장에서 루트 컨텍스트의 빈으로 정의된 프로퍼티의 값을 가져오는 건 간단하다.

물론 하나의 프로퍼티 파일 정보를 루트와 서블릿 컨텍스트 간에 공유하게 하는게 바람직한지 시비를 걸 수도 있겠지만, 뭐 쓰는 사람 맘이지.

그리고, “모든 Bean 설정 파일에 p-p를”이라는 건 아닌듯 싶다. <import>를 쓰거나 configLocation에 *를 사용해서 한 컨텍스트가 여러개의 빈 설정 파일을 사용하게 하는 경우라면 p-p는 한번만 넣어줘도 된다.

아무튼 3.0은 그랬지만 3.1에선 더 이상 이런 문제가 없다. 3.1에선 런타임 환경 정보를 통해서 다양한 프로퍼티 소스를 하나로 통합해서 가져오게 하는 방식을 사용하기 때문에 개념적으로 pull인 셈이다. 심지어 <context:property-placeholder>를 사용하더라도 그렇다. 3.1 스타일로 @PropertySource를 사용해서 p-p와 분리한다면 말할 것도 없고.

그러니 3.1에선 프로퍼티 파일 하나를 일개 빈으로 설정하는 SpEL방식보다 프로퍼티 소스로 추상화해서 사용하는 방식을 추천하고, ${} 스타일을 원한다면 예전에 한번 설명했던 PropertySourcePlaceholderConfigurer를 사용하면 될 것이다. XML을 사용하지 않는 경우라면 @Value의 ${}보다는 Environment에서 직접 프로퍼티를 읽는 방식을 써도 좋다.

스프링이 기본적으로 제공하는 6가지 프로퍼티 소스(구현 클래스가 아니라 정말 소스)외에 커스톰 프로퍼티 소스를 사용하고 싶으면 ApplicationContextInitializer를 쓰면 되는데 이게 3.1.1에서도 살짝쿵 버그가 있는 것 같아서 조금 주의해야 할 것 같다. 이 얘긴 다음에.

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha