공통 인터페이스 기능
- 김영한님의 실전! 스프링 데이터 JPA 강의를 기반으로 순수 JPA 구현 시 발생하는 반복적인 CRUD 코드를 스프링 데이터 JPA의
JpaRepository공통 인터페이스를 통해 어떻게 자동화하고 재사용할 수 있는지, 그 내부 원리와 계층 구조를 정리함
순수 JPA 기반 리포지토리
회원 리포지토리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Repository
public class MemberJpaRepository {
@PersistenceContext
private EntityManager em;
public Member save(Member member) {
em.persist(member);
return member;
}
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
}
팀 리포지토리
1
2
3
4
5
6
7
8
9
10
11
12
@Repository
public class TeamJpaRepository {
@PersistenceContext
private EntityManager em;
public Team save(Team team) {
em.persist(team);
return team;
}
}
- 회원과 팀 리포지토리의 구조가 엔티티 타입만 다를 뿐 거의 동일함
- 스프링 데이터 JPA는 이러한 반복적인 코드를 공통 인터페이스를 통해 획기적으로 제거해 줌
순수 JPA 리포지토리 기본 동작 테스트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@SpringBootTest
@Transactional
public class MemberJpaRepositoryTest {
@Autowired MemberJpaRepository memberJpaRepository;
@Test
public void testMember() {
Member member = new Member("memberA");
Member savedMember = memberJpaRepository.save(member);
Member findMember = memberJpaRepository.find(savedMember.getId());
assertThat(findMember).isEqualTo(member); // JPA 엔티티 동일성 보장
}
}
공통 인터페이스 설정
- 스프링 부트를 사용하면
@SpringBootApplication이 위치한 패키지와 그 하위 패키지를 자동으로 스캔하여 인터페이스를 인식하므로, 대부분 별도 설정이 불필요함 -
패키지 위치가 기준과 다를 경우에만 아래와 같은 설정을 명시적으로 추가함
1 2 3 4
// 스프링 부트 미사용 시 또는 패키지 위치가 다를 때만 필요 @Configuration @EnableJpaRepositories(basePackages = "jpabook.jpashop.repository") public class AppConfig {}
-
스프링 데이터 JPA 동작 원리

공통 인터페이스 적용
스프링 데이터 JPA 기반 MemberRepository
1
2
3
// 인터페이스 선언만으로 CRUD 메서드가 완성됨
public interface MemberRepository extends JpaRepository<Member, Long> {
}
스프링 데이터 JPA 기반 TeamRepository
1
2
public interface TeamRepository extends JpaRepository<Team, Long> {
}
스프링 데이터 JPA 테스트
- 순수 JPA 테스트와 코드는 완벽하게 동일하게 유지되면서 리포지토리 의존성만 변경됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootTest
@Transactional
public class MemberRepositoryTest {
@Autowired MemberRepository memberRepository; // 주입되는 의존성만 다름
@Test
public void testMember() {
Member member = new Member("memberA");
Member savedMember = memberRepository.save(member);
Member findMember = memberRepository.findById(savedMember.getId()).get();
Assertions.assertThat(findMember).isEqualTo(member); // JPA 엔티티 동일성 보장
}
}
공통 인터페이스 계층 구조

주요 메서드 정리
| 메서드 | 내부 동작 | 설명 |
|---|---|---|
save(S) |
em.persist() 또는 em.merge() |
새 엔티티는 저장, 이미 존재하는 엔티티는 병합 |
delete(T) |
em.remove() |
엔티티 삭제 |
findById(ID) |
em.find() |
엔티티 단건 조회, Optional 반환 |
getReferenceById(ID) |
em.getReference() |
프록시로 조회 (구 getOne() 대체) |
findAll(...) |
JPQL | 전체 조회, Sort/Pageable 파라미터 가능 |
count() |
JPQL count | 전체 카운트 |
existsById(ID) |
- | 존재 여부 확인 (구 exists(ID) 대체) |
- 제네릭 타입 매핑
T- 엔티티 타입
ID- 엔티티 식별자 타입 (Primary Key)
S- 엔티티와 그 자식 타입
순수 JPA와 스프링 데이터 JPA 비교

연습 문제
-
순수 JPA 리포지토리 구현과 비교했을 때, Spring Data JPA 사용의 주요 장점은 무엇일까요?
a. 기본적인 CRUD 작업을 위한 구현 코드를 직접 작성할 필요가 없음
- Spring Data JPA는
JpaRepository와 같은 공통 인터페이스를 상속받는 것만으로도 저장, 조회 등 기본 CRUD 메서드 구현체를 자동으로 제공해 개발자의 코드 작성 부담을 줄여줌
- Spring Data JPA는
-
Spring Data JPA는
JpaRepository를 상속받은 인터페이스만으로 리포지토리 기능을 사용할 수 있게 하는 내부 메커니즘은 무엇인가요?a. Spring Data JPA가 애플리케이션 로딩 시점에 프록시 기반의 구현체를 동적으로 만들어 주입함
- Spring Data JPA는 개발자가 정의한 리포지토리 인터페이스를 인식하고, 런타임에 해당 인터페이스의 실제 동작을 수행하는 프록시(Proxy) 객체를 생성하여 Spring 빈으로 등록함
-
Spring Data 인터페이스 계층 구조(
Repository->CrudRepository->PagingAndSortingRepository->JpaRepository)에서 기본적인 CRUD 작업을 위한 메서드들을 정의하고 있는 인터페이스는 무엇인가요?a. CrudRepository
CrudRepository는 엔티티의 저장(save), 단건 조회(findById), 전체 조회(findAll), 삭제(delete) 등 가장 기본적인 데이터 조작 기능을 추상화한 인터페이스임
-
Spring Data JPA에서
JpaRepository<Entity, ID>인터페이스를 상속받는 리포지토리를 사용할 때, 개발자가 직접 해야 하는 작업은 무엇인가요?a. 엔티티 클래스와 ID 타입을 지정하여 인터페이스만 정의하면 됨
- Spring Data JPA의 가장 큰 장점은 개발자가
JpaRepository<T, ID>를 상속받는 인터페이스만 정의하면, Spring Data JPA가 엔티티 T와 ID 타입 ID를 바탕으로 필요한 기본 구현체를 자동으로 제공한다는 것임
- Spring Data JPA의 가장 큰 장점은 개발자가
-
페이징(
Pageable) 및 정렬(Sort) 기능과 같이 특정 데이터 접근 기술(JPA, MongoDB 등)에 종속되지 않고 여러 기술에서 공통적으로 사용되는 기능은 Spring Data 프로젝트의 어느 모듈에서 제공될까요?a. Spring Data Commons
- Spring Data 프로젝트는 여러 모듈을 지원하며, 기술 간에 공통적으로 사용되는 인터페이스나 기능은
Spring Data Commons모듈에서 관리됨 - Spring Data JPA는 이를 상속받아 JPA 특화 기능만을 추가함
- Spring Data 프로젝트는 여러 모듈을 지원하며, 기술 간에 공통적으로 사용되는 인터페이스나 기능은
요약 정리
- 순수 JPA에서는 엔티티마다
EntityManager를 주입받아 CRUD 로직을 반복 작성해야 하지만, 스프링 데이터 JPA는JpaRepository를 상속하는 인터페이스 선언만으로 프록시 기반의 CRUD 구현체를 자동으로 주입해 줌 - 데이터 저장 기술에 구애받지 않는 핵심 공통 기능(페이징, 정렬 등)은
Spring Data Commons의CrudRepository와PagingAndSortingRepository에서 제공하며,JpaRepository는 이를 상속받아 JPA에 특화된 메서드(flush(),getReferenceById()등)를 별도로 추가 제공함