[스프링 부트 쇼핑몰 프로젝트 with JPA] 7장 정리

주문 기능 구현에는 상품 재고 관리, 비즈니스 로직의 메소드화, 양방향 관계 설정, 주문 엔티티 생성, 비동기 처리, 데이터 바인딩 검사, 로그인 유저 정보 접근, Ajax를 이용한 비동기 주문 로직 호출, CSRF 토큰 값 조회 등이 포함됩니다. 주문 이력 조회는 주문 상품 정보 및 주문 정보 클래스 생성, 주문 이력 조회 쿼리 작성, 주문 목록 조회 로직 구현, 주문 목록 데이터 반환 등을 포함하며, 주문 취소 기능은 상품 재고 증가 메소드, 주문 취소 시 재고 증가 메소드, 주문 취소 로직, 주문 취소 권한 검사 등을 포함합니다.
DriedPollack's avatar
Apr 08, 2024
[스프링 부트 쇼핑몰 프로젝트 with JPA] 7장 정리

🌼주문 기능 구현하기

💡핵심 키워드

  • 고객이 상품을 주문하면 현재 상품의 재고에서 주문 수량만큼 재고를 감소시켜야 한다.
    • 고객이 주문을 했는데 실제 재고가 없다면 배송을 하지 못하고 결품 처리가 되기 때문에 주문 수량만큼 상품의 재고를 감소시켜야 한다.
    • 또한 주문 수량이 현재 재고 수보다 클 경우 주문이 되지 않도록 구현한다.
  • 엔티티 클래스 안에 비즈니스 로직을 메소드로 작성하면 코드의 재사용과 데이터의 변ㅂ경 포린트를 한군데로 모을 수 있다는 장점이 있다.
  • 만약 엔티티가 서로 양방향 관계라면 각각의 객체를 setter로 세팅해줘야 한다.
  • 상품 페이지에서는 1개의 상품을 주문하지만, 장바구니 페이지에서는 한 번에 여러 개의 상품을 주문할 수 있다.
    • 따라서 리스트 형태로 파라미터 값을 받으며 주문 객체에 주문 상품 객체를 추가한다.
  • 회원 정보와 주문할 상품 리스트 정보를 이용해서 주문 엔티티를 생성한다.
  • 스프링에서 비동기 처리를 할 때 @RequestBody@ResponseBody 어노테이션을 사용한다.
    • @RequestBody : HTTP 요청의 본문 body에 담긴 내용을 자바 객체로 전달
    • @ResponseBody : 자바 객체를 HTTP 요청의 body로 전달
  • 객체에 데이터 바인딩 시 에러가 있는지 검사하기 위해 BindingResult를 사용한다.
  • 현재 로그인 유저의 정보를 얻기 위해 @Controller 어노테이션이 선언된 클래스에서 메소드 인자로 Principal 객체를 넘겨 줄 경우 해당 객체에 직접 접근할 수 있다.
  • form 태그를 사용하여 submit 방식으로 서버에 요청하게 되면 페이지가 새로 고침이 된다는 단점이 있다.
    • 이를 해결하기 위해 Ajax를 이용하여 주문 로직을 비동기 방식으로 호출한다.
  • 스프링 시큐리티를 사용할 경우 기본적으로 POST 방식의 데이터 전송에는 CSRF 토큰 값이 필요하므로 해당 값들을 자바스크립트에서 조회한다.
    • 주문할 상품의 아이디와 주문 수량 데이터를 전달할 객체를 생성한다.
    • contentType 속성을 통해서 서버에 데이터를 보낼 형식을 json으로 지정한다.
    • dataType 속성을 통해서 서버에서 결괏값으로 받을 데이터의 타입을 json으로 설정한다.
    • success 속성을 통해서 주문 로직 호출이 성공하면 보여줄 메소드를 지정할 수 있다.
    • error 속성을 통해서 주문 로직이 실패했을 경우나, jqXHR 파라미터를 통해 로그인한 상태가 아닐 경우 보여줄 메소드를 지정할 수 있다.
 

🌼주문 이력 조회하기

💡핵심 키워드

  • 주문 상품 정보를 담을 클래스의 생성자로 주문상품 객체와 이미지 경로를 파라미터로 받아서 멤버 변수값을 세팅한다.
  • 주문 정보를 담을 클래스의 생성자로 주문 객체를 파라미터로 받아서 멤버 변수 값을 세팅한다.
    • 주문 날짜의 경우 yyyy-MM-dd HH:mm 형태로 전달하기 위해 .format(DateTimeFormatter.ofPattern()을 사용한다.
  • @Query 어노테이션을 이용해서 JPQL을 통해 주문 이력을 조회하는 쿼리를 작성한다.
  • 서비스에서 주문 목록을 조회하는 로직을 구현한다.
    • 유저 아이디와 페이징 조건을 이용하여 주문 목록을 조회한다.
    • 유저의 주문 총 개수를 구한다.
    • 주문 리스트를 순회하면서 구매 이력 페이지에 전달할 DTO를 생성한다.
    • 주문한 상품의 대표 이미지를 조회한다.
    • 페이지 구현 객체를 생성하여 반환한다.
  • 구매이력을 조회할 수 있도록 컨트롤러에 구현한 로직을 호출하는 메소드를 만든다.
    • Pageable 객체에 PageRequest.of(page.isPresent() ? page.get() : 0, 4) 메소드를 이용해서 한 번에 가지고 올 주문의 개수를 4개로 설정할 수 있다.
    • 이메일과 페이징 객체를 파라미터로 전달하여 화면에 전달한 주문 목록 데이터를 리턴 값으로 받는다.
  • 구매 이력 페이지에서 성능적으로 향상시킬 수 있는 부분이 있다.
    • getOrderList() 메소드에서 for문을 순회하면서 order.getOrderItems()를 호출할 때마다 조회 쿼리문이 추가로 실행된다.
    • 이 경우 orders 리스트의 사이즈 만큼 쿼리문이 실행된다.
    • 만약 orders의 주문 아이디를 where order_id in (209, 210, 211, 212) 이런 식으로 in 쿼리로 한 번에 조회할 수 있다면 100개가 실행될 쿼리를 하나의 쿼리로 조회할 수 있다.
    • 이를 위해 application.properties 파일에서 spring.jpa.properties.hibernate.default_batch_fetch_size=100 을 통해 조건절에 in 쿼리문을 사용할 수 있다.
 

🌼주문 취소하기

💡핵심 키워드

  • 상품 클래스에 상품의 재고를 증가시키는 메소드를 생성한다.
  • 주문상품 클래스에 주문을 취소할 경우 상품의 재고를 증가시키는 메소드를 생성한다.
  • 주문 클래스에 주문 취소 시 주문 수량을 상품의 재고에 더해주는 로직과 주문 상태를 취소 상태로 바꿔주는 메소드를 구현한다.
  • 서비스 클래스에 주문을 취소하는 로직을 구현한다.
    • 현재 로그인한 사용자와 주문 데이터를 생성한 사용자와 같은지 검사한다.
    • 주문 취소 상태로 변경하면 트랜잭션이 끝날 때 update 쿼리를 실행한다.
  • 컨트롤러 클래스에 주문번호를 받아서 주문 취소 로직을 호출하는 메소드를 만든다.
    • 자바스크립트에서 취소할 주문 번호는 조작이 가능하므로 다른 사람의 주문을 취소하지 못하도록 주문 취소 권한 검사를 한다.
 

🏁결론

해당 내용을 정리하면서 주문, 주문이력 조회, 주문 취소 기능 구현을 통해서 주문 프로세스를 학습할 수 있었다.
또한 Spring Data JPA를 이용해서 주문 데이터 조회 시 조회를 최적화하는 방법을 학습할 수 있었다.
Share article

More articles

See more posts

👨🏻‍💻DriedPollack's Blog