본문 바로가기

Programing/Framework

[spring boot] Type-safe Configuration Properties 쓸 때 주의점

스프링부트에서 Configuration Properties의 기능은 설정을 접두어를 통한 그룹핑을 할 수 있어서 유용하다.

어제 배포 과정에서 실제 환경에 배포를 하였음에도 테스트 환경의 설정이 적용되어 배포 지연이 있었다.
원인을 살펴보니 yml 파일에 boolean 타입의 프로퍼티가 is가 붙어 있는 형태였다.

is-real: true

이에 대응하는 Java 클래스는 아래와 같았다.

private boolean isReal;

문제는 해당 필드는 설정이 적용되지 않는 것이었다.

어떻게 확인을 했나?

1. 생성자에서 초기화 테스트

생성자를 만들어서 해당 필드를 임의의 값을 설정해서 했는데, 스프링 프레임워크에 의한 값 덮어씀이 발생하지 않았다.
따라서 값 매핑이 제대로 되지 않는다고 판단할 수 있다.

2. Setter 호출이 되는지 확인

Setter를 통해 스프링 부트 초기화 되는 지점을 우선 찾았다. 아래와 같은 부분이었다.
org.springframework.boot.context.properties.bind.JavaBeanBinder#bind(org.springframework.boot.context.properties.bind.JavaBeanBinder.BeanSupplier, org.springframework.boot.context.properties.bind.BeanPropertyBinder, org.springframework.boot.context.properties.bind.JavaBeanBinder.BeanProperty)

private <T> boolean bind(BeanSupplier<T> beanSupplier,
		BeanPropertyBinder propertyBinder, BeanProperty property) {
	String propertyName = property.getName();
	ResolvableType type = property.getType();
	Supplier<Object> value = property.getValue(beanSupplier);
	Annotation[] annotations = property.getAnnotations();
	Object bound = propertyBinder.bindProperty(propertyName,
			Bindable.of(type).withSuppliedValue(value).withAnnotations(annotations));
	if (bound == null) {
		return false;
	}
	if (property.isSettable()) {
		property.setValue(beanSupplier, bound);
	}
	else if (value == null || !bound.equals(value.get())) {
		throw new IllegalStateException(
				"No setter found for property: " + property.getName());
	}
	return true;
}

property가 isSettable이 참이면 property.setValue(beanSupplier, bound); 부분이 호출이 되는데, 프로퍼티 목록에 isReal이라는 값으로 settter가 호출되는 경우가 없었다.

해결책은?

is-real 대신에 real이라는 프로퍼티이름으로 바꾸었다.

real: true

Java 객체도 아래와 같이 바꾸어 준다.

private boolean real;