본문 바로가기

소프트웨어 이야기/장고와 루비온레일즈

(Django) Django에서 Thread를 다룰 때 주의할 점 💡한줄 요약 Django 스크립트에서 Thread를 사용하는 경우, Thread가 종료될 때 명시적으로 DB Connection을 닫아주는 것이 좋다. Djagno에서 Thread를 사용할 때, DB Connection이 관리되는 방식 Django에서 DB에 접근하는 Thread를 사용하는 경우, Thread마다 새로운 DB Connection을 생성된다. Django는 request가 종료될때, request_finished signal을 발생시켜 지난 DB Connection들을 모두 닫는다. ( 참고 - DB Connection을 관리하는 방법 ) 즉, Thread에서 만들어진 DB Connnecion은 Thread를 실행시킨 메인 프로세스가 종료될 때 닫힌다. import threading fro..
(Celery) 트랜잭션이 커밋된 이후에 Celery Task 전송하기 트랜잭션 안에서 Celery Task가 호출되는 경우, 트랜잭션이 커밋되기 전에 Task가 실행될 수 있다. 이 때, Task가 커밋되지 않은 데이터를 참조하는 경우, 오류가 발생할 수 있다. 위와 같은 상황의 예시와 이를 회피하는 방법에 대해서 정리해보고자 한다. 문제상황 아래의 코드는 회원가입을 처리하는 가상의 코드이다. from django.db import transaction from coupon.util import create_welcome_coupon from mileage.util import create_welcome_mileage @transaction.atomic() def create_user(user_data): user = User.objects.create(**user_dat..
(Django) Association Table Multiple Filter Chaining 주의사항 관계 테이블에 동일한 레벨로 여러 검색 조건을 걸어야하는 경우, 같은 관계 테이블 컬럼은 모두 같은 필터 안에 조건문을 선언해야합니다. 동일한 관계 테이블을 여러 필터에서 나눠 조회하는 경우, 2가지 문제가 발생하게 됩니다. 1. 쿼리가 기대한 대로 동작하지 않습니다. 2. 중복 테이블 조인이 발생하게 됩니다. ( T3, T4, T5 같은 테이블 알리아스가 난무하게 됩니다. 😱) 장고는 하나의 필터를 하나의 조건 세트로 인지합니다. 그래서 메서드 체이닝으로 호출된 필터를 각각 다른 조건으로 보고, 별도의 검색조건 쿼리를 만들어냅니다. 메인 테이블에 속한 컬럼에 조건을 거는 경우에는 이런 문제가 발생하지 않아요. 괜찮습니다. 글로 설명하려니 굉장히 복잡하네요. 문제가 되는 샘플 케이스를 보면 이해가 되실거..
(Django) Django와 PostgreSQL 성능 개선을 위한 7가지 패턴 Django와 PostgreSQL으로 구성된 서비스를 6개월간 최적화를 하면서, 패턴화한 것들을 정리해보고자 합니다. 아래의 9가지 원칙을 반복하면, 점진적으로 시스템을 개선할 수 있습니다. 1. 인덱스 추가하기 2. 인덱스를 잘 타도록 쿼리 개선하기 3. N+1 쿼리 줄이기 4. 불필요한 트래픽 줄이기 5. Transaction은 짧게 유지하기 6. 실시간성이 필요하지 않은 기능은 비동기로 처리하기 7. 캐시 적용하기 1. 인덱스 추가하기 a. 빈번하게 사용되는 검색조건에는 인덱스를 추가해줍니다. 디스크 사용량이 우려된다면, 인덱스 파티셔닝을 적절하게 활용하여 인덱스를 추가하는게 좋습니다. b. FK에 BTREE Index 추가하기 Ruby On Rails와 Django의 마이그레이션은 FK 관계로 설..
(Django) Django에서 비즈니스 로직 관리하기 Django와 Ruby On Rails를 사용하면서, 항상 고민되는 점이 있다. 각 프레임워크에서 비즈니스 로직을 모아두고, 관리하기에 적합한 위치가 어디인가에 대한 점이다. Rails 3/4 버전을 사용하면서, 찾아봤던 글은 레일즈에 Service/Decorator Layer 적용하기에 정리했었다. 이번에는 Django에서 비즈니스 로직을 관리하는 방법에 대해서 정리해보고자 한다. Django에서 비즈니스 로직을 추가할만한 곳은 크게 4가지이다. 그리고 이들 모두 각각 장/단점을 갖고 있다. model view service queryset / manager 1. Model Django에서 제안하는 비즈니스로직 관리 방식은 Model에 기능을 추가하는 것이다. MVC의 기본 설계 패턴은 Fat Mode..
(Django) CacheOps - ORM에 Redis Cache 쉽게 적용하기 django-cacheops는 Django에 Redis Cache를 쉽게 적용하고, 관리할 수 있도록 도와주는 라이브러리이다. Cacheops의 가장 큰 장점은 ORM에 캐시를 간편하게 적용할 수 있단 점이다. 이번 포스팅에서는 Cacheops의 특징과 주의할점에 대해서 정리해보고자 한다. Cacheops의 특징 A. ORM Cache A-1. 사용방법 모델에서 캐시를 바라보도록 변경하고 싶으면, 설정 파일에 아래와 같은 옵션을 추가해주면 된다. CACHEOPS = { 'auth.user': {'ops': 'get', 'timeout': 60}, } 위와 같이 추가하면, User 모델을 get으로 조회하는 경우, DB보다 캐시를 먼저 바라보게 된다. User.objects.get(user_id=1) 특정..
(Django) cached_property 란? 동일한 인스턴스의 Property를 여러번 호출하는 경우, 중복으로 연산작업을 하게 된다. Property 안에서 호출하는 함수가 비용이 큰 연산작업인 경우, 중복 연산 작업이 API 성능을 크게 떨어트릴 수 있다. Django의 cached_property decorator를 사용하면 이러한 이슈를 해결할 수 있다. cached_property는 처음 호출된 Property 함수 결과값을 캐싱해둔다. 그리고 이후에는 캐싱된 결과값을 리턴한다. 그러면 동일한 Property를 여러번 호출하더라도, 한 번의 연산만 하게 된다. Sample from django.utils.functional import cached_property from weather.utils import WeatherAPI from ..
(saleor) 가독성 좋은 함수명 만들 때 유용한 팁 모음집 이 글은 Django E-commerce OpenSource인 Saleor에서 얻은 팁들을 정리한 문서입니다. 1. 값을 증분할 때는 increase / decrease 동사를 prefix으로 붙인다.def increase_voucher_usage(voucher): voucher.used = F('used') + 1 voucher.save(update_fields=['used']) def decrease_voucher_usage(voucher): voucher.used = F('used') - 1 voucher.save(update_fields=['used']) 2. 상태를 확인할 때에는 is 동사를 prefix으로 붙인다. def is_category_on_sale(category, sale): """..