RESTful API 컨트롤러 (@RestController)의 @GetMapping은 HTTP Get Method에 해당하는 단축 표현으로 서버의 리소스를 조회할 때 사용하는데요.🤨
컨트롤러에서 데이터를 파라미터로 받을 때는 @RequestParam, @ModelAttribute, @PathVariable (경로 변수), 어노테이션 생략(DTO 객체) 등 다양한 방법이 있습니다.
헷갈리지 않도록 각각의 차이에 대해 정리하려 합니다. 🧐
(추가로 HttpServletRequest, @RequestBody, @RequestPart도 같이 정리)
1. @RequestParam 사용
개별 쿼리 파라미터를 1:1로 매핑하여 사용합니다. (body를 직접 조회하지 않습니다.)
@RequestParam은 단일 값(예: String, int, boolean 등) 또는 Map<String, String> 타입에 적합합니다. (Enum도 가능)
• 장점: 간단하고 직접적으로 요청 파라미터를 받아올 수 있습니다.
• 단점: 파라미터가 많을 경우 메서드 시그니처가 길어지고, 유지보수가 어려울 수 있습니다.
예시:
@GetMapping("/example")
public ResponseEntity<?> exampleHandler(@RequestParam String param1,
@RequestParam(required = false, defaultValue = "value2") String param2,
@RequestParam Map<String, String> map) {
// required는 파라미터의 필수 여부로 디폴트값은 true이다.
// defaultVaule는 required="false"면서 만약 해당 파라미터를 받지않았다면 파라미터의 기본값을 설정한다.
// 만약 requried="true"인데 파라미터가 없을 경우 400에러 발생
// param1, param2, map 등을 사용하여 로직 수행
}
GET /example?param1=value1¶m2=value2¶m3=value3
그리고 혹시라도.. 아래와 같이 사용하면 400 Error가 납니다.
@GetMapping("/example")
public ResponseEntity<?> exampleHandler(@RequestParam ExampleRequestDto requestDto) {
// 처리 로직
}
이유는 -> @RequestParam은 DTO를 받을 수 없습니다. @RequestParam은 개별 요청 파라미터를 메서드 파라미터에 바인딩하기 위해 사용됩니다. 따라서 DTO 객체를 사용하려면 @ModelAttribute를 사용해야 합니다.!! (Map은 가능) 어쩐지 자꾸 에러가 나더라..🥲
2. @ModelAttribute 사용
요청 파라미터를 바탕으로 객체를 자동으로 생성하고, 객체의 필드에 해당 파라미터 값을 할당합니다.
즉, 여러 파라미터들을 받아서 객체로 한번에 바인딩해서 받습니다. (setter함수(또는 생성자)가 필요합니다. 없으면 저장 안됨)
• 장점: HTML 폼 데이터와 유사한 방식으로 요청 파라미터를 처리할 수 있으며, 바인딩 규칙을 활용하여 유효성 검사 등을 수행할 수 있습니다. (@Valid 사용해서 검증 가능)
• 단점: RESTful API의 자원 식별을 위한 경로 변수나 쿼리 파라미터 처리에는 적합하지 않을 수 있습니다.
예시:
@GetMapping("/example")
public ResponseEntity<?> exampleHandler(@ModelAttribute ExampleRequestDto requestDto) {
// 처리 로직
}
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ExampleRequestDto {
private String hello;
private String hi;
}
GET /example?hello=value1&hi=value2
3. @PathVariable (경로 변수) 사용
URL 경로에서 변수를 추출하여 사용합니다.
• 장점: RESTful URI 설계에 맞추어 리소스 식별이 쉽고 명확합니다.
• 단점: URI 구조가 복잡해질 수 있으며, 경로 변수의 이름을 바꾸면 연관된 많은 코드를 수정해야 할 수 있습니다.
예시:
@GetMapping("/example/{hello}")
public ResponseEntity<?> exampleHandler(@PathVariable String hello) {
// hello를 사용하여 로직 수행
}
GET /example/value
4. 어노테이션 생략 (String, Dto객체)
어노테이션을 생략하고 간단하게 받을 수도 있습니다. 대신 변수명과 동일한 파라미터값만 받을 수 있습니다.
@ModelAttribute나 @RequestParam을 생략해도 String, int들은 RequestParam으로, 기타 객체들은 ModelAttribute로 자동으로 처리한다고 합니다. 이럴수가..지금까지 dto 받을 때 @ModelAttribute 선언하는거랑 선언안하는거랑 다른건줄..🥺
예를 들어
@ModelAttribute가 명시적으로 사용되지 않더라도, 객체 타입의 메서드 파라미터가 선언되면 Spring MVC는 해당 객체를 생성하고 요청 파라미터를 객체의 필드에 자동으로 매핑합니다. 예를 들어, 아래와 같은 코드는 동일하게 동작합니다:
@GetMapping("/example")
public ResponseEntity<?> exampleHandler(ExampleRequestDto requestDto) {
// requestDto를 사용하여 로직 수행
}
@GetMapping("/example")
public ResponseEntity<?> exampleHandler(@ModelAttribute ExampleRequestDto requestDto) {
// requestDto를 사용하여 로직 수행
}
- 단! @ModelAttribute 어노테이션을 사용하면 BindingResult를 사용하여 바인딩 에러를 처리하거나,
@ModelAttribute를 사용하여 더 세부적인 바인딩 설정을 할 수 있습니다.
@GetMapping("/example")
public ResponseEntity<?> exampleHandler(Long id) {
// id를 사용하여 로직 수행
}
@GetMapping("/example")
public ResponseEntity<?> exampleHandler(@RequestParam Long id) {
// id를 사용하여 로직 수행
}
- 위 두가지 로직은 같게 동작합니다. 단! @RequestParam 어노테이션을 사용하면 required나 defaultValue와 같은 추가적인 속성 설정을 할 수 있습니다.
따라서, 기본적인 사용에서는 생략해도 무방하지만, 추가적인 설정이 필요한 경우에는 @ModelAttribute나 @RequestParam를 사용하는 것이 좋습니다.
결론: 선택 기준
• 구조화된 데이터: 요청 파라미터가 여러 개이고 관련성이 있는 경우 DTO 객체를 사용하여 구조화된 데이터를 관리하는 것이 좋습니다.
• 단순한 요청 파라미터: 개별적이고 관계 없는 쿼리 파라미터를 받아야 할 경우 @RequestParam을 사용하는 것이 간편합니다.
• 리소스 식별: 리소스의 식별자를 경로에서 추출하여 사용해야 할 경우 @PathVariable (경로 변수)를 사용합니다.
따라서 RESTful API 개발에서는 요청의 특성과 목적에 맞게 애너테이션을 선택하여 사용하는 것이 중요합니다.
그 외
5. HttpServletRequest
HttpServletRequest는 서블릿 API로부터 제공되며, HTTP 요청에 대한 정보를 직접 접근할 수 있게 해줍니다. 주로 요청 헤더, 파라미터, 세션 등에 접근할 때 사용됩니다.
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/example")
public class ExampleController {
@GetMapping("/request")
public ResponseEntity<?> handleRequest(HttpServletRequest request) {
String param = request.getParameter("param");
String header = request.getHeader("headerName");
// 로직 수행
return ResponseEntity.ok("Parameter: " + param + ", Header: " + header);
}
}
6. @RequestBody
@RequestBody는 HTTP 요청의 본문(body)을 Java 객체로 변환하는 데 사용됩니다. 주로 JSON 형식의 요청 본문을 처리할 때 사용됩니다. MessageConverter를 통해 자바 객체로 변환되기때문에 Setter가 필요 없습니다.
POST 요청과 함께 사용됩니다. (GET 방식의 메소드에는 Body가 없기 때문에 에러 발생)
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/example")
public class ExampleController {
@PostMapping("/requestBody")
public ResponseEntity<?> handleRequestBody(@RequestBody ExampleRequestDto requestDto) {
// requestDto를 사용하여 로직 수행
return ResponseEntity.ok("Received: " + requestDto);
}
}
7. RequestPart
@RequestPart는 멀티파트 요청의 특정 부분을 처리하는 데 사용됩니다. 주로 파일 업로드와 같은 멀티파트 데이터의 일부를 Java 객체로 변환할 때 사용됩니다.
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/example")
public class ExampleController {
@PostMapping("/upload")
public ResponseEntity<?> handleFileUpload(@RequestPart("file") MultipartFile file) {
String fileName = file.getOriginalFilename();
// 파일 처리 로직 수행
return ResponseEntity.ok("Uploaded file: " + fileName);
}
}
'Framework > Spring' 카테고리의 다른 글
[Spring] Jasypt란? Spring Boot 설정 파일 암호화 적용 방법 (1) | 2024.07.05 |
---|---|
[Spring] Spring Security 기본 설정 방법 (Spring Boot 3, SecurityFilterChain) (0) | 2024.07.04 |
[Spring] Spring Boot 기본, 자주 사용하는 어노테이션 (애너테이션) (0) | 2024.07.02 |
[Spring Boot] application.yml이란? application.yml 설정 방법 (0) | 2024.06.29 |
[Spring Boot] application.properties와 application.yml 차이 (0) | 2024.06.29 |