#6 [스프링 스터디] 쇼핑몰 만들기 프로젝트 - 상품 CRUD 기능

myeonji·2022년 1월 19일
1

오늘은 Entity, Repository, Service, Controller로 나누고, 상품의 CRUD 기능을 구현해보겠습니다.

CRUD는 Create, Read, Update, Delete로, 현재 쇼핑몰 프로젝트에 비유하면

  • Create - 상품 등록

  • Read - 상품 읽기

  • Update - 상품 갱신

  • Delete - 상품 삭제

라고 할 수 있습니다.

이전 게시글에 포스팅 된 DB 설계를 토대로 Entity를 먼저 만듭니다.

<< Entity>>

Item, Cart, CartItem의 Entity를 만들어야 합니다.

< Item Entity >

먼저, 상품의 Entity(VO)가 필요합니다.

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@Entity
public class Item {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name; // 상품 이름

    private String text; // 상품에 대한 상세설명

    private int price; // 상품 가격

    private int count; // 판매 개수

    private int stock; // 재고

    private boolean isSoldout; // 상품 상태 (판매중 / 품절)

    @ManyToOne
    @JoinColumn(name="user_id")
    private User user; // 판매자 아이디

    @OneToMany(mappedBy = "item")
    private List<CartItem> cart_items = new ArrayList<>();

    private String photo; // 상품 사진
}

상품의 Entity를 이름, 설명, 가격, 판매량, 재고, 상태, 사진 으로 구성하였습니다.

판매자 아이디는 User Entity로써, 회원가입할 때 사용자 정보를 담는 Entity 입니다.

로그인/회원가입 부분은 Spring Security에 따로 다루었습니다.

상품을 판매하고 있는 판매자가 누구인지 알아야 하기 때문에 @ManyToOne으로 판매자 아이디를 넣습니다. @ManyToOne인 이유는 쉽게 말해서 판매자 한 명이 여러 개의 상품을 팔 수 있기 때문입니다.

또한 CartItem Entity도 필요한데 이것은 유저의 장바구니 안에 들어있는 상품들을 의미하는 Entity 입니다.

< Cart Entity >
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
public class Cart {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="user_id")
    User user; // 해당 유저의 장바구니

    @OneToMany(mappedBy = "cart")
    private List<CartItem> cart_items = new ArrayList<>();
}

Cart Entity를 보면 CartItem Entity가 @OneToMany로 들어가 있습니다.

장바구니 안에는 장바구니 상품들이 담겨있기 때문에 둘의 연관 관계를 @OneToMany로 지정한 것입니다.

< CartItem Entity >
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
public class CartItem {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="cart_id")
    private Cart cart;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="item_id")
    private Item item;

    private int cartCount; // 카트에 담긴 상품 개수

}

Cart Entity 에서는 CartItem Entity가 @OneToMany 였지만,

여기서(CartItem Entity)는 Cart Entity가 @ManyToOne 입니다.

Item Entity도 마찬가지 입니다.

<< Repository >>

이제 각 Entity의 Repository를 만들어야 합니다.

Repository에서는 JPA를 상속받습니다.

< Item Repository >
public interface Item extends JpaRepository<Cart, Integer> {}
< Cart Repository >
public interface Cart extends JpaRepository<Cart, Integer> {}
< CartItem Repository >
public interface CartItem extends JpaRepository<Cart, Integer> {}

<< Service >>

다음은 Service를 만들어야 합니다.

이 게시물에서는 상품의 CRUD 기능을 다룰 것이기 때문에 ItemService만 보도록 하겠습니다. 추후에 기능을 추가하기 위해서는 CartService 와 같은 Service를 더 구현해야 합니다.

< ItemService >

Service에는 CRUD의 기능이 구현되어 있으므로 기능 하나씩 살펴보겠습니다.

Create - 상품 등록

public void saveItem(Item item) { itemRepository.save(item); }

JPA를 상속받는 Repository의 save 함수를 사용하여 DB에 입력한 상품 정보를 저장 합니다.

Read - 상품 불러오기 (읽기)

public Item itemView(Integer id) { return itemRepository.findById(id).get(); }

여기서는 findById 함수를 사용하는데, 개별 상품을 읽어들일 때 사용합니다.

public List<Item> allItemView() { return itemRepository.findAll(); }

findAll 함수는 함수명에서 예측할 수 있듯이 전체 상품 List를 받아올 때 사용합니다.

html에서 전체 상품 리스트를 보여줘야 할 때 사용하는 함수입니다!

Update - 상품 수정

public void itemModify(Item item, Integer id) {
    Item update = itemRepository.findItemById(id);
    update.setName(item.getName());
    update.setText(item.getText());
    update.setPrice(item.getPrice());
    update.setStock(item.getStock());
    itemRepository.save(update);
}

상품 수정 기능에서는 update라는 새로운 Item 변수를 만듭니다.

이유는 이전에 입력되어있던 정보를 update라는 변수에 넣어두고, 새로운 정보를 set 을 통해 바꿔주는 것입니다.

따라서 최종적으로 Repository에 save 되는 것은 새로운 정보가 저장된 update 변수입니다.

Delete - 상품 삭제

public void itemDelete(Integer id) { itemRepository.deleteById(id); }

deleteById는 DB에서 id에 해당하는 데이터를 삭제시킵니다.

<< Controller >>

Service에서 구현한 기능들을 Controller에서 사용합니다.

< ItemController >
@Controller
@RequiredArgsConstructor
public class ItemController {

    private final ItemService itemService;

	// 상품 등록 페이지 (GET)
    @GetMapping("/item/new")
    public String itemSaveForm() { 
    
    	return "/seller/itemForm"; 
    }

    // 상품 등록 (POST)
    @PostMapping("/item/new/pro")
    public String itemSave(Item item) { 
      
    	itemService.saveItem(item); return "/main"; 
    }

    // 상품 수정 페이지 (GET)
    @GetMapping("/item/modify/{id}")
    public String itemModifyForm(@PathVariable("id") Integer id, Model model) {
      
      	model.addAttribute("item", itemService.itemView(id));
      
      	return "/seller/itemModify"; 
    }

    // 상품 수정 (POST)
    @PostMapping("/item/modify/pro/{id}")
    public String itemModify(Item item, @PathVariable("id") Integer id) { 
      
      	itemService.itemModify(item, id);
      
      	return "redirect:/main";
    }

    // 상품 상세 페이지
    @GetMapping("/item/view/{id}")
    public String itemView(Model model, @PathVariable("id") Integer id) {
      
      model.addAttribute("item", itemService.itemView(id));
      
      return "/seller/itemView";
    }


    // 상품 삭제
    @GetMapping("/item/delete/{id}")
    public String itemDelete(@PathVariable("id") Integer id) {
      
      itemService.itemDelete(id);
      
      return "/main";
    }

이렇게 Controller에서는 @GetMapping과 @PostMapping을 이용하여 url을 설정하고, Service에서 구현한 기능들을 사용합니다.

여기서 주의할 점은 상품의 CRUD 기능은 관리자 혹은 판매자만 접근해야 하는 기능입니다. 쇼핑몰 회원들은 구매, 장바구니 등 이외에 상품을 등록하거나 삭제하는 등의 기능에는 접근을 할 수 없기 때문입니다.

즉, 위에 구현한 기능들은 모두 역할이 관리자/판매자 일 때만 가능해야 합니다.

관리자/판매자와 구매자 간의 권한 설정은 다음 게시물에서 다뤄보겠습니다!

profile
DBA, 경제 그리고 고냥이

0개의 댓글