당니의 개발자 스토리
주문 목록 검색, 취소 본문
주문 목록 검색, 취소
자 여러분 이번 시간에는 주문 목록과 그리고 취소 기능을 한번 만들어 보겠습니다.

먼저, 상품 주문으로 들어가셔서 데이터 하나 만들어 가지고 Submit 하면,

지금은 없거든요. 이거는 재고 부족으로 안되는 거긴 한데,

아무튼 이번 시간에는 마지막 주문 내역을 한번 만들어 보겠습니다.
주문 내역은 OrderController에서 하면 됩니다.

@GetMapping을 하시고 전에 만들어 놨던 OrderSearch를 쓸 거예요. 폼에서 넘어오는 데이터들, 그러니까 상품 리스트를 검색하는 조건들이 여기에 다 담겨서 넘어올 거구요.

OrderSearch를 보시면, 얘가 이제 회원 이름과 주문 상태로 검색을 할 수 있는 기능입니다.

그런 다음 Model, 화면을 그려야 되니까 Model을 넘기고

그 다음에 OrderService의 findOrders를 호출을 해야 되는데,

OrderService로 가셔서 저번에 주석처리를 했던 걸 풀어줍니다.

그리고 findAllByCriteria랑 findAllByString이 있는데,

findAllByString으로 할게요. 뭐 아무거나 고르셔도 됩니다.
다시 OrderController로 돌아오셔서

orderService.findOrders를 해줍니다. 그 다음에

cmd + option + v로 반환을 해줍니다. 그런데 참고로 findOrders를 들어가시면

그냥 단순하게 위임만 한단 말이에요. 이런 기능 같은 경우에는 고민을 해보시고 그냥 컨트롤러에서 repository로 바로 불러도 괜찮아요. 정말 단순하게 화면에서 조회하기 위한 기능이면 아키텍쳐를 어떻게 잡느냐에 따라 다르긴 한데, 저 같은 경우에는 기본적으로 repository에 접근하는 것은

단순한 조회 같은 경우, 이렇게 단순 위임이면 그냥 호출을 하는 편입니다.

근데 여기서는 코드도 얼마 없고 하니 그냥 다 서비스에 한번에 위임 하도록 했는데요. 선택하시면 됩니다. 크게 이런 것에 얽매이실 필요는 없어요.

그래서 이제 model에다가 OrderSearch를 통해 검색 조건에 맞는 orders를 담고, order/orderList를 한번 뿌려봐야 되겠죠.
화면을 만들겠습니다.

order에 orderList를 만들고요. 이것도 제가 좋아하는 복사 붙이기로 해결하겠습니다.

이제 돌려보겠습니다. 주문 내역을 뿌릴 거거든요.

그 다음에 주문 내역에 들어가면,

이렇게 나옵니다. 데이터가 없으니까 일단 주문을 또 해야 되겠네요.

회원을 등록하고,

상품도 저장하고 이제

상품 주문으로 들어가겠습니다.

이렇게 해서 주문을 하면,

orders로 넘어가서 잘 나옵니다. 일단 기능이 되는지 한번 볼게요.

ORDER 검색하면 잘 나오고,

CANCEL 검색하면 CANCEL인 상태는 없으니까 이렇게 나오는 게 맞죠.

다시 전체 검색으로 돌리고 회원명 test 입력하면 잘 나옵니다.

그리고 만약 회원명을 xx로 해보면 안 나와야겠죠.
자 이제 대략적으로 하나씩 설명을 드리겠습니다.

우선 이걸 그려야 되거든요. 이 검색 조건들을 form을 만들어서 해야 돼요.

여기 보시면 <form> </form> 이 있습니다. 여기까지의 영역이 어디냐면,

바로 이 부분입니다.

지금 보시면, 타임리프의 object로 OrderSearch 라고 되어있죠.

OrderController에서 이 OrderSearch로 받을 수 있어요. 그러니까 @ModelAttribute에 이렇게 세팅을 해두시면,

"orderSearch"에 우리가 만들었던 OrderSeach 객체 인티티가 model 박스에 자동으로 담긴다고 보시면 돼요.
그러니까 굳이 orderSeach를 model.addAttribute로 안 담아도 자동으로 담기고, 또 담긴 게 form submit 하면 orderSeach에 값이 들어옵니다.
자 그래서 뿌릴 수도 있고 담을 수도 있어요.

쉽게 말씀드리면 이 코드가 하나 생략이 되어 있는 거에요. 이렇게 이해해 주시면 됩니다.
자세한 건 Spring MVC 강의에 있어요. Spring MVC를 공부하시면 되게 기본적인 거여서 넘어갈게요.

그래서 어쨌든 이 OrderSearch를 가지고 우선 데이터를 다 뿌립니다.

처음에는 데이터가 없으니까 안 뿌릴 거고요.

근데 제가 만약에 회원명을 test 라고 적고 주문 상태를 ORDER라고 해서 검색을 딱 눌렀어요.

그러면 form submit이 되면서 이게 넘어갑니다.

자 그러면서 여기서 계속 넘기기 하는 건데

어쨌든 form submit이 되면서 이게 넘어가구요.
그러면서 이 name, ORDER, CANCEL 이 상태 값,

지금 name은 input text로 받고 있고요. 그 다음에 주문 상태에 대해서는

여기 select box로 받고 있죠.

form submit을 하면 이 orderSeach에 값이 있고, 값이 있는 상태로

이 orderSeach의 필드에 binding이 됩니다.

지금 보시면 Get 방식으로 파라미터 넘어가는 거 보이시죠?

이거대로 바인딩이 됩니다.
자 그리고 뿌릴 때 어떻게 합니까?

값이 있으면 이제 컨트롤러에서

이 검색을 딱 누르면 일단은 컨트롤러로 가겠죠. @GetMapping으로 orders에 가니까

데이터가 여기 바인딩 된 상태로 orderList로 넘어가게 됩니다.

자 그러면 orderList에서 검색에 충족하는 값이 있으니까 값이 있는 memberName이랑

select box에서 값이 있는 상태로 선택이 됩니다.

자 그런데 저같은 경우에는 이 enum 타입의 ORDER랑 CANCEL, 둘 다 뿌려야 되거든요.

그러니까 orderStatus를 루프를 돌리면서 다 뿌려야 되는데,

그거는 이제 ThymeLeaf에서 문법을 써서 뿌리면 됩니다.

그러면 enum에 있는 value()를 호출해서 그 값을 다 가져온 다음에

여기 enum 타입의 값을 다 뿌린 거죠. 그렇게 해서 이렇게 select box를 뿌렸습니다.

그 다음은 컨트롤러에서 이 orders 가져온 거를 model.addAttribute로 담고 루프를 돌려야 되겠죠.


그건 이렇게 해서 쭉 돌립니다.

orders를 item으로 바꿔 가지고 그냥 쭉 돌립니다. 사실 item이 아니라 order라고 이름 붙이는 게 맞는데 그냥 두겠습니다.
자 그 다음 이제 남은 기능이 있죠.

주문 취소 CANCEL, 이걸 누르면 어쨌든 CANCEL은 또 상태를 변화하는 거기 때문에 기본적으로 이런건 Post로 만드시는게 낫겠죠.

그래서 얘는 만약에 상태가 'ORDER'인 경우에만 이 버튼을 노출되게 기능을 만든 겁니다.

그래서 이렇게 버튼이 노출되고, 이걸 누르게 되면

얘가 JavaScript를 호출합니다. 그래서

그래서 cancel을 호출하면 cancel이 form을 만들어서 Post로 해서 /orders에 id/cancel을 호출하게 됩니다. 그러면 저희는 이걸 만들어야 되겠죠.

먼저, @PostMapping 으로 orderId를 @PathVariable을 통해서 바인딩 해야되구요. 이거는 한줄 호출하면 끝나겠죠.

orderService.cancelOrder로 id 넣어주고 redirect 해서 orders로 다시 가게하면 되겠죠.
메서드를 추가했기 때문에 다시 서버를 띄우겠습니다.
회원이랑 상품이 없어서 다시 후딱 만들겠습니다. 이 과정은 생략해도 되겠죠.

그래서 딱 주문을 Submit 하면,

이렇게 뜨죠.

여기서 CANCEL 딱 눌러보면,

지금 상태가 CANCEL로 바뀌었죠. 그리고 redirect가 돼서 다시 여기로 온 겁니다. 상태가 CANCEL이 아니니까 CANCEL 버튼이 안뜨게 하는 건 아까 말씀드렸구요.
그래서 이제 ORDER를 검색하면,

아무 것도 안 뜨고 CANCEL로 검색하면

잘 뜨는 걸 보실 수 있습니다.

자 여러분 여기까지 하면 회원 가입하고, 회원 목록 보고, 상품 등록하고, 상품 목록 보고, 상품 수정을 했어요.
상품 수정을 할 때 되게 강조를 드렸죠. merge를 쓰지 말고 가급적이면 Dirty Checking, 변경 감지를 쓰라구요. merge를 쓰면 데이터를 다 덮어버리기 때문에, 잘못하면 null까지 다 덮어버리기 때문에 최대한 병합을 사용하지 말고 변경감지를 사용해서 엔티티를 수정하세요. 라고 말씀드렸습니다.
자 그리고 상품 주문은 이전에 해봤고, 그 다음에 주문 내역 보면서 검색이랑 취소하는 로직까지 다해서 전체적인 사이클을 한번 돌아봤습니다.
이렇게 해서 기본적으로 Thymeleaf를 가지고 화면을 렌더링 하는 것들은 다 작업을 해봤구요. 이 다음 시간에는 API를 만들어 볼 거에요.
과거에는 화면 만드는 것 정도로 끝난 일이 되게 많았는데, 요즘의 개발이라는 것은 주로 싱글 페이지 애플리케이션도 되게 많고 그 다음에 Reactor나 Vue.js 같은 걸로 거의 API를 통신해야 되는 상황도 되게 많습니다. 그리고 이제 뭐 안드로이드나 아이폰처럼 이렇게 앱과 통신해야 되는 경우도 되게 많고, 또 마이크로 서비스 아키텍처가 더 많이 되면서 다른 시스템들끼리 API를 통신해야 되는 경우가 정말 많잖아요.
그래서 이제 JPA를 가지고 어떻게 API를 잘 설계하고 만들어내는지, 그리고 순수하게 API로 CRUD 하는 거 한번 해보고, 그 다음 시간에는 성능 최적화 해서 되게 복잡한 API를 어떻게 만드는지. 관련된 성능 최적화 부분을 한번 설명드리도록 하겠습니다.