Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5, 6주차/리키] 워크북 제출합니다. #74

Merged
merged 3 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions keyword/chapter05/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
## Domain

▶️ 특정 시스템이 다루는 비즈니스 규칙, 데이터, 기능 등을 포함하는 개념

즉, 시스템이 다루는 비즈니스 문제 영역

ex) 쇼핑몰 → 고객, 상품, 주문 등…

금융 시스템 → 계좌, 거래, 고객 등…

### JPA에서 도메인

- JPA에서는 도메인을 표현하기 위해 도메인 엔티티 클래스 정의 (@Entity)
- 데이터베이스 테이블과 매핑되며, 특정 도메인에 해당하는 데이터와 비즈니스 로직을 캡슐화

### DB에서 도메인

- 각 속성들이 가질 수 있는 값의 모임

ex) 성별 → 남성, 여성

나라 → 대한민국, 미국, 중국, 일본

- 각 도메인은 테이블, 뷰, 인덱스, 제약조건 등의 구조로 설계됨

### 도메인의 중요성

- 시스템이 해결하려는 비즈니스 문제의 핵심이므로 정확한 설계가 중요
- 비즈니스 요구사항을 잘 반영해야 이후 유지보수 및 기능 확장에 용이
- 데이터 무결성을 유지하는데 중요함



## 연관관계 매핑

### ▶️ 두 객체가 서로 참조해야 하는 상황에서 정의하는 연관관계 방식

- 양방향 관계는 단방향 관계 2개를 맺은 것

→ 실제로 양방향 연관관계는 없음, 단지 양방향인 것 처럼 보이게 한 것

- 양방향 객체 둘 중 하나는 반드시 외래 키를 관리해야 함

### MappedBy

- 양방향 매핑을 할 때에는 반드시 한쪽 객체에 MappedBy 옵션을 설정해야 함

```java
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
@Builder.Default
private List<Review> reviewList = new ArrayList<>();
```

### 연관관계 주인

- 객체의 두 관계 중 하나를 연관관계의 주인으로 지정해야 함
- 연관관계 주인만 외래 키를 관리해야 함
- 주인은 mappedBy 속성을 사용하지 않음
- 주인이 아니면 mappedBy 속성으로 주인을 지정

#### 주인 정하기

- 외래 키가 있는 곳을 주인으로 정함
- N : 1 관계일 경우 N에 해당하는 쪽에 외래 키가 존재 (N이 주인)

→ @ManyToOne 어노테이션을 사용하는 클래스가 주인


## N+1 문제
### ▶️ 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 개수(N) 만큼 연관관계의 조회 쿼리가 추가로 발행하여 데이터를 읽어오는 것

ex) 1번의 쿼리를 날렸을 때 의도하지 않은 N번의 쿼리가 추가적으로 실행

- JPA Repository를 활용해 인터페이스 메소드를 호출할 때 발생
- 1 : N 또는 N : 1 관계를 가진 엔티티를 조회할 때 발생

### 발생 상황

- JPA Fetch 전략이 EAGER 전략으로 데이터를 조회하는 경우
- JPA Fetch 전략이 LAZY 전략으로 데이터를 가져온 이후에 연관 관계인 하위 엔티티를 다시 조회하는 경우

### 발생 이유

- JPA Repository로 find시 실행하는 첫 쿼리에서 하위 엔티티까지 한번에 가져오지 않고 하위 엔티티를 추가로 조회하기 때문
- JPQL은 기본적으로 글로벌 Fetch 전략을 무시하고 JPQL만 가지고 SQL을 생성하기 때문

### EAGER (즉시 로딩)인 경우

1. JPQL에서 만든 SQL을 통해 데이터를 조회
2. 이후 JPA에서 Fetch 전략을 가지고 해당 데이터의 연관 관계인 하위 엔티티들을 추가 조회
3. 2번 과정으로 인해 N + 1 문제 발생

### LAZY (지연 로딩)인 경우

1. JPQL에서 만든 SQL을 통해 데이터를 조회
2. JPA에서 Fetch 전략을 가지지만, 지연 로딩이기 때문에 추가 조회는 하지 않음
3. 하위 엔티티를 가지고 작업을 하게 되면 추가 조회가 발생하면서 N + 1 문제 발생

### 해결 방법

#### Fetch join

- N + 1 자체가 발생하는 이유는 한쪽 테이블만 조회하고 연결된 다른 테이블은 따로 조회하기 때문
- 미리 두 테이블을 JOIN하여 한 번에 모든 데이터를 가져오면 됨

80 changes: 80 additions & 0 deletions keyword/chapter06/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# 제목 없음

## **지연로딩과 즉시로딩의 차이**

### 지연 로딩 (Lazy Loading)

▶️ 엔티티를 처음 조회할 때 연관 엔티티 데이터를 가져오지 않고, 해당 데이터가 실제로 필요한 시점에 가져오는 방식

1. 장점
- 메모리 효율이 증가
- 불필요한 데이터베이스 호출 감소
- 초기 조회에서 연관 데이터를 가져오지 않기 때문에 성능 향상
2. 단점
- 실제로 데이터를 사용할 때 추가적인 호출이 필요하므로 시스템 설계에 따라 해당 과정에서 과부하가 걸린다면 성능이 저하됨
- 연관된 데이터를 사용하는 시점에 트랜잭션이 반드시 열려있어야 함

### 즉시 로딩 (Eager Loading)

▶️ 엔티티를 조회할 때 연관된 모든 데이터를 함께 가져오는 방식

1. 장점
- 초기 조회 시 연관된 데이터를 함께 가져오기 때문에 이후에 추가 쿼리가 발생하지 않음
2. 단점
- 불필요한 데이터까지 가져와서 메모리가 낭비될 수 있음
- 연관 데이터가 많을 경우 속도가 저하됨
- 필요하지 않은 데이터를 조회하게 되면 전체적인 성능과 효율이 감소

### 차이점

| 지연 로딩 | 구분 | 즉시 로딩 |
|:------------------------------------:|:-------:|:-----------------------------:|
| 실제로 필요할 때 | 로딩 시점 | 처음 엔티티 조회할 때 |
| 초기 조회가 빠름, 추가 쿼리 발생 가능 | 성능 | 처음 조회가 느림, 추가 쿼리가 없음 |
| 불필요한 데이터가 없어 메모리 사용이 적음 | 메모리 사용 | 모든 데이터를 로딩하기 때문에 메모리 사용량이 증가 |
| fetch = FetchType.LAZY | 설정 방식 | fetch = FetchType.EAGER |
| 연관된 데이터를 사용할지 여부가 불확실하거나 필요하지 않은 경우 | 사용 기준 | 연관 데이터가 자주 사용되거나 항상 필요한 경우 |

## QueryDSL

▶️ JPQL을 Java 코드로 작성할 수 있도록 하는 라이브러리로 도메인 특화 언어

### 1. 특징

- 타입 안전성 : 컴파일 시점에서 검사가 되기 때문에 런타임 오류를 사전에 방지
- 도메인 특화 : 도메인 엔티티에 맞춘 쿼리를 작성할 수 있는 API를 제공
- 다양한 데이터베이스와 연계 가능

### 2. 장점

- 유연한 쿼리 작성 가능 : 복잡한 동적 쿼리를 쉽게 작성할 수 있음
- 조건 추가나 수정이 쉬어 비즈니스 로직의 가독성과 유지보수성 증가
- 타입 안전성
- JPQL과 SQL을 모두 지원하기 때문에 유연한 사용이 가능

### 3. 단점

- 설정이 복잡하고 Gradle 버전에 따른 지원 여부가 다름
- 엔티티 구조가 변경되면 Q 클래스도 다시 생성되어야 하기 때문에 추가 설정이 필요

### 4. 사용 설정

```java
dependencies {
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta' // Q클래스 자동 생성
}
```

### 5. 사용 예제

```java
QMember member = QMember.member;
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);

List<Member> members = queryFactory
.selectFrom(member)
.where(member.age.lt(20)) // 20살 이하 회원 조회
.fetch();

```
Binary file added mission/chapter05/img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions mission/chapter05/mission.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
![img.png](img.png)