프로젝트 JPA 성능 개선기 (1) - 로그인 시 성능을 올려보자~!
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부에서 이어가보자