앞에서 엔티티를 만들었다면, 이제 남은 질문은 하나다.
“그래서 이 엔티티를 어떻게 저장하고, 어떻게 조회하지?”
그 답이 바로 Repository다.
이번 글에서는 Repository를 “API처럼 쓰는 법”이 아니라, “왜 이 구조를 선택하는지” 중심으로 정리한다.
1. Repository는 왜 인터페이스인가
Spring Data JPA에서 Repository는 구현을 숨기는 계층이다.
public interface UserRepository extends JpaRepository<User, Long> {
}
이 한 줄의 의미는: “User 엔티티를, Long 타입 PK로, JPA 방식으로 저장/조회하겠다”
👉 어떻게 저장하는지는 신경 쓰지 않겠다는 선언이다.
2. Repository 계층 구조를 먼저 본다
Spring Data JPA의 Repository 계층은 이렇게 생겼다.
Repository
↑
CrudRepository
↑
PagingAndSortingRepository
↑
JpaRepository
이걸 외우는 게 목적이 아니라, “왜 보통 JpaRepository를 쓰는지”를 이해하는 게 목적이다.
3. Repository<T, ID> - 최소 계약
Repository<User, Long>
- 마커 인터페이스
- CRUD 메서드 없음
- “이게 Repository다”라는 정체성만 제공
👉 보통 거의 직접 쓰지 않는다.
4. CrudRepository<T, ID> - 기본 CRUD
CrudRepository<User, Long>
얘가 제공하는 것들:
- save()
- findById()
- findAll()
- deleteById()
- count()
👉 기본적인 DB 작업은 여기서 끝난다.
하지만 단점이 있다.
- findAll() 반환 타입이 Iterable
- 정렬, 페이징 없음
5. JpaRepository<T, ID> - 실무 기본값
그래서 대부분 이렇게 쓴다.
JpaRepository<User, Long>
- CrudRepository 포함
- PagingAndSortingRepository 포함
- JPA에 특화된 기능 추가
추가로 제공되는 것들
- findAll(Pageable pageable)
- flush()
- 배치 삭제 메서드
- 정렬/페이징 지원
👉 “JPA + 실전” 기준에서는 거의 기본 선택지다.
JPA 쓴다 → 웬만하면 JpaRepository
6. 쿼리 메서드: 구현 없이 조회하는 이유
Spring Data JPA의 가장 강력한 기능 중 하나다.
List<User> findByEmail(String email);
이 메서드에는:
- SQL 없음
- JPQL 없음
- 구현 클래스 없음
그런데도 동작한다.
왜 되나?
Spring Data JPA가:
- 메서드 이름을 읽고
- findBy + Email 패턴을 해석해서
- 내부적으로 JPQL 생성
- Hibernate가 SQL로 변환
👉 “메서드 이름 = 쿼리 정의” 구조다.
7. 자주 쓰는 쿼리 메서드 규칙
패턴은 생각보다 단순하다.
기본 조회
findByName(String name)
findByEmailAndStatus(String email, Status status)
조건 연산
findByAgeGreaterThan(int age)
findByCreatedAtBetween(LocalDateTime from, LocalDateTime to)
정렬
findByStatusOrderByCreatedAtDesc(Status status)
규칙은 많지만, 자주 쓰는 건 몇 개 안 된다.
복잡해지면 @Query로 넘어가면 된다.
8. 페이징이 왜 중요한가
이런 코드는 잘안쓴다.
List<User> users = userRepository.findAll();
- 데이터는 계속 쌓인다
- 한 번에 다 가져오면:
- 느림
- 메모리 낭비
- 장애 가능성
그래서 페이징은 기본 옵션이다.
9. Pageable - 페이징 감 잡기
Page<User> page = userRepository.findAll(PageRequest.of(0, 10));
이 한 줄의 의미:
- 0번째 페이지
- 페이지당 10건
- 자동으로 limit / offset 적용
Page 객체가 주는 정보
- getContent() → 실제 데이터
- getTotalElements() → 전체 개수
- getTotalPages() → 전체 페이지 수
- hasNext() → 다음 페이지 여부
👉 단순 조회 + 메타 정보를 한 번에 준다.
10. Repository는 “DB 접근 API”다
여기서 중요한 관점 하나.
Repository는 “비즈니스 로직을 담는 곳”이 아니라 “데이터 접근을 캡슐화한 API”다.
그래서:
- 트랜잭션 ❌
- 로직 조합 ❌
- 조건 분기 ❌
그건 전부 Service의 책임이다.
11. 지금 단계에서 기억해야 할 핵심
- JPA 쓰면 보통 JpaRepository 선택
- CRUD 구현은 이미 프레임워크 안에 있다
- 쿼리 메서드는 “이름으로 쿼리 선언”
- 페이징은 옵션이 아니라 기본 설계 요소
- Repository는 DB 접근 전용 계층
12. 한 줄 요약
JpaRepository는 JPA 기반 CRUD·쿼리·페이징을 모두 포함한 기본 선택지이며, Repository는 DB 접근을 추상화한 계층이다.
'백엔드' 카테고리의 다른 글
| [스프링 로드맵] D-2. Validation 응답 설계 - BindingResult vs 예외 처리 (0) | 2026.01.20 |
|---|---|
| [스프링 로드맵] D-1. Validation 기본 - DTO 검증이 필요한 이유 (0) | 2026.01.20 |
| [스프링 로드맵] C-2. 엔티티 설계 - @Entity와 기본 생성자의 의미 (0) | 2026.01.19 |
| [스프링 로드맵] C-1. JPA 큰 그림 - JPA vs Hibernate vs Spring Data JPA (0) | 2026.01.19 |
| [스프링 로드맵] B-3. DI/Bean 실전 - @Autowired, @Qualifier, Profile (0) | 2026.01.19 |