@PathVariable vs @ModelAttribute

jduckling_1024·2021년 7월 26일
0

이것저것

목록 보기
9/13

코드 리팩토링하고 테스트코드 짜는데 자꾸 에러나서 찡얼거렸던 하루... 였는데 알고보니 내 잘못이었다 ㅎㅎ @PathVariable과 @ModelAttribute에 대해서 뭔가 알지 못했던 부분이 있었던 것이다.


@PathVariable

URL의 값을 정의한 이름과 같은 이름의 인자랑 매핑시키고자 할 때 사용한다. 아래와 같이 사용할 수 있다.

public class TestController {
    @GetMapping("/{name}")
    public ResponseEntity<String> test(@PathVariable String name){
        System.out.println(name);
        return ResponseEntity.ok("OK");
    }
}

GET으로 요청할 때 다음과 같다.
http://localhost:8080/jin

주의할 점
null이나 공백이 들어오는 경우에는 사용하면 안된다.
값에 .이 포함되어 있다면 그 뒤는 잘려서 들어온다.


@ModelAttribute

물론, @RequestParam으로 값을 여러 개 받을 수 있긴 하다. 하지만, 파라미터를 다 적어주자니 코드가 지저분해질 것이다. 이럴 때 인자로 클래스를 받도록 하고 앞에 @ModelAttribute를 써줄 수 있다. 아래와 같이 말이다.


Dto.java

public class DTO {
    String name;
    String age;
    ...
    // getter
    // setter
}

TestController.java

@RestController
public class TestController {
    @GetMapping("/")
    public ResponseEntity<String> test(@ModelAttribute Dto dto){
        System.out.println(dto.getName());
        System.out.println(dto.getAge());
        return ResponseEntity.ok("OK");
    }
}

name과 age에 대한 값은 Dto 클래스의 setter를 통해 각 변수에 매핑된다. 따라서 @ModelAttribute를 사용하고 싶다면 Dto 클래스에 setter가 있어야 한다.


위의 사실까지는 알고 있었지만 URL을 뜯어본 것은 처음이었다.
(그래서 단위 테스트 하면서 오류를 맞이했다는...)

GET으로 요청할 때 다음과 같다.
http://localhost:8080?name=jin&age=23

@RequestParam으로 하나하나 작성했을 때와 같은 형태다.


여담

파일 다운로드 기능을 리팩토링 중이었다. 파일 명을 전달 받아야 하는 상황이었는데 돌아가는 것만 보고 Swagger로 URL을 뜯어보지 않은 것이 잘못이었다.

@RestController
public class FileDownloadController {
    @GetMapping("/{name.+}")
    public ResponseEntity<String> test(@ModelAttribute FileDto dto){
        ...
    }
}

FileDto에는 파일 이름만 속성으로 들어있는 상태다. 이거 돌아가기는 잘 돌아가는데, URL이 말도 안되게 나와서 애먹었다...

결론

속성들을 전부 파라미터로 적어주고 @PathVariable을 써줄지 DTO 하나 만들어서 @ModelAttribute를 써줄지는 속성 개수에 따라, 본인 코딩 스타일에 따라 달라질 것 같다.

profile
Coding Duck

0개의 댓글