- 해당 게시물은 인프런 - "스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술" 강의를 참고하여 작성한 글 입니다.
- 유료강의이므로 자세한 내용은 없고, 간단한 설명 위주로 정리했습니다.
강의 링크 -> 김영한 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술(유료강의)
스프링 부트 스타터에서 프로젝트를 생성한다.
상품을 관리하는 서비스를 만들 것이다.
- 상품 도메인 모델
상품 ID, 상품명, 가격, 수량- 상품 관리 기능
상품 목록, 상품 상세, 상품 등록, 상품 수정
main/java/hello/itemservice/domain/item/Item
편하게 @Getter, @Setter lombok을 한 번에 사용하기 위해,
@Data
애노테이션을 사용한다.
상품 ID, 상품명, 가격, 수량 변수들을 각각 만들어 준다.
여기서 int가 아닌 Integer를 사용하는 이유는 null 값도 들어갈 수 있게 하기 위해서다.
private Long id;
private String itemName;
private Integer price;
private Integer quantity;
생성자를 만들어 준다.
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
main/java/hello/itemservice/domain/item/ItemRepository
저장소이기 때문에 @Repository
애노테이션을 붙여준다.
저장할 공간인 HashMap을 만들고,
상품 ID 값을 매번 +1 씩 증가하기 위해 sequence를 만든다.
private static final Map<Long, Item> store = new HashMap<>();
private static long sequence = 0L;
필요한 기능들인 save, findById, findAll, update, clearStore 를 만들어 준다.
// 저장
public Item save(Item item) {
// sequence 값에 +1을 하고, id값에 넣는다.
item.setId(sequence++);
// id값과 item 객체를 store에 넣는다.
store.put(item.getId(),item);
// item 반환
return item;
}
// id로 item 조회
public Item findById(Long id) {
// store에서 id 값으로 item을 가져와 반환
return store.get(id);
}
// item 전체 조회
public List<Item> findAll() {
// store에서 모든 value값을 가져와 새로운 배열에 넣고, 반환
return new ArrayList<>(store.values());
}
// 아이템 수정
public void update(Long itemId, Item updateParam) {
// id를 통해, item 조회
Item findItem = findById(itemId);
// param 정보를 통해, item 값 하나 씩 수정
findItem.setItemName(updateParam.getItemName());
findItem.setPrice(updateParam.getPrice());
findItem.setQuantity(updateParam.getQuantity());
}
// store 내용 비우기
public void clearStore() {
store.clear();
}
test/java/hello/itemservice/domain/item/itemRepositoryTest
위에서 만든 repository가 정상적으로 동작하는지 확인하기 위해 Test 코드를 작성한다.
public class itemRepositoryTest {
ItemRepository itemRepository = new ItemRepository();
@AfterEach // 각각 test 실행 끝날 때 실행
void afterEach() {
// 저장소를 clearStore
}
@Test
void save() {
// item 객체 생성
// item 객체를 저장소에 저장해 savedItem 반환
// item id로 저장소 조회하여 findItem 반환
// id로 찾은 findItem과 저장한 saveItem 객체가 같은지 비교
}
@Test
void findAll() {
// item1, item2 객체 생성
// item1, item2 객체 저장소에 저장
// 저장소에 저장된 것을 모두 찾아, result 라는 List에 담음
// List의 사이즈가 2인지 비교
// List에 item1, item2 객체가 들었는지 비교
}
@Test
void updateItem() {
// item 객체 생성
// item 객체를 저장소에 저장
// 저장한 itemd의 id인 itemId를 반환
// update할 새로운 updateParam 객체 생성
// itemId를 updateParam 내용으로 업데이트
// itemId로 객체 findItem을 찾아 반환
// findItemp의 값과 updateParam의 값이 같은지 비교
}
}
Test를 실행하면 정상적으로 동작하는 것을 볼 수 있다.
HTML을 만들기 전에 부트스트랩을 다운 받는다.
다운 받은 압축 폴더에서 bootstrap.min.css
파일을 찾아,
인텔리제이에 있는 main/resources/static/css
폴더에 해당 파일을 붙여 넣는다.
부트스트랩을 사용하여 상품 목록(items.html), 상품 상세 (item.html), 상품 등록 폼(addForm.html), 상품 수정 폼(editForm.html) 을 만들어 준다.
<link href="../css/bootstrap.min.css" rel="stylesheet">
main/java/hello/itemservice/web/item/basic/BasicItemController
컨트롤러이므로 @Controller
애노테이션을 추가하고,
"/basic/items" 경로로 들어왔을 때, 실행하기 위해 @RequestMapping
애노테이션을 추가하고,
@RequiredArgsConstructor
애노테이션을 추가하여, final이 붙은 변수에 자동적으로 생성자를 주입한다.
@Controller
@RequestMapping("/basic/items")
@RequiredArgsConstructor
상품 목록 페이지의 컨트롤러를 생성한다.
저장소에 있는 모든 item List를 가져와 model에 담아주고 뷰 템플릿을 호출해준다.
@GetMapping
public String items(Model model) {
List<Item> items = itemRepository.findAll();
model.addAttribute("items",items); // model에 item 담아줌
return "basic/items"; // "basic/items" 라는 뷰 템플릿 호출
}
테스트용으로 데이터를 추가하여 회원 목록 기능이 정상 동작하는지 확인할 수 있게 해준다.
@PostConstruct // 의존관계가 모두 주입되고 나서 초기화 용도로 호출
public void init() {
itemRepository.save(new Item("itemA",10000,30));
itemRepository.save(new Item("itemB",20000,10));
itemRepository.save(new Item("itemC",15000,28));
}
/resources/static/items.html
에서 만든 정적 html을
/resources/templates/basic/items.html
에서 뷰 템플릿(templates)으로 수정해준다.
<html xmlns:th="http://www.thymeleaf.org">
...
<link href="../css/bootstrap.min.css"
th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
...
<button class="btn btn-primary float-end"
onclick="location.href='addForm.html'"
th:onclick="|location.href='@{/basic/items/add}'|"
type="button">상품 등록
</button>
...
<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}">10000</td>
<td th:text="${item.quantity}">10</td>
</tr>
...
http://localhost:8080/basic/items 에 들어가서 확인을 해보면 작성한 뷰가 호출되고, 그 안에 Test용 데이터들이 있는 것을 확인할 수 있다.
위에서 만든 상품 목록과 똑같이 컨트롤러와 뷰를 생성해 준다.
main/java/hello/itemservice/web/item/basic/BasicItemController
{itemId}
의 mapping이 들어오고,
URL 경로로 들어온 값인 itemId로 저장소에 있는 item을 조회한다.
@GetMapping("/{itemId}")
public String item(@PathVariable Long itemId, Model model) {
Item item = itemRepository.findById(itemId);
// 모델에 item 을 담고, "basic/item" 라는 뷰 템플릿 호출
}
/resources/static/item.html
에서 만든 정적 html을
/resources/templates/basic/item.html
에서 뷰 템플릿(templates)으로 수정해준다.
...
<button class="w-100 btn btn-primary btn-lg"
onclick="location.href='editForm.html'"
th:onclick="|location.href='@{/basic/items/{itemId}/edit(itemId=${item.id})}'|" type="button">상품 수정
</button>
...
<button class="w-100 btn btn-secondary btn-lg"
onclick="location.href='items.html'"
th:onclick="|location.href='@{/basic/items}'|" type="button">목록으로
</button>
...
상품 목록 페이지에서 상품을 선택하면 정상적으로 상품 상세 페이지가 작동하는 것을 볼 수 있다.
다음 내용은 다음 게시물에 . . .
지금까지 김영한 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술(유료강의) 강의를 참고하여 스프링 MVC - 웹 페이지 만들기 1 에 대해 공부하였다.