15. Service → JPA / MyBatis 분기
서비스 계층에 들어오면, 이제 데이터 접근 방식은 애플리케이션의 선택에 따라 갈립니다. 이 페이지는 Spring Data JPA 경로와 MyBatis 경로가 어디서 갈라지는지를 오픈소스 구현 기준으로 정리하는 개요 페이지입니다.
이번 단계의 역할
서비스는 자신이 호출할 저장소 추상화만 알면 됩니다.
하지만 실제 구현은 JPA라면 SimpleJpaRepository, MyBatis라면 MapperProxy와 SqlSessionTemplate이 뒤에서 동작합니다.
호출 흐름 요약
- 서비스 메서드가 데이터 조회/저장을 위해 저장소를 호출합니다.
- JPA를 쓰면 Spring Data JPA 구현체가
EntityManager로 위임합니다. - MyBatis를 쓰면 Mapper 프록시가
SqlSession으로 위임합니다. - 두 경로는 결국 DB에 도달하지만, 중간 계층과 결과 매핑 방식은 다릅니다.
호출 흐름 다이어그램
핵심 코드
1) JPA 쪽 진입점
// SimpleJpaRepository.java
public SimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
this.entityManager = entityManager;
}
public Optional<T> findById(ID id) {
return Optional.ofNullable(entityManager.find(domainType, id));
}
2) MyBatis 쪽 진입점
// MapperProxy.java
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
}
// MapperMethod.java
public Object execute(SqlSession sqlSession, Object[] args) {
Object param = method.convertArgsToSqlCommandParam(args);
return sqlSession.selectOne(command.getName(), param);
}
두 경로 모두 서비스는 단순 메서드 호출만 하지만, 뒤에서 연결되는 구현은 완전히 다릅니다.
코드 해설
1) 서비스는 추상화만 보고 호출합니다
서비스는 보통 Repository 인터페이스나 Mapper 인터페이스를 주입받아 호출합니다.
오픈소스 기준으로 JPA는 SimpleJpaRepository, MyBatis는 MapperProxy가 실제 진입 구현체입니다.
2) 분기 이후에는 데이터 접근 모델이 달라집니다
JPA는 EntityManager를 중심으로 영속성 컨텍스트와 엔티티 매핑이 붙고,
MyBatis는 SqlSession과 StatementHandler, ResultSetHandler를 중심으로 SQL과 결과 매핑이 진행됩니다.
설계 의도
1) 서비스가 데이터 접근 구현체에 직접 묶이지 않게 하기 위해
서비스는 “무엇을 조회할지”만 알고, 내부적으로 JPA인지 MyBatis인지 몰라도 됩니다. 이 구조 덕분에 데이터 접근 방식 교체나 혼용이 쉬워집니다.
2) 저장소 패턴과 SQL 매퍼 패턴을 모두 수용하기 위해
Spring 생태계는 객체 중심 접근(JPA)과 SQL 중심 접근(MyBatis)을 모두 지원합니다. 따라서 15번은 하나의 단일 흐름이 아니라 분기점으로 설명하는 것이 맞습니다.
다음 단계 연결
JPA 경로는 15-J1부터, MyBatis 경로는 15-M1부터 이어집니다.
← 이전: 14. Controller → Service: 비즈니스 로직 호출 | 다음: 15-J1. Service → JpaRepository