# Django 6.0 완전 가이드 2026: 복합 기본 키, 백그라운드 태스크, 기술 면접 질문 > Django 6.0의 핵심 기능을 분석합니다. CompositePrimaryKey를 활용한 복합 기본 키, 내장 백그라운드 태스크, 템플릿 파셜, CSP 미들웨어 설정법과 2026년 기술 면접 대비 질문을 코드 예제와 함께 다룹니다. - Published: 2026-06-09 - Updated: 2026-06-09 - Author: SharpSkill - Tags: django, python, composite-primary-keys, background-tasks, csp - Reading time: 8 min --- Django 6.0은 2026년 Python 웹 프레임워크 생태계에서 중대한 전환점을 나타냅니다. 이번 메이저 릴리스는 커뮤니티가 오랜 기간 요청해온 기능들을 프레임워크 코어에 직접 통합합니다. ORM에서의 복합 기본 키 네이티브 지원, 외부 브로커 없이 동작하는 내장 백그라운드 태스크 시스템, 템플릿 파셜을 통한 재사용 가능한 UI 컴포넌트, 그리고 Content Security Policy 미들웨어가 핵심 변경 사항입니다. 각 기능은 서드파티 패키지에 대한 의존도를 줄이고 프로덕션 Django 애플리케이션의 아키텍처를 단순화하는 방향으로 설계되었습니다. > **2026년 Django 버전 타임라인** > > Django는 약 8개월 주기로 메이저 버전을 릴리스합니다. Django 5.2 LTS(2025년 4월)에서 복합 기본 키가 안정 기능으로 최초 도입되었습니다. Django 6.0(2025년 12월)은 이를 ORM 전반에 완전히 통합하면서 백그라운드 태스크 시스템, 템플릿 파셜, CSP 미들웨어를 추가했습니다. Django 6.1은 2026년 8월 출시가 예정되어 있으며, Python 3.12 이상이 필수 요구 사항입니다. ## CompositePrimaryKey를 활용한 복합 기본 키 관계형 데이터베이스에서 복합 기본 키는 두 개 이상의 컬럼 조합으로 레코드를 고유하게 식별하는 방식입니다. Django 5.2 이전까지 이러한 관계를 모델링하려면 `unique_together` 제약 조건이나 서드파티 패키지를 사용하는 우회 방법이 필요했습니다. `CompositePrimaryKey`는 이 문제를 ORM 레벨에서 근본적으로 해결합니다. 가장 대표적인 사용 사례는 두 개의 외래 키 조합이 레코드의 고유 식별자를 구성하는 중간 테이블입니다. 다음 예제는 각 제품이 각 창고에서 보유하는 수량을 나타내는 재고 모델을 정의합니다. ```python # models.py from django.db import models class Product(models.Model): name = models.CharField(max_length=100) sku = models.CharField(max_length=20, unique=True) class Warehouse(models.Model): code = models.CharField(max_length=10, primary_key=True) location = models.CharField(max_length=200) class Inventory(models.Model): pk = models.CompositePrimaryKey("product_id", "warehouse_id") product = models.ForeignKey(Product, on_delete=models.CASCADE) warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE) quantity = models.PositiveIntegerField(default=0) last_restocked = models.DateTimeField(auto_now=True) ``` `pk` 필드는 모델 필드 이름이 아닌 데이터베이스의 실제 컬럼 이름을 인자로 받습니다. Django는 데이터베이스 레벨에서 `PRIMARY KEY (product_id, warehouse_id)` 제약 조건을 생성하며, 자동 증가 `id` 필드 없이도 레코드의 유일성을 보장합니다. 이 접근 방식은 관계형 데이터베이스의 표준 모델링 원칙에 부합합니다. ## ORM에서 복합 키 조회하기 복합 기본 키를 사용하는 모델과의 상호작용은 기존 Django ORM 인터페이스를 그대로 유지합니다. 복합 키는 Python 튜플로 표현되며, 레코드의 생성, 필터링, 할당이 직관적으로 수행됩니다. ```python # views.py from .models import Inventory, Product, Warehouse # Create records laptop = Product.objects.create(name="Laptop Pro", sku="LP-001") warehouse_a = Warehouse.objects.create(code="WH-A", location="Berlin") item = Inventory.objects.create( product=laptop, warehouse=warehouse_a, quantity=50 ) # Access the composite pk as a tuple print(item.pk) # (1, "WH-A") # Filter by composite pk result = Inventory.objects.filter(pk=(1, "WH-A")).first() # Assign a composite pk directly new_item = Inventory(pk=(2, "WH-B")) print(new_item.product_id) # 2 print(new_item.warehouse_id) # "WH-B" ``` 이 기능은 기존 데이터베이스 스키마를 다루거나 복합 키를 이미 지원하는 다른 ORM에서 마이그레이션하는 팀에게 특히 유용합니다. Django Admin, Django REST Framework의 시리얼라이저, 그리고 마이그레이션 시스템 모두 `CompositePrimaryKey`를 사용하는 모델을 자동으로 인식합니다. 기존의 `unique_together` 방식과 달리 불필요한 대리 키(surrogate key) 없이 데이터베이스의 의미론적 무결성을 유지할 수 있습니다. ## @task 데코레이터를 활용한 내장 백그라운드 태스크 Django 6.0은 프레임워크 내부에 백그라운드 태스크 시스템을 직접 통합합니다. `django.tasks` 모듈은 `@task` 데코레이터와 `.enqueue()` 메서드를 제공하여, 외부 메시지 브로커나 별도의 워커 프로세스를 구성하지 않고도 함수 실행을 비동기로 지연시킬 수 있습니다. 이 시스템은 HTTP 요청-응답 사이클을 차단해서는 안 되는 일반적인 작업을 대상으로 합니다. 이메일 발송, 리포트 생성, 파일 처리, 외부 API 호출 등이 대표적입니다. 태스크 정의는 Django의 기존 관례에 따라 각 앱의 `tasks.py` 모듈에서 수행합니다. ```python # tasks.py from django.tasks import task from django.core.mail import send_mail @task def send_welcome_email(user_email, username): """Send a welcome email after user registration.""" send_mail( subject="Welcome to the platform", message=f"Hello {username}, your account is ready.", from_email=None, # uses DEFAULT_FROM_EMAIL recipient_list=[user_email], ) return f"Email sent to {user_email}" @task def generate_report(report_id, format="pdf"): """Generate an export report asynchronously.""" from .services import ReportService report = ReportService.generate(report_id, format=format) return report.file_path ``` 뷰에서 태스크를 디스패치할 때는 `.enqueue()` 메서드를 사용합니다. 이 메서드는 인자를 직렬화하여 설정된 백엔드로 전달하고, 태스크가 비동기적으로 실행되도록 예약합니다. ```python # views.py from .tasks import send_welcome_email, generate_report def register_user(request): # ... user creation logic ... # Enqueue the task for background execution send_welcome_email.enqueue( user_email=user.email, username=user.username ) return redirect("dashboard") def export_view(request, report_id): generate_report.enqueue(report_id=report_id, format="csv") return JsonResponse({"status": "processing"}) ``` Django 6.0은 데이터베이스 기반의 기본 백엔드와 함께 더 높은 처리량이 필요한 시나리오를 위한 Redis 백엔드를 제공합니다. `settings.py`에서 백엔드 선택, 워커 수, 폴링 간격 등의 파라미터를 조정할 수 있습니다. > **내장 백그라운드 태스크 vs Celery** > > Django 6.0의 네이티브 태스크 시스템은 단순하거나 중간 수준의 비동기 작업을 효율적으로 처리합니다. 그러나 고급 큐 라우팅, 복잡한 워크플로우(chain, chord, group), 지수 백오프를 포함한 세밀한 재시도 정책, 또는 여러 서버에 걸친 분산 처리가 필요한 경우에는 [Celery](/ko/blog/django/django-celery-async-tasks-interview-2026)가 여전히 적합한 도구입니다. 내장 태스크는 fire-and-forget 패턴에 최적화되어 있고, Celery는 엔터프라이즈 수준의 태스크 오케스트레이션에 적합합니다. ## 템플릿 파셜: 재사용 가능한 UI 프래그먼트 Django의 템플릿 엔진에 프론트엔드 프레임워크에서는 이미 기본 기능으로 자리잡은 기능이 추가됩니다. 하나의 파일 내에서 재사용 가능한 프래그먼트를 정의하고 선택적으로 참조할 수 있는 기능입니다. `{% partialdef %}` 태그와 `{% partial %}` 태그를 사용하면 여러 UI 컴포넌트를 단일 템플릿 파일에 묶어두고 필요한 프래그먼트만 선택적으로 사용할 수 있습니다. 다음 예제는 하나의 제품에 대해 카탈로그 뷰용 카드와 재고 테이블용 행이라는 두 가지 시각적 표현을 동일한 템플릿 파일에 정의합니다. ```html {% partialdef product_card %}
{{ product.price|floatformat:2 }} EUR
{% if product.in_stock %}In Stock{% else %}Sold Out{% endif %}