장고의 transaction 모듈은 db 가 수정될 때 atomic 하게 처리될 수 있도록 해주는 아주 좋은 모듈이다. 그런데 정확히 언제 이 로직이 작동되는지 알고 써야한다.
처음에 나는 오 에러나니까 그 함수에서 실행됐던 모든 것들이 rollback 되네? 하고
신나서 db 변경 로직이 있는 함수마다 데코레이터로 달고 다녔다.
하지만 모든 경우에 그렇게 하면 안되는 걸 알았고, 에러가 나지 않으면 transaction rollback 이 되지 않는다는 것도 사용하다 보니 깨닫게 되었다.
다음 코드 snippet 은 order 로직을 처리하는 view 이다.
처음에 재고가 수량보다 적으면 return JsonResponse()
로 status 400 을 처리했는데, 그렇게하니까 rollback 이 안됐다. 왜냐면 에러가 난 것이 아니라 그냥 if 조건문을 타고 에러없이 return 을 처리했기 때문이다.
그래서 다음과 같이 코드를 변경했다.
상단에 Exception 클래스를 상속해서 custom error 들을 만들었다.
그 뒤 return 이 아니라, 다음과 같이 error 를 발생시켰다.
if cart.product_option.stock - cart.quantity < 0:
raise StockDoesNotExist
이렇게 하니 transaction.atomic() 로직이 실행되어 변경된 db 사항이 성공적으로 rollback 되었다.
또한 @transaction.atomic 데코레이터를 사용하여 함수 내 전체 로직에 트랜잭션을 적용하는게 아니라, with 문을 사용하여 아니라 원하는 부분만 rollback 할 수 있는 구조로 짜는 것이 더 효율적인 코드라는 것을 배웠다.
👍🏻 역시 TK!