어제 오늘 내일

[Spring Boot/JPA] SQL도, 구현체도 필요 없다! JpaRepository의 마법 (Spring Data JPA) 본문

IT/SpringBoot

[Spring Boot/JPA] SQL도, 구현체도 필요 없다! JpaRepository의 마법 (Spring Data JPA)

hi.anna 2026. 3. 12. 07:23

 

 

지난 포스팅에서 JPA가 SQL을 대신 짜준다고 했죠?
하지만 EntityManager를 직접 다루려면 여전히 코드가 좀 깁니다.

// 순수 JPA 코드 (좀 귀찮음)
public void save(Member member) {
    em.persist(member);
}
public Member findOne(Long id) {
    return em.find(Member.class, id);
}

Spring Data JPA는 이 귀찮음마저 없애줍니다. "인터페이스만 정의하면, 스프링이 알아서 구현체를 만들어준다!" 이것이 핵심입니다.

 


 

1. 인터페이스 하나면 끝! (JpaRepository)

사용법은 너무 간단해서 허무할 정도입니다.
그냥 인터페이스를 하나 만들고 JpaRepository를 상속받으면 됩니다.

public interface MemberRepository extends JpaRepository<Member, Long> {
    // 아무것도 안 적어도 됨!
}
  • <Member, Long>: <엔티티 타입, PK 타입>을 지정합니다.
  • 구현체는요?: 여러분이 안 만듭니다. 스프링 부트가 애플리케이션 시작 시점에 프록시(Proxy) 기술을 써서 가짜 구현체를 뚝딱 만들어서 주입해 줍니다.

 


 

2. 기본 제공 메서드 (CRUD 공짜!)

상속만 받았을 뿐인데, 수십 가지 메서드를 바로 쓸 수 있습니다.

  • save(S entity): 저장 및 수정 (식별자가 없으면 persist, 있으면 merge)
  • delete(T entity): 삭제
  • findById(ID id): 단건 조회 (Optional로 반환되어 Null 처리가 편함!)
  • findAll(): 전체 조회
  • count(): 개수 조회

 


 

3. 이름으로 쿼리 만들기 (Query Methods) ★

이게 진짜 마법입니다. 메서드 이름만 규칙에 맞춰 지으면, 스프링이 이름을 분석해서 JPQL(SQL)을 만들어줍니다.

예시 1: 이름으로 회원 찾기

// select m from Member m where m.username = ?
List<Member> findByUsername(String username);

예시 2: 이름과 나이로 찾기 (AND 조건)

// select m from Member m where m.username = ? and m.age = ?
List<Member> findByUsernameAndAge(String username, int age);

예시 3: 특정 나이보다 많은 사람 찾기 (Greater Than)

// select m from Member m where m.age > ?
List<Member> findByAgeGreaterThan(int age);

규칙: findBy + 속성명 + 조건 (And, Or, Between, LessThan, Like 등등)



 

4. 복잡한 쿼리는요? (@Query)

이름이 너무 길어지거나(예: findByUsernameAndAgeAndAddressAnd...), 조인이 복잡해서 이름만으로 해결이 안 될 때는 @Query 어노테이션으로 직접 JPQL을 작성하면 됩니다.

@Query("select m from Member m where m.username = :username and m.age > 18")
List<Member> findAdultMember(@Param("username") String username);
  • 장점: SQL과 비슷해서 익숙하고, 오타가 나면 애플리케이션 로딩 시점에 에러를 잡아줍니다. (컴파일 타임 체크!)

 


 

5. 페이징과 정렬도 자동! (Pageable)

게시판 만들 때 제일 귀찮은 게 페이징 쿼리(LIMIT, OFFSET) 계산이죠?
Spring Data JPA는 Pageable 인터페이스만 넘기면 알아서 해줍니다.

// 사용 코드 (서비스 계층)
PageRequest pageRequest = PageRequest.of(0, 10, Sort.by(Direction.DESC, "username"));
Page<Member> result = memberRepository.findByAge(10, pageRequest);

// 결과
List<Member> members = result.getContent(); // 데이터
int totalPages = result.getTotalPages();    // 전체 페이지 수
long totalElements = result.getTotalElements(); // 전체 데이터 수

쿼리 결과뿐만 아니라 전체 페이지 수, 다음 페이지 존재 여부까지 싹 다 계산해서 Page 객체에 담아줍니다. 감동적이죠?

 


 

마치며

오늘의 결론입니다.

  1. JPA는 기술 명세(Interface)이고, Hibernate는 구현체이며, Spring Data JPA는 이를 편하게 쓰게 해주는 모듈이다.
  2. JpaRepository를 상속받으면 CRUD 메서드가 공짜다.
  3. 메서드 이름만 잘 지으면 쿼리가 자동 생성된다. (findBy...)

이제 SQL 지옥에서 탈출하셨습니다! 하지만 JPA를 쓸 때 가장 조심해야 할 것은 "객체 간의 관계(연관관계)"를 어떻게 맺느냐입니다. 잘못 맺으면 성능이 박살 나거든요.

다음 포스팅에서는 JPA의 핵심 난제: 연관관계 매핑 (N:1, 1:N, 1:1) 완벽 가이드로 찾아오겠습니다.

도움이 되셨다면 좋아요와 댓글 부탁드립니다! 😊

 

 

반응형
Comments