안녕하세요. 새내기 개발자입니다. 공부하면서 정리하는 글로 틀린 부분은 언제나 댓글로 환영입니다!
📌 JPA란 무엇인가?
**JPA(Java Persistence API)**는 자바 애플리케이션에서 관계형 데이터베이스(RDB)를 객체 지향적으로 다룰 수 있도록 지원하는 ORM(Object-Relational Mapping) 기술입니다. SQL을 직접 작성하는 대신, 자바 객체(Entity)와 데이터베이스 테이블 간의 매핑을 통해 데이터 저장 및 조회를 수행할 수 있습니다.
1️⃣ JPA의 핵심 개념
🔹 1.1 ORM(Object-Relational Mapping) 이란?
JPA는 ORM(Object-Relational Mapping) 기술의 한 종류입니다.
✅ ORM이란? 객체(Object)와 관계형 데이터베이스(Relational Database) 간의 불일치를 해결하는 기술로, SQL 대신 객체 지향 코드로 데이터베이스를 조작할 수 있습니다.
🔹 1.2 JPA의 주요 기능
- 객체와 테이블 매핑(@Entity, @Table)
- SQL 대신 메서드로 데이터 조작 (@Query, JPQL 사용 가능)
- 자동 변경 감지(Dirty Checking) 및 트랜잭션 관리
- 지연 로딩(Lazy Loading) 및 즉시 로딩(Eager Loading)
2️⃣ JPA 설정 및 사용 방법
🔹 2.1 JPA 설정 (Spring Boot 기준)
Spring Boot 환경에서는 spring-boot-starter-data-jpa를 추가하면 JPA를 쉽게 설정할 수 있습니다.
📌 Gradle 의존성 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.mysql:mysql-connector-j'
}
📌 application.properties (MySQL 설정 예시)
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=1234
spring.jpa.hibernate.ddl-auto=update # 스키마 자동 업데이트
spring.jpa.show-sql=true # 실행되는 SQL 출력
spring.jpa.properties.hibernate.format_sql=true # SQL 가독성 개선
3️⃣ JPA 엔티티(Entity) 매핑
🔹 3.1 기본 엔티티 매핑
JPA에서 **Entity(엔티티)**는 데이터베이스의 테이블과 매핑되는 클래스입니다.
아래는 User 테이블을 엔티티로 매핑하는 예제입니다.
import jakarta.persistence.*;
@Entity // 엔티티 선언
@Table(name = "users") // 매핑할 테이블명 지정
public class User {
@Id // 기본 키 (Primary Key)
@GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가
private Long id;
@Column(nullable = false, length = 50) // NOT NULL 및 길이 제한 설정
private String name;
@Column(unique = true) // 유니크 제약 조건 설정
private String email;
}
4️⃣ JPA 기본 CRUD 예제 (Repository 활용)
Spring Data JPA를 사용하면 별도의 SQL 작성 없이 CRUD 기능을 구현할 수 있습니다.
🔹 4.1 Repository 인터페이스 생성
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email); // 이메일로 유저 조회
}
🔹 4.2 서비스(Service) 계층에서 사용
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User saveUser(User user) {
return userRepository.save(user);
}
public User getUserByEmail(String email) {
return userRepository.findByEmail(email);
}
}
🔹 4.3 컨트롤러(Controller)에서 사용
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
@GetMapping("/{email}")
public User getUser(@PathVariable String email) {
return userService.getUserByEmail(email);
}
}
5️⃣ JPA의 주요 기능
🔹 5.1 JPQL (Java Persistence Query Language)
JPA에서는 SQL 대신 **JPQL(Java Persistence Query Language)**을 사용하여 객체 지향적인 쿼리를 작성할 수 있습니다.
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.name = :name")
User findByName(@Param("name") String name);
}
📌 SQL vs JPQL 비교
-- 일반 SQL
SELECT * FROM users WHERE name = 'John';
-- JPQL (객체 기준)
SELECT u FROM User u WHERE u.name = 'John';
🔹 5.2 연관관계 매핑 (1:N, N:M)
JPA는 객체 간의 관계를 테이블에 자동으로 매핑해 줍니다.
1:N (One-to-Many) 관계 예제
@Entity
public class User {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "user") // User가 여러 개의 Order를 가짐
private List<Order> orders = new ArrayList<>();
}
@Entity
public class Order {
@Id @GeneratedValue
private Long id;
private String product;
@ManyToOne
@JoinColumn(name = "user_id") // 외래 키(FK) 설정
private User user;
}
6️⃣ JPA의 장점과 단점
✅ 장점
✔ SQL을 직접 작성하지 않아도 데이터 조작 가능
✔ 객체 지향적인 방식으로 데이터베이스 조작 가능
✔ 트랜잭션 관리 및 자동 변경 감지 지원
✔ 지연 로딩(Lazy Loading)으로 성능 최적화 가능
❌ 단점
❌ 복잡한 쿼리는 SQL보다 성능이 떨어질 수 있음
❌ 자동 매핑된 쿼리를 최적화해야 함 (N+1 문제 발생 가능)
❌ 학습 비용이 필요함
7️⃣ JPA 사용 시 주의할 점 (N+1 문제 해결)
JPA의 Lazy Loading(지연 로딩) 때문에 발생하는 대표적인 성능 문제 중 하나가 N+1 문제입니다.
이를 해결하기 위해 Fetch Join을 사용할 수 있습니다.
📌 N+1 문제 해결 예제 (Fetch Join 사용)
@Query("SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id")
User findUserWithOrders(@Param("id") Long id);
N+1 문제에 대해서는 다음에 더 정리해서 오겠습니다!
🔥 결론: JPA를 언제 사용해야 할까?
✔ SQL을 직접 다루는 JDBC보다 코드 가독성이 높고 유지보수가 용이
✔ 데이터베이스 종속성을 줄이고 싶을 때 유용
✔ 복잡한 데이터 관계가 있는 프로젝트에서 활용 가치가 높음
✔ 하지만 **쿼리 최적화(N+1 문제 해결)**는 반드시 고려해야 함
🚀 JPA는 강력한 ORM 기술이지만, 성능 최적화와 함께 사용해야 한다는 점!
'백엔드' 카테고리의 다른 글
[DB] 관계형(RDB) vs 비관계형(NoSQL) 데이터베이스 비교 (1) | 2025.02.10 |
---|---|
[자바/JAVA] Null Pointer Exception (NPE) (1) | 2025.02.08 |
[자바/JAVA] 자바 스프링 AOP(Aspect-Oriented Programming) 이해하기 (0) | 2025.02.08 |
[자바/JAVA] JPA N+1 문제란? (1) | 2025.02.05 |
[자바/JAVA] 스프링 기술 면접 질문 및 답변 정리 (2) | 2025.02.01 |