[Spring] 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 강의 정리 - 8

JJAM·2022년 10월 5일
0
post-thumbnail

📖 스프링 MVC - 웹 페이지 만들기

📒 프로젝트 생성

스프링 부트 스타터에서 프로젝트를 생성한다.

📒 요구사항 분석

상품을 관리하는 서비스를 만들 것이다.

  • 상품 도메인 모델
    상품 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

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 에 대해 공부하였다.

profile
☘️

0개의 댓글