1. 쿼리 최적화에 대해 설명해주시고 방법에 대해 설명해주세요.
웹 어플리케이션에서 DB는 필수로 사용되는 요소입니다. DB는 저장하고 조회하는 작업이 주를 이루게 되는데, 서버 처리시간의 대부분이 SQL을 처리하는 시간에 들어가고 서버의 응답이 느려질수록 유저의 만족도는 떨어지게됩니다. 즉 어플리케이션의 성능을 좌우하는 요소 중 하나가 쿼리최적화입니다.
쿼리최적화는 Fetch 전략을 EAGER로 설정했을 때 발생하는 문제점을 해결하는 방법이 있습니다. One으로 끝나는 연관관계는 모두 Fetch전략의 Default타입이 EAGER라는 점이 있습니다. EAGER로 설정했을 때 문제점은 DB를 조회할 때 연관관계를 맺고 있는 다른 데이터까지 함께 조회하게 됩니다. 단순히 하나의 DB의 정보만 필요한데, 다른 DB까지 함께 조회하는 쿼리를 실행하는 것은 분명한 낭비입니다. 그렇기 때문에 Fetch 전략을 LAZY로 수정하면 DB하나를 조회되는 시점에 다른 DB를 프록시 객체로 가져와서 실제 연관 DB가 사용되는 시점이 실행됩니다.
두 번째 쿼리 최적화 방법은 N+1 문제를 해결하는 것입니다. N+1이란 findAll()이란 메서드를 통해 특정 DB 전체를 조회하게 되면 그 DB 전체를 조회하는 쿼리가 한번 나가고, 그 데이터의 수만큼 데이터와 연관관계를 맺고있는 다른 DB를 조회하는 쿼리가 추가로 실행되는 것입니다. 예를 들어 특정 User가 10명이 존재한다고 가정했을 때 findAll() 메서드를 한번 실행하게 되면 전체 User를 조회하는 쿼리 1번, 그 User DB와 연관관계가 있는 DB를 조회하는 쿼리 10번이 실행되는 문제를 일으킵니다.
N+1 문제를 해결하기 위해선 User를 조회할 때 해당 User와 연관관계를 맺고 있는 DB까지 한번에 조회해버리면 간단하게 해결할 수 있습니다. Spring Data JPA에서는 @EntityGraph 으로 간단하게 N+1 문제를 해결할 수 있습니다.
2. DB 로직 최소화를 하려면 어떻게 해야 할까요?
DB 로직 최소화를 위해서는 데이터베이스와 관련된 작업을 최적화하고 효율적으로 처리하는 방법을 적용해야 합니다.
첫 번째는 일관된 데이터 모델링입니다. 데이터베이스 테이블과 엔티티를 일관성 있게 설계합니다. 중복 데이터를 피하고 정규화를 적용하여 데이터 중복을 최소화하며 데이터 무결성을 유지합니다.
두 번째는 비즈니스 로직 분리입니다. 데이터베이스에 직접적인 비즈니스 로직을 내장시키는 것을 피하고, 서비스나 애플리케이션 레이어에서 비즈니스 로직을 처리하도록 분리합니다.
세 번째는 조회 최적화입니다. 쿼리를 작성할 때 필요한 데이터만 조회하고 Join 등 복잡한 연산을 최소화합니다. 필요한 데이터를 미리 계산하여 캐싱하거나, 데이터베이스 뷰를 활용하여 미리 계산된 결과를 조회하는 방식을 고려합니다.
네 번째는 인덱스 활용입니다. 필요한 컬럼에 인덱스를 생성하여 검색 성능을 향상시킵니다.
다섯 번째는 쿼리 캐싱입니다. 자주 사용되는 쿼리 결과를 캐시하여 반복적인 쿼리 실행을 피하고 성능을 향상시킵니다. 캐싱 시 데이터 갱신 주기와 데이터의 유효성을 고려해야 합니다.
마지막으로 트랜잭션 사용 최소화입니다. 트랜잭션은 데이터의 일관성과 무결성을 유지하기 위해 필요하지만, 필요하지 않은 범위에서 트랜잭션을 사용하는 것을 피하고, 트랜잭션 범위를 최소화합니다.