2024. 10. 9. 21:21ㆍSpring Framework/Web on Servlet Stack
Spring의 컨트롤러 메서드 리턴 값은 클라이언트에 대한 응답을 구성하는 데 매우 중요한 역할을 합니다. 아래에서는 지원되는 리턴 값 유형을 자세히 설명하고, 각 유형에 대한 샘플 코드를 제공하겠습니다.
1. @ResponseBody
메서드의 리턴 값이 HttpMessageConverter
를 통해 변환되어 응답 본문에 작성됩니다. 이는 RESTful 웹 서비스에서 JSON 또는 XML 형식으로 데이터를 리턴할 때 자주 사용됩니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ResponseBodyController {
@GetMapping("/responsebody")
@ResponseBody
public User getUser() {
return new User("Alice", 30);
}
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getters
public String getName() { return name; }
public int getAge() { return age; }
}
}
2. HttpEntity<B>, ResponseEntity<B>
HttpEntity
또는 ResponseEntity
를 사용하면 HTTP 헤더와 본문을 모두 포함하는 전체 응답을 리턴할 수 있습니다.
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EntityController {
@GetMapping("/responseentity")
public ResponseEntity<User> getUser() {
HttpHeaders headers = new HttpHeaders();
headers.add("Custom-Header", "value");
User user = new User("Bob", 25);
return ResponseEntity.ok()
.headers(headers)
.body(user);
}
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getters
public String getName() { return name; }
public int getAge() { return age; }
}
}
3. HttpHeaders
헤더만 리턴하고 본문은 포함하지 않는 경우입니다.
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HeadersController {
@GetMapping("/headers")
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.add("Custom-Header", "value");
return headers;
}
}
4. String
/ View
문자열을 리턴하면 뷰 이름으로 해석되어 ViewResolver
를 통해 렌더링됩니다.
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class StringViewController {
@GetMapping("/viewname")
public String getViewName(Model model) {
model.addAttribute("message", "Hello, Thymeleaf!");
return "greeting"; // greeting.html로 이동
}
}
5. ModelAndView
모델과 뷰 속성을 모두 포함하여 리턴할 수 있습니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@RestController
public class ModelAndViewController {
@GetMapping("/modelandview")
public ModelAndView getModelAndView() {
ModelAndView mav = new ModelAndView("greeting");
mav.addObject("message", "Hello, ModelAndView!");
return mav;
}
}
6. void
메서드가 void
를 리턴하면 응답이 완전히 처리된 것으로 간주되며, ServletResponse, OutputStream 인수 또는 @ResponseStatus 애너테이션을 사용할 수 있습니다.
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class VoidResponseController {
@PostMapping("/void")
public void handleVoid(HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
}
7. DeferredResult<V>
비동기적으로 결과를 리턴할 수 있습니다. 예를 들어, 백그라운드에서 작업이 완료된 후 결과를 클라이언트에 반환합니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.DeferredResult;
import java.util.concurrent.CompletableFuture;
@RestController
public class DeferredResultController {
@GetMapping("/deferred")
public DeferredResult<String> handleDeferred() {
DeferredResult<String> deferredResult = new DeferredResult<>();
// 비동기 작업 예시
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(2000); // 지연 시간
deferredResult.setResult("Deferred Result after 2 seconds");
} catch (InterruptedException e) {
deferredResult.setErrorResult("Error occurred");
}
});
return deferredResult;
}
}
8. Callable<V>
Spring MVC 관리 스레드에서 비동기적으로 리턴할 수 있습니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.Callable;
@RestController
public class CallableController {
@GetMapping("/callable")
public Callable<String> handleCallable() {
return () -> {
Thread.sleep(2000); // 지연 시간
return "Callable Result after 2 seconds";
};
}
}
9. StreamingResponseBody
비동기적으로 응답 OutputStream에 작성할 수 있습니다. 스트리밍 데이터 전송에 유용합니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.io.IOException;
import java.io.OutputStream;
@RestController
public class StreamingResponseBodyController {
@GetMapping("/stream")
public StreamingResponseBody stream() {
return outputStream -> {
try {
for (int i = 0; i < 10; i++) {
outputStream.write(("Line " + i + "\n").getBytes());
outputStream.flush();
Thread.sleep(500); // 지연 시간
}
} catch (IOException | InterruptedException e) {
// 예외 처리
}
};
}
}
10. 기타 리턴 값
리턴 값이 다른 방법으로 해결되지 않으면, 모델 속성으로 처리됩니다. 단, 간단한 유형인 경우에는 @ModelAttribute로 간주됩니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OtherReturnValueController {
@GetMapping("/other")
public User getUser() {
return new User("Charlie", 35);
}
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getters
public String getName() { return name; }
public int getAge() { return age; }
}
}
Spring에서 컨트롤러 메서드의 리턴 값은 클라이언트에 대한 응답을 정의하는 중요한 역할을 합니다. 다양한 리턴 값 유형을 통해 RESTful API부터 전통적인 MVC 구조까지 여러 가지 방식으로 응답을 처리할 수 있습니다. 각 리턴 값의 유형은 사용 사례에 따라 다르게 활용될 수 있습니다.
'Spring Framework > Web on Servlet Stack' 카테고리의 다른 글
Annotated Controllers (0) | 2024.10.09 |
---|---|
Type Conversion (0) | 2024.10.09 |
Method Arguments (0) | 2024.10.09 |
Handler Method (0) | 2024.10.09 |
Mapping Requests (0) | 2024.10.09 |