Spring Boot 3.5에서 도입된 WebClient 글로벌 설정SSL 서비스 연결 자동 구성은 HTTP 클라이언트 설정의 복잡성을 획기적으로 줄여줍니다. 기존에는 WebClient마다 개별적으로 타임아웃, 리다이렉트, SSL 등을 설정해야 했지만, 이제 application.properties 한 곳에서 글로벌하게 관리할 수 있습니다.

WebClient 글로벌 설정

Spring Boot 3.4에서 RestClient와 RestTemplate에 대한 프로퍼티 기반 설정이 추가된 데 이어, 3.5에서는 WebClient에도 동일한 수준의 글로벌 설정을 지원합니다.

application.yml 설정

spring:
  webflux:
    webclient:
      # 연결 타임아웃 (밀리초)
      connect-timeout: 5000
      # 읽기 타임아웃
      read-timeout: 10000
      # 리다이렉트 설정 (기본값: true, 3.5에서 변경)
      follow-redirects: true
      # 최대 리다이렉트 횟수
      max-redirects: 5
      # 최대 메모리 버퍼 크기
      max-in-memory-size: 10MB
      # 압축 요청 활성화
      compression: true

자동 구성된 WebClient.Builder 사용

@Service
public class ApiService {

    private final WebClient webClient;

    // 자동 구성된 WebClient.Builder 주입
    // 글로벌 설정이 이미 적용되어 있음
    public ApiService(WebClient.Builder builder) {
        this.webClient = builder
            .baseUrl("https://api.example.com")
            .build();
    }

    public Mono<UserResponse> getUser(String userId) {
        return webClient.get()
            .uri("/users/{id}", userId)
            .retrieve()
            .bodyToMono(UserResponse.class);
    }

    public Flux<OrderResponse> getUserOrders(String userId) {
        return webClient.get()
            .uri("/users/{id}/orders", userId)
            .retrieve()
            .bodyToFlux(OrderResponse.class);
    }
}

특정 WebClient에 개별 설정 오버라이드

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient paymentClient(WebClient.Builder builder) {
        // 결제 API용: 글로벌 설정 기반 + 추가 커스터마이징
        return builder
            .baseUrl("https://payment.example.com")
            .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer ${token}")
            .filter(ExchangeFilterFunctions.basicAuthentication("user", "pass"))
            .filter((request, next) -> {
                // 요청 로깅
                System.out.println("Payment API 호출: " + request.url());
                return next.exchange(request);
            })
            .build();
    }

    @Bean
    public WebClient internalClient(WebClient.Builder builder) {
        // 내부 서비스용: 짧은 타임아웃
        return builder
            .baseUrl("http://internal-service:8080")
            .codecs(configurer -> configurer
                .defaultCodecs()
                .maxInMemorySize(256 * 1024)) // 256KB로 제한
            .build();
    }
}

SSL 서비스 연결 자동 구성

Spring Boot 3.5에서는 Testcontainers와 Docker Compose 통합 시 SSL 연결이 자동으로 구성됩니다.

SSL 번들 설정

spring:
  ssl:
    bundle:
      jks:
        # PEM 파일 기반 SSL 번들
        server-cert:
          keystore:
            certificate: classpath:server.crt
            private-key: classpath:server.key
          truststore:
            certificate: classpath:ca.crt

        # JKS 파일 기반 SSL 번들
        client-cert:
          keystore:
            location: classpath:client-keystore.jks
            password: changeit
          truststore:
            location: classpath:client-truststore.jks
            password: changeit

WebClient에 SSL 번들 적용

@Configuration
public class SecureWebClientConfig {

    @Bean
    public WebClient secureClient(
            WebClient.Builder builder,
            SslBundles sslBundles) {

        SslBundle bundle = sslBundles.getBundle("client-cert");

        // Reactor Netty HttpClient에 SSL 적용
        HttpClient httpClient = HttpClient.create()
            .secure(spec -> spec.sslContext(
                bundle.createSslContext()));

        return builder
            .baseUrl("https://secure-api.example.com")
            .clientConnector(new ReactorClientHttpConnector(httpClient))
            .build();
    }
}

Testcontainers SSL 통합

@SpringBootTest
@Testcontainers
class SecureServiceTest {

    @Container
    @ServiceConnection // SSL 자동 구성 포함
    static PostgreSQLContainer<?> postgres =
        new PostgreSQLContainer<>("postgres:17")
            .withCopyFileToContainer(
                MountableFile.forClasspathResource("server.crt"),
                "/var/lib/postgresql/server.crt")
            .withCommand("postgres",
                "-c", "ssl=on",
                "-c", "ssl_cert_file=/var/lib/postgresql/server.crt");

    @Test
    void shouldConnectWithSSL(@Autowired DataSource ds) throws Exception {
        try (var conn = ds.getConnection()) {
            // SSL 연결이 자동으로 구성됨
            var meta = conn.getMetaData();
            assertThat(meta.getURL()).contains("ssl=true");
        }
    }
}

Bootstrap Executor 자동 구성

Spring Boot 3.5의 또 다른 주요 기능인 Bootstrap Executor는 빈의 백그라운드 초기화를 자동으로 지원합니다.

spring:
  threads:
    virtual:
      enabled: true  # Virtual Thread 사용

# Bootstrap Executor가 자동 구성됨
# @Lazy 없이도 무거운 빈을 백그라운드에서 초기화
@Configuration
public class AppConfig {

    // backgroundInit = true로 백그라운드 초기화
    @Bean(backgroundInit = true)
    public HeavyService heavyService() {
        // 시간이 오래 걸리는 초기화 작업
        // 다른 빈 초기화를 블로킹하지 않음
        return new HeavyService(loadLargeModel());
    }

    @Bean(backgroundInit = true)
    public CacheWarmer cacheWarmer(CacheManager cacheManager) {
        // 캐시 워밍도 백그라운드에서
        var warmer = new CacheWarmer(cacheManager);
        warmer.warmAll();
        return warmer;
    }
}

구조화된 로깅 (Structured Logging)

Spring Boot 3.4에서 도입되어 3.5에서 더 강화된 구조화된 로깅입니다.

spring:
  logging:
    structured:
      format: ecs  # Elastic Common Schema
      # 또는: gelf, logstash

# 출력 예시 (ECS 포맷)
# {"@timestamp":"2026-04-04T12:00:00.000Z",
#  "log.level":"INFO",
#  "message":"User login successful",
#  "service.name":"my-app",
#  "trace.id":"abc123"}

Spring Boot 3.5는 프로퍼티 기반의 글로벌 HTTP 클라이언트 설정, SSL 자동 구성, 백그라운드 빈 초기화 등 운영 편의성을 대폭 개선했습니다. 특히 WebClient 글로벌 설정은 마이크로서비스 환경에서 여러 외부 API를 호출할 때 일관된 설정을 유지하면서도 필요한 부분만 오버라이드할 수 있어 매우 실용적입니다.