반응형

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 대시보드 - 인프런 | 강의 (inflearn.com)

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

HTTP 요청 메시지 - JSON

json 형식을 HelloData 객체로 바로 받을 수 있음

객체를 return하면 json 형식으로 출력

1
2
3
4
5
6
@ResponseBody
@PostMapping("/request-body-json-v5")
    public HelloData requestBodyJsonV5(@RequestBody HelloData helloData throws IOException {
    log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
    return helloData;
}
cs
 

응답 - 정적 리소스, 뷰 템플릿

@ResponseBody 붙이면 화면에 "response/hello" 출력됨

1
2
3
4
5
@RequestMapping("/response-view-v2")
public String responseViewV2(Model model) {
    model.addAttribute("data""hello");
    return "response/hello";
}
cs

view 이름과 url 같으면 return 생략 가능

하지만, 명시성이 떨어지고 일치하는 경우가 별로 없음

1
2
3
4
@RequestMapping("/response/hello")
public void responseViewV3(Model model) {
    model.addAttribute("data""hello");
}
cs

 

HTTP 응답 - HTTP API, 메시지 바디에 직접 입력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@GetMapping("/response-body-json-v1")
public ResponseEntity<HelloData> responseBodyJsonV1() {
    HelloData helloData = new HelloData();
    helloData.setUsername("userA");
    helloData.setAge(11);
 
    return new ResponseEntity<>(helloData, HttpStatus.OK);
}
 
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2() {
    HelloData helloData = new HelloData();
    helloData.setUsername("userA");
    helloData.setAge(11);
 
    return helloData;
}
cs

 

@ResponseBody를 사용하면 HelloData를 바로 return 할 수 있음.

하지만, @ResponseStatus()를 어노테이션으로 지정해야하므로, HttpStatus 동적으로 변경 불가.

응답 코드를 동적으로 변경해야 한다면, V1처럼 ResponseEntity<>()를 return함

 

HTTP 메시지 컨버터

스프링 MVC는 다음의 경우에 HTTP 메시지 컨버터를 적용한다.

HTTP 요청: @RequestBody , HttpEntity(RequestEntity) ,

HTTP 응답: @ResponseBody , HttpEntity(ResponseEntity) ,

 

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 대시보드 - 인프런 | 강의 (inflearn.com)

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com

타임리프 (Thymeleaf)

속성 변경 - th:href

th:href="@{/css/bootstrap.min.css}"

href="value1" 을 th:href="value2" 의 값으로 변경한다.

 

URL 링크 표현식 - @{...},

th:href="@{/css/bootstrap.min.css}"

 

속성 변경 - th:onclick

onclick="location.href='addForm.html'"

th:onclick="|location.href='@{/basic/items/add}'|"

 

리터럴 대체 - |...|

<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
-> <span th:text="|Welcome to our application, ${user.name}!|">

location.href='/basic/items/add'
-> th:onclick="'location.href=' + '\'' + @{/basic/items/add} + '\''"
-> th:onclick="|location.href='@{/basic/items/add}'|"

 

반복 출력 - th:each

<tr th:each="item : ${items}">

 

변수 표현식 - ${...}

<td th:text="${item.price}">10000</td>

 

내용 변경 - th:text

<td th:text="${item.price}">10000</td>

 

URL 링크 표현식2 - @{...},

th:href="@{/basic/items/{itemId}(itemId=${item.id})}"

 

쿼리 파라미터 생성 가능

예) th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}"

생성 링크: http://localhost:8080/basic/items/1?query=test

 

URL 링크 간단히

th:href="@{|/basic/items/${item.id}|}"

1
2
3
4
5
6
<tr th:each="item : ${items}">
    <td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
    <td><a href="item.html" th:href="@{|/basic/items/${item.id}|}" th:text="${item.itemName}">상품명</a></td>
    <td th:text="${item.price}">가격</td>
    <td th:text="${item.quantity}">수량</td>
</tr>
cs

 

상품 등록 폼

th:action에 값이 없으면 현재 url 전송

1
2
<form action="item.html" th:action="/basic/items/add" method="post">
<form action="item.html" th:action method="post">
cs

상품 등록 처리 - @ModelAttribute

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@PostMapping("/add")
public String addItemV1(@RequestParam String itemName,
                        @RequestParam int price,
                        @RequestParam Integer quantity,
                        Model model) {
    Item item = new Item();
    item.setItemName(itemName);
    item.setPrice(price);
    item.setQuantity(quantity);
 
    itemRepository.save(item);
    model.addAttribute("item", item);
    return "basic/item";
}
cs

 

 

@ModelAttribute() 사용하면 model.addAttribute()까지 같이 해줌

1
2
3
4
5
@PostMapping("/add")
public String addItemV2(@ModelAttribute("item") Item item) {
    itemRepository.save(item);
    return "basic/item";
}
cs

 

괄호를 지우면 클래스명 첫 글자를 소문자로 바꿔서 model.addAttribute()

1
2
3
4
5
@PostMapping("/add")
public String addItemV3(@ModelAttribute Item item) {
    itemRepository.save(item);
    return "basic/item";
}
cs

 

@ModelAttribute 생략 가능

1
2
3
4
5
@PostMapping("/add")
public String addItemV4(Item item) {
    itemRepository.save(item);
    return "basic/item";
}
cs

PRG Post/Redirect/Get

상품 등록을 완료하고 웹 브라우저의 새로고침 버튼을 클릭해보자.

상품이 계속해서 중복 등록되는 것을 확인할 수 있다.

 

새로고침 시 마지막에 서버에 전송한 데이터를 다시 전송

마지막 행위: POST /add

 

POST 처리 후 Redirect하면 마지막 요청이 GET으로 변경됨

새로고침하면 GET 호출됨

 

※ 주의

"redirect:/basic/items/" + item.getId() redirect에서 +item.getId() 처럼 URL에 변수를

더해서 사용하는 것은 URL 인코딩이 안되기 때문에 위험하다.

 

RedirectAttributes

상품 등록 후에 "저장되었습니다" 띄우기

-> Redirect 한 곳에서 처리

 

redirectAttributes.addAttribute()에 넣은 값으로 치환 가능
URL 인코딩 문제 해결 가능
치환 안하면 쿼리 파라미터로 넘어감

1
2
3
4
5
6
7
@PostMapping("/add")
public String addItemV6(Item item, RedirectAttributes redirectAttributes) {
    Item savedItem = itemRepository.save(item);
    redirectAttributes.addAttribute("itemId", savedItem.getId());
    redirectAttributes.addAttribute("status"true);
    return "redirect:/basic/items/{itemId}";
}
cs
반응형

+ Recent posts