: 버전0으로 가장 간단한 예제 만들기
상품 주문 프로세스로 가정하고 일반적인 웹 애플리케이션에서 Controller → Service → Repository
흐름을 최대한 단순하게 만들었다.
✔️ OrderRepositoryV0.java
@Repository // 안에 @Component가 있어 자동으로 컴포넌트 스캔 대상이 됨(스프링 빈 등록)
@RequiredArgsConstructor
public class OrderRepositoryV0 {
public void save(String itemId) {
// 저장 로직
if(itemId.equals("ex")) { // (다양한 예제를 위해)"ex"라는 것이 넘어오면 예외 발생시킬
throw new IllegalStateException("예외 발생!");
}
sleep(1000); // 상품을 저장하는데 1초 정도 걸린다고 가정
}
private void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Repository
: 컴포넌트 스캔의 대상이 됨. 따라서 스프링 빈으로 자동 등록됨.
sleep(1000)
: 리포지토리는 상품을 저장하는데 약 1초가량 소요되는 것으로 가정하기 위해 1초 지연을 부여함.
그리고 예외 발생 상황을 확인하기 위해 itemId의 값이 "ex"로 넘어온다면 IllegalStateException
예외가 발생하도록 했다.
✔️ OrderServiceV0.java
@Service // @Service 안에 @Component가 있어 자동으로 컴포넌트 스캔의 대상이 됨(자동으로 스프링 빈 등록)
@RequiredArgsConstructor // 생성자 자동 생성
public class OrderServiceV0 {
private final OrderRepositoryV0 orderRepository;
public void orderItem(String itemId) {
orderRepository.save(itemId);
}
}
@Service
: 컴포넌트 스캔의 대상이 됨. 따라서 마찬가지로 스프링 빈으로 자동 등록됨.
실무에서는 복잡한 비즈니스 로직이 서비스 계층에 포함되지만, 예제이기 때문에 단순함을 살리기 위해 리포지토리에 저장을 호출하는 코드만 넣었다.
✔️ OrderControllerV0.java
@RestController // @Controller + @ResponseBody
@RequiredArgsConstructor
public class OrderControllerV0 {
private final OrderServiceV0 orderService;
@GetMapping("/v0/request")
public String request(String itemId) {
orderService.orderItem(itemId);
return "ok";
}
}
@RestController
: 컴포넌트 스캔과 스프링 (📌아래 참고) RestController로 인식됨.
이들은 Spring에서 컨트롤러를 지정해주기 위한 annotation들이다.
전통적인 Spring MVC의 컨트롤러인 @Controller
,
그리고 Restful 웹 서비스의 컨트롤러인 @RestController
이 둘의 주요 차이점은 HTTP Response Body가 생성되는 방식이다.
전통적인 Spring MVC의 컨트롤러인 @Controller
는 주로 View를 반환하기 위해 사용한다.
출처: 망나니 개발자
이런 과정을 통해 Spring MVC Container는 Client의 요청으로부터 View를 반환한다.
- 클라이언트는 URI 형식으로 웹 서비스에 요청을 보냄.
- Mapping 되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트.
- Controller가 요청을 처리한 후, 응답을 DispatcherServlet으로 반환하고 DispatcherServlet은 View를 사용자에게 반환.
‼️ @Controller
가 View를 반환하기 위해서는 ViewResolver가 사용되며, ViewResolver 설정에 맞게 View를 찾아 렌더링한다.
하지만 Spring MVC의 컨트롤러에서도 데이터를 반환해야 하는 경우도 있다.
Spring MVC의 Controller에서는 데이터를 반환하기 위해 @ResponseBody
어노테이션을 사용해야 한다.
이를 통해 Controller도 Json 형태로 데이터를 반환할 수 있다.
출처: 망나니 개발자
- 클라이언트는 URI 형식으로 웹 서비스에 요청을 보냄.
- Mapping 되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트.
@ResponseBody
를 사용해 Client에게 Json 형태로 데이터 반환 ➡️ [Controller - View]와 차이
@RestController
가 데이터를 반환하기 위해서는 viewResolver 대신 HttpMessageConverter가 동작한다.
HttpMessageConverter에는 여러 Converter가 등록되어 있고, 반환해야 하는 데이터에 따라 사용하는 Converter가 달라진다.
단순 문자열
의 경우 StringHttpMessageConverter 사용, 객체
의 경우 MappingJackson2HttpMessageConverter 사용
➡️ 데이터 종류에 따라 서로 다른 MessageConverter 작동
Spring은 클라이언트의 HTTP Accept 헤더와 서버의 컨트롤러 반환 타입 정보 둘을 조합해 적합한 HttpMessageConverter를 선택해 이를 처리한다.
@RestController
는 Spring MVC Controller에 @ResponseBody
가 추가된 것이다.
당연히 RestController의 주 용도는 Json 형태로 객체 데이터를 반환하는 것이다.
(참고한 포스트의 작성자분께선 VueJs+SpringBoot 프로젝트 시 SpringBoot를 API 서버로 활용할 때, 그리고 Android 앱 개발을 하며 데이터를 반환할 때 사용하였다고 하심)
출처: 망나니 개발자
- 클라이언트는 URI 형식으로 웹 서비스에 요청을 보냄.
- Mapping 되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트.
- RestController는 해당 요청을 처리하고 데이터를 반환
1, 2 과정은 동일