🎁 모든 강의 30% + 무료 강의 선물🎁

[인프런워밍업클럽 3기 BE] 3주차 발자국

[인프런워밍업클럽 3기 BE] 3주차 발자국

1. 강의

1.1 학습내용

  • @RestControllerAdvice

    • Spring에서 예외 처리를 전역적으로 관리할 수 있도록 도와주는 어노테이션이다.

    • JSON 형태로 응답을 반환하는 데 최적화 되어 있다.

    • @ExceptionHandler와 함께 사용하여 세부적인 특정 예외 유형 처리가 가능하다.

      • @ExceptionHandler는 컨트롤러 내부에서 사용하면 개별 처리, @RestControllerAdvice와 함께 사용하면 전역 예외 처리 가능하다.

      • 여러 개의 예외를 한 메서드에서 처리 가능하다.

    @RestControllerAdvice
    class AdminApiControllerAdvice {
    
        val log = LoggerFactory.getLogger(AdminApiControllerAdvice::class.java)
    
        @ExceptionHandler
        fun handleException(e: AdminException):ResponseEntity<String> {
            log.info(e.message , e)
            return ResponseEntity.status(e.httpStatus).body(e.message)
        }
    
        @ExceptionHandler
        fun handleException(e: MethodArgumentNotValidException):ResponseEntity<String> {
            log.info(e.message , e)
    
            val fieldError = e.bindingResult.fieldErrors[0]
            val message = "[${fieldError.field} ${fieldError.defaultMessage}]"
    
            return ResponseEntity.badRequest().body(message)
        }
    }

    1.2 느낀 점

    템플릿 라이센스 문제로 이번주 봐야될 강의가 줄어들어 미션에 좀 더 집중 할 수 있었다.


2. 미션

2.1. 조회 REST API 만들기

2.2. 삽입, 수정, 삭제 API 만들기

  • 테스트 케이스를 만들면서 상품, 주문 정보가 없는 경우 사용자 정의 에러를 만들어서 던지게 변경하였다.

class OrderNotFoundException(val orderNo: Long) : CustomException("해당 주문정보가 없습니다. [주문번호 : $orderNo]")
class ProductNotFoundException(val productCd: Long) : CustomException("해당 상품코드가 없습니다. [상품코드 : $productCd]")
  • 주문 등록

     

   @Transactional
    fun create(requestDTO: RequestCreateDTO): ResponseEntity<ResponseDTO> {
        // 주문 마스터 생성
        val orderHeader = Order(orderSts = OrderSts.PAYMENT_COMPLETED.code)
        orderRepository.save(orderHeader)

        // 주문 상세 생성
        requestDTO.items.forEach { item ->
            val product = productRepository.findById(item.productCd).orElseThrow {
                ProductNotFoundException(item.productCd) // 상품 코드가 없을 경우 예외 던지기
            }
            val orderDetail = OrderDetail(
                order = orderHeader,
                product = product,
                price = item.price,
                qty = item.qty,
                memo = item.memo
            )
            orderDetailRepository.save(orderDetail)
        }

        val response = ResponseDTO(
            code = 200,
            msg = "주문 등록 성공",
            orderNo = orderHeader.orderNo,
            orderSts = orderHeader.orderSts
        )

        return ResponseEntity.status(HttpStatus.OK).body(response)
    }
  • 주문 수정

@Transactional
    fun update(orderNo: Long, requestDTO: RequestUpdateDTO): ResponseEntity<ResponseDTO> {
        // 주문 마스터
        val orderHeader = orderRepository.findById(orderNo).orElseThrow {
            OrderNotFoundException(orderNo) // 주문 정보가 없을 경우 예외 던지기
        }

        if ("60".equals(orderHeader.orderSts)) {
            val errorRes = ResponseDTO(
                code = 400,
                msg = "배송완료 상태는 수정 할 수 없습니다. [주문번호 : ${orderNo}]",
                orderNo = null,
                orderSts = null
            )

            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorRes)
        }

        if (requestDTO.orderSts > 0 ) {
            // 주문 상태가 유효한 코드인지 확인하고 적용
            val orderSts = OrderSts.values().find { it.code == requestDTO.orderSts } ?: throw ApiException("유효하지 않은 주문 상태 코드입니다. [주문상태 : ${requestDTO.orderSts}]")

            // 주문 마스터 업데이트
            orderHeader.orderSts = orderSts.code // code 값으로 업데이트
            orderRepository.save(orderHeader) // 주문 상태를 업데이트
        }

        // 주문 상세
        val orderDetail = orderDetailRepository.findByOrderNo(orderNo)

        requestDTO.items.forEach { item ->
            val product = productRepository.findById(item.productCd).orElseThrow {
                ProductNotFoundException(item.productCd) // 상품 코드가 없을 경우 예외 던지기
            }

            // 주문 상세 업데이트
            val updateOrderDetail = orderDetail.find { it.product == product }
            if (updateOrderDetail != null) {
                updateOrderDetail.price = item.price
                updateOrderDetail.qty = item.qty
                updateOrderDetail.memo = item.memo
                orderDetailRepository.save(updateOrderDetail) // 업데이트
            }
        }

        // 응답 반환
        val response = ResponseDTO(
            code = 200,
            msg = "주문 수정 성공",
            orderNo = orderNo,
            orderSts = orderHeader.orderSts
        )

        return ResponseEntity.status(HttpStatus.OK).body(response)
    }
  • 주문 삭제

 @Transactional
    fun delete(orderNo: Long): ResponseEntity<ResponseDTO> {
        val orderHeader = orderRepository.findById(orderNo).orElseThrow {
            OrderNotFoundException(orderNo) // 주문 정보가 없을 경우 예외 던지기
        }

        val orderSts = orderHeader.orderSts
        if ("60".equals(orderSts)) {
            val errorRes = ResponseDTO(
                code = 400,
                msg = "배송완료 상태는 삭제 할 수 없습니다. [주문번호 : ${orderNo}]",
                orderNo = null,
                orderSts = null
            )

            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorRes)
        }

        // 주문 마스터
        orderHeader.delYn = "Y"
        orderRepository.save(orderHeader)

        // 주문 상세
        val orderDetailList = orderDetailRepository.findByOrderNo(orderNo)
        orderDetailList.forEach { it.delYn = "Y" } // delYn 필드 값을 "Y"로 변경
        orderDetailRepository.saveAll(orderDetailList) // 변경된 리스트를 저장


        val response = ResponseDTO(
            code = 200,
            msg = "주문 삭제 성공",
            orderNo = orderNo,
            orderSts = null
        )
        return ResponseEntity.status(HttpStatus.OK).body(response)
    }

2.3. 느낀 점

조회 API 만들기 미션은 제출하지 못했고 삽입, 수정, 삭제 API 만들기 미션은 겨우 제출하였다.

생각보다 내가 원하는 기능은 구현하는게 빠르게 되지 않아서 많이 검색해보았다.

개발하고 나서 사용하지 않는 테이블과 컬럼들을 정리하였다. 초기 ERD와 좀 다르게 되어서 ERD도 다시 수정하였다.

출처

채널톡 아이콘