| MVC
- MVC란? Model + View + Controller 의 약자를 말하며,
- 스프링은 내부적으로 Dispatcher가 있어, 어떤 요청이 있을 때마다 적절한 컨트롤러를 찾아 매핑한다고 했다.
- 이때 말하는 요청이란, 사용자가 보내는 HTTP 요청을 말하며 오늘날 웹 환경은 일반적으로 REST 방식을 따른다.
- REST는 URI의 자원에 고유한 이름-표현(ex. name, userId)-을 주어 자원의 상태 정보를 주고 받는 것으로,
GET/POST/PUT/DELETE와 더불어 ?파라미터명=값 과 같이 자신만의 규칙을 갖고 있다.
- 스프링에서는 HTTP 요청을 해석하기 위해 RestController를 사용하며, 해당 컨트롤러의 메소드와 매핑하기 위해,
RequestMapping 또는 축약형 Mapping (ex.@GetMapping)을 사용한다.
- HTTP의 패킷은 다른 프로토콜과 마찬가지로 Header와 Body를 가지고 있는데, 일반적으로 DB에 데이터를 추가하거나 수정할 때에는 이때 말하는 RequestHeader와 RequestBody를 통해 데이터를 읽고 소통한다.
@GetMapping | @PostMapping | @PutMapping | @PatchMapping | @DeleteMapping |
데이터를 가져옴 | 데이터를 전송 | 전체 수정 | 일부 수정 | 삭제 |
@PathVariable (id) @RequestParam |
@RequestHeader @RequestBody |
@PathVariable (id) @RequestParam |
- Spring MVC의 흐름
[1] Dispatcher Servlet이 요청 URL을 받아 HandlerMapping에 전달 * Dispatch : 파견 보내다. rf. 도서관의 사서(dispatcher)는 도서를 요청(request)받았고, 도서 코드 목록(HalderMapping)서 도서를 어떻게 찾을지 본다. [2] HandlerMapping는 요청 URL에 맞는 Controller와 Method 정보를 반환 rf. 도서의 코드 목록에 따르면 해당 도서는 '역사' 카테고리 구역에 있단다. [3] Dispatcher Servlet이 Handler Adapter에게 요청 처리를 위임 rf. 사서는 인턴에게 '역사' 카테고리 책장으로 이동해서, 가나다순으로 진열된 책들을 보면 된다고 알려준다. [4] HandlerAdapter가 Controller와 Method를 실행 rf. 인턴이 찾으려는 도서의 코드와, 사서의 안내를 가지고 '역사' 구역에 가서 도서를 찾는다. [5] Cotroller는 비즈니스 로직을 처리하고, 그 결과를 바탕으로 뷰(ex.JSP)에 전달할 객체를 Model 객체에 저장 rf. 인턴은 찾은 도서를 가져와 책수레에 담는다. [6] Dispatcher Servlet은 view name을 View Resolver에 전달하여 View 객체를 얻음 rf. 사서는 인턴으로부터 "00책 가져왔어?"라고 물어보고, 인턴은 "00책 여기있어요."하고 책수레에 있던 도서를 전달한다. [7] Dispatcher Servlet은 View 객체에 화면 표시를 의뢰 rf. 사서는 책을 요청한 사람에게 책을 전달하기 위해 "00책 요청하신분~?"하고 물어본다. [8] View 객체는 해당하는 뷰(ex.JSP.Thymeleaf)를 호출하며, 뷰는 Model 객체에서 화면 표시에 필요한 객체를 가져와 화면 표시를 처리 rf. 사서는 책을 요청한 사람에게 책을 대여해주고, 반납일에 대해 안내한다. |
| HTTP 요청 - RestController
- HTTP 요청 및 응답은 Rest 방식에 따른다.
구분 | 의미 | SQL | REST API |
CREATE | 삽입 | INSERT | PUT/POST |
READ | 조회 | SELECT | GET |
UPDATE | 갱신 | UPDATE | PUT/PATCH |
DELETE | 삭제 | DELETE | DELETE |
- 데이터 타입은 일반적으로 JSON 타입을 많이 사용한다. (XML보다 경량)
- Controller와 RestController의 차이
Controller | 기본적으로 HTML으로 응답값 전달 |
RestController | Rest API 요청에 따른 응답값(ex.JSON) 전달 |
- 웹을 통해서 받는 URI의 경우 아래와 같이 [URL + 전달하려는 데이터]로 구성되어 있다.
URI 예시
https://why-dev.tistory.com/252?category=964854
- RestController를 만들어주기 위해서는 아래와 같이 @RestController를 작성해주어야 한다.
@RestController
public class SampleController{
}
+ 여기에 만약에 롬복을 추가할 경우,
@Slf4j
@RestController
public class SampleController{
}
| HTTP 요청 매핑
[1] Mapping Annotation
- 요청방식을 직접 지정 (GET,POST...)
// GET, POST 등의 요청방식을 직접 지정
@RequestMapping(value = "/page/252", method = RequestMethod.GET)
public String getPage(){
log.info("Get some page information");
return "page:252"; // JSON 방식
}
+ RequestMethod는 enum이다.
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
[2] 축약형 Mapping Annotation
- 최근에는 Mapping Annotation보다 축약형을 많이 사용한다.
@GetMapping | @PostMapping | @PutMapping | @PatchMapping | @DeleteMapping |
데이터를 가져옴 | 데이터를 전송 | 전체 수정 | 일부 수정 | 삭제 |
- 아래와 같이 각 타입에 맞게 Annotation을 넣어주면 된다.
@GetMapping("/page/252")
public String getPage(){
log.info("Get some page");
return "pageId : 252";
}
@PostMapping("/page")
public String createPage(){
return "page created -> pageId : 252";
}
- 만약에 HTTP 전송에 대한 테스트를 하고 싶다면, 아래의 툴들을 이용할 수 있다.
인텔리J | HTTP Client |
POSTMAN | https://www.postman.com/ |
| HTTP 요청 파라미터 전송
[1] Get과 Delete - @PathVariable, @RequestParam
(1) PathVariable : id를 path에 넣어 받는다
- 여기서의 id는 주문 번호(order id)와 같이 고유한 id 값을 의미한다.
- @PathVariable
@GetMapping("/{pageId}")
public String getCategory(@PathVariable("pageId") String pageId) {
log.info("Get some page");
return "pageId : " + pageId;
}
(2) query-params : 추가적인 정보들을 입력한다.
- @RequestParam
- 주로 게시판의 검색 필터 페이징에서 많이 사용한다.
- 만약에 추가적으로 필수사항이나 디폴트 옵션을 주고 싶다면 아래 키워드를 넣어줄 수도 있다.
@required | 필수 입력 정보 * 기본적으로 true로 되어 있다. |
@defaultValue | 디폴트 값 지정 |
@GetMapping("/{pageId}")
public String getPage(@PathVariable("pageId") String pageId,
@RequestParam("category") String category) {
log.info("Get some page");
return "pageId : " + pageId + ", category : " + category;
}
>> 요청
// 요청
GET http://localhost:8080/252?category=964854
Content-Type: application/json
>> 응답
// 응답
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 31
Date: Sat, 10 Sep 2022 17:58:31 GMT
Keep-Alive: timeout=60
Connection: keep-alive
pageId : 252, category : 964854
- Delete도 Get과 마찬가지로 PageVariable을 쓸 수 있다.
@DeleteMapping("{pageId}")
public String deletePage(@PathVariable String pageId){
log.info("Delete some page");
return "deleteId : " + pageId;
}
@require 사용 예시
@GetMapping("/{pageId}")
public String getPage(@PathVariable(value = "pageId") String pageId,
@RequestParam(value = "category", required = false) String category) {
log.info("Get some page");
return "pageId : " + pageId + ", category : " + category;
}
>> 요청
GET http://localhost:8080/252
Content-Type: application/json
>> 응답
pageId : 252, category : null
[2] Post, Put, Patch - @RequestBody, @RequestHeader
- CS 네트워크 시간에서 배운 HTTP 패킷의 구조를 생각나게 하는 Annotation이다.
@RequestHeader | REST의 모든 메소드에서 사용 가능 - 메타정보, 인증키(토큰), 계정 정보 등을 담는다. |
@RequestBody | 실제 데이터. 일반적으로 JSON 방식으로 데이터를 받는다. - JSON 방식을 사용하면 큰 데이터의 전송이 편하다. |
@PostMapping("/order")
public String createPageOrder(
@RequestBody CreateOrderRequest createOrderRequest,
@RequestHeader String userAccountId) {
log.info("Create order : " + createOrderRequest +
", userAccountId : " + userAccountId);
return "orderId : " + createOrderRequest.getOrderId()
+ ", orderAmount : " + createOrderRequest.getOrderAmount();
}
@Data
public static class CreateOrderRequest{
private String orderId;
private Integer orderAmount;
}
>> 요청
POST http://localhost:8080/order
Content-Type: application/json
userAccountId: account800
{"orderId" : "123", "orderAmount" : 10000}
>> 응답
http://localhost:8080/order
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 34
Date: Sat, 10 Sep 2022 18:32:23 GMT
Keep-Alive: timeout=60
Connection: keep-alive
orderId : 123, orderAmount : 10000
| 정리
- HTTP 요청, 응답 시 REST방식에 따르며, 데이터 타입은 JSON을 일반적으로 많이 사용한다. - HTTP Controller 클래스를 선언할 때엔 @RestController를 붙인다. - HTTP Mapping을 할 때에는 @GetMapping, @PostMapping, @DeleteMapping.. 등의 축약형 매핑 Annotation을 쓴다. * 이때, Put은 전체를 수정할 때, Patch는 일부를 수정할 때에 사용한다. - HTTP 요청 파라미터를 전송할 때, (1) Get과 Delete의 경우 - @PathVariable로 고유한 id를 받고, @RequestParam으로 parameter를 받는다. (2) Post, Put, Patch의 경우 - @RequestHeader와 @RequestBody를 통해 parameter를 받을 수 있다. * RequestBody를 쓸 경우, 큰 데이터를 쉽게 받을 수 있다. |
[ 출처 및 참조 ]
부트 캠프 강의를 들은 후 정리
'Framework > Spring' 카테고리의 다른 글
[스프링] 프로젝트 전 꼭 알아두면 좋은 것들 (0) | 2022.09.13 |
---|---|
[스프링] 스프링 MVC - 예외처리 (1) | 2022.09.11 |
[스프링] 스프링 MVC - 필터, 인터셉터 (1) | 2022.09.11 |
[스프링] 스프링의 주요기술 (0) | 2022.09.05 |
[스프링] OOP의 SOLID 원칙과 스프링 (0) | 2022.08.29 |