✅ 개요
팀 프로젝트 진행 중 한 팀원분이 `autoCommit: false` 설정을 언급해 주셨습니다. 이에 대한 내용을 전혀 모르고 있다가 다른 글들을 보니 이 설정 하나로 성능 최적화를 할 수 있었다고 해서 꽤 흥미로운 내용인 것 같아 제가 이해한 내용을 정리해보려고 합니다.
✅ autoCommit=false 설정
스프링 부트에서는 다음과 같이 설정 파일로 간단하게 autoCommit을 설정할 수 있습니다.
spring:
datasource:
hikari:
auto-commit: false
그렇다면 이 설정 하나로 어떻게 성능 최적화가 가능한지 디버깅해 보았습니다.
1️⃣ LogicalConnectionManagedImpl - begin()
먼저 직접 설정하거나 또는 `JpaRepository` 내부적으로 `@Transactional`이 설정되어 있다면 이 클래스에서 트랜잭션을 시작하는 것 같습니다. `auto-commit: false`로 설정하면 `providerDisablesAutoCommit`이 true를 반환하게 되어 결국 `initiallyAutoCommit`는 false로 트랜잭션을 시작합니다.

2️⃣ AbstractLogicalConnectionImplementor - begin()
1️⃣에서 `super.begin()`을 호출하여 부모 클래스로 왔습니다. 이 부분이 중요한 것 같습니다.

코드를 보면 if문을 통과하면 `setAutoCommit(false)` 실행하는 것을 확인할 수 있었습니다. if문의 조건은 1️⃣에서 보았던 메서드를 실행하여 true를 반환합니다. 즉 if문을 실행하지 않습니다.
여기서 "`setAutoCommit(false)`가 그렇게 오래 걸리는 작업인가?"라는 의문이 들었습니다. 그래서 `auto-commit`을 true로 설정해 보고(기본값) if문 내부를 따라가 봤습니다.

코드가 너무 길어서 잘랐습니다. 정확히 어떤 식으로 `setAutoCommit` 쿼리를 실행하는지는 모르겠지만 내부적으로 락 동기화가 구현되어 있었습니다. 아마 여러 쿼리들이 쌓이고 쌓이다 보면 이 부분에서 오버헤드가 발생할 것 같습니다.
3️⃣ AbstractLogicalConnectionImplementor - resetConnection()
트랜잭션이 걸려있는 커넥션을 사용하고 다시 풀에 반납하기 전에 `autoCommit` 모드를 다시 true로 설정하는 로직 같습니다. 하지만 여기서도 if문을 통과해야 실행하는 것을 확인할 수 있습니다.

1️⃣에서 `initiallyAutoCommit`이 false로 설정되었기 때문에 if문을 실행하지 않습니다. 여기서도 마찬가지로 `setAutoCommit(true)`를 실행한다면 락 동기화로 인한 오버헤드가 발생할 수 있을 것입니다.
💡 trace 로그를 확인하고 싶다면 다음 설정을 추가하면 됩니다.
logging: level: org.hibernate:.resource.jdbc.internal: trace
📌 정리
대규모 서비스를 운영해 본 적이 없기에 체감되는 성능 이점은 느끼지 못했습니다. 하지만 디버깅해보며 어떤 포인트에서 최적화가 가능한지 확인할 수 있었습니다. 또한 직접적인 성능 최적화는 이미 다른 글들에서 충분히 검증이 된 것 같기 때문에 JPA를 사용한다면 고려해 봐도 좋은 설정이라고 생각합니다.
같은 고민을 하고 계시는 다른 분들에게 조금이나마 도움이 되었으면 좋겠고, 더 좋은 의견 주시면 감사하겠습니다.
🔖 참고
https://pkgonan.github.io/2019/01/hibrnate-autocommit-tuning