[JAVA] Spring Data JPA 소개와 기본 사용법

Spring Boot 프로젝트를 하다 보면 JPA는 거의 필수처럼 등장합니다. 그중에서도 Spring Data JPA는 JPA의 생산성을 극대화하는 도구로, 반복적인 CRUD 코드를 없애고 개발자의 생산성을 높여줍니다.

 

1. JPA vs Spring Data JPA – 개념 정리

  • JPA(Java Persistence API): 자바 ORM 표준 명세입니다. Hibernate, EclipseLink 등이 구현체입니다.
  • Spring Data JPA: JPA 위에 얹혀 있는 Spring 기반 프레임워크로, Repository 인터페이스만 정의하면 대부분의 CRUD 기능을 자동 구현해줍니다.

즉, JPA는 ORM의 기반이고, Spring Data JPA는 이를 실무에서 더욱 쉽게 쓸 수 있도록 도와주는 생산성 도구입니다.

2. Spring Boot에서 Spring Data JPA 설정하기

2.1 의존성 추가

// build.gradle
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'com.mysql:mysql-connector-j' // 또는 사용 중인 DB
}

2.2 application.yml 설정 예시

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: secret
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true

 

3. Entity 클래스 정의하기

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String email;

    // 생성자, Getter, Setter 생략
}

@Entity는 해당 클래스가 JPA로 매핑될 엔티티임을 의미하며, @Id는 기본 키를 나타냅니다.

 

4. Repository 인터페이스 정의하기

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

JpaRepository를 상속하면, findAll, findById, save, delete 등의 기본 메서드를 별도 구현 없이 사용 가능합니다.

 

5. Service & Controller 연동

// UserService.java
@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User createUser(String name, String email) {
        return userRepository.save(new User(name, email));
    }

    public Optional<User> findUser(String email) {
        return userRepository.findByEmail(email);
    }
}
// UserController.java
@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping
    public User create(@RequestBody UserDto dto) {
        return userService.createUser(dto.getName(), dto.getEmail());
    }

    @GetMapping
    public ResponseEntity<User> getByEmail(@RequestParam String email) {
        return userService.findUser(email)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
}

 

6. 실무 팁

  • JpaRepository 대신 CrudRepository, PagingAndSortingRepository도 존재하지만 대부분 JpaRepository가 포함하고 있어 실무에서는 이것만 사용해도 충분합니다.
  • JPQL 사용은 @Query 어노테이션을 통해 가능하며, 복잡한 쿼리는 QueryDSL 또는 Native Query로 처리하기도 합니다.
  • 트랜잭션 처리 시에는 @Transactional의 위치에 주의해야 합니다. 일반적으로 Service 계층에 선언하는 것이 좋습니다.

 

결론

Spring Data JPA는 반복되는 코드 없이 빠르게 API를 구성할 수 있도록 도와줍니다. 특히 엔티티와 리포지토리만으로 CRUD API를 빠르게 구성할 수 있어 프로토타입 → MVP 개발까지의 속도를 극대화할 수 있습니다.

하지만 모든 복잡한 쿼리를 감당하진 못하므로 적절한 시점에 QueryDSL이나 직접적인 JPQL 작성을 고려하는 것도 필요합니다.