[스프링 부트 쇼핑몰 프로젝트 with JPA] 7장 정리
주문 기능 구현에는 상품 재고 관리, 비즈니스 로직의 메소드화, 양방향 관계 설정, 주문 엔티티 생성, 비동기 처리, 데이터 바인딩 검사, 로그인 유저 정보 접근, Ajax를 이용한 비동기 주문 로직 호출, CSRF 토큰 값 조회 등이 포함됩니다. 주문 이력 조회는 주문 상품 정보 및 주문 정보 클래스 생성, 주문 이력 조회 쿼리 작성, 주문 목록 조회 로직 구현, 주문 목록 데이터 반환 등을 포함하며, 주문 취소 기능은 상품 재고 증가 메소드, 주문 취소 시 재고 증가 메소드, 주문 취소 로직, 주문 취소 권한 검사 등을 포함합니다.
Apr 08, 2024
🌼주문 기능 구현하기
💡핵심 키워드
- 고객이 상품을 주문하면 현재 상품의 재고에서 주문 수량만큼 재고를 감소시켜야 한다.
- 고객이 주문을 했는데 실제 재고가 없다면 배송을 하지 못하고 결품 처리가 되기 때문에 주문 수량만큼 상품의 재고를 감소시켜야 한다.
- 또한 주문 수량이 현재 재고 수보다 클 경우 주문이 되지 않도록 구현한다.
- 엔티티 클래스 안에 비즈니스 로직을 메소드로 작성하면 코드의 재사용과 데이터의 변ㅂ경 포린트를 한군데로 모을 수 있다는 장점이 있다.
- 만약 엔티티가 서로 양방향 관계라면 각각의 객체를 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