N+1 문제
Q. 운영 중인 웹 서비스에서 갑자기 데이터베이스 쿼리 성능이 저하되는 현상이 발생했습니다. 로그를 확인해보니 특정 API 엔드포인트에서 N+1 문제가 발생하고 있다는 것을 발견했습니다. 이 문제를 어떻게 해결하시겠습니까?
우선, N+1 문제가 발생하는 상황을 정확히 파악해야 합니다. 보통 ORM을 사용할 때 연관된 엔티티를 조회하는 과정에서 발생하는 문제로 예를 들어, 게시글 목록을 가져오면서 각 게시글의 작성자 정보를 개별적으로 조회하는 경우 이런 문제가 발생합니다. 해결 방안으로는 크게 두 가지를 고려해볼 수 있습니다. 첫번째는 Eager Loading을 사용하는 방법으로 JPA를 예로 들면 join fetch를 사용해서 연관 엔티티를 한 번의 쿼리로 함께 조회하는 방법입니다. 이렇게 하면 N번의 추가 쿼리를 방지할 수 있습니다. 두번째는 BatchSize를 설정하는 방법입니다. 완전한 Eager Loading이 부담스러운 경우, BatchSize를 설정해서 정해진 숫자로 끊어서 조회하는 것 입니다.
Q. 언급하신 해결책들을 적용했을 때, 이러한 성능 개선이 실제로 효과가 있었는지 어떻게 측정하고 모니터링 하시겠습니까?
개선 전후를 정확하게 비교하기 위해서는 몇 가지 지표들을 측정해야 합니다. 첫째로, 응답 시간(Response Time)을 모니터링 합니다. 특히 해당 API의 p95, p99 응답 시간을 측정하는데 이는 대부분의 사용자가 경험하는 실제 성능을 반영하기 때문입니다. 이를 위해 Prometheus와 Grafana 같은 모니터링 도구를 활용할 수 있습니다. 둘째로, 데이터베이스 관련 메트릭을 확인합니다. 실행되는 쿼리의 수가 얼마나 줄었는지, 각 쿼리의 실행 시간은 어떻게 변했는지 등을 측정할 수 있습니다. 이를 위해서는 slow query log같은 기능을 활성하고, 데이터베이스 모니터링 도구를 사용할 수 있습니다. 셋째로, 서버 리소스 사용량을 체크합니다. CPU, 메모리 사용량, DB 커넥션 수 등의 변화를 관찰하여 개선이 전반적인 시스템 성능에 미치는 영향을 파악합니다. 그리고 이러한 모니터링은 단발성이 아니라 지속적으로 이루어져야 합니다. 예를 들어 트래픽이 많은 시간대나 특정 이벤트 기간에도 개선된 성능이 잘 유지되는지 확인해야합니다.
Q. 서비스의 BatchSize를 설정하면 어떠한 일이 발생하나요?
먼저 쿼리 실행 패턴이 변경됩니다. 예를들어 BatchSize를 100으로 설정했다면 원래는 WHERE절로 하나씩 조회하던 것이 IN절을 사용해서 100개씩 묶어서 조회하는 방식으로 변경됩니다. 이러한 방식은 메모리 사용량에 영향을 줍니다. BatchSize를 너무 크게 설정하면 한 번에 많은 데이터를 메모리에 로드하게 되므로 메모리 부하가 증가할 수 있습니다. 반대로 너무 작게 설정하면 쿼리 횟수가 늘어나서 성능상 이점이 줄어들 수 있습니다. 또한 BatchSize가 크면 하나의 쿼리가 DB Connection을 점유하는 시간이 길어질 수 있기 때문에, BatchSize는 데이터베이스 Connection Pool에도 영향을 미칩니다.
Last updated