[Spring] 간단한 SHOP 제작(3)

JJoSuk·2023년 6월 20일
0
post-thumbnail

본 프로젝트 자료는 김영한님의 실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발을 참고 제작됐음을 알립니다.

상품 도메인 개발

Item - 상품 엔티티 코드 추가

  • addStock() 메서드는 파라미터로 넘어온 수만큼 재고를 늘린다. 이 메서드는 재고가 증가하거나 상품 주 문을 취소해서 재고를 다시 늘려야 할 때 사용한다.
  • removeStock() 메서드는 파라미터로 넘어온 수만큼 재고를 줄인다. 만약 재고가 부족하면 예외가 발생한 다. 주로 상품을 주문할 때 사용한다.

NotEnoughStockException 클래스를 생성해서 예외를 추가해줘야 한다.

NotEnoughStockException - 예외 추가 클래스 생성


상품 리포지토리 개발

ItemRepository - 상품 리포지토리 생성

save 에 대한 부연 설명

  • id 가 없으면 생성.
  • id 가 있으면 이미 데이터베이스에 저장된 엔티티를 수정한다고 인식, 업데이트.

상품 서비스 개발

ItemService - 상품 서비스 코드 생성

상품 서비스는 상품 리포지토리에 단순히 위임만 하는 클래스 다.


주문 도메인 개발

구현 기능

  • 상품 주문
  • 주문 내역 조회
  • 주문 취소

순서

  • 주문 엔티티, 주문상품 엔티티 개발
  • 주문 리포지토리 개발
  • 주문 서비스 개발
  • 주문 검색 기능 개발
  • 주문 기능 테스트

주문 엔티티 개발

Order - 주문 엔티티 코드 추가

  • 생성 메서드( createOrder() ): 주문 엔티티를 생성할 때 사용한다. 주문 회원, 배송정보, 주문상품의 정보 를 받아서 실제 주문 엔티티를 생성한다.

  • 주문 취소( cancel() ): 주문 취소시 사용한다. 주문 상태를 취소로 변경하고 주문상품에 주문 취소를 알린 다. 만약 이미 배송을 완료한 상품이면 주문을 취소하지 못하도록 예외를 발생시킨다.
  • 전체 주문 가격 조회: 주문 시 사용한 전체 주문 가격을 조회한다. 전체 주문 가격을 알려면 각각의 주문상품 가격을 알아야 한다. 로직을 보면 연관된 주문상품들의 가격을 조회해서 더한 값을 반환한다. (실무에서는 주로 주문에 전체 주문 가격 필드를 두고 역정규화 한다.)

OrderItem, cancle, getTotalPrice 비어 있는 메서드를 생성해주자.

OrderItem - 메서드 추가


주문 리포지토리 개발

주문 리포지토리에는 주문 엔티티를 저장하고 검색하는 기능을 넣었다.


주문 서비스 개발

OrderService - 주문 서비스 코드 생성

주문 서비스는 주문 엔티티와 주문 상품 엔티티의 비즈니스 로직을 활용해서 주문, 주문 취소, 주문 내역 검 색 기능을 제공한다.


주문 검색 기능 개발

JPA에서 동적 쿼리를 어떻게 해결해야 하는가?

OrderSearch - 주문 검색창 생성

OrderRepository - 접근 권한 생성

findAll(OrderSearch orderSearch) 메서드는 검색 조건에 동적으로 쿼리를 생성해서 주문 엔티티를 조회한다.

JPQL 쿼리를 문자로 생성하기는 번거롭고, 실수로 인한 버그가 충분히 발생할 수 있다.

  • JPA Criteria는 JPA 표준 스펙이지만 실무에서 사용하기에 너무 복잡하다. 아마 사용하는 부분에서 추천하지 않는다.


웹 계층 개발

  • 홈 화면
  • 회원 기능
    • 회원 등록
    • 회원 조회
  • 상품 기능
    • 상품 등록
    • 상품 수정
    • 상품 조회
  • 주문 기능
    • 상품 주문
    • 주문 내역 조회
    • 주문 취소

홈 화면과 레이아웃

HomeController - 홈 뷰 생성

타임리프 템플릿 등록

home - 뷰 생성

이대로 생성해봐야 아무것도 안뜬다. fragments 로 추가 HTMl 을 제작해줘야 한다.

fragments/header - 뷰 생성

fragments/bodyHeader - 뷰 생성

fragments/footer - 뷰 생성

이렇게만 일단 등록해주고 실행시켜본다.

결과 화면

여기서 끝내기엔 화면이 너무 조잡해 보인다. 그렇다고 직접 꾸미기엔 시간이 많이 걸려 (https://getbootstrap.com/) 를 사용해 복붙으로 꾸며보자.

(https://getbootstrap.com/) 링크를 타고 들어가면 중앙 하단에 다운로드를 확인할 수 있을 것이다. 클릭하자.

지금 현재 원하는 버전은 현재 기준 5.3이 아닌 4.3이 필요한 상황이니, 4.3으로 변경하고 엔터쳐주자.

아래와 같은 화면이 보일텐데 다운로드 눌러주면 원하는 자료를 받을 수 있을 것이다.

다운을 받고 압축을 풀게 된다면 css 와 js 파일을 확인할 수 있을 것이다.

현재 넣고자 하는 혹은 진행 중인 프로젝트에 넣어주면 된다.

  • /Users/joseoghwan/Desktop/study/jpa shop/src/main/resources

그리고 프로젝트에 다시 돌아와,

resources/static 에 넣었던 파일이 존재한다면 오른쪽 클릭 후 동기화 진행을 해주면 다운받은 파일을 적용시킬 수 있다.

그리고 css 폴더에 jumbotron-narrow.css 파일을 추가만 해주면 끝난다.

jumbotron-narrow - css 추가

이제 실행시켜서 화면이 제대로 호출되었는지 확인해보자.

결과 화면

아까와 비교해서 깔끔해진걸 확인 할 수 있다.


회원 등록

폼 객체를 사용해서 화면 계층과 서비스 계층을 명확하게 분리해야 한다.

MemberForm - 회원 등록 폼 객체 생성

MemberController - 회원 등록 컨트롤러 생성

createMemberForm - 회원 등록 폼 뷰 생성

실행 결과

값을 정확하게 입력했을 경우,

값을 만약 null 로 했을 경우.

정상적으로 실행되는 것을 확인 할 수 있다.


회원 목록 조회

MemberController - 회원 목록 컨트롤러 추가

MemberController 컨트롤러 클래스 하단에 내용 추가.

  • 뷰에 전달할 데이터를 MVC가 제공하는 모델( Model ) 객체에 보관.
  • return, 실행할 뷰 이름을 반환

memberList - 멤비 리스트 뷰 생성

실무에서 엔티티보다 폼 객체 사용을 추천하는 이유는, 요구사항이 복잡해지기 시작하면 엔티티에 화면을 처리하기 위한 기능이 많아진다. 결국 코드가 지저분해지는 원인이 되고, 점점 화면에 종속적으로 변해 유지보수하기 힘들어진다.

엔티티는 핵심 비즈니스 로직만 유지하고 화면을 위한 로직은 없애야 한다. 화면이나 API 에 맞는 폼 객체나 DTO 사용을 추천한다.

실행 결과

회원가입을 진행하고 회원 목록을 조회해봤다.

다음과 같이 입력한 회원 리스트가 출력된다면 성공적으로 실행됐다.


상품 등록

BookForm - 상품 등록 폼 생성

ItemController - 상품 등록 컨트롤러 생성

createItemForm - 상품 등록 뷰 생성

  • 상품 등록 폼에서 데이터를 입력하고 Submit 버튼을 클릭하면 /items/new 를 POST 방식으로 요청
  • 상품 저장이 끝나면 상품 목록 화면( redirect:/items )으로 리다이렉트

상품 목록

ItemController - 상품 목록 컨트롤러 추가

ItemController 컨트롤러 클래스에 내용을 추가.

itemList - 상품 리스트 뷰 생성

model 에 담아둔 상품 목록인 items 를 꺼내서 상품 정보를 출력했다.

출력 결과

리스트에 입력한 정보가 출력되는지 확인.

성공적으로 출력되는 것을 확인 할 수 있다.


상품 수정

ItemController - 상품 수정과 관련된 컨트롤러 코드 추가

ItemController 컨트롤러 클래스에 수정과 관련 컨트롤러 추가.

상품 수정 폼 이동

  • 수정 버튼을 선택하면 /items/{itemId}/edit URL을 GET 방식으로 요청.
  • 그 결과로 updateItemForm() 메서드를 실행하는데 이 메서드는 itemService.findOne(itemId) 를 호출해서 수정할 상품을 조회.
  • 조회 결과를 모델 객체에 담아서 뷰(items/updateItemForm)에 전달

상품 수정 실행

상품 수정 폼 HTML에는 상품의 id(hidden), 상품명, 가격, 수량 정보 있음

updateItemForm - 수정 뷰 생성

  • 상품 수정 폼에서 정보를 수정하고 Submit 버튼을 선택
  • /items/{itemId}/edit URL을 POST 방식으로 요청하고 updateItem() 메서드를 실행
  • 이때 컨트롤러에 파라미터로 넘어온 item 엔티티 인스턴스는 현재 준영속 상태다. 따라서 영속성 컨텍스트의 지원을 받을 수 없고 데이터를 수정해도 변경 감지 기능은 동작X

실행 결과

상품 등록 후 수정 입력.

원하는 변경 값으로 변경 후 입력.

제대로 변경된 것을 확인 할 수 있다.


상품 주문

OrderController - 상품 주문 컨트롤러

orderForm - 상품 주문 뷰 생성

실행 결과


주문 목록 검색, 취소

OrderController - 주문 목록 검색 컨트롤러 추가

Get 방식으로 주문 목록 검색 조회, Post 방식으로 주문 목록 취소 로직을 넣었다.

orderList - 주문 목록 조회 뷰 생성

실행 결과

로직대로 동작하는지 상품 목록에 있는 상품을 주문해보려고 한다.

test 상품 100개가 정상적으로 동작하는걸 확인했고, 상품 목록 수량이 줄었는지 확인해보자.

정상적으로 줄었다면 성공적으로 출력한걸 확인 할 수 있다.


회원 목록 조회

MemberController - 회원 목록 컨트롤러 추가

MemberController 컨트롤러 클래스 하단에 내용 추가.

  • 뷰에 전달할 데이터를 MVC가 제공하는 모델( Model ) 객체에 보관.
  • return, 실행할 뷰 이름을 반환

memberList - 멤비 리스트 뷰 생성

실무에서 엔티티보다 폼 객체 사용을 추천하는 이유는, 요구사항이 복잡해지기 시작하면 엔티티에 화면을 처리하기 위한 기능이 많아진다. 결국 코드가 지저분해지는 원인이 되고, 점점 화면에 종속적으로 변해 유지보수하기 힘들어진다.

엔티티는 핵심 비즈니스 로직만 유지하고 화면을 위한 로직은 없애야 한다. 화면이나 API 에 맞는 폼 객체나 DTO 사용을 추천한다.

실행 결과

회원가입을 진행하고 회원 목록을 조회해봤다.

다음과 같이 입력한 회원 리스트가 출력된다면 성공적으로 실행됐다.


상품 등록

BookForm - 상품 등록 폼 생성

ItemController - 상품 등록 컨트롤러 생성

createItemForm - 상품 등록 뷰 생성

  • 상품 등록 폼에서 데이터를 입력하고 Submit 버튼을 클릭하면 /items/new 를 POST 방식으로 요청
  • 상품 저장이 끝나면 상품 목록 화면( redirect:/items )으로 리다이렉트

상품 목록

ItemController - 상품 목록 컨트롤러 추가

ItemController 컨트롤러 클래스에 내용을 추가.

itemList - 상품 리스트 뷰 생성

model 에 담아둔 상품 목록인 items 를 꺼내서 상품 정보를 출력했다.

출력 결과

리스트에 입력한 정보가 출력되는지 확인.

성공적으로 출력되는 것을 확인 할 수 있다.


상품 수정

ItemController - 상품 수정과 관련된 컨트롤러 코드 추가

ItemController 컨트롤러 클래스에 수정과 관련 컨트롤러 추가.

상품 수정 폼 이동

  • 수정 버튼을 선택하면 /items/{itemId}/edit URL을 GET 방식으로 요청.
  • 그 결과로 updateItemForm() 메서드를 실행하는데 이 메서드는 itemService.findOne(itemId) 를 호출해서 수정할 상품을 조회.
  • 조회 결과를 모델 객체에 담아서 뷰(items/updateItemForm)에 전달

상품 수정 실행

상품 수정 폼 HTML에는 상품의 id(hidden), 상품명, 가격, 수량 정보 있음

updateItemForm - 수정 뷰 생성

  • 상품 수정 폼에서 정보를 수정하고 Submit 버튼을 선택
  • /items/{itemId}/edit URL을 POST 방식으로 요청하고 updateItem() 메서드를 실행
  • 이때 컨트롤러에 파라미터로 넘어온 item 엔티티 인스턴스는 현재 준영속 상태다. 따라서 영속성 컨텍스트의 지원을 받을 수 없고 데이터를 수정해도 변경 감지 기능은 동작X

실행 결과

상품 등록 후 수정 입력.

원하는 변경 값으로 변경 후 입력.

제대로 변경된 것을 확인 할 수 있다.


상품 주문

OrderController - 상품 주문 컨트롤러

orderForm - 상품 주문 뷰 생성

실행 결과


주문 목록 검색, 취소

OrderController - 주문 목록 검색 컨트롤러 추가

Get 방식으로 주문 목록 검색 조회, Post 방식으로 주문 목록 취소 로직을 넣었다.

orderList - 주문 목록 조회 뷰 생성

실행 결과

로직대로 동작하는지 상품 목록에 있는 상품을 주문해보려고 한다.

test 상품 100개가 정상적으로 동작하는걸 확인했고, 상품 목록 수량이 줄었는지 확인해보자.

정상적으로 줄었다면 성공적으로 출력한걸 확인 할 수 있다.

profile
안녕하세요

0개의 댓글