자동목차
API Versioning 의 필요성
- 하위 호환성 유지
- API를 사용하는 사용자는 특정 API 인터페이스에 의존하게 됩니다. 만약 API가 변경되거나 새로운 기능이 추가되면서 기존의 인터페이스가 변경된다면 하위 호환성을 유지하지 않으면 기존 클라이언트에서 오류가 발생할 수 있습니다.
- 버전 관리를 통해 이전 버전의 API를 유지하면서 새로운 기능을 추가한 버전을 제공할 수 있습니다.
- 점진적인 기능 개선
- API는 시간이 지남에 따라 개선되고 확장됩니다. 새로운 기능을 추가하거나 성능을 개선하거나 보안을 강화하는 등의 작업이 필요할 때 버전 관리를 통해 단계적으로 새로운 버전을 릴리스할 수 있습니다. 이를 통해 클라이언트는 자신에게 필요한 시점에 새 버전을 선택적으로 사용할 수 있습니다.
- 기존 클라이언트 지원
- 다양한 사용자가 API를 사용하고 있으며 이들 중 일부는 최신 버전으로 쉽게 업그레이드할 수 없는 경우가 많습니다. API 버전 관리를 통해 기존 클라이언트가 계속해서 안정적으로 동작할 수 있도록 지원할 수 있습니다.
- API 수명 주기 관리
- 모든 API는 수명 주기가 있으며, 버전 관리를 통해 API의 수명 주기를 체계적으로 관리할 수 있습니다. 이는 API의 기능이 오래된 경우 폐기하고, 새로운 기능으로 전환할 수 있도록 도와줍니다.
- 비즈니스 요구사항 반영
- 비즈니스 환경이 변화하면서 새로운 요구사항이 발생할 수 있습니다. API 버전 관리를 통해 이러한 요구사항을 반영한 새로운 버전을 릴리스하면서도 기존 비즈니스 논리를 보호할 수 있습니다.
API Versioning 종류와 그 방법
API 버저닝 방법에는 API URL을 활용하거나 params, 요청 헤더, accept 헤더 4가지 방법이 있습니다.
먼저 시작하기 전에 응답 데이터를 정의하기 위해 각각 버전1, 버전2의 응답 바디를 아래와 같이 정의하도록 하겠습니다.
{ // version 1
"lastName": "Son"
"firstName": "Seunggi"
}
{ // version 2
"name" : {
"lastName": "Son"
"firstName": "Seunggi"
}
}
위 json 형식과 매핑되는 클래스를 아래 코드와 같이 생성해줍시다.
@Getter
public class PersonV1 {
private String firstName;
private String lastName;
public PersonV1(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
@Getter
public class PersonV2 {
private Map<String, String> name;
public PersonV2(String firstName, String lastName) {
this.name = new HashMap<>();
name.put("firstName", firstName);
name.put("lastName", lastName);
}
}
그럼 이제 api versioning 실습을 위한 준비가 되었습니다.
먼저 api url 을 통한 방법입니다.
API URL
말 그대로 api url 패턴을 통해 버저닝을 관리하는 방법입니다. url에 v1, v2, v3… 와 같이 버전을 포함시키는 방법입니다.
@RestController
public class VesioningPersonController {
// url을 통해 버저닝
@GetMapping("/v1/person")
public PersonV1 getFirstVersionPerson() {
return new PersonV1("Seung gi", "Son");
}
@GetMapping("/v2/person")
public PersonV2 getSecondVersionPerson() {
return new PersonV2("Seung gi", "Son");
}
위의 코드를 보시면 /v1/person
, /v2/person
과 같이 버전기록을 url에 포함 시키고있습니다./v1/person
으로 접근해보면
v1에 해당하는 응답 데이터인
{
firstName: "Seung gi",
lastName: "Son"
}
위 형식과 같이 출력이 되고
/v2/person
으로 접근을 하면
{
name : {
firstName: "Seunggi"
lastName: "Son"
}
}
위 형식과 같이 출력 되는 것을 볼 수 있을 것입니다.
RequestParam
다음은 매개변수를 통해 버저닝 하는 방법입니다.
// param을 통해 버저닝
@GetMapping(value = "/person", params = "version=1")
public PersonV1 getFirstVersionPersonWithRequestParam() {
return new PersonV1("Seung gi", "Son");
}
@GetMapping(value = "/person", params = "version=2")
public PersonV2 getSecondVersionPersonWithRequestParam() {
return new PersonV2("Seung gi", "Son");
}
위 코드 역시 간단합니다. params 속성에 version의 버전을 명시해주면 됩니다.
http://localhost:8080/person?version=1
혹은
http://localhost:8080/person?version=2
에 접근 하면 각 버전에 맞는 응답 데이터 형식을 볼 수 있을 것입니다.
Request Header
요청 헤더를 통한 방법입니다.
// 요청헤더를 통해 버저닝
@GetMapping(value = "/person/header", headers = "X-API-VERSION=1")
public PersonV1 getFistVersionPersonWithRequestHeader() {
return new PersonV1("Seung gi", "Son");
}
@GetMapping(value = "/person/header", headers = "X-API-VERSION=2")
public PersonV2 getSecondVersionPersonWithRequestHeader() {
return new PersonV2("Seung gi", "Son");
}
headers 속성에 X-API-VERSION=1
과 같이 명시해 줍니다. header의 key 값은 원하시는대로 명시해주셔도 됩니다.
위와 같이 header에 key value를 지정 해주고 요청을 해보면 해당 response를 받는 것을 확인할 수 있습니다.
Media Type
마지막으로 MediaType을 통해 버저닝 하는 방법입니다.
// MediaType을 통한 버저닝
@GetMapping(value = "/person/accept", produces = "application/vnd.company.app-v1+json")
public PersonV1 getFistVersionPersonWithAcceptHeader() {
return new PersonV1("Seung gi", "Son");
}
@GetMapping(value = "/person/accept", produces = "application/vnd.company.app-v2+json")
public PersonV2 getSecondVersionPersonWithAcceptHeader() {
return new PersonV2("Seung gi", "Son");
}
produces 라는 attribute 값에 application/vnd.company.app-v1+json
와 같은 값을 명시해줍니다.
application/vnd.company.app-v1+json
와 같은 형식은 정해져 있는 것은 아니지만 관례상 이와 같이 명시한다고 합니다.
위와 같이 accept header에 v2 버전으로 요청을 보냈을때 정상적으로 응답을 받을 수 있는 것을 확인할 수 있습니다.
API 버저닝 시 고려사항
- api url 방식은 버전이 url에 직접적으로 명시되기 때문에 api url이 깔끔하지 않습니다.
- 요청 헤더는 원래 버저닝을 위한 요소가 아닙니다. 또한, 클라이언트 사이드에서 헤더를 직접 설정해야 합니다.
- 헤더에 기반한 api 생성을 지원 하지 않을 수도 있습니다. header 방식 이용 시 이에 대한 고려도 필요합니다.
이렇게 API 버전 관리 방법에 대하여 알아보았습니다. 실제로 x(구 트위터)에서는 api url 방식을 사용중이고, request param은 아마존, header는 마이크로소프트, media type은 깃허브에서 사용 중이라고 합니다.
api versioning이 왜 필요한지, 왜 해야하는지 그리고 개발 중인 팀과 프로젝트에 잘 어우러지게 고려하여 어떤 방식을 채택하면 좋을 지 잘 생각해보시면 좋을 것 같습니다.
'BackEnd' 카테고리의 다른 글
마이크로 서비스 간 분산추적 with Zipkin (1) | 2024.10.08 |
---|---|
Spring Cloud로 MSA 구축해보기 (3) | 2024.09.30 |
[Spring] OAuth Client로 네이버 로그인 구현하기 (1) | 2024.09.03 |
[Spring] AOP (0) | 2023.08.29 |
[Java] String클래스의 메소드들 (0) | 2023.08.22 |