레포지토리는 내부에서 @Component를 통해 컴포넌트 스캔 대상으로 등록한다.
지난번에 Controller와 Service 계층을 비교했을 때 Service 어노테이션엔 아무런 기능이 없다고 해서 Repository도 이와 같지 않을까 했다. 그러나 차이점이 있었다.
컴포넌트 스캔과 더불어 기능을 더 수행하는데 대표적인게 바로 예외처리 부분이다.
보통 데이터베이스 예외는 SqlException
이 발생하는데, @Repository
가 붙은 클래스에서 터지는 SqlException
은 스프링 계층의 DataAccessException
으로 래핑되어 반환된다.
여기서 스프링의 주요 철학 중 하나인 AOP가 등장하는데 이러한 예외처리도 AOP의 일종이기 때문이다
Aspect Oriented Programming
스프링의 주요 구성 요소인 AOP를 찍먹해보자.
자주 반복되는 공통 기능을 한 곳에서 정의하고 다른 필요한 부분에 자동으로 삽입하게 도와주는 기능이다.
자주 사용하는 공통 기능을 모듈화시키는 기술이다.
Aspect Oriented Programming with Spring :: Spring Framework
Repository는 예외가 터지면 AOP에 등록된 예외 변환기(PersistenceExceptionTranslationPostProcessor)를 사용해서 이를 스프링 계층 예외(DataAccessException)로 래핑한다.
이에 따라 원시적인 예외가 아닌 스프링 단계에서의 예외를 처리할 수 있게 된다.
앞서 말했듯 SQLException을 DataAccessException으로 변환한다.
만약에 여러가지 JdbcTemplate을 한꺼번에 쓰고 있다면 어떻게 될까? 여러 분기에 대해 개발자가 모두 처리해야 하므로 번거롭다.
try {
repository.save(...);
} catch (SQLException e) {
// JDBC
} catch (PersistenceException e) {
// JPA
} catch (HibernateException e) {
// Hibernate
}
이걸 DataAccessException 계층으로 추상화하면 개발자는 스프링 예외만 캐치하면 된다.
try {
service.save();
} catch (DataAccessException e) {
log.error("오류 발생", e);
}
스프링 내부에서 DataAccessException 계열의 예외 발생 시 자동 롤백이 진행된다고 한다. 트랜잭션에 대한 내용은 다음에 알아보자.