YOUNG-JIN.OH
웃어라. 온 세상이 너와 함께 웃을 것이다.
울어라. 너 혼자만 울게 될 것이다.

URI 그리고 RESTFul API Versioning

참고 사이트:

인터넷 검색을 할 때 웹 브라우저 URL(Uniform Resource Locator) 에 주소를 입력하면 다른 컴퓨터 또는 서버에 접속하여 정보를 받아올 수 있습니다. 이름에서 의미하듯이 URL은 인터넷 상에서 특정 자원(Resource)을 표시하는 유일한 경로라고 할 수 있는데 문법은 다음과 같습니다.

scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]

Spring 에서 어떻게 처리하는지 내용을 확인해 봅니다. IntelliJ 에서 Spring Boot – Web 프로젝트를 생성하고 아래의 파일을 생성합니다.

package com.example.demo;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CalcController {

    @GetMapping("/plus")
    public ResponseEntity plus(
            @RequestParam("param1") String param1,
            @RequestParam("param2") String param2) {

        var result = Integer.parseInt(param1) + Integer.parseInt(param2);

        return new ResponseEntity(result, HttpStatus.OK);
    }

    @GetMapping("/minus/{param1}/{param2}")
    public ResponseEntity minus(
            @PathVariable("param1") String param1,
            @PathVariable("param2") String param2) {

        var result = Integer.parseInt(param1) - Integer.parseInt(param2);

        return new ResponseEntity(result, HttpStatus.OK);
    }
}

http://localhost:8080/plus?param1=10&param2=20
Query String 으로부터 여러 개의 값을 입력받아 결과를 출력합니다. (결과값 30)

http://localhost:8080/minus/10/20
URI 중간의 Path 의 구분을 통해 값을 입력받아 결과를 출력합니다. (결과값 -10)

Path를 구분하여 URI를 지정하는 것이 REST (REpresentational State Transfer) API를 구현하는 방식입니다. RESTFul 한 API를 구현하기 위한 지침은 참고 사이트를 보시고 아래의 문서도 정리가 잘 되어 있습니다.

여기서는 기술적으로 이 RESTFul API를 Versioning 하는 내용을 추가로 알아봅니다.

    @GetMapping("/api/v1/concat/{param1}/{param2}")
    public ResponseEntity concatV1(
            @PathVariable("param1") String param1,
            @PathVariable("param2") String param2) {

        var result = param1.concat(param2);

        return new ResponseEntity(result, HttpStatus.OK);
    }

    @GetMapping("/api/v2/concat/{param1}/{param2}")
    public ResponseEntity concatV2(
            @PathVariable("param1") String param1,
            @PathVariable("param2") String param2) {

        var result = param2.concat(param1);

        return new ResponseEntity(result, HttpStatus.OK);
    }

도메인 명이나 서비스의 범위에 따라 URI 패턴을 정하되 API의 버전을 경로에 추가합니다. 참고로 RESTFul 하지는 않지만, YouTube API 는 이런 식의 패턴으로 관리되고 있고 보통의 경우에는 이렇게 많이 사용합니다.

  • https://www.googleapis.com/youtube/v3/channels
  • https://www.googleapis.com/youtube/v3/videos

이렇게 했을 때 문제는 URI 관리대상이 늘어나고 도메인 표현의 대상이 아닌 버전 내용이 Path에 포함되는 문제도 있습니다. URI는 고정시키면서 다른 버전을 호출하게 하려면 Accept Header를 이용하는 방법을 생각해 봅니다.

@GetMapping(value = "/api/concat/{param1}/{param2}", produces = "application/vnd.x1fingers-v1+json")
    public ResponseEntity concatV1(
            @PathVariable("param1") String param1,
            @PathVariable("param2") String param2) {

        var result = param1.concat(param2);

        return new ResponseEntity(result, HttpStatus.OK);
    }

    @GetMapping(value = "/api/concat/{param1}/{param2}", produces = "application/vnd.x1fingers-v2+json")
    public ResponseEntity concatV2(
            @PathVariable("param1") String param1,
            @PathVariable("param2") String param2) {

        var result = param2.concat(param1);

        return new ResponseEntity(result, HttpStatus.OK);
    }

$ curl -H “Accept: application/vnd.x1fingers-v1+json” http://localhost:8080/api/concat/a/b
ab

$ curl -H “Accept: application/vnd.x1fingers-v2+json” http://localhost:8080/api/concat/a/b
ba

이 방법은 웹 브라우저에서 실행할 수 없는 단점이 있습니다. 그 외에 API 버전별 문서관리의 문제도 있고 캐쉬나 HTTP 헤더의 용도에 맞지않는 등의 문제도 있습니다.


You may also like...

2 Responses

  1. 2019-02-17

    […] URI 그리고 RESTFul API Versioning […]

  2. 2019-10-23

    […] URI 그리고 RESTFul API Versioning […]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.