[Java, Spring] Restful API에 버전관리를 추가해보자

API서비스가 복잡하게 증가하다보면 버전관리 문제는 피할수가 없다.
나중에 생각할게 아니라 규칙을 정해 미리 적용한다면, 구웃.

버전 명명 규칙을 굳이 정하자면 아래와 같을 수 있고

/api/v3/greetings // 서비스 수준
/api/v3/greetings/v3.1/hello // 서비스 단위 및 기능 수준
/api/v3/greetings/v3/hello // 기능 수준

보편적인 URL맵핑 방식을 보자면 크게 Class단위에서 정의, Method 단위에서 정의하는 두가지 방법이 있을것이다.

API에 버전을 지정하는 방법론은 몇가지가 있는데, 대표적으로

1. http 헤더를 변조하여 버전 정보를 추가하거나 미디어타입 변경. (Accept: application/v3+json)
2. url path에 추가함(http://google.com/v1/search)
3. url 파라미터로 추가함 (http://google.com?v=v1)

1번은 일반적이지 않고 클라이언트에 따라 작업하기 까다로울 수 있다.
3번은 뭔가 Rest스럽지 않다.
2번은 여러 URI가 생기겠지만 그래도 뭐 괜찮다. 

기존에 사용하던 레거시 코드에 붙여야했는데 URI Path규칙이 이미 정해져있기 떄문에
버전명을 서비스 단위로 붙일지 기능단위로 붙일지 고민해야했다.
@Version(v1) 과 같이 어노테이션을 활용하여 한꺼번에 붙이는 기능을 만들고 싶어,
github와 여러 블로그 글을 참조했는데, 

서버가 뜰때 RequestMapping을 가로채 버전명을 끼워넣어 새로 URL을 맵핑시켜주는 아이디어는 얻었으나
실제로 적용해볼만한 코드는 없었고. 클래스 단위, 메소드 단위에서
URL맵핑을 정의하는 케이스를 포괄하는 케이스는 아무도 없었다.

컨셉을 잡고 수정 보완하기 시작하여 아래와 같이
@ApiVersion을 명시해주면 버전관리가 되는 코드를 만들어 서비스에 적용할 수 있었다.
클래스 단위, 메소드 단위의 맵핑이 모두 적용되고, 동시에 붙을 경우 메소드 내에 있는 버전을 우선으로 한다.
그리고 버전은 배열로 받아 여러개의 중복 버전도 생성할 수 있게 해준다.

https://gitlab.com/htrucci/apiversion

@ApiVersion

It Can ApiVersioning Easier With Annotation Must Express Position of API Version With {version}

@RequestMapping("/service/api/{version}/")

It’s Possible ApiVersioning Both Class Level RequestMapping And Method RequestMapping


@Controller
@RequestMapping("/service/api/")
public class ApiController {

  // /service/api/v2/test
  @ApiVersion(version = Version.V2)
    @RequestMapping(value = "/{version}/test", method = {RequestMethod.GET, RequestMethod.POST})
    public String testv2(HttpServletRequest httpReq, Model model) throws Exception{
        System.out.println("testv2");
        return "test";
    }
}

If You Declare Class And Method Both Then Class Declare is Ignored. Method Annotation is Priority First.


@Controller
@RequestMapping("/service/api/{version}/")
@ApiVersion(version = Version.V3)
public class ApiTobeController {

  // /service/api/v3/test
    @RequestMapping(value = "/test", method = {RequestMethod.GET, RequestMethod.POST})
    public String testv3(HttpServletRequest httpReq, Model model) throws Exception{
        return "test";
    }

  // /service/api/v4/test
  // /service/api/v5/test  
    @ApiVersion(version = {Version.V4, Version.V5})
    @RequestMapping(value = "/{version}/test", method = {RequestMethod.GET, RequestMethod.POST})
    public String testv45(HttpServletRequest httpReq, Model model) throws Exception{
        return "test";
    }
}

It’s Possible Create Multiple Version UrlMapping


@ApiVersion(version = {Version.V4, Version.V5})
@RequestMapping(value = "/{version}/test", method = {RequestMethod.GET, RequestMethod.POST})
public String testv45(HttpServletRequest httpReq, Model model) throws Exception{
  return "test";
}

You may also like...

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.