23/11/10 TIL Django-ORM

김민재·2023년 11월 11일
0


ORM이란?

객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해서 연결해주는 것을 의미한다. 객체 지향적인 코드(class)로 인해 프로그래밍하는데 편리하고 재사용 및 유지보수에 효과적이다. SQL의 절차적이고 순차적인 접근이 아닌 객체 지향적인 접근으로 생산성이 증가하는 것도 장점이다. Django-ORM은 장고에서 제공하는 object와 database의 mapping 관련 기능이고 SQL문을 사용하지 않고 python을 이용하여 데이터베이스를 조작할 수 있게 해준다. 다만 ORM 의존 문제가 발생할 수 있고 반드시 효율적인 SQL문으로 변환해주지 않는다는 단점도 존재한다.


Lazy-loading vs Eager-loading

Django-ORM은 다른 ORM들과 마찬가지로 lazy-loading 방식을 사용하는데, ORM에서 명령을 실행할 때마다 데이터베이스에 접근해서 데이터를 가져오는 것이 아니라 실제 데이터가 이용될 때 데이터를 로딩하는 방식이다. 이런 상황에선 다수의 SQL Query를 이용하여 여러번 DB에 접근해야 하는데, 이와 반대되는 개념이 Eager-loading 방식이다. eager-loading 방식은 지금 당장 사용하지 않을 데이터를 포함하여 데이터 전부에 접근해서 특정 데이터에 명령이 있으면 관련 명령을 실행한 후 query문을 실행하는 방식이다. django에서 eager-loading을 실행하는 방법은 selected_relatedprefetch_related 메소드를 사용하면 된다.


SerializerMethodField 사용에서의 N+1 이슈

SerializerMethodField는 원하는 key,value 값을 query문에 추가해줄 수 있는데 잘못사용한다면 N+1이슈를 발생시킬 수 있다. 특정 모델의 foreign key 필드의 json변환에서 이러한 이슈가 발생할 가능성이 높은데, 앞서 말했듯이 Django-ORM은 기본적으로 lazy-loading 방식을 사용한다. comment 모델이 user 모델을 fk로 필드화하여 가지고 있는데, serializerMethodField로 user의 정보를 가져오고 싶으면 전체 comment를 가져오는 쿼리가 한 번, 각 인스턴스가 user 관련 정보를 호출 하는 쿼리가 한 번 씩, 총 N번 쿼리를 발생시켜서 N+1 쿼리가 발생하게 된다. 실행중인 raw query를 확인하기 위해서 장고의 제공 기능인 connection을 활용할 수 있는데, 관련 views.py 코드 상단에 from django.db import connection 형태로 connection을 import해주고 쿼리문을 확인하고 싶은 줄에서 print(connection.queries)를 입력해줘서 현재까지의 쿼리문을 다 리턴 받을 수 있다. 프로젝트에서 SerialzierMethodField를 다수 사용해서 N+1 이슈가 발생할 줄 알았는데, 확인해봐도 해당 이슈가 발생하지는 않는 것 같았다. 성능 문제로 다수의 쿼리를 발생시키는 N+1 이슈가 발생한다면 위에서 언급한 Eager-loading 방식을 실행하기 위해 selected_related와 prefetch_related 메소드를 활용할 수 있을 것 같다.

0개의 댓글