TIL (Today I Learned)
[Spring] Spring Data JPA에서 @Repository를 사용하지 않는 이유
기만나🐸
2025. 2. 9. 17:16
spring data jpa로 프로젝트를 구현할때, Repository 클래스에 Repository 어노테이션을 사용하지 않는 이유가 궁금해져서 알아보았다.
spring jdbc로 구현할 때는 @Repository를 썼었는데, JPA에서는 Repository 클래스에 @Repository를 사용하지 않아도 되는 이유가 뭘까?
Spring JDBC vs Spring Data JPA
Spring JDBC | Spring Data JPA | |
레포지터리 | `JdbcTemplate`을 이용하여 직접 SQL 작성 | `JpaRepository` 또는 `CrudRepository`를 상속하여 자동으로 구현 |
@Repository 필요 여부 | 명시적으로 `@Repository`를 선언해야 스프링 빈(Bean)으로 등록됨 | Spring이 자동으로 빈(Bean) 등록 (@Repository를 명시해도 문제는 없음!) |
예외 변환 (AOP 적용 여부) |
`@Repository`를 선언해야 Spring의 예외 변환(AOP)이 적용됨 | 자동으로 예외 변환 지원 |
Spring Data JPA의 Repository
Spring Data JPA에서 JpaRepository를 상속받는 인터페이스는 Spring Boot가 자동으로 구현체를 생성해준다.
그래서 굳이 @Repository를 명시할 필요 없이 자동으로 빈으로 등록된다.
예시: 일정관리 API의 Repository
import com.example.schedule.entity.Schedule;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ScheduleRepository extends JpaRepository<Schedule, Long> {
}
Spring Data JPA의 예외 변환 자동화(AOP)
Spring Data JPA는 @Repository 없이도 자동으로 예외 변환을 수행한다.
JPA 구현체(Hibernate 등)에서 발생하는 기본 예외(RuntimeException) 를 Spring의 일관된 데이터 접근 계층 예외(DataAccessException) 로 변환하여 처리한다.
예시: 일정 조회 API의 예외 발생 orElseThrow
@Service
@RequiredArgsConstructor
public class ScheduleService {
private final ScheduleRepository scheduleRepository;
public Schedule getSchedule(Long id) {
return scheduleRepository.findById(id)
.orElseThrow(() -> new RuntimeException("존재하지 않는 아이디입니다."));
}
}
Spring이 자동으로 예외를 변환하는 과정
- Spring이 @Repository 빈을 감싸는 프록시(proxy)를 생성
- Repository 메서드를 실행할 때 AOP가 적용된 프록시가 먼저 실행됨
- JPA 예외가 발생하면 AOP가 예외를 감지하고, Spring의 DataAccessException으로 변환
- 서비스(Service) 계층에서는 변환된 Spring 예외를 받아서 처리 가능
결론
1️⃣ Spring Data JPA는 JpaRepository를 상속받으면 자동으로 빈으로 등록됨
2️⃣ @Repository 없이도 Spring이 예외 변환(AOP) 기능을 자동 지원
3️⃣ Spring JDBC에서는 @Repository가 필요했지만, JPA에서는 생략 가능
4️⃣ 필요하면 @Repository를 추가해도 무방하지만 일반적으로 불필요함 🎯