Spring Boot - API Versioning
API๋ฅผ ๊ฐ๋ฐํ๋ค๋ณด๋ฉด API ๋ฒ์ ์ ๋ํ ์๊ฐ์ ํ๊ฒ ๋๋ค.
๋ฒ์ ๋(Versioning)์ ํ์ง ์์ผ๋ฉด input/output์ด ๋ณ๊ฒฝ๋์์ ๋ ์ด๋ฅผ ์ฌ์ฉํ๊ณ ์๋ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋๋ก ์๋น์คํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ด๋ฌํ API Versioning์ ํ๊ธฐ ์ํด ์ง๊ธ๊น์ง ๋จ์ํ URI์ version์ ๋ช ์ํ๋ ๋ฐฉํฅ์ผ๋ก๋ง ์งํํด์๋๋ฐ, ๋ ๋ค์ํ ๋ฐฉ๋ฒ์ด ์์ด ์ด๋ฅผ ์ ๋ฆฌํด๋๊ณ ์ ํ๋ค.
URI Versioning / URI ์ด์ฉํ๊ธฐ #
// v1
@RestController
@RequestMapping("/api/uri/v1")
public class UriVersionControllerV1 {
@GetMapping("/versions")
public ResponseEntity<List<String>> getVersions() {
return ResponseEntity.ok(List.of("v1.1", "v1.2", "v1.3"));
}
}
// v2
@RestController
@RequestMapping("/api/uri/v2")
public class UriVersionControllerV2 {
@GetMapping("/versions")
public ResponseEntity<List<String>> getVersions() {
return ResponseEntity.ok(List.of("v2.1", "v2.2", "v2.3"));
}
}
์์ ์ด์ผ๊ธฐํ ๊ฒ์ฒ๋ผ URI์ ํน์ ๋ฒ์ ์ ๋ช ์ํ๋ ๋ฐฉ๋ฒ์ด๋ค.
๊ตฌํํ๊ธฐ ์ฝ๊ณ , URI๋ฅผ ํตํด ๋ฐ๋ก ๋ฒ์ ์ ํ์ธํ ์ ์์ผ๋ฏ๋ก ์ง๊ด์ ์ด๋ค.
ํ์ง๋ง URI ์์ฒด๊ฐ ๊ธธ์ด์ง๊ณ , URI๋ฅผ ๊น๋ํ๊ฒ ๊ด๋ฆฌํ๊ธฐ๋ ์ด๋ ต๋ค.
Request parameter Versioning #
@RestController
@RequestMapping("/api/parameter")
public class ParameterVersionController {
@GetMapping(value = "/versions", params = "version=1")
public ResponseEntity<List<String>> getVersionsV1() {
return ResponseEntity.ok(List.of("v1.1", "v1.2", "v1.3"));
}
@GetMapping(value = "/versions", params = "version=2")
public ResponseEntity<List<String>> getVersionsV2() {
return ResponseEntity.ok(List.of("v2.1", "v2.2", "v2.3"));
}
}
ํน์ ๊ฐ์ Request parameter๋ฅผ ํตํด์ ๋ฒ์ ์ ๊ตฌ๋ถํ ์๋ ์๋ค.
URI Versioning์ ๋นํด URI๋ฅผ ๊น๋ํ๊ฒ ๊ด๋ฆฌํ ์ ์์ง๋ง, Client ์ธก์์ ์ ์ ํ version parameter๋ฅผ ๊ผญ ๊ณ ๋ คํด์ผ๋ง ํ๋ค.
Header Versioning #
@RestController
@RequestMapping("/api/header")
public class HeaderVersionController {
@GetMapping(value = "/versions", headers = "X-API-Version=1")
public ResponseEntity<List<String>> getVersionsV1() {
return ResponseEntity.ok(List.of("v1.1", "v1.2", "v1.3"));
}
@GetMapping(value = "/versions", headers = "X-API-Version=2")
public ResponseEntity<List<String>> getVersionsV2() {
return ResponseEntity.ok(List.of("v2.1", "v2.2", "v2.3"));
}
}
Custom header๋ฅผ ํตํด ๋ฒ์ ์ ๊ตฌ๋ถํ ์ ์๋ค. Request parameter ๋ฐฉ์๊ณผ ์ฅ๋จ์ ์ ์ ์ฌํ๋ค.
๋ง์ฝ ์ฌ๊ธฐ์ ๋๋ถ์ด gateway ๋๋ reverse proxy๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด header์ ๋ํ ์ ํ์ด ์๋์ง ํ์ธํด๋ด์ผ ํ ํ์๊ฐ ์๋ค.
Content negotiation Versioning #
@RestController
@RequestMapping("/api/header/accept")
public class AcceptHeaderVersionController {
@GetMapping(value = "/versions", produces = "application/double.b.api.v1+json")
public ResponseEntity<List<String>> getVersionsV1() {
return ResponseEntity.ok(List.of("v1.1", "v1.2", "v1.3"));
}
@GetMapping(value = "/versions", produces = "application/double.b.api.v2+json")
public ResponseEntity<List<String>> getVersionsV2() {
return ResponseEntity.ok(List.of("v2.1", "v2.2", "v2.3"));
}
}
HTTP Content negotiation ๋ฐฉ์์ ์ด์ฉํ Versioning ๋ฐฉ๋ฒ์ด๋ค.
HTTP์ ํน์ฑ์ ๋ฐ๋ผ custom header/request parameter ์์ด๋ ๋ฒ์ ๊ด๋ฆฌ๋ฅผ ํ ์ ์๋ค.
์ด ๋ถ๋ถ๋ Client ์ธก์์ Accept
header๋ฅผ ์๋ชจ๋ฅด๋ฉด ์ ๋ฐฉ์์ด ์ดํด๊ฐ์ง ์์ ๊ฒ ๊ฐ์ Request ์์๋ฅผ ์์ฑํด๋ณด์๋ค.
### accept header -> version 1
GET localhost:8080/api/header/accept/versions
Accept: application/double.b.api.v1+json
### accept header(content negotiation) -> version 1 - order
GET localhost:8080/api/header/accept/versions
Accept: application/double.b.api.v1+json, application/double.b.api.v2+json,
### accept header -> version 2
GET localhost:8080/api/header/accept/versions
Accept: application/double.b.api.v2+json
### accept header(content negotiation) -> version 2 - order
GET localhost:8080/api/header/accept/versions
Accept: application/double.b.api.v2+json, application/double.b.api.v1+json,
### accept header(content negotiation) -> version 1 - q factor
GET localhost:8080/api/header/accept/versions
Accept: application/double.b.api.v1+json;q=0.3, application/double.b.api.v2+json;q=0.1
### accept header(content negotiation) -> version 2 - q factor
GET localhost:8080/api/header/accept/versions
Accept: application/double.b.api.v1+json;q=0.7, application/double.b.api.v2+json;q=0.9
๊ฒฐ๋ก #
์ด๋ ๋ฏ 4๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด์๋ค.
๋น์ฐํ ์ ๋ต์ ์๋ค. ํ/์กฐ์ง์์ ์ ์ ํ ๋ฐฉ๋ฒ์ ํ์ฉํด ์ฌ์ฉํ๋ฉด ๋๋ค.
๋์ ์ค์ํ ๊ฒ์ โ์ผ๊ด๋๊ฒ ์ฌ์ฉํ๊ณ ์๋๊ฐโ ์ธ ๊ฒ ๊ฐ๋ค.