확실히 알고 쓰자: Django (1)

이규락·2022년 10월 22일
0

확실히 알고 쓰자

목록 보기
1/2
post-custom-banner

1. Django의 장점

  1. 다양한 기능들이 내부에 구현되어 있어 이를 구현하는데 필요한 리소스가 줄어들어요. (django-admin, django.contrib.sessions 등등...)
  2. 강력한 orm을 기본으로 제공해요.
  3. 프로젝트를 app 단위로 기본 세팅할 수 있어 도메인 별 분업이 수월한 편이에요.

2. Django ORM의 Lazy Loding과 N+1 문제

  • Lazy Loading이란?

    Django ORM은 쿼리를 선언했을 때 바로 데이터를 가져오는 것이 아닌 실제 데이터가 필요할 때 쿼리를 호출해 데이터를 가져오게 되는데, 이를 Lazy Loading이라 해요. 이때 실제로 데이터를 가져오는 경우는 다음과 같은 것 등이 있어요.

    __repr__
    list()
    len()
    bool()
    slicing # index slicing 및 ORM의 .first() 등등.

  • N+1 문제란?

    외래키를 포함한 데이터를 조회할 때 Lazy Loding 때문에 발생하는 문제로, 실제 필요한 데이터를 다른 테이블에서 얻어야 할 때 실제 호출해야하는 쿼리보다 한 번 더 쿼리를 호출하는 문제에요. 예를 들어,

    post = Post.objects.get(id=1) # hit!
    comments = post.comment_set.all() # hit!

    이렇게 글에 해당되는 댓글 데이터를 가져오는 쿼리를 작성했을 때, 실제 쿼리 호출 횟수는 post를 가져올 때 한 번 post에 해당하는 comments를 가져올 때 한 번 총 두 번 발생해요. 위의 예시같은 경우에는 두 번 쿼리가 실행된 게 큰 문제는 아니라고 할 수 있지만, 만약 가져와야 하는 데이터가 많을 경우, 심각한 성능 저하로 이어질 수 있어요.

  • 해결책

    이렇게 불러와야할 데이터가 많은 경우 사용하는 방법이 바로 Eagar Loding이에요. Eagar Loding은 데이터가 필요할 때마다 DB를 hit하는 것이 아니라, 우선 모든 데이터를 가져와 캐싱해 필요할 때 마다 꺼내 쓰는 방식이에요. 앞의 예시를 Eagar Loding으로 바꿔보면,

    post = Post.objects.prefetch_related('comment_set').get(id=1) # hit!
    comments = post.comment_set.all() # using cache

    이렇게 prefetch_related를 사용해 필요한 정보들을 모두 캐싱 해놓고 이후 캐싱한 정보들을 가져오면 실질적인 쿼리 호출 횟수는 1번으로 제한할 수 있어요. (정참조 관계에서는 select_related를 사용하면 돼요.)

3. MTV 패턴이란?

MTV 패턴은 Model(모델) - Template(템플릿) - View(뷰)로 구성되어 있는 디자인 패턴이에요

모델은 어플리케이션의 데이터를 가지고 있는 역할을 하며, 하나의 모델은 하나의 테이블과 매칭돼요.

템플릿은 유저에게 보여지는 화면을 의미하며 뷰에서 처리된 로직을 html로 유저에게 보여주는 역할을 해요.

뷰는 요청에 따른 로직을 처리하며, 이 결과를 템플릿으로 랜더링 하는 역할을 해요. 그리고 이 뷰와 URL을 매핑하는 역할을 하는 URLconf라는 단계가 하나 더 추가돼요.

4. Django의 커넥션 풀 관리

Django는 기본적으로 모든 요청마다 커넥션을 맺고 끊어요. 하지만 settingsDATABASES에서 CONN_MAX_AGE 를 설정해 커넥션을 재활용 할 수 있어요.

다만 이는 요청으로 맺어진 커넥션을 관리하는 수단이기 때문에 배치 등등의 작업으로 맺어진 커넥션은 관리가 어려워요. 추가로 Django는 기본적으로 하나의 쓰레드당 하나의 커넥션을 맺는데 만약 멀티 쓰레딩을 했고, 배치와 같은 작업을 한다면 해당 커넥션이 Idle 상태에 빠질 수도 있어요.

이를 방지하기 위해 로직의 마지막에는 항상 명시적으로 커넥션을 끊어주는 것이 좋아요.

from django import db
db.connections.close_all()

profile
python을 주로 다루는 주니어 개발자 입니다.
post-custom-banner

0개의 댓글