TIL

3_2.리팩토링 사례 실습

꿀승 2025. 1. 13. 14:30
728x90
반응형
SMALL

학습내용

  1. 리팩토링
  2. 실습

학습정리

1. 리팩토링

  • 정의

    • 기존 애플리케이션의 기능적인 동작을 유지하면서, 코드의 구조를 체계적으로 개선하는 작업
    • 가독성, 유지보수성, 확장성을 높이는 작업
  • 주요 기법

    • 메서드 추출 : 긴 메서드에서 관련 있는 블록을 별도의 메서드로 추출

      @Transactional
      public Boolean create(OrderRequest request) {
        try {
            //order 저장 별도의 메서드로 추출
            Order order = save(request.getUserId(), request.getShoppingAddress());
            //orderItems 저장 별도의 메서드로 추출
            List<OrderItem> orderItems = orderProcessService.saveOrderItems(order, request.getOrderProducts());
      
            //총합 금액 설정 별도의 메서드로 추출
            BigDecimal totalPrice = orderProcessService.getOrderTotalPrice(orderItems);
            order.setTotalPrice(totalPrice);
            orderRepository.save(order);
      
            return true;
        } catch (ServiceException e){
          log.error("주문 처리 중 서비스 예외 발생 : {}", e.getMessage(),e);
          throw e;
        } catch (Exception e){
          log.error("주문 처리 중 시스템 예외 발생 : {}", e.getMessage(),e);
          throw new RuntimeException("주문 처리 중 문제가 발생했습니다.", e);
        }
      }
    • 클래스 분리 : 하나의 클래스가 너무 많은 책임을 가지는 경우, 역할에 따라 분리

      @Service
      @RequiredArgsConstructor
      public class OrderService {
        //orderProcessService 로 분리
        private final OrderProcessService orderProcessService;
      
        private final OrderRepository orderRepository;
        private final UserRepository userRepository;
      
        @Transactional
        public Order order(OrderRequest request) {
            ...생략
            //역할 분리로 OrderProcessService와 OrderService 분리
            //OrderProcessService를 주입받아 사용
            Order order = save(...);    
            OrderItems orderItems = orderProcessService.createOrderItems(..)
            orderProcessService.validateStock(..)
        }
      
        public Order save(Long userId) {
            ...
        }
      }
      
      @Service
      @RequiredArgsConstructor
      public class OrderProcessService {
      
        private final OrderItemRepository orderItemRepository;
        private final ProductRepository productRepository;
      
        public List<OrderItem> createOrderItems(OrderRequest request, Order order){
              ...
        }
      
        public BigDecimal calculateTotalPrice(List<OrderItem> orderItems) {
          ...
        }
        //해당 OrderProcessService에서만 사용되는 메서드는 private 
        private void validateStock(OrderProductRequest orderProduct, Product product) {
            ...
        }
      
        private OrderItem buildOrderItem(Order order, Product product, OrderProductRequest orderProduct) {
            ...
        }
      }
      
    • 중복 코드 제거 : 여러 곳에서 반복되는 코드는 공통 메서드로 추출

      public Order save(Long userId) {
        User orderUser = getUser(userId);
      
        ...
      }
      
      public void cancelOrder(Long userId, Long orderId) {
        User orderUser = getUser(userId);
      
        ...
      }
      //중복되는 코드 공통 메서드로 추출
      private User getUser(Long userId) {
        return userRepository.findById(userId)
            .orElseThrow(() -> new ServiceException(ServiceExceptionCode.NOT_FOUND_USER));
      }
      
    • 상태와 행위 분리 : 엔티티와 비즈니스 로직을 분리하여 설계

      //기존 분리전
      @Entity
      ...생략
      public class Product{
          ...생략
      
          public void update(String name,String description){
              this.name = name;
              this.description = description;
          }
      }
      //분리 후
      //ProductProcessor(Service) 클래스 
      private Product updateProduct(Long id, ProductRequest request) {
          //공통 메서드로 추출한 getProduct, getCategory
          Product product = getProduct(id);
          Category category = getCategory(request.getCategoryId());
          //해당 엔티티 필드 setter를 이용하여 
          product.setName(request.getName());
          product.setCategory(category);
      
          return productRepository.save(product);
      }
      

추가적으로..

리팩토링의 중요성을 알고는 있었지만, 실천하기가 어려웠는데
이번 강의와 실습을 통해서 유용하게 리팩토링하는 방법도 배워서 좋았다.

마지막에 상태와 행위 분리부분에서 배운 내용은 계속해서 고민이 있던 부분였는데
처리 방법을 하나 배운 것 같아서 뜻 깊은 시간였습니다.

아직까지 리팩토링의 기준점이 잘 잡히지는 않았지만
많은 연습을 통해서 나의 확실한 기준을 잡아야 할 것 같다.

728x90
반응형
LIST

'TIL' 카테고리의 다른 글

3_4.API테스트 작성 연습  (0) 2025.01.13
3_3.클린코드 원칙 이해  (0) 2025.01.13
3_1.Spring AOP를 활용한 로깅 및 예외 처리  (0) 2025.01.10
2_5.QueryDSL 활용  (0) 2025.01.10
2_4.QueryDSL 설정 및 활용  (0) 2025.01.10