본문 바로가기
Spring

[Spring 공식문서] Spring Boot. Core Features

by 매트(Mat) 2024. 5. 16.

스프링 공식문서 정리할 두 번째 내용은 Spring Boot 프로젝트의 Core Features 파트이다. 스프링 부트의 코어 기능인데, 모두 정리하기는 힘들어서 중요하다고 생각되는 몇가지만 정리해보았다. (근데 이것도 주관적이라.. 흠..)

Core Features

SpringApplication

SpringApplication 클래스는 main() 메서드에서 시작되는 Spring 애플리케이션을 부트스트랩하는 편리한 방법을 제공한다.

부트스트랩(Bootstrap): 클래스 로더의 로딩 과정에서 JVM을 실행할 때 생성되며, Object 클래스들을 비롯한 자바 API들을 로드한다.

Startup Failure

애플리케이션 실행시 실패하면 FailureAnalyzers 클래스가 에러 메시지와 어떻게 하면 해결할 수 있는지 action을 제시해준다.

스프링 부트에서는 FailureAnalyzer 인터페이스를 기반으로 다양한 구현체들을 제공한다.

Lazy Initialization

SpringApplication은 지연 초기화(Lazy Initialization)를 제공한다. 활성화되면 애플리케이션 실행시점이 아닌 실제 필요해지면 그 때 빈들을 생성해준다.

  • 장점은 애플리케이션 실행 시간이 단축된다는 점과 웹에서 HTTP 요청이 수신이될 때까지 많은 웹 관련 Bean이 초기화되지 않는다.
  • 단점은 애플리케이션 초기에 문제 발견이 어려울 수 있다 즉, 해당 빈을 사용하지 않는한 조기에 문제를 발견할 수 없다. 또한 빈들이 필요해져서 사용했을 때 메모리가 충분한지 성능 테스트를 하여 검증해야 한다.

기본적으로 지연 초기화는 비활성화시켜주는 것이 좋다. (default=false)

Application Events and Listeners

ContextRefreshedEvent 와 같은 일반적인 Spring Framework Event 외에도 SpringApplication은 몇 가지 추가 애플리케이션 Event를 보낸다.

일부 Events는 실제로 ApplicationContext가 생성되기 전에 트리거 되므로 해당 Event에 대한 Listener를 @Bean으로 등록할 수 없다. 등록하는 방법은 SpringApplication.addListeners(…) 메서드를 사용한다.

쉽게 말해, Application이 실행되었을때, Application이 실행 되기 전에, Application Context가 실행 되었을 때 등등.. 여러 시점에서 실행할 Event Listener를 구현할 수 있다.

Web Environment

SpringApplication은 사용자를 대신하여 올바른 유형의 ApplicationContext를 생성하려고 시도한다. WebApplicationType 에 따라 결정된다.

  • Spring Mvc use → AnnotationConfigServletWebServerApplicationContext
  • Spring Mvc not use and Spring WebFlux use → AnnotationConfigReactiveWebServerApplicationContext
  • 둘 다 아니면 AnnotationConfigApplicationContext 를 생성한다.

Spring MVC와 Spring WebFlux 둘 다 사용하게 되면 기본적으로 Spring MVC를 사용하게 되고, 오버라이딩도 가능하다.

setWebApplicationType(WebApplicationType)

Using the ApplicationRunner or CommandLineRunner

SpringApplication이 실행된 후 특정 코드를 실행시켜야 하는 경우 ApplicationRunner 또는 CommandLineRunner 인터페이스를 구현할 수 있다. 두 인터페이스 모두 같은 방법을 제공하여 run() 메서드를 제공한다.

Externalized Configuration

Spring Boot를 사용하면 구성을 외부화하여 다양한 환경에서 동일한 애플리케이션 코드로 작업할 수 있다. 다양한 외부 구성 소스를 사용할 수 있다.

  • Java properties files
  • YAML files
  • environment variables
  • command-line arguments

Spring Boot는 합리적인 값 재정의를 허용하도록 설계된 매우 특별한 PropertySource 순서를 사용한다.

Profile Specific Files

Spring Boot는 네이밍 규칙 application-{profile}을 사용하여 profile별 파일 로드를 시도한다.

예를 들어, 애플리케이션이 prod profile을 활성화시키면(YAML files), application.yamlapplication-prod.yaml 둘 다 사용된다. 즉, profile 네이밍이 없는 경우 항상 오버라이딩된다.

Importing Additional Data

Application properties는 spring.config.import를 사용하여 다른 위치의 설정 데이터를 import 할 수 있다.

spring.config.import=my.properties

Working With Multi-Document Files

Spring Boot를 사용하면 하나의 파일에 각 독립적으로 실행할 수 있는 멀티 문서를 허용해준다.

예제를 보면 이해가 금방된다. (--- 로 구분한다.)

spring:
  application:
    name: "MyApp"
---
spring:
  application:
    name: "MyCloudApp"
  config:
    activate:
      on-cloud-platform: "kubernetes"

Type-safe Configuration Properties

application.properties의 값을 사용할 때 @Value("${property}") 방식을 사용할 수 있는데 이는 번거로울 수 있다.

  • Type-safe 하지 않다. (문자열로 입력해야 한다.)
  • Multi properties 를 구성할 경우

이를 해결하기 위해 스프링 부트는 JavaBean Properties Binding 을 제공한다.

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "naver.openapi")
public class NaverProperties {

    private String bookUrl;
    //...
}
  • @ConfigurationProperties 애노테이션을 사용하여 properties 에 있는 값들을 매핑시킨다.
  • setter 를 사용하지 않으면 에러가 발생하는데, 사용하지 않아도 되는 경우가 있다.
  • @ConfigurationPropertiesjava.util.Optional 을 같이 사용하는 것은 권장하지 않는다. 차라리 null을 반환시키는 것이 좋다.
  • 위 방식 말고도 @EnableConfigurationProperties 애노테이션을 사용하는 방법도 있는데, 오직@ConfigurationProperties 애노테이션을 권장한다. 특히 스프링 컨텍스트에 있는 다른 빈들을 주입하지 말아야 한다.
  • 자세한건 https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.typesafe-configuration-properties.java-bean-binding 참고

@ConfigurationProperties Validation

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

    @NotNull
    private InetAddress remoteAddress;

    // getters/setters...

}

스프링 부트는 @Validated 을 사용하여 검증할 수도 있다.

Profile

Spring Profiles는 애플리케이션 설정 정보를 분리하고 특정 환경(environment)에서만 사용할 수 있도록 하는 방법을 제공한다.

@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {

    // ...

}
  • @Profile를 사용하여 production profile 인 경우에만 실행된다.
  • application.properties에 직접 지정할 수도 있다. → spring.profiles.active=dev,hsqldb

Logging

스프링 부트는 기본적으로 로그 인터페이스를 구현한 구현체들을 제공한다.

  • Java Util Logging
  • Log4j2
  • Logback

Log 특징들

  • 스프링 부트는 기본적으로 로그 포맷을 제공한다.
  • 콘솔에 출력할 수 있다.
  • 로그 레벨별로 Color로 표시한다.
  • 파일로 출력이 가능하다.
  • properties를 통해 원하는 패키지의 로그 레벨을 세팅할 수 있다.
  • 로그 파일이나 콘솔에 출력되는 포맷, 히스토리 시간 등 로그 설정을 커스터마이징 할 수 있다.
    • Logback을 사용하는 경우 logback-spring.xml 파일을 작성한다. (파일명은 규칙이므로 동일하게 생성해야 한다.)

Internationalization (국제화)

스프링 부트는 애플리케이션이 다양한 언어 기본 설정을 가진 사용자를 수용할 수 있도록 현지화된 메시지들을 지원한다. 스프링 부트는 기본적으로 MessageSource 인터페이스를 제공한다.

Aspect-Oriented Programming

스프링 부트는 AOP를 위한 auto-configuration을 제공하고, 기본적으로 AOP는 CGLib 프록시를 사용한다.

JSON

스프링 부트는 3개의 JSON 매핑 라이브러리를 제공한다.

  • Gson
  • Jackson
  • JSON-B

기본적으로 Jackson 라이브러리를 선호하며 주로 사용한다. (나머지는 거의 사용하지 않는다.)

Jackson을 위한 auto-configuration이 제공되며, spring-boot-starter-json 의존성에 속한다. Jackson 라이브러리를 사용하면 자동으로 ObjectMapper가 빈으로 등록되어 사용할 수 있다.

Testing

스프링 부트는 애플리케이션의 테스트를 위한 다양한 테스트 라이브러리를 제공한다. 스프링 부트가 기본적으로 제공하는 Starter인 spring-boot-starter-test 을 주로 사용한다.

  • JUnit 5
  • AssertJ
  • Hamcrest
  • Mockito
  • JSONassert
  • JsonPath
  • Awaitility

기본적으로 테스트 환경에서 @Transactional 을 사용하면 각 테스트 메서드가 끝나고 나면 트랜잭션 롤백을 시킨다. 하지만 RANDOM_PORT나 DEFINED_PORT를 사용하는 경우 암시적으로 실제 서블릿 환경을 제공하므로 HTTP 클라이언트와 서버는 별도의 스레드로 실행된다. 따라서 별도의 트랜잭션이 실행되는데 이 경우 서버에서 시작된 트랜잭션은 롤백되지 않는다.

테스트 환경에서만 사용할 수 있는 설정 파일을 정의할 수 있다. (@TestConfiguration 사용)

스프링 부트의 auto-configuration 시스템은 테스트하기에 조금 과할 수 있다. 그래서 큰 설정을 분리하면 각 기능에 맞는 테스트 설정을 제공한다.

댓글