스프링 DB 2 정리 - 8. 데이터 접근 기술 - 활용 방안 (22.8.30)

피아노과 개발자도전?·2022년 8월 30일
0

Today I learned

목록 보기
49/75
post-thumbnail

김영한 개발자님의 스프링 DB 2편 강의를 수강하고 중요한 내용을 정리했습니다.

8.1. 스프링 데이터 JPA 예제와 트레이드 오프

지난 시간에 했던 스프링 데이터 JPA 예제를 다시 돌아보자.

중간에서 JpaItemRepositoryV2 가 어댑터 역할을 해준 덕분에 ItemService 가 사용하는 ItemRepository 인터페이스를 그대로 유지할 수 있고 클라이언트인 ItemService 의 코드를 변경하지 않아도 되는 장점이 있다.

하지만 구조를 맞추기 위해서, 중간에 어댑터가 들어가면서 전체 구조가 너무 복잡해지고 사용하는 클래스도 많아지는 단점이 생겼다. 유지보수를 할 때 어댑터 코드와 실제 코드까지 함께 해야 하는 어려움도 발생한다.

다른 선택

여기서 ItemService 코드를 일부 고쳐서 직접 스프링 데이터 JPA를 사용하는 선택을 할 수도 있다.

DI, OCP 원칙을 포기하는 대신에, 복잡한 어댑터를 제거하고, 구조를 단순하게 가져갈 수 있는 장점이 있다.

트레이드 오프

DI, OCP를 지키기 위해 어댑터를 도입하고, 더 많은 코드를 유지한다. 어댑터를 제거하고 구조를 단순하게 가져가지만, DI, OCP를 포기하고, ItemService 코드를 직접 변경한다.

개발을 할 때는 항상 자원이 무한한 것이 아니다. 그리고 어설픈 추상화는 오히려 독이 되는 경우도 많다. 무엇보다 추상화도 비용이 든다. 인터페이스도 비용이 든다. 이 추상화 비용을 넘어설 만큼 효과가 있을 때 추상화를 도입하는 것이 실용적이다.

그러므로 현재 상황에 맞는 선택을 하는게 좋다.


8.2. 실용적인 구조

스프링 데이터 JPA의 기능은 최대한 살리면서, Querydsl도 편리하게 사용할 수 있는 구조

기본 CRUD와 단순 조회는 스프링 데이터 JPA가 담당하고, 복잡한 조회 쿼리는 Querydsl이 담당한다.

데이터 접근 기술 적용의 최종본이니 코드를 한번 읽어보자.

ItemRepositoryV2

public interface ItemRepositoryV2 extends JpaRepository<Item, Long> {}

ItemQueryRepositoryV2

import static hello.itemservice.domain.QItem.item;
@Repository
public class ItemQueryRepositoryV2 {
 	private final JPAQueryFactory query;
    
 	public ItemQueryRepositoryV2(EntityManager em) {
 		this.query = new JPAQueryFactory(em);
 	}
 public List<Item> findAll(ItemSearchCond cond) {
 	return query.select(item)
 		.from(item)
 		.where(
 			maxPrice(cond.getMaxPrice()),
 			likeItemName(cond.getItemName()))
 		.fetch();
 }
 
 	private BooleanExpression likeItemName(String itemName) {
 		if (StringUtils.hasText(itemName)) {
 			return item.itemName.like("%" + itemName + "%");
 		}
 		return null;
 	}
    
 	private BooleanExpression maxPrice(Integer maxPrice) {
 		if (maxPrice != null) {
 		return item.price.loe(maxPrice);
 		}
 	return null;
 	}
}

ItemServiceV2

@Service
@RequiredArgsConstructor
@Transactional
public class ItemServiceV2 implements ItemService {
 	private final ItemRepositoryV2 itemRepositoryV2;
 	private final ItemQueryRepositoryV2 itemQueryRepositoryV2;
 
 	@Override
 	public Item save(Item item) {
 		return itemRepositoryV2.save(item);
 	}
    
 	@Override
 	public void update(Long itemId, ItemUpdateDto updateParam) {
 		Item findItem = findById(itemId).orElseThrow();
 		
        findItem.setItemName(updateParam.getItemName());
 		findItem.setPrice(updateParam.getPrice());
 		findItem.setQuantity(updateParam.getQuantity());
 	}
    
 	@Override
 		public Optional<Item> findById(Long id) {
 		return itemRepositoryV2.findById(id);
 	}
    
 	@Override
 		public List<Item> findItems(ItemSearchCond cond) {
 		return itemQueryRepositoryV2.findAll(cond);
 	}
}

8.3. 다양한 데이터 접근 기술 조합

어떤 데이터 접근 기술을 선택하는 것이 좋을까? 비즈니스 상황과, 현재 프로젝트 구성원의 역량에 따라서 결정해야한다.

JdbcTemplate 이나 MyBatis 같은 기술들은 SQL을 직접 작성해야 하는 단점은 있지만 기술이 단순하기 때문에 SQL에 익숙한 개발자라면 금방 적응할 수 있다.

JPA, 스프링 데이터 JPA, Querydsl 같은 기술들은 개발 생산성을 혁신할 수 있지만, 학습 곡선이 높기 때문에, 이런 부분을 감안해야 한다. 그리고 매우 복잡한 통계 쿼리를 주로 작성하는 경우에는 잘 맞지 않는다.

김영한 개발자님은 JPA, 스프링 데이터 JPA, Querydsl을 기본으로 사용하고, 만약 복잡한 쿼리를 써야 하는데, 해결이 잘 안되면 해당 부분에는 JdbcTemplate이나 MyBatis를 함께 사용하는 것을 추천하신다.

트랜잭션 매니저 선택

JpaTransactionManagerDataSourceTransactionManager 가 제공하는 기능도 대부분 제공한다. JPA라는 기술도 결국 내부에서는 DataSource와 JDBC 커넥션을 사용하기 때문이다.

결과적으로 JpaTransactionManager 를 하나만 스프링 빈에 등록하면, JPA, JdbcTemplate, MyBatis 모두를 하나의 트랜잭션으로 묶어서 사용할 수 있다.

profile
공부한 내용 정리

0개의 댓글