상세 컨텐츠

본문 제목

Spring Boot 4 에서 의 API versioning

Spring Framework

by Wanderer Kim 2025. 12. 2. 04:47

본문

728x90

이번에 Spring Boot 4가 정식으로 릴리즈되면서 여러가지 유용한 기능들이 추가되었는데요. 그중에 API versioning에 대해서 살펴보도록 하겠습니다.

그동안 spring framework에서 표준적으로 제공되는 것이 아닌 개발자가 팀과 합의 후 직접 적용해야 했는데요, Spring Boot 4에서는 이런 API versioning에 대한 표준 방법을 framework에서 지원해줘서 개발자가 해야하는 일이 많이 줄어 들었습니다.

API versioning의 장점

  • framework에서 지원해주는 interface를 사용하면 그동안 개발자가 작성해야 했던 많은 코드를 줄일 수 있습니다.
  • 표준화된 interface를 제공해줍니다.
  • Spring ecosystem과의 호환성이 매우 좋습니다.

API versioning 적용 방법

@RequestMapping의 version attribute를 통해서 version을 명시하고 ApiVersionConfigurer나 properties를 통해서 versioning 관련 설정을 합니다.

Configuration Options

두 가지 방법으로 versioning을 설정할 수 있습니다.

  1. WebMvcConfigurer를 통한 java configuration
  2. application.properties를 통한 configuration

 Java Configuration

package dev.danvega.users.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ApiVersionConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureApiVersioning(ApiVersionConfigurer configurer) {
        configurer
                // Choose ONE of these approaches (they cannot be mixed)
                //.usePathSegment(1)                              // Path-based: /api/v1/users
                //.useRequestHeader("X-API-Version")              // Header-based
                //.useQueryParam("version")                       // Query parameter-based
                .useMediaTypeParameter(MediaType.APPLICATION_JSON, "version")  // Media type
                .addSupportedVersions("1.0","2.0")
                .setDefaultVersion("1.0")
                .setVersionParser(new ApiVersionParser());
    }
}

Properties-based Configuration

# Basic versioning configuration
spring.mvc.apiversion.supported=1.0,2.0
spring.mvc.apiversion.default=1.0

# Choose ONE versioning strategy:

# Path segment versioning (e.g., /api/v1/users)
spring.mvc.apiversion.use.path-segment=1

# Request header versioning (e.g., X-API-Version: 1.0)
spring.mvc.apiversion.use.header=X-API-Version

# Query parameter versioning (e.g., ?version=1.0)
spring.mvc.apiversion.use.query-parameter=version

# Media type parameter versioning (e.g., Accept: application/json;version=1.0)
spring.mvc.apiversion.use.media-type-parameter[application/json]=version

Versioning 전략들

Path Segment Versioning

URL path를 통해서 versiong하는 방법입니다.

@GetMapping(value = "/{version}/users", version = "1.0")
public List<User> findAllv1() {
    return userRepository.findAll();
}

@GetMapping(value = "/{version}/users", version = "2.0")
public List<User> findAllv2() {
    // Return updated response structure
    return userRepository.findAll();
}

Configuration in Java

@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
    configurer
        .usePathSegment(1)  // Index of the path segment containing version
        .addSupportedVersions("1.0", "2.0")
        .setDefaultVersion("1.0");
}

Configuration in properties

spring.mvc.apiversion.use.path-segment=1
spring.mvc.apiversion.supported=1.0,2.0
spring.mvc.apiversion.default=1.0

Client Usage

GET /api/v1/users  # Version 1
GET /api/v2/users  # Version 2

Request Header Versioning

custom header를 이용해서 versioning하는 방법입니다.

@GetMapping(value = "/users", version = "1.0")
public List<UserDTOv1> getUsersV1() {
    return userRepository.findAll()
        .stream()
        .map(userMapper::toV1)
        .collect(Collectors.toList());
}

@GetMapping(value = "/users", version = "2.0")
public List<UserDTOv2> getUsersV2() {
    return userRepository.findAll()
        .stream()
        .map(userMapper::toV2)
        .collect(Collectors.toList());
}

Configuration in Java

configurer.useRequestHeader("X-API-Version");

Configuration in properties

spring.mvc.apiversion.use.header=X-API-Version

Client Usage

GET /api/users
X-API-Version: 2.0

Query Parameter Versioning

query parameter를 이용해서 versioning하는 방법입니다.

@GetMapping(value = "/users/list", params = "version=1.0")
public List<UserDTOv1> listUsersV1(@RequestParam String version) {
    return userRepository.findAll()
        .stream()
        .map(userMapper::toV1)
        .collect(Collectors.toList());
}

Configuration in Java

configurer.useQueryParam("version");

Configuration in properties

spring.mvc.apiversion.use.query-parameter=version

Client Usage

GET /api/users/list?version=2.0

Media Type Versioning

Media Type을 이용해서 versioning하는 방법입니다.

@GetMapping(value = "/users/media", version = "1.0", produces = "application/json")
public List<UserDTOv1> getUsersMediaV1() {
    return userRepository.findAll()
        .stream()
        .map(userMapper::toV1)
        .collect(Collectors.toList());
}

Configuration in Java

configurer.useMediaTypeParameter(MediaType.APPLICATION_JSON, "version");

Configuration in properties

spring.mvc.apiversion.use.media-type-parameter[application/json]=version

Client Usage

GET /api/users/media
Accept: application/json;version=2.0

Custom Version Parsing

ApiVersionParser를 이용하면 유저 진화적인 version를 parsing할 수 있습니다.

package dev.danvega.users.config;

public class ApiVersionParser implements org.springframework.web.accept.ApiVersionParser {

    @Override
    public Comparable parseVersion(String version) {
        // Allow "v1" or "v2" instead of "1.0" or "2.0"
        if (version.startsWith("v") || version.startsWith("V")) {
            version = version.substring(1);
        }
        
        // Auto-append ".0" for major versions
        if (!version.contains(".")) {
            version = version + ".0";
        }
        
        return version;
    }
}

위 설정은 아래와 같은 역할을 한다

  • /api/1.0/users 대신 /api/v1/users 호출 가능
  • ?version=2.0 대신 ?version=2 호출 가능
  • X-API-Version: 1.0 대신 X-API-Version: v1 호출 가능

특징

  • 자동 version 탐지: framework에서 자동으로 호환되는 version을 탐지해줍니다.
  • 향상된 error handling: 만약 지원하지 않는 version을 호출하면 400 Bad Request를 InvalidApiVersionException과 함께 반환 합니다.
  • Deprecation 지원: framework에서 version deprecation에 대한 힌트를 제공할 수 있습니다.
  • Optional Versioning: spring framework에서는 기본적으로 versioning을 지원하지만 해당 기능을 끌 수도 있습니다.
configurer.setVersionRequired(false);

spring.mvc.api-versioning.version-required=false
반응형

'Spring Framework' 카테고리의 다른 글

DispatcherServlet이란?  (2) 2025.05.20
Spring MVC 구조  (0) 2025.05.20
ModelAndView란?  (0) 2025.05.17
Servlet forward와 include의 차이점  (0) 2025.05.01
BeanFactory와 ApplicationContext의 차이점  (0) 2025.02.16

관련글 더보기

댓글 영역