코딩 하는 가든

Django - bulk_create와 사용시 주의할 점 본문

Django

Django - bulk_create와 사용시 주의할 점

가든리 2020. 4. 1. 23:24

Bulk_create란?

백엔드 개발을 하다 보면 한 번의 요청으로 테이블에 대량의 레코드를 삽입하게 될 경우가 있다. 예를들어 서비스를 이용하는 모든 유저들에게 노티스를 보내고 싶을 때, 다음과 같은 코드로 노티스 레코드를 생성 할 수 있을 것이다.

users = User.objects.all()

for user in users:
    Notification(user=user, contents="반갑습니다.").save()

 

하지만 위와 같은 방법으로 for문을 돌며 다수의 오브젝트를 만들어 낼 경우 save() 메소드 한 번당 DB와의 connection이 한번 발생 하며 insert구문을 수행 하게 된다. 즉, 반복 횟수 == connection수가 되어서 서비스에 큰 부하가 생겨 장애를 야기할 수도 있다. 실제로 로컬에서 테스트를 하다가 설정해둔 최대 connection수를 넘겨버린 경우도 있었다;;

 

이럴때 사용하는것이 bulk operation이며 이 bulk를 사용하면 다수의 레코드를 생성, 업데이트 할 때 한 번의 커넥션 만으로 insert 혹은 update를 수행 할 수 있다. 사용법은 매우 간단하다. 만들고자 하는 테이블 모델의 오브젝트 리스트를 만들어 bulk_create의 인자로 넘겨준다.

users = User.objects.all()

# notification 오브젝트 리스트를 만든다.
new_noti_list = [Notification(user=user, contents="반갑습니다.") for user in users]

Notification.objects.bulk_create(new_noti_list)

 

실제로 현재 다니고 있는 회사에서 반복문을 돌며 db insert를 하는 방법에서 bulk operation으로 바꾸고 난 뒤 응답시간이 약 5배 정도 상승한 메소드도 있었다.

 

Bulk_create 사용시 주의할 점

 Bulk_create는 매우 편리한 기능이지만 사용할 때 꼭 주의해야 할 점이 있다. 바로 bulk 를 사용하면 Django Model 클래스에서 제공 하는 기본 메소드(save, clean... 등) 들을 사용하지 못한다는 점이다. 어떤 모델은 save(), clean() 메소드 등을 오버라이드 하여 오브젝트 저장 시점에 특별한 액션(트랜잭션, 유효성 검사 등)을 취할 수 있다. 하지만 bulk 를 사용하면 오브젝트를 DB에 직접 때려박는 식이기 때문에 모델 클래스의 기본 메소드 지원을 받을 수 없다. 그말은 즉 bulk operation을 통해 데이터 베이스에 유효하지 못한 값이 들어가거나 데이터의 무결성이 깨질 가능성이 생긴다는 것이다.

 

 따라서 bulk를 사용하기 전 해당 모델의 생성에 의해 영향을 받는 모델이 있는지, 모든 필드에 유효한 값이 들어오는지 등의 전수조사를 철저히 해야 한다.