우리가 Java Spring으로 API endpoint의 Controller를 만들 때, 값을 받아올 수 있도록 Spring은 여러 방법을 지원하고 있다.
주로 함수의 파라미터 형태로 값을 받아오는 형태이다. 구체적으로 그 방식에는 아래와 같은 것들이 있다.(Annotation이 포함된 코드입니다.)

  • @PathVariable
  • @RequestParam
  • @RequestBody
  • @RequestHeader

순서대로 하나씩 알아보자

  • 이 글에서는 용법을 주로 다루고 있습니다. 원리를 다루지 않고 있음을 알려드립니다.
  • Spring의 경우에는 내부의 Servlet의 메소드들의 동작을 기반으로 아래와 같은 Annotation이 지원됩니다.

Spring 기준입니다!


@PathVariable

  • 서버에서는 파라미터로 칭한다.
  • 요청 Url 형식 : 정해진 위치에 Variable의 값을 적은 형태이다.
http://localhost:8080/foos/abc

method의 parameter로 받아오는 코드

  • 예시와 같이 요청이 오면 id의 값은 abc가 되겠다.
@GetMapping("/foos/{id}")
@ResponseBody
public String getFooById(@PathVariable String id) {
    return "ID: " + id;
}

[Tip] PathVariable을 Optional로 활용하기

PathVariable을 사용하는 형태와 사용하지 않은 형태를 한 메소드로 둘 다 지원하는 형태다. (다형성)

http://localhost:8080/myfoos/optional/abc
----
ID: abc
http://localhost:8080/myfoos/optional
----
ID: null


method의 parameter로 받아오는 코드

required = false를 기재해주면 id 부분이 비어 있는 url 요청도 처리 가능하다.
단, 비어있다면 id 변수는 null로 처리되니 각별히 주의가 필요하다.

@GetMapping({"/myfoos/optional", "/myfoos/optional/{id}"})
@ResponseBody
public String getFooByOptionalId(@PathVariable(required = false) String id){
    return "ID: " + id;
}

@RequestParam

  • 서버에서는 Query Parameter로 칭한다.
  • 요청 Url 형식 : ? 로 쿼리임을 명시적으로 적어주고 그 뒤에 바로 변수명=값 형태로 url에 적어준다.
  • 예시로 다음의 쿼리는 id를 "abc" 가 PathVariable이 되겠다.
    http://localhost:8080/foos?id=abc


method의 parameter로 받아오는 코드
쿼리에 날라오는 id와 변수의 이름을 똑같이 만들어주면 String 타입 파라미터 id에 쿼리로 보낸 값이 할당 된다. (id = "abc")

@GetMapping("/foos")
public String getFooByIdUsingQueryParam(@RequestParam String id) {
    return id;
}

Optional, defaultValue 설정, 여러 개의 값 받기

  • required 옵션으로 Optional Parameter로 사용하기
    @RequestParam(value = "searchKeyWord1", required = false) final String searchKeyWord1
  • 초기값 (defaultValue) 설정하기
    @RequestParam(value = "writer", defaultValue = "MangKyu")
  • 여러 개의 값 받기
    • 여러 값을 받을 땐 값들 사이에 &&를 사용한다.
http://localhost:8080/foos?id=abc&&name=Lim

@RequestBody

@RequestBody는 클라이언트가 전송하는 Json(application/json) 형태의 HTTP Body 내용을 Java Object로 변환시켜주는 역할을 한다.
그렇기 때문에 요청시 Body 없이 @RequestBody를  사용하는 메소드를 활용하려고 한다면 에러가 발생하게 된다.
주로 POST, PUT method를 받을 때 사용한다.

  • 한 줄로 읽는 내부 동작 탐구
  • @RequestBody로 받는 데이터는 Spring에서 관리하는 MessageConverter들 중 하나인 MappingJackson2HttpMessageConverte를 통해 Java 객체로 변환된다. Spring은 메세지를 변환되는 과정에서 객체의 기본 생성자를 통해 객체를 생성하고, Reflection을 사용해 값을 할당한다.
@PostMapping("/foo") 
public ResponseEntity<Board> requestBody(@RequestBody final Board board) {
  return ResponseEntity.ok(boardService.add(board));
}
  • 여기서 Board는 requestDto에 해당한다.
@Getter
@Setter 
public class Board { 
    private int index; // 게시물의 번호를 저장하는 변수 
    private String writer; // 작성자의 이름을 저장하는 변수 
    private String contents; // 작성 내용을 저장하는 변수 }
}

  • 이 때 형식에 맞는 요청은 아래와 같다. 데이터 타입에는 XML, JSON, Multi From 등이 사용될 수 있다. 제일 많이 사용하는 타입인 Json으로 예시를 들겠다.
    • Url: http://localhost:8080/foo
    • Content-Type: application/json
    • Body:
      {
        index : 1
        writer: "Lim"
        contents : "어쩌고저쩌고"
      } 

@RequestHeader

  • RequestBody는 Request의 Body 부분에 적어주는 것이라면 Header 부분에 적어주는 것이다.
  • 요청 먼저 보자
Content-Type: application/json accept-language: kor MyPin: limser


method의 parameter로 받는 코드
위의 요청을 받는 다면 language는 kor이 되겠다.

@GetMapping("/greeting")
public ResponseEntity<String> greeting(@RequestHeader("accept-language") String language) {
    // code that uses the language variable
    return new ResponseEntity<String>(greeting, HttpStatus.OK);
}

@RequestHeader를 받아오는 여러가지 타입


@RequestHeader로 받는 방식 몇 가지를 더 소개하고자 한다. 편한 방법을 사용하면 된다.

  1. Annotation 파라미터로 header 이름 적어주기

@RequestHeader("accept-language") String language

  1. Map 사용
  • MultiValueMap을 사용하기도 한다.
    @RequestHeader Map<String, String> headers
  1. HttpHeaders Object로 받기

@RequestHeader HttpHeaders headers



Controller에 값을 받아오고 싶은 당신도 API의 동작 설계를 고려해 용도에 맞게 사용하기를 바란다.


Reference

+ Recent posts