미완성) Spring Web Annotations
안녕하세요.
저번 시간에 이어서 XSS 방지 기능을 리팩토링하며 배운 정보들을 정리해보는 시간을 갖겠습니다.
이번엔 SpringBindAnnotations입니다.
스프링은 HTTP Method 및 ContentType과 컨트롤러 메서드 인자에 선언된 SpringBindAnnotations 에 따라 각각의 경우 값을 다르게 바인딩합니다.
SpringBindAnnotations가 생각보다 여러 상황에서 유연하게 값을 바인딩해주기 때문에.. 개발을 하면서 예상치 못했던 상황이 종종 있었습니다.
이번 기회에 확실히 ! 정리해보겠습니다.
Spring Web Annotations
- Spring Web Annotations는 HTTP 요청 값에 대해 스프링이 값은 다양하게 바인딩하는 것을 지원합니다.
- 기존에 자세히 알아보지 않고 인터넷의 정보를 받아 들였었는데, 틀린 사실이 많아 자세히 정리해야겠다는 생각이 들었습니다.
- Spring Web Annotation는 다양하게 값을 처리하기 때문에 특정 HTTP Method, HTTP Content-Type, 파라미터 요청, 혹은 바디 요청에 대해 다양한 경우의 수가 생깁니다. 따라서 인터넷에서 위의 대한 설명은 실무적으로 사용하는 Best Practice의 접근으로 이해하면 좋을 것 같아요..
(@RequestParam은 HTTP 파라미터에 대해 바인딩을 처리한다든지의.. 하지만 Body데이터도 바인딩할 수 있다...)
또한, Best Practice의 관점은 주관이 강하고, 시간에 따라 변하기 때문에 (생각보다 기본적인 주제인데도 불구하고) 명확한 기준도 찾아보기 힘들었습니다..
@ModelAttribute
- 컨트롤러 메서드 인자에 아무런 바인딩 메서드를 선언하지 않았다면 스프링은 기본적으로 @ModelAttribute를 달아준 것과 동일하게 처리한다.
[받을 수 있는 조건]
- HTTP Parameter 와 HTTP Body 둘다 바인딩 할 수 있음
- HTTP Method - 모든 Method를 받을 수 있다.
- GET : 쿼리스트링을 바인딩
- POST / PUT / PATCH : 주로 Body를 바인딩
- HTTP Content-Type (Body로 데이터를 요청하는 경우 - POST/PUT/PATCH)
- application/x-www-form-urlencoded
- multipart/form-data (서브 content-type이 form인경우와 파일만 인것같음 확인 필요)
- text/plain(확인필요)
- HTTP Content-Type (Body로 데이터를 요청하는 경우 - POST/PUT/PATCH)
- DELETE : 주로 URL 경로로 식별자를 받으므로 사용할 경우가 드물다
// GET 요청
// 예시코드
// multipart 단독 파일 잘 받음
@Controller
public class MyController {
@PostMapping("/submit")
public String handleFileUpload(@ModelAttribute("file") MultipartFile file) {
// 'file' 파라미터로 전달된 파일이 MultipartFile로 바인딩됩니다.
return "result";
}
}
// 이런식의 요청은 multipart/form-data 내부에 w-xxx-form-urlencoded의 조합은 file만 제대로 받게 된다..
POST http://localhost:8080/submit
Host: example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="metadata"
Content-Type: application/x-www-form-urlencoded
name=JohnDoe&email=john.doe%40example.com&age=30
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain
(file content here)
------WebKitFormBoundary7MA4YWxkTrZu0gW--
// 컨트롤러 메서드
@PostMapping(value="submit", consumes = "multipart/form-data")
public String submitForm(
@ModelAttribute UserForm userForm, //값을 null로 받는다
@ModelAttribute("file") MultipartFile file) // file은 제대로 받는다
throws UnsupportedEncodingException {
return "success";
}
// 단독으로 보내는 x-www-form-urlencoded는 잘 받고 있음
POST http://localhost:8080/submit HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
name=JohnDoe&email=john.doe%40example.com&age=30
@PostMapping(consumes = "application/x-www-form-urlencoded")
public String submitForm(@ModelAttribute UserForm userForm) {
return "success";
}
-> 하지만 multipart + parameter 요청의 조합인 경우는 또 받아짐..
@RequestParam
@RequestBody
@RequestPart