get_or_create 메소드 설명
장고의 get_or_create
함수는 특정 kwargs
로 데이터베이스 객체를 탐색하고 이를 불러오거나 존재하지 않는 경우 새롭게 생성하는 간편한 메소드입니다.
메소드 실행 결과 (object, created)
튜플이 반환됩니다. object
는 불러온 객체이거나 생성된 객체이며, created
는 불리언 값입니다.
이는 중복된 객체가 생성되는 것을 방지하고, 다음과 같은 로직을 한번에 처리할 수 있는 메소드입니다.
try:
obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
obj.save()
여기서 인식해야 하는 개념은 위의 요청이 동시에 발생할 시 동일한 파라미터로 Person
을 저장하려는 시도가 이뤄지는 race conditon이 발생할 수 있다는 것입니다. get_or_create()
를 사용하면 기본적으로 이러한 race condition을 방지할 수 있습니다.
obj, created = Person.objects.get_or_create(
first_name='John',
last_name='Lennon',
defaults={'birthday': date(1940, 10, 9)},
)
레이스 컨디션 문제
앞서 get_or_create
를 사용하면 race condition을 방지할 수 있다고 정리했습니다. 그러나 여기에는 데이터베이스 단에서 unique
또는 unique_together
가 처리되어 있어야 한다는 전제가 있습니다. 그렇지 않은 경우, 메소드를 동시에 호출하면 동일한 파라미터를 가진 열이 중복해서 생성될 수 있습니다.
보다 정확하게는 unique
처리가 되지 않은 객체에서 하나의 스레드(탐색이 완료되고 아무런 결과가 리턴되지 않은 상황)를 통해 코드의 일부를 실행하는 중에 다른 스레드에서 객체가 생성될 경우 IntegrityError
가 리턴되지 않아 두 개의 객체가 생성될 수 있습니다. 결론적으로 데이터베이스에는 두 개의 객체가 생성되는 의도치 않은 문제가 발생합니다.
따라서 데이터베이스 레벨에서 unique
제약이 추가되지 않은 객체에서는 get_or_create
를 사용하지 않는 것이 좋습니다. 반대로, 이러한 제약이 추가되어 있다면 다수의 스레드를 통해 발생하는 race condition을 마주하지 않을 것이기 때문에 get_or_create
를 사용하는 것이 더 좋을 수 있습니다.
참고 자료:
https://youngminz.netlify.app/posts/get-or-create-deadlock
https://adriennedomingus.medium.com/the-perils-of-get-or-create-race-conditions-485fc8fb2068
https://docs.djangoproject.com/en/4.0/ref/models/querysets/#get-or-create
'Django' 카테고리의 다른 글
장고 SECRET_KEY 관리 방법: 환경 변수와 로컬 파일 설정 (0) | 2022.03.13 |
---|---|
장고 개발 환경에 따라 settings.py 분리하는 방법 (0) | 2022.03.13 |
장고 Q를 활용한 필터링, 정렬, 검색 방법 (0) | 2022.02.20 |
장고에서 HTTP GET, POST 요청 처리하는 방법 (0) | 2022.02.20 |
장고 ORM과 쿼리셋의 개념 (0) | 2022.02.07 |