작성
·
20
·
수정됨
0
오랜만에 인사드립니다 강사님. 저는 수강한 강의내용을 토대로 현재 진행하고있는 프로젝트를 리팩토링하고 있습니다.
본론으로 들어가자면, 일단 아래와 같이 특정 비지니스 로직을 검증하는 코드가 있습니다.
======== BEFORE =========
private void checkCrewInfoIsMatch(Long requestCrewId, Squad squad) {
if (!squad.getCrew().getId().equals(requestCrewId)) {
throw new SquadBusinessException.NotMatchCrewInfo(NOTMATCH_CREWINFO);
}
}
private void checkDifferenceSquadCreator(Squad squad, CrewMember crewMember) {
if (squad.getCrewMember().equals(crewMember)) {
throw new SquadBusinessException.OwnerCantParticipant(OWNER_CANT_PARTICIPANT);
}
}
그리고 위 코드를 리팩토링하고나서 아래와 같은 코드가 나오게 되었습니다.
========== AFTER ===========
private void checkCrewInfoIsMatch(Long requestCrewId, Squad squad) {
if (squad.hasNotSameCrewId(requestCrewId)) {
throw new SquadBusinessException.NotMatchCrewInfo(NOTMATCH_CREWINFO);
}
}
private void checkDifferenceSquadCreator(Squad squad, CrewMember crewMember) {
if (squad.isSameOwner(crewMember)) {
throw new SquadBusinessException.OwnerCantParticipant(OWNER_CANT_PARTICIPANT);
}
}
이렇게 Getter 로 값을 꺼내 직접 값을 비교했던 (Before) 에서, 값의 비교를 객체에게 위임하는 형태인 (After) 로 리팩통해보았습니다.
하지만 값의 비교를 객체에게 위임하는 After 방식으로 리팩토링했더니, 엔티티와 연관된 다른 프록시 객체들의 초기화로 인해 불필요한 쿼리가 나가는 문제를 확인하게 되었습니다.
물론 fetchJoin 을 통해 해결하긴 했습니다.
정리하면 아래와 같습니다.
기존에는 Service Layer 에서 직접 특정 엔티티와 연관된 엔티티를 직접 Getter 로 꺼내 값을 비교했었고, N + 1 이 터지지 않았습니다. (Before)
하지만 남용된 Getter 를 개선하기 위해 값의 비교를 엔티티 내부에서 진행하는 방식으로 리팩토링했을때는 N + 1 이 터졌고, 이를 fetchJoin 으로 해결했습니다. (After)
물론 지금은 fetchJoin 으로 N + 1 문제를 해결하였지만, After 와 같은 방식으로 리팩토링을 하려면 "연관된 엔티티를 모두 fetchJoin 미리 땡겨와야하는건가? (column 들을 너무 많이 땡겨오면 성능문제 걱정)" 라는 생각이 들게되었습니다.
JPA 를 사용할때, 강사님은 어떠한 방식으로 연관된 엔티티들의 값 비교를 어떤 방식으로 진행하는지 매우 궁금
합니다. 원래 JPA 를 사용하면 객체지향적인 설계를 가져가기 어려운건지도 궁금합니다.
(깃헙에서 다른 사람이 한 프로젝트를 분석하다보면, 가끔 연관관계 자체를 맺지 않고, FK 를 Long 으로 가져가버리는 Case 도 본것 같은데 흠.. 나중에 질문)
답변