📚 개발백과

[Spring Data JPA] 서비스 레이어의 어느 메서드에 @Transactional을 안붙이면?

the0 2025. 6. 27. 01:38
728x90

Spring 3.x, Spring Data JPA(+ Hibernate) 를 쓰는 환경이다.

 

예시 코드 설명:

  • exampleService 클래스의 한 메서드인 example() 이다.
  • example()은 authUser 를 인자값으로 받아 이를 userRepository에 Read로 접근한다.
public exampleResponse example(AuthUser authUser) {
    User user = userRepository.findByOauthId(authUser.getOauthId())
            .orElseThrow(() -> new BusinessExceptionHandler("유저가 존재하지 않습니다.", ErrorCode.NOT_FOUND_ERROR));
    ...
}

 

 

내가 가진 의문점은 다음과 같다.

DB에 접근하는 코드를 가진 메서드에 @Transactional을 붙이지 않으면
누가, 언제 DB 커넥션을 획득하고 릴리즈하는가?

 

 

 

이전에 내가 알고 있던 사실은 다음과 같다.

@Transactional 어노테이션이 없는 Repository 직접 접근의 경우
각 쿼리( 예: repository.method() ) 호출마다 독립적인 트랜잭션이 생성되고 쿼리 실행이 완료되면 커넥션이 반환된다.

 

 

이 아티클은 위의 내용이 참인지, 그리고 어떻게 동작하는지 알아본다.


 

(위의 코드에 이어서 설명) UserRepository 처럼 개발자가 정의하는 커스텀 Repository 인터페이스는,

 Spring Data JPA가 SimpleJpaRepository를 기반으로 런타임에 동적으로 구현한다.

 

참고

 

SimpleJpaRepository 클래스에는 여러 메서드들이 구현되어 있다.

 

 

메서드 종류는 IDE를 통해서 볼 수도 있고 혹은 공식문서(https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/support/SimpleJpaRepository.html) 가 있다.

예를 들어, 자주 사용하는 save(), findAll(), delete() 등 기본적인 CRUD 메서드들이 있다.

 

 

중요하게 봐야하는 부분은 다음과 같다.

  • SimpleJpaRepository 클래스 레벨에서 @Transactional(readOnly = true) 이 적용되어 있다!
  • 각 메서드 별로 @Transactional 등 적절한 트랙잭션 설정이 되어 있다!
@Repository
@Transactional(readOnly = true) // ✅
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
	
    @Override
	@Transactional // ✅
	public <S extends T> S save(S entity) {

		Assert.notNull(entity, ENTITY_MUST_NOT_BE_NULL);

		if (entityInformation.isNew(entity)) {
			entityManager.persist(entity);
			return entity;
		} else {
			return entityManager.merge(entity);
		}
	}
    
    @Override
	@Transactional // ✅
	public void deleteById(ID id) {

		Assert.notNull(id, ID_MUST_NOT_BE_NULL);

		findById(id).ifPresent(this::delete);
	}

}

 


결론

 

이전에 내가 알고 있던 사실은 사실이 맞다.

@Transactional 어노테이션이 없는 Repository 직접 접근의 경우
각 쿼리( 예: repository.method() ) 호출마다 독립적인 트랜잭션이 생성되고 쿼리 실행이 완료되면 커넥션이 반환된다.

 

 

내가 가진 의문점에 하나씩 대답한다.

DB에 접근하는 코드를 가진 메서드에 @Transactional을 붙이지 않으면 
누가, 언제 DB 커넥션을 획득하고 릴리즈하는가?

 

 

언제 DB 커넥션을 획득하고 릴리즈하는가?

기존에 알고 있었을 트랜잭션 관련 사실: 
@Transactional 이 수행됨에 따라 DB 커넥션을 획득하고, 트랜잭션이 종료됨에 따라 DB 커넥션이 릴리즈된다.

SimpleJpaRepository 클래스 내에 각 CRUD 메서드들은 @Transactional 이 적용되어 있다.

예를 들어 Service layer의 어느 메서드 내에 customRepository.save() 를 한다.
이 save() 메서드는 내부적으로 @Transactional이 적용되어 트랜잭션 수행된다.
@Transactional이 수행됨에 따라 DB 커넥션을 획득하고, 종료됨에 따라 커넥션이 릴리즈된다.

 

누가 DB 커넥션을 획득하고 릴리즈하는가?

JpaTransactionManager에 의해 entityManagerFactory로부터 엔티티 매니저가 생성된다. 
각 엔티티 매니저는 커넥션 풀에 있는 한 커넥션을 점유해 DB에 접근한다.
이후 엔티티 매니저가 커넥션을 릴리즈한다.
(일반 개념. 이 아티클 주제인 `@Transactional을 서비스 레이어 메서드에 붙/안붙 차이` 와는 직접 관련X. )
728x90