티스토리 뷰

싱숭생숭

 

 

 

이번에는 인프런에서 수강한 스프링 강의를 토대로 간단한(?) 웹 페이지 만들기를 복습하면서 프로젝트에 기능들을 추가해 볼 예정이다.

 

그동안 공부했던 '초보 웹 개발자를 위한 스프링 5 프로그램 입문' 책의 스프링과  스프링 강의(인프런) 내용은 전체적인 결은 비슷하지만 인프런 강의가 최근이고 그에 맞게 트렌드도 최신이기 때문에 책보단 강의를 먼저 보는 게 더 좋을 것 같다. 

 

 

1. 스프링 부트 프로젝트를 생성

스프링 부트 스타트 사이트를 사용하여 프로젝트를 만들어본다. 

(최근 실무에서는 Maven보다 Gradle을 사용한다고한다.)

 

※ 스프링이 버전 업 되면서 validation을 따로 dependencies에 추가해야 한다.  

 

 

2. 프로젝트 열고 서버 정상 작동 확인하기

프로젝트를 열어 서버가 정상 작동하는지 메인 메서드를 실행하자 클릭

localhost:8080에 접속해 보면 아래와 같이 에러 페이지지만 정상적으로 접속이 되는 것을 확인할 수 있다.

 

(서버가 제대로 작동한다는 것)                                                      localhost:8080 접속 시 화면

 

 

3. 일반적인 웹 애플리케이션 계층 구조를 생각하면서 상품(item) 구현하기

스프링을 공부하면서 이 계층 구조를 어떻게 정하고 만들어야 할지 선뜻 만들지 못했다. 이 부분은 개발자마다 선호하는 구조가 있다고 하며, 강의에서는 크게 기능 별로 구조를 나눠 작성했다.

  • 컨트롤러 : 웹 MVC의 컨트롤러 역할
  • 서비스 : 핵심 비즈니스 로직 구현
  • 리포지토리 : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
  • 도메인 : 비즈니스 도메인 객체, 예) 회원, 주문, 쿠폰 등등 주로 데이터베이스에 저장하고 관리됨

 

 

 

4. 상품 클래스와 상품을 저장하는 클래스를 만든다

상품(Item)은 아이디, 상품이름, 가격, 수량 4가며, 상품 저장 DB는 메모리에 저장할 수 있게 HashMap을 사용했다.

lombok 라이브러리 사용하여 getter/setter 메서드 작성 코드 줄였음.

domain/item.java

더보기
package magazink.re.domain.item;

import lombok.Data;

@Data
public class Item {

    private Long id;
    private String itemName;
    private int price;
    private int quantity;

    public Item(){
    }

    public Item(String itemName, int price, int quantity){
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }
}

 domain/itemRepository.java

더보기
package magazink.re.domain.item;

import org.springframework.stereotype.Repository;

import java.util.*;

@Repository
public class ItemRepository {

    private static final Map<Long, Item> store = new HashMap<>(); //static 사용
    private static long sequence = 0L; //static 사용
 
    // 저장 
    public Item save(Item item) {
        item.setId(++sequence);
        store.put(item.getId(), item);
        return item;
    }
    // id 찾는 메서드
    public Item findById(Long id) {
        return store.get(id);
    }
    // 모든 상품 찾는 메서드
    public List<Item> findAll() {
        return new ArrayList<>(store.values());
    }
    // 상품 업데이트 메서드
    public void update(Long itemId, Item updateParam) {
        Item findItem = findById(itemId);
        findItem.setItemName(updateParam.getItemName());
        findItem.setPrice(updateParam.getPrice());
        findItem.setQuantity(updateParam.getQuantity());
    }
    // test 작성 시 삭제하기위한 메서드
    public void clearStore() {
        store.clear();
    }
}

 

 

5. 상품 목록을 볼 수 있는 컨트롤러뷰 템플릿을 작성한다.

이 컨트롤러(ItemController)는 ItemRepository에 들어있는 상품을 조회한 후 모델에 담고 뷰 템플릿을 호출한다.

(상품 전체 리스트 보기, 상품 추가하기, 상품 수정하기 코드가 여기에 작성될 예정)

 

클래스앞에 @Controller를 선언해주었다.

그리고 fianl 이 붙은 멤버 변수만 사용해서 생성자를 자동으로 만들어 주는 @RequiredArgsConstructor를 사용하였다.  

※  fianl를 생략하면 안된다.

@RequestMapping 애너테이션을 사용하여 url 경로를 지정해준다.

 

web/item/ItemController.java

더보기
package magazink.re.web.item;

import lombok.RequiredArgsConstructor;

import magazink.re.domain.item.Item;
import magazink.re.domain.item.ItemRepository;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@Controller
@RequiredArgsConstructor
@RequestMapping("/items")
public class ItemController {

    private final ItemRepository itemRepository;
    
    // 상품 메인 리스트 화면
    @GetMapping
    public String items(Model model) {
        List<Item> items = itemRepository.findAll();
        model.addAttribute("items", items);
        return "items/items";
    }
}

 

뷰 템플릿은 강의 내용 대로 jsp를 사용하지 않고 타임리프를 사용하였다. 

(스프링에서도 사용을 권장하는 라이브러리이면서 최근 트랜드는 타임리프를 사용한다고 한다는데, 아직 까지 jsp를 사용하는 곳이 많다.) 

타임리프는 기존 jsp파일처럼 html 속성과 사용법이 비슷한데, 대부분의 html 속성을 th:xxx로 변경할 수 있다고한다.

 

타임리프 사용 선언

<html xmlns:th="http://www.thymeleaf.org">

 

resources/templates/items/items.html

더보기
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="utf-8">
</head>

<body>
	<div class="container" style="max-width: 600px">
		<div class="py-5 text-center">
			<h2>상품 목록</h2>
		</div>
 		<div class="row">
 		<div class="col">
		<button class="btn btn-primary float-end"
			onclick="location.href='addForm.html'"
			th:onclick="|location.href='@{/basic/items/add}'|"
          		type="button">상품 등록</button>
 		</div>
 		</div>
 		<hr class="my-4">
 			<div>
 		<table class="table">
 	 <thead>
                     <tr>
                     <th>ID</th>
                     <th>상품명</th>
                     <th>가격</th>
                     <th>수량</th>
                     </tr>
         </thead>
             <tbody>
 			<tr th:each="item : ${items}">
 		 	<td><a href="item.html" th:href="@{/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>
                </tbody>
         	</table>
 		</div>
	</div> <!-- /container -->
</body>
</html>

 

이제 http://localhost:8080/items 경로 접속 하면 아래와 같이 위에서 작성한 코드대로 items 템플릿 화면을 볼 수 있다.

→ 

'study > Spring' 카테고리의 다른 글

웹 페이지 만들기 - 2 (복습)  (0) 2023.04.07
chap 14 - @PathVariable, 익셉션 처리  (0) 2023.02.27
chap 13 - Cookie  (0) 2023.02.23
chap 13 - HandlerInterceptor  (0) 2023.02.23
chap 13 - HttpSession  (0) 2023.02.21
댓글