@Value
@Value
어노테이션은 설정을 코드에 수집하는 가장 간단한 방법이다.
패턴 매칭과 SpEL을 중심으로 짜여져 있기 때문에 간단하고 강력하게 설정할 수 있다.
예를 들어 설정파일인 application.properties파일에 아래와 같이 작성하고
greeting-name=Iknow
다음과 같은 컨트롤러를 작성한다.
@RestController
@RequestMapping("/greeting")
class GreetingController {
@Value("${greeting-name: Mirage}")
private String name;
@GetMapping
String getGreeting() {
return name;
}
}
주의: 이때 사용하는
@Value
어노테이션은 Lombok의@Value
가 아닌 Springframework의@Value
이다
@value
어노테이션은 멤버 변수에 적용되며 만약 application.properties또는 application.yml에 greeting-name이 정의되어 있지 않다면 @Value
어노테이션에서 기본값으로 정의된 Mirage가 적용된다.
직접 만든 프로퍼티와 함께 @Value
를 사용하면 한 프로퍼티의 값을 다른 프로퍼티의 값을 사용하여 파생하여 구축할 수 있다. 프로퍼티 중첩은 다음과 같이 작동한다.
#application.properties
greeting-name=Iknow
greeting-coffee=${greeting-name} is dringking Cafe Cereza
@RestController
@RequestMapping("greeting")
public class GreetingController {
@Value("${greeting-name: Mirage}")
private String name;
@Value("${greeting-coffee: ${greeting-name} is drinking Cafe Ganador}")
private String coffee;
@GetMapping
public String getGreeting() {
return name;
}
@GetMapping("/coffee")
String getNameAndCoffee() {
return coffee;
}
}
@Value
를 사용 할 때 주의 해야 할 점은 속성의 기본값을 제공했기 때문에 application.properties파일 내에서 존재하지 않거나 주석처리 하여도 기본값을 나타내지만, 속성 파일 내의 모든 프로퍼티들을 주석처리 또는 삭제한다면, 이를 정의하는 환경 소스가 없어지기 때문에 Controller Bean을 초기화 하려고 할때 에러가 발생한다.
## applictaion.properties
#greeting-name=Iknow
#greeting-coffee=${greeting-name} is dringking Cafe Cereza
또한 application.properties에 정의되고 @Value
를 통해서만 사용되는 프로퍼티는 코드에서 문자열 변수 내에서만 참조 되므로 코드와 직접 연결되지 않기 때문에 IDE에서 작성하고 있는 애플리케이션에서 사용하는 것으로 인식하지 못한다. 때문에 프로퍼티의 철자와 사용법이 올바른지를 수작업으로 확인해야 하는 어려움이 존재한다.
위와 같은 단점을 개선하기 위해서 @ConfigurationProperties를 사용하고 프로퍼티를 정의하고, 관련 프로퍼티를 그룹화 하므로써 검증 가능하고, typesafe한 방법으로 사용할 수 있다.
먼저 구성 프로퍼티를 사용하기 위해서 먼저 원하는 관련 프로퍼티를 캡슐화 할 수 있는 POJO를 정의해야 한다.
@ConfigurationProperties(prefix = "greeting")
public class Greeting {
private String name;
private String coffee;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCoffee() {
return coffee;
}
public void setCoffee(String coffee) {
this.coffee = coffee;
}
}
설정 속성의 속성을 관리하기 위해 @ConfigurationProperties
어네테이션을 추가하고 모든 Greeting 클래스 의 속성에 사용할 접두사를 지정할 수 있다.
또한 애플리케이션이 @ConfigurationProperties
클래스를 처리하고 해당 속성을 추가하기 위해 기본 애플리케이션 클래스에 @ConfigurationPropertiesScan
어노테이션을 추가해야한다.
@SpringBootApplication
@ConfigurationPropertiesScan
public class SburRestDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SburRestDemoApplication.class, args);
}
}
또한 IDE에서 @ConfigurationProperties 어노테이션을 사용할 때, 메타데이터를 생성하고 application.properties에서 정의된 속성을 연결 할 수 있도록 Spring-boot-configuration-processor 의존성을 추가 해야 한다.
이렇게 설정하면 위와 같이 properties파일을 작성할 때 자동완성을 제안하는 것을 확인 할 수 있다.
서드 파티 컴포넌트를 래핑하고 해당 프로퍼티를 애플리케이션의 환경에 통합하여 프로퍼티를 통합할 수 도 있다.
이 기능을 가장 편리하게 사용하는 방법은 프로젝트에 외부 종속성을 추가하고 구성요소의 설명서를 참조하여 Spring Bean을 생성할 클래스를 결정하는 것이지만 여기서는 Spring Bean을 직접 생성하여 구현한다.
public class Droid {
private String id, description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
위 Droid클래스는 id와 description 속성, getter, setter가 정의되어 있다.
구성요소를 Spring Bean으로 인스턴스화 한다.
Spring Bean은 여러가지 방법으로 POJO에서 생성 할 수 있다. 여기서는 @Configuration
어노테이션이 달린 클래스 내에서 @Bean
어노테이션이 달린 메서드를 달아서 Spring Bean을 생성한다.
@Configuration
어노테이션을 통합하는 메타 어노테이션은 @SpringBootApplication
이기때문에 종종 여기에 Bean 생성 메서드를 배치한다
그렇기 때문에 다음 코드에선 환경내에서 최상위 프로퍼티 그룹인 droid아래 Droid프로퍼티가 통합되어야 함을 나타낸다.
@SpringBootApplication
@ConfigurationPropertiesScan
public class SburRestDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SburRestDemoApplication.class, args);
}
@Bean
@ConfigurationProperties(prefix="droid")
Droid createDroid() {
return new Droid();
}
}
적당한 컨트롤러를 작성하고 테스트 해보면 정상적으로 droid프로퍼티가 작동하는 것을 확인할 수 있다.
Spring Boot는 자동 구성을 통해 개발자 대신 애플리케이션을 설정하는 작업을 수행한다.
여기서는 어떤 Bean이 생성 되고, 어떤 Bean이 생성되지 않으면 어떤 조건이 어떤 결과를 초래했는지 확인하는 방법을 알아본다.
JVM을 통해 디버그 플래그를 사용하여 자동 설정 보고서를 생성하는 것은 간단하다.
Java -jar bootapplication.jar --debug
디버그 옵션을 통해 애플리케이션의 jar파일 실행Java -debug=true -jar bootapplication.jar
JVM 매개변수를 사용하여 애플리케이션의 jar파일 실행debug=true
추가autoconfiguration report의 positive matches 섹션은 참으로 평가된 작업 수행된 조건들이 나열되어 있다.
Negativa mathces에는 스프링부트의 autoconfiguration이 수행하지 않은 작업과 그 이유들이 나열되어 있다.
위의 경우에는 jakarta.jms.ConnectionFactory클래스를 찾기 못했기 때문에 ActiveMQAutoConfiguration이 수행되지 않았다는 것을 의미한다.
마지막으로 Unconditional Classes에는 조건을 충족하기 않아도 생성되는 작업들을 나열한다.
n. One that actuates specifically: a mechanical device for moving or controlling something
Actuator는 HTTP엔드포인트와 JMX를 통해 실행중인 앱의 모니터링 및 관리 기능을 제공하며, 스프링 부트의 모든 프로덕션 지원기능을 포괄하고 노출시킨다.
Actuator를 통합시키기 위해 spring-boot-start-actuator 의존성을 추가해야 한다.
종속성을 추가하고 애플리케이션을 추가하고 기본 엔트포인트(/actuator)에 액세스하면 액추에이터가 어떤 정보를 노출하는 지 확인 할 수 있다.
Actuator의 자동 구성은 매우 제한된 상태와 정보만을 노출하면 그 외에는 거의 즉시 사용 가능한 상태로는 제공하지 않는다.
`management.endpoints.web.exposure.include= env, info, helth` 를 추가해주므로서 간단하게 /actuator/env, /actuator/info, /actuator/health 엔트포이트만 노출하도록 설정할 수 있다.
와일드카드를 사용하여 보안을 완전히 비활성화 할 수도 있다.
`management.endpoints.web.exposure.include=*`
스프링부트 애플리케이션을 시작하면 아래 표시된 것처럼 노출되고 있는 엑추에이터 엔드포인트와 도달하는 루트경로를 보고하는 것을 확인할 수 있다.
2024-01-08T04:52:15.656+09:00 INFO 5534 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 13 endpoint(s) beneath base path '/actuator'
아래는 엑추에이터 엔드포인트 일부 목록이다.
비정상적인 코드를 직접 작성하였을때 문제를 해결하기위해 가장 먼저 해야하는 것은 모든 가정을 확인하는 것이다. 특히 입력에 의해 결과가 좌우되는 코드의 경우 액추에이터는 이 작업을 간편하게 도와준다.
/actuator/env 엔드포인트를 쿼리하면 다음과 같이 모든 환경 정보가 반환된다.
엑추에이터는 각 속성의 현재 값 뿐만 아니라 각 값이 정의된 줄과 열 번호까지 그 소스도 표시한다.
여기서 만약 환경 값중 하나 이상이 애플리케이션 실행시 외부 환경 변수나 명령주 인수와 같은 다른 소스에 의해 재정의 되면 어떻게 되는지 살펴본다
mvn clean package
를 실행한 다음 다음 명령으로 스프링부트를 실행하면 greeting.name
속성이 Sertanejo로 변한다.
java -jar target/sbur-rest-demo-0.0.1-SNAPSHOT.jar --greeting.name=Sertanejo
이렇게 실행하면 /actuator/env를 쿼리하였을때 명령줄 파라미터에 따른 새 섹션이 존재하고 greeting.name에 대한 속성 항복이 있는 것을 확인 할 수 있다.
/greeting을 쿼리하면 Sertanejo가 반환되고 /greeting/coffee를 쿼리할 경우 재정의된 값이 SpEL표현식을 통해 응답에 통합된 것을 확인 할 수 있다.
로깅수준을 선택하는데 있어 많은 장단점이 존재한다.
더 많은 로깅을 선택하면 시스템 수준의 작업과 스토리지가 더 많이 소모되고 관련 없는 데이터를 모두 캡쳐하게 되고 이는 문제를 찾는 것을 훨씬 더 어렵게 만들 수 있다.
Actuator는 이 문제를 해결하기 위해 INFO와 같은 일반적인 로깅 수준으로 설정하고 중요한 문제가 발생한 경우 해당 수준을 일시적으로 변경할 수 있도록 지원한다.
이는 해당 엔트포인트에 POST 요청을 통해 로깅 수준의 변경을 쉽게 가능하다.
org.springframework.data.web에 대한 기본 로깅 수준이 INFO로 설정되어 있는 것을 확인할 수 있다.
만약 실행중인 애플리케이션에 문제가 있다고 판단되고 이를 진단하기 위해 로깅을 늘리고 싶은 경우 다음과 같이 구성된 JSON 형식을 해당 엑추에이터 엔드포인트로 post하면 된다.
다시 한번 /actuator/loggers를 쿼리하였을때 configuredLevel이 "TRACE"로 변한것을 확인 할 수 있다.