프로젝트를 하던 중 궁금중이 생겼다.
제목 그대로
Character character = characterRepository.findByUserId(userPrincipal.getId()).orElseThrow(CharacterNotFoundException::new);
List<Quest> quests = character.getQuests();
//둘의 차이는??
qeustRepository.findByCharacter(character)
이 둘의 차이가 궁금해졌다.
List<Quest> quests = character.getQuests();
이 코드는 @oneTomany를 사용할 경우
즉 양방향 관계에서 많이 사용된다.
근데 개발을 하다보면 양방향 관계를 많이 사용하지 않게 된다.
그래서 자연스럽게
qeustRepository.findByCharacter(character)
이 코드를 많이 사용하게 된다.
장,단점은 있는 것 같다.
1. getQuests()를 사용하는 경우
장점:
코드가 직관적이고 간단하다.
엔티티 객체를 이미 메모리로 로드한 상태에서 로직을 처리할 수 있다.
단점:
비효율성: 만약 캐릭터와 연관된 퀘스트가 매우 많다면, 모든 퀘스트를 메모리에 로드한 후 필터링하기 때문에 불필요한 데이터까지 메모리에 로드될 수 있다. 이로 인해 메모리 사용량이 증가하고 성능이 저하될 수 있다.
성능 문제: 필터링과 정렬 작업이 애플리케이션 레벨에서 수행되므로, 데이터가 많을 경우 성능에 영향을 줄 수 있다.
이걸보면서 생각한 것은 만약 필터링을 걸어야할 quest라면 전체를 다 가져오는 것 보단 JPA를 사용하는 것이 성능상 더 좋다고 느껴졌다.
만약 100만개의 데이터 중 특정날짜만 가져올껀데 getQuests로 100만개를 다 가져올 필요가 없게된다.
2. findBy를 사용하는 경우
동작 방식: questRepository.findBy 같은 메서드를 사용하여 데이터베이스 쿼리 단계에서 특정 날짜에 해당하는 퀘스트만 가져오고, 정렬도 데이터베이스 쿼리에서 처리한다.
장점:
성능 최적화: 필요한 데이터만 데이터베이스에서 가져오기 때문에 메모리 사용량이 줄어들고, 데이터베이스의 성능을 활용하여 필터링과 정렬 작업이 더 효율적으로 수행된다.
데이터 전송 최소화: 불필요한 데이터를 메모리로 로드하지 않기 때문에 성능이 더 좋다.
단점:
코드가 약간 더 복잡해질 수 있으며, 필요한 쿼리를 직접 정의해야 한다.
추천 방안
데이터의 양이 적거나 단순한 작업인 경우: getQuests() 방식이 충분히 유효하다. 코드가 간단하고 명확하므로, 유지보수도 용이하다.
데이터의 양이 많거나 성능이 중요한 경우: questRepository.findByCharacterAndCreatedTime과 같은 findBy 메서드를 사용하여 데이터베이스에서 조건에 맞는 데이터를 필터링하고 정렬하는 것이 더 나을 수 있다. 이렇게 하면 성능을 최적화할 수 있다.