Django dan Next.js adalah pasangan yang populer. Django membawa ORM yang matang, migrasi database, panel admin, dan ekosistem Python yang besar. Next.js membawa server rendering, navigasi yang cepat, dan ekosistem React. Kombinasi ini bekerja dengan baik, tapi masalah biasanya muncul di batas antara keduanya: autentikasi yang gagal antar domain, error CORS, tipe data yang tidak lagi sama, dan cache yang menampilkan data lama. Artikel ini membahas keputusan-keputusan yang membuat pasangan ini nyaman dipakai.
Kapan Backend dan Frontend Perlu Dipisah
API dan frontend yang terpisah menambah komponen yang harus dikelola, jadi pastikan ada manfaatnya. Pemisahan ini layak dilakukan kalau API yang sama melayani aplikasi web dan aplikasi mobile, ketika frontend butuh interaksi yang kaya atau SEO yang kuat lewat server rendering, atau ketika backend dan frontend dikerjakan tim yang berbeda. Untuk aplikasi internal yang isinya form dan tabel sederhana, template Django atau Django admin saja mungkin lebih cepat selesai. Banyak proyek memakai keduanya: Next.js untuk halaman yang dilihat pelanggan, dan Django admin untuk back office.
Struktur Proyek
- Simpan proyek Django dan aplikasi Next.js di satu repository dengan dua folder, supaya fitur yang menyentuh keduanya cukup satu perubahan dan satu review.
- Bagi Django menjadi beberapa app per domain bisnis, misalnya orders, billing, dan accounts.
- Beri versi pada API dengan prefix seperti /api/v1/ sejak awal, supaya aplikasi mobile yang tidak bisa langsung update tetap berjalan.
- Pakai satu file docker compose untuk development lokal yang menjalankan PostgreSQL, Redis, Django, dan Next.js sekaligus.
Autentikasi: Jauhkan Token dari JavaScript
Kesalahan yang paling sering adalah menyimpan JWT di localStorage, tempat script apa pun yang berhasil disisipkan bisa membacanya. Pilihan yang lebih aman menyimpan kredensial di cookie httpOnly. Kalau frontend dan API berada di domain induk yang sama, misalnya app.example.com dan api.example.com, autentikasi session bawaan Django dengan token CSRF bekerja dengan baik dan mudah dicabut. Kalau butuh JWT, misalnya karena aplikasi mobile memakai API yang sama, djangorestframework-simplejwt bisa menerbitkan token yang diterima aplikasi web sebagai cookie httpOnly. Pilihan lain yang rapi adalah meneruskan panggilan API lewat rewrites di Next.js, sehingga browser hanya melihat satu origin dan masalah CORS hilang sama sekali.
Pengaturan CORS dan CSRF yang Benar
| Pengaturan | Fungsinya | Nilai yang umum |
|---|---|---|
| CORS_ALLOWED_ORIGINS | Origin frontend mana saja yang boleh memanggil API dari browser | URL Next.js yang persis untuk setiap environment, jangan wildcard di production |
| CORS_ALLOW_CREDENTIALS | Mengizinkan cookie ikut terkirim di request lintas origin | True kalau memakai autentikasi berbasis cookie |
| CSRF_TRUSTED_ORIGINS | Origin mana saja yang boleh mengirim request seperti POST dengan token CSRF | URL frontend yang sama, lengkap dengan skemanya |
| SESSION_COOKIE_SAMESITE dan CSRF_COOKIE_SAMESITE | Mengatur kapan browser mengirim cookie | Lax untuk domain induk yang sama |
CORS ditangani dengan package django-cors-headers. Kalau request gagal, cek dulu tab network di browser. Respons preflight OPTIONS biasanya menyebutkan dengan jelas header atau origin mana yang ditolak.
Berbagi Tipe Lewat Skema OpenAPI
Tanpa kontrak yang jelas, frontend dan backend lama-lama tidak sinkron, biasanya gara-gara ada field yang diganti nama tanpa kabar. Buat skema OpenAPI dari serializer dan view DRF dengan drf-spectacular, lalu buat tipe TypeScript atau client yang sudah bertipe dengan tool seperti openapi-typescript. Jalankan proses ini di CI dan buat build gagal kalau frontend tidak lagi cocok dengan skema terbaru. Jadi kalau ada field yang diganti namanya, build langsung gagal dan halaman di production tetap aman.
Mengambil Data di Next.js
- Ambil data di Server Components kalau data itu dibutuhkan untuk tampilan pertama atau untuk SEO, dan teruskan cookie pengguna kalau request-nya perlu autentikasi.
- Tentukan cache secara eksplisit untuk setiap request: data katalog publik boleh di-cache dan diperbarui berkala, sedangkan data milik pengguna sebaiknya tidak di-cache.
- Pakai library di sisi client seperti TanStack Query untuk data yang berubah selama pengguna membuka halaman, misalnya notifikasi atau status terkini.
- Tangani error API di satu tempat, supaya pengguna dengan session kedaluwarsa langsung diarahkan ke halaman login.
Jaga API Tetap Cepat
Serializer bertingkat sangat mudah memicu ratusan query untuk satu endpoint list. Pakai select_related untuk foreign key dan prefetch_related untuk relasi many-to-many dan relasi balik, lalu cek jumlah query di test atau dengan Django Debug Toolbar saat development. Beri pagination di setiap endpoint list. Pindahkan pekerjaan yang lambat, seperti mengirim email, membuat PDF, atau memanggil payment gateway, ke background job dengan Celery dan Redis, supaya API merespons dengan cepat dan proses ulang bisa dilakukan dengan aman.
Deployment
- 1Buat Docker image untuk Django yang menjalankan gunicorn, atau uvicorn kalau memakai async view, dengan collectstatic dijalankan saat build.
- 2Jalankan migrasi database sebagai langkah terpisah sebelum versi baru menerima trafik.
- 3Deploy Next.js sebagai server Node.js atau di platform yang mendukungnya, dengan URL API diberikan lewat environment variable di setiap environment.
- 4Pasang HTTPS untuk keduanya dengan domain yang sudah direncanakan untuk cookie dan CORS, lalu set DEBUG ke False dan ALLOWED_HOSTS yang ketat di production.
- 5Tambahkan health check untuk kedua layanan, lalu pantau latency dan error rate API.
Siapkan autentikasi di kedua aplikasi pada minggu pertama, dengan domain yang sama seperti nanti di production. Masalah cookie dan CORS jauh lebih mudah diperbaiki selagi aplikasinya masih kecil.
Poin penting
- Pisahkan Django dan Next.js kalau API melayani beberapa jenis client, frontend butuh server rendering, atau tiap sisi dipegang tim yang berbeda.
- Simpan kredensial di cookie httpOnly, baik dengan session dan CSRF maupun JWT di cookie, dan jangan simpan token di localStorage.
- Atur CORS dan CSRF dengan origin yang persis, atau teruskan panggilan API lewat rewrites Next.js supaya tidak perlu CORS sama sekali.
- Buat tipe TypeScript dari skema drf-spectacular dan cek di CI.
- Hindari N+1 query, beri pagination di setiap list, dan pindahkan pekerjaan lambat ke Celery.


