오늘의 호기심 해결 주제는 Django의 request.session.get()이 성능 저하를 일으키는가? 입니다! 🎯
Django 개발을 하면서 request.session.get('key_name')
을 여러 번 호출하는 경우가 많죠? 그런데 문득 이런 생각이 들었습니다.
"세션도 결국 DB에 저장되는 거라면,
request.session.get()
을 호출할 때마다 DB 쿼리가 발생하는 걸까?""아니면 Django가 뭔가 똑똑한 처리를 해두어서 추가적인 쿼리가 발생하지 않는 걸까?"
이 궁금증을 해결하기 위해 Django의 SessionMiddleware 소스 코드 깊숙한 곳까지 파헤쳐 보고, 실험을 통해 확인해보았습니다. 🚀
1️⃣ Django에서 request.session은 어떻게 생성될까?
Django가 request 객체를 만들 때 세션을 언제 로드하는지 알아보겠습니다.
우리는 보통 뷰 함수에서 이렇게 세션 데이터를 가져옵니다.
session_username = request.session.get('username')
그런데 request.session.get('username')
을 사용할 때마다 Django가 DB 쿼리를 날리는 것이라면, 성능에 큰 영향을 미칠 수도 있겠죠?
🔍 Django 내부를 살펴보자!
사실 Django는 SessionMiddleware
라는 미들웨어를 통해 요청이 들어올 때 세션 데이터를 미리 로드해둡니다. 이 과정에서 DB 쿼리가 딱 한 번 발생하고, 이후에는 request 객체 안에 세션 데이터를 유지하게 됩니다.
Django의 SessionMiddleware
코드를 보면 다음과 같은 처리가 이루어집니다.
class SessionMiddleware(MiddlewareMixin):
def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)
📌 여기서 중요한 점!
- ✅
request.COOKIES
에서 세션 키(session_key
)를 가져온다. - ✅
self.SessionStore(session_key)
를 호출하여, 세션 데이터를 한 번만 DB에서 가져와 request.session에 저장한다. - ✅ 즉, 뷰 함수에서
request.session.get()
을 여러 번 호출하더라도 추가적인 DB 쿼리는 발생하지 않는다! 🎯
2️⃣ request.session.get()은 DB 쿼리를 발생시키는가?
이제 핵심 질문으로 돌아가 보겠습니다.
"뷰에서
request.session.get('username')
을 호출하면 DB 쿼리가 발생하는가?"
🚀 결론부터 말하면, request.session.get()
을 호출해도 추가적인 DB 쿼리는 발생하지 않습니다.
이유는 간단합니다.
✔ Django는 요청이 들어올 때 세션 데이터를 한 번 로드한 후, request.session
에 저장합니다.
✔ 이후 request.session.get()
을 호출하는 것은 이미 메모리에 로드된 데이터를 가져오는 것이므로 추가적인 DB 조회가 필요하지 않습니다.
실제로 DB에서 세션을 조회하는 순간은 요청 초기에 한 번뿐입니다. 이때 실행되는 SQL 쿼리는 다음과 같습니다.
SELECT session_data FROM django_session WHERE session_key = 'xyz123' LIMIT 1;
즉, ✅ 뷰에서 request.session.get()
을 여러 번 호출해도 Django는 추가적인 DB 쿼리를 실행하지 않는다!
✅ DB에서 데이터를 불러오는 것은 요청이 처음 발생했을 때 단 한 번만 실행된다!
3️⃣ 템플릿에서 세션 데이터를 사용할 때도 쿼리가 발생할까?
"뷰에서 세션 데이터를 조회한 뒤 템플릿으로 넘기고, 템플릿에서 이를 사용할 때도 추가적인 DB 쿼리가 발생할까?"
예를 들어, 뷰에서 세션 데이터를 이렇게 넘긴다고 가정해봅시다.
def my_view(request):
session_username = request.session.get('username') # DB 조회 발생? ❌
return render(request, 'my_template.html', {'session_username': session_username})
그리고 템플릿에서 이렇게 사용한다고 해볼게요.
<p>Logged in as: {{ session_username }}</p>
이 경우에도 추가적인 DB 쿼리는 발생하지 않습니다!
✔ session_username
은 이미 request.session에서 가져온 값이므로, Django가 이를 템플릿으로 넘길 때 추가적인 DB 조회는 필요하지 않습니다.
✔ Django는 request.session
을 메모리 캐시처럼 관리하기 때문에, 템플릿에서도 안전하게 사용할 수 있습니다.
4️⃣ 세션 데이터를 변경하면 DB에 저장될까?
"그럼 request.session['username'] = 'new_value'처럼 데이터를 변경하면?"
🚀 이 경우에는 DB에 변경 사항이 저장되면서 추가적인 DB 쿼리가 발생합니다!
만약 아래와 같이 세션 데이터를 변경하면,
request.session['username'] = 'new_value'
Django는 응답을 보낼 때 변경된 세션 데이터를 DB에 저장합니다. 이때 실행되는 SQL 쿼리는 다음과 같습니다.
UPDATE django_session SET session_data = 'new_value' WHERE session_key = 'xyz123';
✔ 세션을 읽는 것은 DB 쿼리를 발생시키지 않지만, 세션을 변경하면 Django가 이를 저장하기 위해 DB에 쿼리를 실행합니다.
5️⃣ 세션 저장 방식(백엔드)에 따른 차이
Django에서는 세션을 저장하는 방식(백엔드)을 변경할 수 있습니다. 백엔드에 따라 쿼리 발생 여부가 달라질 수 있음을 주의해야 합니다.
세션 백엔드 | 설명 | DB 쿼리 발생 여부 |
---|---|---|
django.contrib.sessions.backends.db |
기본 DB 기반 세션 | ✅ 요청 시 한 번 발생 |
django.contrib.sessions.backends.cache |
캐시 기반 세션 (Redis, Memcached) | ❌ DB 쿼리 없음 |
django.contrib.sessions.backends.cached_db |
캐시 + DB 세션 (캐시 없으면 DB 조회) | 🚀 캐시에 없으면 발생 |
django.contrib.sessions.backends.signed_cookies |
쿠키 기반 세션 | ❌ DB 쿼리 없음 |
🚀 즉, cache
나 signed_cookies
백엔드를 사용하면 DB 쿼리 없이 세션을 가져올 수도 있습니다. ✔ 성능이 중요한 경우 CACHED_DB_SESSION
을 고려하는 것도 좋은 방법입니다.
🎯 결론
- ✅ Django는 요청(Request) 초기에
SessionMiddleware
를 통해 세션 데이터를 미리 로드하여request.session
객체에 저장합니다. - ✅ 따라서, 뷰에서
request.session.get('username')
을 호출하는 것은 추가적인 DB 쿼리를 발생시키지 않습니다. - ✅ 템플릿에서 세션 데이터를 사용할 때도 추가적인 DB 쿼리는 발생하지 않습니다.
- ✅ 하지만, 세션 값을 변경하면 Django가 응답을 보낼 때 DB에 변경된 데이터를 저장합니다.
- ✅ Django의 세션 백엔드 설정에 따라 쿼리 발생 여부가 다를 수 있으므로, 캐시 기반(
cache
또는cached_db
)을 사용하면 DB 부하를 줄일 수 있습니다.
🔥 다음 화 예고: request
객체는 언제 사라질까?
그렇다면 request
객체는 언제 사라질까요?
-
요청이 끝나도 계속 메모리를 차지하고 있는 걸까요?
-
시스템에서 자동으로 청소해주나요, 아니면 우리가 직접 정리해야 할까요?
🚀 다음 화에서는 Django의 request
객체의 수명과 메모리 관리에 대해 탐구해 보겠습니다! 기대해 주세요! 😃
Add a New Comment