

목 차
1. JPA란 무엇인가?
2. Spring Data JPA란?
3. JPA와 Spring Data JPA의 관계.
4. JPA 아키텍쳐 구조.
- 계층 구조
- 각 계층의 역할.
5. JPA의 주요 구성 요소.
6. JPA의 성능 최적화
7. 예시 코드

플젝을 할 때 개인적으로 mybatis를 썼을 때는 복잡한 sql문이 필요할 때는 비교적 편리하게 작성할 수 있다는 장점이 있었습니다.
하지만 DB를 중간에 변경하기 어렵고, 기획 변경사항이 생길 때마다 sql문을 일일이 수정해줘야하는 반복 작업을 수행해야 했습니다.(빡침 포인트..)
그래서 CRUD를 하루종일 짜고 있는 개발에서 벗어나 비즈니스 로직에 집중하기 위해 ORM 에 관심을 가지게 되었습니다.

Java 진영에서 관계형-데이터베이스(RDB)와 '객체 간의 데이터를 매핑' 하기 위한
'표준 ORM(Object Relational Mapping) 기술' 입니다.
JPA는 '인터페이스'의 모음으로, 자체적으로 동작하지 않으며
Hibernate, EclipseLink, OpenJPA와 같은 구현체를 통해 실제로 동작합니다.


ORM(Object Relational Mapping)은 객체와 관계형 데이터베이스를 매핑하여
SQL문을 직접 작성할 필요없이 데이터를 관리할 수 있도록 해주는 기술입니다.
이를 통해 객체는 객체대로 설계하고,
데이터베이스는 데이터베이스대로 설계 가능합니다.


: 자바 객체(Entity)를 데이터베이스 테이블과 매핑하여 객체 지향적으로 데이터를 관리합니다.
: SQL과 유사한 쿼리 언어로, 데이터베이스 독립적인 쿼리를 작성할 수 있습니다.
: 반복적인 SQL 작성 없이,
필드 변경만으로 데이터베이스 작업을 처리할 수 있어 생산성과 유지보수성이 높습니다.
: 1차 캐시, 트랜잭션 쓰기 지원, 지연 로딩 등 다양한 성능 최적화 기능을 제공합니다.

JPA를 더 쉽고 편리하게 사용할 수 있도록 스프링 진영에서 제공하는 라이브러리입니다.
JPA 구현체(Hibernate 등)를 추상화하여,
기본적인 CRUD 기능을 자동으로 제공하며, 개발자는 인터페이스만 정의하면 됩니다.

: JpaRepository 인터페이스를 상속하면 기본 CRUD 기능이 자동으로 구현됩니다.
: 메서드 이름만으로 JPQL 쿼리를 생성하고 실행할 수 있습니다.
: 복잡한 쿼리는 @Query 어노테이션을 사용해 직접 작성할 수 있습니다.

JPA는 표준 ORM 기술로, Hibernate와 같은 구현체를 통해 동작합니다.
Spring Data JPA는 JPA 구현체를 사용하여 기본 CRUD 기능을 자동으로 제공하며,
개발자는 인터페이스만 정의하면 됩니다.

생산성 향상: 기본 CRUD 기능을 자동으로 제공하여 개발 시간을 단축합니다.
쿼리 메서드: 메서드 이름만으로 JPQL 쿼리를 생성하고 실행할 수 있습니다.
쿼리 최적화: Spring Data JPA는 쿼리 최적화를 위한 다양한 기능을 제공합니다.


: 클라이언트 요청을 처리하고 응답을 반환합니다.
: 비즈니스 로직을 담당하며 Repository 계층과 상호작용합니다.
: 데이터베이스와 직접 상호작용하며, Entity를 기반으로 데이터를 저장하거나 조회합니다.


: API 요청을 받아 Service Layer에 전달하고, 처리 결과를 클라이언트에 반환합니다.
: 비즈니스 로직을 포함하며, 여러 Repository 호출이나 데이터 가공 작업을 수행합니다.
: Spring Data JPA가 제공하는 JpaRepository 인터페이스를 확장하여 CRUD 작업을 수행합니다.




2.DB 벤더에 종속되지 않는 쿼리를 작성할 수 있음.
String jpql = "SELECT u FROM User u WHERE u.email LIKE :pattern";
List<User> users = entityManager.createQuery(jpql, User.class)
.setParameter("pattern", "%@example.com")
.getResultList();
-- SELECT * FROM users WHERE email LIKE ‘%@example.com’;
@Query(value = "SELECT * FROM users WHERE email LIKE :pattern", nativeQuery = true)
List<User> findUsersWithNativeQuery(@Param("pattern") String pattern);

: 트랝개션 경계와 변경 감지 ( Dirty Checking )
@Transactional
public void updateUser(Long id, String newEmail) {
User user = entityManager.find(User.class, id);
if (user != null) {
user.setEmail(newEmail); // 변경
// 커밋 시점에 UPDATE 쿼리 자동 생성
}
}

- Entity 조회.
- OneToOne, ManyToOne 관계는 fetch join으로 쿼리 수를 최적화합니다.
- ToOne 관계는 fetch join 하더라도 대상이 1이기 때문에 데이터가 뻥튀기 되지 않습니다.
- 컬렉션 fetch join 시 페이징이 불가능하므로, Lazy Loading 설정을 유지하고 hibernate.default_batch_fetch_size 또는 @BatchSize 설정으로 지연 로딩을 최적화합니다
- DTO 직접 조회.
- Entity 조회와 동일하게 OneToOne, ManyToOne 관계는
fetch join 대신 단순 join으로 쿼리 수를 최적화합니다.
- OneToMany 관계인 컬렉션은 in 절을 사용해서 메모리에 미리 조회하고
이후 값을 셋팅 해주는 방법으로 최적화합니다
Entity 조회 방식 사용
: 모든 연관관계는 지연 로딩으로 변경합니다.
DTO 조회 방식 사용
: Entity 조회 방식으로 해결이 안되면, DTO 조회 방식 사용해서 네트워크 전송량을 줄입니다.
NativeSQL 또는 JdbcTemplate 사용
: DTO 조회 방식으로도 해결이 안되면 NativeSQL 또는 스프링 JdbcTemplate을 사용해서 최적화합니다
프로젝션 사용
: 필요한 필드만 선택하여 데이터 전송량을 줄입니다.
뷰 사용
: 복잡한 SELECT 쿼리를 단순화하고, 데이터 접근을 용이하게 합니다.
비지터 패턴 사용
: Visitor 패턴을 사용하여 객체의 다형성을 활용하고,
프록시 객체를 다운캐스팅하거나 벗기는 일 없이 메소드를 호출할 수 있습니다

@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// Getters and Setters
}
public interface UserRepository extends JpaRepository<User, Long> {
}
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getAllUsers() {
return userRepository.findAll();
}
public User saveUser(User user) {
return userRepository.save(user);
}
}
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@PostMapping
public User saveUser(@RequestBody User user) {
return userService.saveUser(user);
}
}

Spring Boot와 JPA는 객체 지향적인 방식으로 관계형 데이터를 쉽게 관리할 수 있는 강력한 도구입니다.
Controller, Service, Repository 계층으로 나뉜 아키텍처는 코드의 가독성과 유지보수성을 높이는 데 기여하며, Spring Data JPA를 활용하면 개발자가 구현 클래스를 작성하지 않아도 기본 CRUD 기능을 사용할 수 있습니다.
이러한 구조는 백엔드 개발자로서 효율적이고 확장 가능한 애플리케이션 구축에 필수적입니다.
JPA와 Spring Data JPA의 관계를 이해하고,
성능 최적화 기법을 적절히 활용하면 더 나은 시스템을 설계하고 구축할 수 있을 것입니다.