ServletUriComponentsBuilder과 ResponseEntity

윤현우·2023년 7월 6일
0
post-thumbnail

REST API에 대하여 공부하는 중, ServletUriComponentsBuilder를 사용하여 필요한 URI를 만들어 반환하는 것에 대해 궁금증이 생겨 정리해 보았다.


UriComponentsBuilder

인터넷상에 존재하는 모든 자원(Resource)은 URI를 이용하여 그 위치를 나타내게 된다.

따라서, 웹 애플리케이션을 개발할 때 어떤 데이터를 리턴해주기 위해서 내부적으로 URI를 이용해 요청을 전송하게 된다.

UriComponentsBuilder는 이러한 URI를 작성할 때 실수를 범하거나 유지보수 측에서 유리하게 작성하기 위해 사용하는 클래스이다.

UriComponentsBuilder는 UriComponents들을 쉽게 작성하기위해 만들어진 builder 클래스이다.


Static Factory Method 중에 하나를 이용하여 UriComponentsBuilder 객체를 생성한다.

  1. Static Factory Method의 종류는 아래와 같다.

    • newInstance()

    • fromPath(String)

    • fromUri (URI)

    • fromUriString (String)

    • fromHttpUrl (String)

    • fromHttpRequest (HttpRequest)

    • fromOriginHeader (String)


  1. 대응되는 각 메서드를 이용하여 URI 구성요소를 설정하거나 인코딩을 설정한다.

    • scheme(String)

    • userInfo(String)

    • host(String)

    • port(String or int)

    • path(String)

    • queryParam(String, Object...)

    • queryParams(MultiValueMap<String, String>)

    • fragment(String)

    • encode(void or Charset) : void일 경우 UTF-8 로 인코딩

    • expand(Map<String, ?> or Object... or UriTemplateVariables) : URI 템플릿 변수 값을 지정


  1. build() 메서드를 이용하여 UriComponents 인스턴스를 Build 한다.

    또는 buildAndExpand() 메서드를 이용하여 URI 템플릿 변수를 설정한 후 Build한다.

    이후 toUri()를 통하여 URI 객체로 변환 시킨다.

// 1. 간단한 링크 생성
UriComponents uriComponents1 = UriComponentsBuilder.newInstance()
    .scheme("https").host("blog.naver.com/aservmz").path("/222313864092").build(); 
    // https://blog.naver.com/aservmz/222313864092
        
//  2. URI 인코딩
UriComponents uriComponents2 = UriComponentsBuilder.newInstance()
    .scheme("http").host("www.example.com").path("/encodeTest test").build().encode();
    // http://www.example.com/encodeTest%20test
        
//  3. path 내에 템플릿 변수설정 방법 => path() 내에 {}로 변수명 지정 후 buildAndExpand()메서드에서 값 설정
URI uriComponents3 = UriComponentsBuilder.newInstance()
    .scheme("http").host("www.example.com").path("/{키워드는}/{아무렇게나 지정해도 됩니다.}")
    .buildAndExpand("UriTemplate", "setting")
    .toUri();
    // http://www.example.com/UriTemplate/setting
        
// 4. Query Parameter가 포함된 URI 생성
URI uriComponents4 = UriComponentsBuilder.newInstance()
    .scheme("http").host("www.example.com").path("/{경로}")
    .query("q={queryValue1}").query("p={queryValue2}").buildAndExpand("testPath", "value1", "value2")
    .toUri();
    // http://www.example.com/testPath?q=value1&p=value2

// 5. toUriString()을 이용한 방법
UriComponents uriComponents5 = UriComponentsBuilder
    .fromUriString("https://example.com/test/{testVariable}")
    .queryParam("q", "{q}").encode().buildAndExpand("test", "12345");
    // https://example.com/test/test?q=12345

이후 인코딩 시에는 항상 UriComponentsBuilder안에서 인코딩을 해야한다.


ServletUriComponentsBuilder

ServletUriComponentsBuilder 클래스는 UriComponentsBuilder클래스를 상속하고 있다.

UriComponentsBuilder는 직접 URI를 생성 및 인코딩 한다면, ServletUriComponentsBuilder는이전 요청의 URI를 재사용하여 보다 편리하게 URI를 사용할 수 있도록 하는 클래스이다.


  • fromContextPath(HttpServletRequest)

  • fromServletMapping(HttpServletRequest)

  • fromRequestUri(HttpServletRequest)

  • fromRequest(HttpServletRequest)

// 이 메서드들은 요청 객체를 RequestContextHolder로부터 얻는다는 점을 제외하고 위의 메서드들과 동일합니다.

  • fromCurrentContextPath()

  • fromCurrentServletMapping()

  • fromCurrentRequestUri()

  • fromCurrentRequest()


@PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User savedUser = service.save(user);

        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(savedUser.getId())
                .toUri();

        return ResponseEntity.created(location).build();
    }

fromCurrentRequest()

  • 현재 요청된 Request 값을 가져옴
  • ex) localhost:8080/users

path("/{id}")

  • 이후 URI 경로 설정

buildAndExpand(savedUser.getId())

  • 위에서 결정한 파라미터 값 생성

toUri()

  • URI로 변경

이렇게 URI를 만들 수 있다.

여기서 URI를 생성해서 반환하는 이유는

하나의 데이터를 생성한 후 데이터의 상세정보를 볼 때 id값을 다시한번 서버에 물어봐야 한다.

하지만 해당 URI를 반환시킨다면, 다시 물어보는 만큼의 네트워크 트래픽을 줄일 수 있기 때문에 사용하는 것이다.


ResponseEntity

RestAPI에서 상태코드와 함께 반환할 때 ResponseEntity를 사용한다.

ResponseEntity에서는 URI를 반환할 때, 필요한 상태코드들을 메서드로 제공한다.

created(201) 뿐만 아니라, accepted(202), noContent(204), badRequest(400), internalServerError(500), notFound(404) 등 자주 쓰이는 상태코드를 가독성 좋은 메소드로 제공한다.

따라서 반환 값을

return ResponseEntity.created(location).build();

로 만든 것이다.

이렇게 상태코드를 200번의 상태코드만이 아닌 다양한 상태코드를 사용하여 상태를 반환할 수 있다.


참고
https://velog.io/@jakeseo_me/Spring-Boot%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-RESTful-Web-Services-%EA%B0%9C%EB%B0%9C-14-HTTP-Status-Code-%EC%A0%9C%EC%96%B4
https://blog.naver.com/PostView.naver?blogId=aservmz&logNo=222322019981

profile
개발자가 되는 그날까지

0개의 댓글