일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 빅분기 필기 pdf
- null 억제 연산자
- 모델 학습 및 예측
- 네트워크 면접 답변
- FLUTTER
- ?. ?? ! late
- MySQL
- 오늘은 1일 2쿼리
- mysql mongo 성능 비교
- 빅데이터 분석기사
- flutter 믹스인
- 빅분기 캐글놀이터
- 작업 2유형
- 주말에도 1일 1쿼리
- 앱개발 가보자고
- my_sql
- 운영체제 면접 답변
- rdbms nosql 차이
- 빅분기 판다스 100제
- null check 연산자
- SQL
- 컴포지션과 집합
- 주말도 한다
- 작업 1유형
- 빅분기 1유형
- 1일 1쿼리
- sqld 시험 정리
- late 키워드
- 빅분기
- 주말도 식지않아
- Today
- Total
subindev 님의 블로그
[Spring] Spirng 표준 ORM 인터페이스 JPA 본문
1. JPA 가 무엇인가요?
JPA는 자바에서 ORM을 사용할 수 있게 해주는 표준 인터페이스입니다. ORM은 객체와 데이터베이스 테이블을 매핑해주는 기술이고, JPA를 쓰면 직접 SQL을 작성하지 않아도 자동으로 쿼리를 생성해줘서 객체 중심으로 데이터 처리가 가능합니다.
2. Mybatis와 JPA의 차이점이 무엇인가요 ?
“MyBatis는 SQL Mapper라서 개발자가 직접 SQL을 작성하고, 결과를 객체에 매핑하는 방식입니다. 복잡한 쿼리를 작성할 때는 이가 더 용이합니다. 또한 개발자가 직접 쿼리문을 작성하므로 쿼리 코스트를 직접적으로 관리할 수 있습니다.
반면 JPA는 ORM 표준으로, 객체를 중심으로 데이터베이스를 다룹니다. SQL을 직접 작성하지 않아도 되고, 자동 쿼리 생성과 캐싱, 지연 로딩 같은 기능을 제공해 생산성이 높습니다.
3. JPA에 관계 매핑에는 어떤 것이 있나요? 관계 매핑을 어떻게 하셨나요?
JPA에서 관계 매핑은 크게 일대일(1:1), 일대다(1:N), 다대일(N:1), 다대다(N:M) 관계가 있습니다.
제가 진행했던 프로젝트에서는 회원과 주문을 예로 들어, 회원(One) - 주문(Many) 관계를 일대다 매핑으로 구현했습니다.
구현 시에는 @ManyToOne을 주로 사용했고, 주문 테이블이 외래키를 가지도록 매핑하여 실제 데이터베이스와 객체 관계가 일치하도록 했습니다. 또한 양방향 매핑에서 발생할 수 있는 무한 루프나 복잡한 연관관계 관리 문제를 경험했기 때문에, 단방향 ManyToOne 매핑을 주로 사용했습니다.
4. JPQL이 뭔가요?
JPA에서 사용하는 객체 지향 쿼리 언어 입니다. SQL 처럼 보이지만 테이블이 아니라 엔티티 객체와 그 필드를 대상으로 쿼리를 작성합니다. 데이터 베이스에 종속되는 것이 아니라 객체 중심으로 데이터를 조회할 수 있습니다.
JPA Repository 에서 @Query 어노테이션을 사용하여 구현할 수 있습니다.
5. JPA의 N+1 문제가 무엇이며 이것을 어떻게 해결합니까?
JPA의 N+1 문제는 한 엔티티를 조회할 때 Eager Loading으로 인해 연관된 엔티티까지 함께 가져오면서, 추가 쿼리가 N번 더 실행되는 비효율을 말합니다.
이를 해결하는 방법은 두 가지가 대표적입니다.
첫째, Fetch Join을 사용하는 방법입니다. @Query 어노테이션과 join fetch를 이용하면 한 번의 조인 쿼리로 필요한 데이터를 모두 가져올 수 있습니다. 다만, 페이징 같은 JPA의 기능을 함께 사용하기 어렵다는 단점이 있습니다.
// Fetch Join 사용
@Query("SELECT o FROM Order o JOIN FETCH o.member")
List<Order> findAllWithMember();
둘째, Batch Size 조절 방법입니다. 연관된 데이터를 IN 절로 한꺼번에 조회하기 때문에 쿼리 수를 줄일 수 있고, 페이징 처리 같은 기능도 그대로 활용 가능합니다. 하지만 Batch Size를 크게 잡으면 한 번에 많은 데이터를 메모리에 적재하여 DB 부하와 메모리 사용량 증가 문제가 생길 수 있다는 단점이 있습니다.
// BatchSize 조절
@Entity
public class Order {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
@BatchSize(size = 100) // 회원을 모아서 가져오도록 설정
private Member member;
}
+) 5-1 Fetch Join시 왜 페이징 처리가 힘듭니까 ?
“Fetch Join을 사용하면 부모 엔티티 하나에 자식 엔티티가 여러 개 매핑되면서 중복된 행이 생깁니다.
이 상태에서 페이징을 적용하면 DB는 중복된 행 기준으로 limit과 offset을 처리하기 때문에, 실제로 원하는 부모 기준 페이징이 불가능해집니다. 이러한 경우에는 Batch Size를 조절하는 방법이 있습니다.
6. 관계 매핑은 어떤 형식을 지향하며, 그 이유는 무엇입니까 ?
저는 관계 매핑에서 기본적으로 단방향 매핑, 특히 ManyToOne 단방향을 지향합니다.
양방향 매핑은 무한 참조나 관리 복잡도가 생길 수 있기 때문입니다.
또한 외래키는 항상 N쪽에 있기 때문에 @ManyToOne만으로도 관계를 충분히 표현할 수 있고, 관리가 단순합니다.
반대로 단방향 @OneToMany는 부모가 외래키를 관리하게 되면서, 자식 입장에서는 부모를 알 수 없어 비효율적인 쿼리(insert 후 update) 문제가 발생할 수 있습니다.
다만, 조회 편의성이 필요할 때는 @OneToMany(mappedBy = )를 보조적으로 사용하여 양방향 매핑을 적용하기도 합니다.