[클론 코딩] 커피 주문 관리 (6)

suRan·2022년 9월 16일
0

🍃 SpringBoot

목록 보기
24/24

Feat: Add API to manage orders

레포지토리를 만들어 DB에 저장

orders, order_items 테이블 생성

  • 테이블 스키마 추가
    • 마스터 - 디테일 관계
    • orders테이블에 order_items테이블을 JSON형태로 집어넣는 방법도 있다.
    • order_itemsorders의 하위 테이블이므로 따로 PRIMARY KEY를 갖지 않고 자동 증가하는 시퀀스로 선언
      seq bigint NOT NULL PRIMARY KEY AUTO_INCREMENT
    • order_id로 검색이 잦기 때문에 인덱스 설정

OrderJdbcRepository 생성

기능 : Order를 추가하고 Order의 order_items만큼 insert를 해야한다.

  • OrderJdbcRepository
    • paraMap.put("email", order.getEmail().getAddress()); // VO에서 address를 가져와야 한다. -> 무슨 의미?
  • orders와 order_items의 created_at, updated_at 는 같은 값을 가진다고 봐야한다.
  • insert 메소드
    • @Transactional : 한 번에 묶어 처리
      • 의문 왜 ProductJdbcRepository의 insert에서는 @Transactional처리를 하지 않았을까?
      • Product는 여러 개의 상품을 한 번에 insert하지 않기 때문에? Product는 관리자가 추가하는 것이라서?

DefaultOrderService 와 OrderRestController

기능 : OrderJdbcRepository를 사용하여 주문 추가 비즈니스 로직을 처리하는 서비스 생성. 그 서비스를 조작하는 컨트롤러도 생성한다.

  • CreateProductRequest
    • Order Post 시 넘겨줄 DTO를 record 타입으로 생성

DAO, DTO, VO

  • DAO

    • DAO(Data Access Object)는 데이터베이스의 data에 접근하기 위한 객체. DataBase에 접근 하기 위한 로직 & 비지니스 로직을 분리하기 위해 사용한다.
  • DTO

    • DTO(Data Transfer Object) 는 계층 간 데이터 교환을 하기 위해 사용하는 객체로, DTO는 로직을 가지지 않는 순수한 데이터 객체(getter & setter 만 가진 클래스)
    • 유저가 입력한 데이터를 DB에 넣는 과정을 예로 살펴보자. 유저가 자신의 브라우저에서 데이터를 입력하여 form에 있는 데이터를 DTO에 넣어서 전송한다. 해당 DTO를 받은 서버가 DAO를 이용하여 데이터베이스로 데이터를 집어넣는다.
  • VO

    • VO(Value Object) 값 오브젝트로써 값을 위해 쓰인다. read-Only 특징(사용하는 도중에 변경 불가능하며 오직 읽기만 가능)
    • DTO와 유사하지만 DTO는 setter를 가지고 있어 값이 변할 수 있다
  • 흐름

    • 서비스는 서비스 자체의 고유한 메소드를 가진다.
    • 컨트롤러는 DTO를 서비스가 필요한 VO나 파라미터의 매개변수로 변환한다.

출처 : https://melonicedlatte.com/2021/07/24/231500.html


  • 오류 발생

    • java.lang.IllegalArgumentException: address should not be null
    • email 생성 도중 오류 발생
    • 오류 원인 : OrderRestController의 reateOrder 메소드의 인자에 @RequestBody 어노테이션을 붙이지 않음
  • 오류 발생

    • OrderJdbcRepository에서
      INSERT INTO 테이블(테이블 필드명1, 필드명2 ...)" + "VALUES (model 클래스의 필드명1, 필드명2 ...) 코드작성 시 실수를 함. model 클래스의 필드명을 snake case로 작성함.
  • 오류 발생

    • java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 에러가 지속적으로 발생
    • 원인: (UNHEX(REPLACE(:orderId, '-', '')))문법의 괄호를 제대로 닫지 않음
  • 오류 발생

Feat: Add controlled component that records orderer information

리액트 화면에서 입력하고 결제하기 버튼 클릭 -> 주문정보가 제출되어 주문관리 API를 통해 DB에 저장된다.

  • 오류발생
    • 리액트 DOM렌더링이 제대로 진행되지 않음
    • 원인 : 서버를 띄우지 않았다.
  • 결제하기 버튼은 Summary에 있음
    • Summary도 상태를 가지고 있어야 한다.
  • 오류발생

    • 리액트 화면에서 react-jsx-dev-runtime.development.js:87 Warning: Each child in a list should have a unique "key" prop. 오류 발생
    • 원인은 잘못된 키 설정! key를 id -> productId로 변경해주었다.
    • 다른 코드도 전부 id -> productId로 변경
  • Summary에서 입력받는 것은 주문정보. 따라서 이용자가 입력하는 타이핑에 대한 상태 관리가 필요하다.

    • 필드로 정의한 뒤 각 input태그와 연결
    • onChange={} 필드 변경 시 이벤트를 잡아내서 order에 연결해야 함
    • 흐름 : input에 onchange가 발생하면 changeInput이 호출된다.
    • 타이핑 시마다 input이 바뀌면 해당 target(요소)의 value를 가져와서 setOrder로 상태 업데이트
  • 오류발생

    • Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
    • state 상태의 초기값 정의로 해결

이제 input이 state와 연결이 되고, 각 이벤트 발생 시마다 값을 변경한 뒤 value속성에 바인딩.

react controller component

  • controlled component : 요소가 리액트 상태와 연결된 것
  • uncontrolled component : 요소가 리액트 상태와 연결되지 않은 것

Feat: Add order result printing function when client press the payment button

결제하기 버튼을 누르면 주문결과 출력

입력값에 대한 검증 skip -> 다음 개인 프로젝트에는 진행시켜보자

실제 form처리에서는 검증할 것이 많은데 프론트엔드 과정이라면 다른 라이브러리를 이용해 검증 처리 했을 것

그리고 폼을 보낸 이후 clear 작업도 진행해야 하지만 프론트엔드 과정이기 때문에 생략

  • Summary에 추가된 값은 부모(App)에 있다.

  • 흐름 : 결제 버튼을 누르면 주문 정보가 합쳐져서 http POST -> 서버요청

    • 위 플로우는 props를 통해 처리한다. (props는 객체 데이터를 Argument로 전달할 수 있게 해준다.)
      부모가 전달해주는 콜백 function에 의해 호출해줘야 함
  • onOrderSubmit 메소드를 호출하면 order를 전달해준다.

  • App.js에서 Summary를 사용하고 있는 부분 -> onOrderSubmit={{handleOrderSubmit} 추가

  • axios.post(url, {json형태로 데이터 정의})

    • axios는 HTTP 비동기 통신 라이브러리
  • 매핑 처리 - UI에서의 변수명과 서버단의 변수명이 다를 수 있으니 매핑 처리 중요

  • 오류 발생

    • Access to XMLHttpRequest at 'http://localhost:8080/api/v1/products' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    • 처음에는 CORS 에러인줄 알았지만 결국 코드 실수였다.
    • axios.post() 내부에 url을 products api의 url로 잘못 작성한 것. CORS는 죄가 없다.
  • 리덕스몹엑스
    • 상태 관리 라이브러리
    • 상태 관리 툴을 사용하지 않으면 콜백을 부모자식으로 전달해주고, 상태 관리를 하는 등의 작업이 필요하기 때문에 매우 불편해진다.
    • 리덕스, 몹엑스를 통해 현재까지 사용한 코드를 깔끔하게 리팩토링 가능
profile
개발 공부를 해라

0개의 댓글