김영한 님의 스프링 DB 2편 - 데이터 접근 활용 기술 강의를 보고 작성한 내용입니다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-2/dashboard
6번 게시글의 3-2번에 있는 사진인데 ItemService를 변경하지 않고 ItemRepository의 구현체를 변경할 수 있도록 하기 위해 중간에 어댑터 역할을 하는 구현체를 추가했다
이로 인해 DI, OCP 원칙은 지켜지게 되었지만 구조가 복잡해졌고, 어댑터 코드와 실제 코드까지 함께 유지보수 해야 하는 문제가 발생
이전처럼 어댑터 역할을 하는 구현체를 추가하지 않고 ItemService에서 직접 SpringDataJpaItemRepository 를 사용
itemService
➜ SpringDataJpaItemRepository(프록시 객체)
DI, OCP 원칙을 포기하는 대신 복잡한 어댑터를 제거하고 구조를 단순하게 가져갈 수 있는데 이것이 트레이드 오프이다
위의 상황에서 발생하는 트레이드 오프는 구조의 안정성과 개발의 편리성 사이의 선택이다
추상화와 인터페이스도 비용이 들기 때문에 무조건 추상화가 좋은 것은 아니다
여기서 비용이란 직접 코드를 작성하거나 어떤 구현체를 사용했는지 직접 살펴봐야 하는 것을 말한다
이런 추상화 비용을 넘어설 만큼 효과가 있을 때만 추상화를 도입하는 것이 실용적이다
ItemRepositoryV2
는 Spring Data JPA 의 기능을 제공
ItemQueryRepositoryV2
는 QueryDSL 을 사용해서 복잡한 쿼리 기능을 제공
ItemServie 에서 단순 조회의 경우 Spring Data JPA 를 사용하도록 하고 복잡한 쿼리의 경우 QueryDSL을 사용하도록 분리
@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 List<Item> findItems(ItemSearchCond cond) {
return itemQueryRepositoryV2.findAll(cond);
}
}
save(), update(), findById() 는 Spring Data JPA 사용
findItems() 는 QueryDSL 을 사용
JPA, Spring Data JPA, QueryDSL 은 모두 JPA 기술을 사용하기 때문에 스프링부트는 자동으로 JpaTransactionManager
를 스프링 빈으로 등록
JdbcTemplate, MyBatis 같은 기술들은 내부에서 JDBC 를 직접 사용하기 때문에 DataSourceTransactionManager
를 사용
JPA 와 JdbcTemplate 을 함께 사용하면 트랜잭션 매니저를 하나로 묶어야 하는데 이 때 JpaTransactionManager
를 사용하면 된다
JPA도 내부에서 DataSource와 JDBC 커넥션을 사용하기 때문에 JpaTransactionManager
는 DataSourceTransactionManager
가 제공하는 기능도 대부분 제공한다
그러므로 JpaTransactionManager
만 스프링 빈에 등록하면 JPA, JdbcTemplate, MyBatis 모두 하나의 트랜잭션으로 묶어서 사용할 수 있다