티스토리 뷰
OneToOne은 기본적으로 Lazy 로딩을 지원하지 않는다. 그렇기 때문에 조회 시 Lazy로 설정 시 다음과 같은 문제가 발생한다.
일단 사전에 코드를 보여주면 다음과 같다.
Member.java
public class Member extends BaseTimeEntity {
// 속성 ... //
@OneToOne(mappedBy = "member", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, orphanRemoval = true)
private MemberCount memberCount;
// == 연관관계 로직 == //
public void addMemberCount(final MemberCount memberCount) {
this.memberCount = memberCount;
}
// 비즈니스 로직 ... //
}
MemberCount.java
public class MemberCount extends BaseTimeEntity {
// 속성 ... //
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
@JoinColumn(name = "member_id", unique = true, nullable = false)
private Member member;
// 비즈니스 로직 ... //
}
AuthService.java
@Transactional
public TokenDTO login(final Email email, final Password password) {
final String userPw = password.password();
CustomUserDetails userDetails = membeRepository.findByEmail(email)
.map(CustomUserDetails::of)
.orElseThrow(() -> new MemberNotFoundException(ErrorCode.USER_NOT_FOUND));
UsernamePasswordAuthenticationToken token
= new UsernamePasswordAuthenticationToken(userDetails, userPw);
Authentication authenticate = managerBuilder.getObject().authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authenticate);
return tokenProvider.createToken(userDetails.getId(), authenticate);
}
보면 로그인 시 시큐리티 컨텍스트에 userDetails 정보를 넣어주기 때문에 findByEmail로 회원을 조회해오고 있다. 이 때 Login을 실행하고 쿼리를 보면 결과가 다음과 같이 나온다.

정말 보기 불편한 상황이다. MemberCount를 Join을 해서 가져올 수 도 있는 상황인데 굳이 select쿼리가 두 번이나 나가 성능을 떨어트리고 있다. 이를 해결하기 위해 필자는 @EntityGraph를 사용했다. @EntityGraph는 서로 연관된 엔티티를 JPA가 불러올 때 어떻게 불러올 것인지를 비교적 유연하게 (fetch = Lazy or EAGER 선언 시 정적이므로 런타임 중에는 변경 하지 못한다.) 표현하기 위해 사용한다.

다음과 같이 선언해주면 이제 JPA는 반드시 Member가 조회되면 memberCount도 조회해오기 때문에 N + 1문제가 발생하지 않을 것이다. 실제로 결과를 보자.

Join을 해서 memberCount를 한번에 가져온다. 그렇기 때문에 한번 더 select쿼리가 나갈 이유가 없어져 N + 1 문제가 해결 되었다.
하지만 여기서도 문제가 역시 발생한다. 각자 생각해보자 로그인을 할 때 과연 memberCount가 필요할 까? 전혀 필요하지 않다고 생각하기 때문에 이것 역시 불필요한 join문이다. 2부에서 이어가보자
'Spring Framwork & JPA > JPA' 카테고리의 다른 글
| JPA 연관관계에 대한 생각 (4) | 2022.07.26 |
|---|---|
| 프로젝트 JPA 성능 개선기(2) - 불필요한 Join 삭제 (0) | 2022.06.04 |
| JPA에서 발생하는 생성, 수정, 삭제 시간을 추적해보자 (2) | 2022.05.14 |
| JPA란 무엇인가? (0) | 2021.10.28 |
| JPA에 시작 (0) | 2021.10.10 |
- Total
- Today
- Yesterday
- 동시성
- 코딩
- 개발
- JPA
- 취업
- 면접준비
- 자바
- Redis
- 프로젝트
- lock
- 게시판
- 코드
- 개발자
- java
- DB
- 면접 준비
- 취업준비
- Kotlin
- 프로그래밍
- 인터뷰
- docker
- 백엔드
- MySQL
- 취준
- DevOps
- Spring
- CS
- IT
- thread
- 면접
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |