MyBatis와 Spring Boot 연동 — mybatis-spring-boot-starter
MyBatis를 Spring Boot에서 쓰려면 SqlSessionFactory를 직접 만들어야 할까요?
mybatis-spring-boot-starter를 사용하면 SqlSessionFactory, SqlSessionTemplate, DataSource 설정이 모두 자동으로 구성됩니다. application.yml에 DB 정보만 적으면 바로 쿼리를 실행할 수 있습니다.
개념 정의
mybatis-spring-boot-starter 는 Spring Boot의 Auto Configuration으로 MyBatis를 자동 설정하는 스타터 의존성입니다. DataSource 빈을 감지하면 SqlSessionFactory와 SqlSessionTemplate을 자동으로 생성합니다.
왜 필요한가
- **수동 설정 제거 **: 순수 MyBatis에서는
mybatis-config.xml에 DataSource, TypeHandler, Mapper 경로를 모두 직접 설정합니다. 스타터는 이 과정을 자동화합니다. - **Spring 트랜잭션 통합 **:
@Transactional이 MyBatis의 SqlSession과 자연스럽게 연동됩니다. - **Spring Boot 생태계 활용 **: Actuator, Testcontainers 등 Spring Boot 도구와 바로 호환됩니다.
설정 단계
의존성 추가
<!-- pom.xml -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
이 하나의 의존성이 mybatis, mybatis-spring, spring-boot-starter-jdbc를 모두 포함합니다.
application.yml 설정
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.domain
configuration:
map-underscore-to-camel-case: true
각 설정의 역할을 정리합니다.
| 설정 | 역할 |
|---|---|
mapper-locations | XML Mapper 파일의 경로 패턴 |
type-aliases-package | resultType="User"처럼 풀 패키지 없이 클래스명만 사용 가능 |
map-underscore-to-camel-case | user_name → userName 자동 매핑 |
map-underscore-to-camel-case: true는 거의 필수입니다. 이 설정 없이는 DB의 snake_case 컬럼이 자바의 camelCase 필드에 매핑되지 않습니다.
@Mapper vs @MapperScan
Mapper 인터페이스를 Spring 빈으로 등록하는 두 가지 방법이 있습니다.
@Mapper — 인터페이스마다 개별 등록
@Mapper // ← 이 인터페이스를 Mapper 빈으로 등록
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User findById(Long id);
}
@MapperScan — 패키지 단위로 일괄 등록
@SpringBootApplication
@MapperScan("com.example.mapper") // ← 이 패키지의 모든 인터페이스를 Mapper로 등록
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
| 방식 | 장점 | 단점 |
|---|---|---|
@Mapper | 어떤 인터페이스가 Mapper인지 명확 | 인터페이스마다 붙여야 함 |
@MapperScan | 한 번에 등록, 새 Mapper 추가 시 설정 불필요 | 의도치 않은 인터페이스도 등록될 수 있음 |
소규모 프로젝트에서는 @Mapper로 충분하고, Mapper가 많아지면 @MapperScan이 편리합니다.
트랜잭션 연동
mybatis-spring은 Spring의 PlatformTransactionManager와 통합됩니다. @Transactional을 그대로 사용할 수 있습니다.
@Service
@RequiredArgsConstructor
public class OrderService {
private final OrderMapper orderMapper;
private final PaymentMapper paymentMapper;
@Transactional // ← Spring 트랜잭션
public void createOrder(OrderRequest request) {
orderMapper.insert(request.toOrder());
paymentMapper.insert(request.toPayment());
// 예외 발생 시 두 INSERT 모두 롤백
}
}
이것이 가능한 이유는 SqlSessionTemplate이 Spring의 트랜잭션 동기화 매니저에 연결되기 때문입니다.
@Transactional이 트랜잭션을 시작합니다.SqlSessionTemplate은 현재 트랜잭션에 바인딩된 커넥션을 사용합니다.- 같은 트랜잭션 안의 모든 Mapper 호출이 같은 커넥션을 공유합니다.
- 메서드 종료 시 커밋 또는 롤백됩니다.
Auto Configuration이 하는 일
스타터가 자동으로 생성하는 빈을 정리합니다.
DataSource (spring.datasource 설정 기반)
│
▼
SqlSessionFactory (DataSource + mybatis 설정 조합)
│
▼
SqlSessionTemplate (스레드 안전한 SqlSession 래퍼)
│
▼
Mapper 프록시 빈 (@Mapper 또는 @MapperScan으로 등록)
Spring Boot 없이 동일한 구성을 수동으로 하려면 @Bean 메서드 3~4개를 직접 작성해야 합니다. 스타터가 이 보일러플레이트를 제거합니다.
주의할 점
mapper-locations 경로 실수
# 잘못된 경로: src/main/resources 기준이 아니라 classpath 기준
mybatis:
mapper-locations: mapper/*.xml # ← classpath: 접두어 누락
# 올바른 경로
mybatis:
mapper-locations: classpath:mapper/*.xml
classpath: 접두어를 빠뜨리면 Mapper XML을 찾지 못해 BindingException이 발생합니다. "분명히 XML 파일이 있는데 왜 못 찾지?" 상황의 대부분이 이 원인입니다.
@Mapper와 @MapperScan 중복 사용
둘을 동시에 쓰면 같은 Mapper가 두 번 등록될 수 있습니다. 빈 충돌은 발생하지 않지만 혼란의 원인이 됩니다. 팀에서 하나의 방식으로 통일하는 것이 좋습니다.
MyBatis와 JPA를 함께 쓸 때 트랜잭션 매니저 충돌
같은 프로젝트에서 JPA와 MyBatis를 함께 사용하면 PlatformTransactionManager 빈이 두 개 생길 수 있습니다. JpaTransactionManager는 JDBC도 지원하므로 보통 JPA 트랜잭션 매니저 하나로 통합할 수 있지만, DataSource가 다르면 별도 설정이 필요합니다.
정리
| 항목 | 설명 |
|---|---|
| 스타터 역할 | SqlSessionFactory, SqlSessionTemplate 자동 생성 |
| 핵심 설정 | mapper-locations, type-aliases-package, map-underscore-to-camel-case |
| @Mapper | 인터페이스 개별 등록 |
| @MapperScan | 패키지 단위 일괄 등록 |
| 트랜잭션 | Spring @Transactional 그대로 사용, SqlSessionTemplate이 자동 연동 |
| 주의 사항 | classpath: 접두어 필수, @Mapper와 @MapperScan 중복 피하기 |