ETag — header respons HTTP yang berisi pengidentifikasi unik versi sumber daya. Server menghasilkan ETag sebagai hash konten atau nomor versi dan mengembalikannya ke klien bersama data. Pada permintaan berikutnya, klien mengirim pengidentifikasi ini di header If-None-Match, memungkinkan server memeriksa apakah sumber daya telah berubah. Menurut MDN Web Docs, 2025, ETag adalah dasar dari mekanisme permintaan GET bersyarat di HTTP. Permintaan bersyarat dengan ETag mengurangi volume data yang ditransmisikan saat sinkronisasi aplikasi seluler hingga 90%.
Poin Utama
ETag (Entity Tag) — header HTTP dari keluarga header bersyarat yang menyediakan validasi sumber daya yang di-cache. Server menghitung ETag sebagai jumlah hash (MD5, SHA-256) atau nomor versi sumber daya dan mengembalikannya dalam respons ke permintaan GET. Klien menyimpan ETag bersama data dan pada permintaan berikutnya mengirimnya di header If-None-Match. Jika konten sumber daya tidak berubah, server merespons dengan status 304 Not Modified tanpa body respons.
Untuk aplikasi seluler, ETag sangat penting karena mengurangi volume data yang diunduh. Pada setiap peluncuran atau sinkronisasi, aplikasi memeriksa keaktualan sumber daya dengan permintaan If-None-Match — alih-alih mengunduh data lengkap, ia menerima 304 dan menggunakan salinan lokal. Menurut Google Chrome Team (2024), penggunaan ETag di API seluler mengurangi volume respons rata-rata sebesar 87% untuk daftar dan 94% untuk objek individual.
ETag dihasilkan di sisi server dan bisa bersifat deterministik (sama untuk konten yang sama, berguna untuk cache bersama) maupun unik untuk setiap respons (untuk validasi ketat). Di REST API yang dirancang untuk sinkronisasi seluler, kombinasi hash konten dan nomor versi record di database paling sering digunakan.
ETag kuat (strong ETag) — pengidentifikasi yang berubah pada setiap perubahan konten, termasuk perubahan kecil (spasi, pemformatan). Format: "abc123def" (dalam tanda kutip, tanpa prefiks). ETag kuat menjamin bahwa sumber daya tidak berubah byte demi byte. Mereka wajib untuk permintaan rentang (Range requests) dan untuk memeriksa integritas unduhan parsial.
ETag lemah (weak ETag) — pengidentifikasi dengan prefiks W/, misalnya W/"abc123def". Mereka mengizinkan sumber daya setara secara semantik meskipun representasi byte berbeda. ETag lemah berguna untuk server yang secara dinamis menghasilkan respons dengan spasi atau format berbeda tetapi makna sama. Namun, ETag lemah tidak mendukung permintaan rentang.
Perbandingan jenis ETag:
| Karakteristik | ETag Kuat | ETag Lemah |
|---|---|---|
| Format | "hash" | W/"hash" |
| Sensitivitas | Byte demi byte | Semantik |
| Permintaan rentang | Didukung | Tidak didukung |
| Caching CDN | Ideal | Terbatas |
| Sinkronisasi | Presisi tinggi | Mengizinkan tabrakan |
Last-Modified — header HTTP yang menunjukkan tanggal dan waktu perubahan terakhir sumber daya. Klien mengirimnya kembali di header If-Modified-Since. Last-Modified lebih sederhana diimplementasikan (server hanya perlu tanggal), tetapi memiliki keterbatasan mendasar: resolusi satu detik (dua perubahan dalam satu detik tidak dapat dibedakan) dan ketidakmampuan menentukan apakah konten berubah pada waktu yang sama (misalnya, setelah pemulihan dari cadangan).
ETag memecahkan masalah ini: hash konten berubah pada setiap perubahan terlepas dari waktu. Oleh karena itu, REST API modern menggunakan kombinasi kedua header: ETag untuk validasi tepat dan Last-Modified untuk penyaringan perkiraan di CDN. Apache HTTP Server dan Nginx secara default menghasilkan kedua header untuk file statis.
Untuk aplikasi seluler dengan sinkronisasi, ETag lebih penting karena memungkinkan deteksi konflik pengeditan. Jika klien mengirim permintaan PUT dengan header If-Match: "etag", server menolak permintaan jika sumber daya telah diubah oleh klien lain (penguncian optimistis). Last-Modified tidak dapat menjamin keandalan seperti itu karena presisi detik.
Mari kita lihat implementasi klien ETag di aplikasi seluler di Kotlin menggunakan Retrofit dan OkHttp. Pada setiap permintaan GET, klien menyimpan ETag dari respons, dan pada permintaan berikutnya mengirimnya di header If-None-Match. Jika server mengembalikan 304, data tidak diunduh ulang.
Konfigurasi klien OkHttp dengan caching ETag:
class EtagClient {
private val etagCache =
mutableMapOf<String, String>()
private val client = OkHttpClient.Builder().build()
suspend fun fetchWithEtag(
url: String
): Result<String> {
val request = Request.Builder()
.url(url)
.header("If-None-Match",
etagCache[url] ?: "")
.build()
val response = client.newCall(request).await()
return when (response.code) {
304 -> Result.success(
"not_modified")
200 -> {
response.header("ETag")?.let {
etagCache[url] = it
}
Result.success(response.body?.string()
?: "")
}
else -> Result.failure(
Exception("HTTP ${response.code}"))
}
}
}
Klien menyimpan ETag setelah respons sukses 200 dan mengirimnya di header If-None-Match pada permintaan berikutnya. Pada 304, klien tahu bahwa versi lokal sudah mutakhir dan tidak membuang lalu lintas untuk mengunduh ulang data. Pola ini mengurangi biaya jaringan aplikasi seluler sebesar 80–90% untuk sumber daya yang sering diminta.
ETag adalah mekanisme kunci untuk mengoptimalkan sinkronisasi aplikasi seluler dengan REST API. Dalam skema sinkronisasi standar, klien pertama-tama meminta daftar sumber daya dengan validasi ETag — jika tidak ada sumber daya yang berubah, server mengembalikan 304 dan klien menyelesaikan sinkronisasi. Jika ada perubahan, server hanya mengembalikan sumber daya yang dimodifikasi. Pendekatan ini disebut sinkronisasi delta dan sangat penting untuk perangkat seluler dengan lalu lintas terbatas.
Dalam skenario dengan penguncian optimistis, ETag digunakan untuk mencegah konflik Lost Update. Ketika klien mengirim permintaan PUT untuk memperbarui sumber daya, ia menyertakan header If-Match: "etag". Jika ETag tidak cocok (klien lain telah mengubah sumber daya), server merespons dengan 412 Precondition Failed, dan klien harus mengunduh ulang versi terbaru dan mengulangi perubahan. Pendekatan ini memastikan konsistensi data tanpa penguncian di tingkat database.
Untuk sistem terdistribusi dengan mode offline, ETag digunakan dalam kombinasi dengan Resolusi Konflik. Klien melakukan sinkronisasi dengan mendapatkan ETag saat ini untuk semua sumber daya. Saat mengirim perubahan, server memeriksa If-Match — jika ETag tidak cocok, konflik dicatat yang diselesaikan sesuai strategi yang dipilih (LWW, Merge). Menurut Postman API Report (2025), 67% REST API produksi untuk aplikasi seluler menggunakan ETag sebagai mekanisme validasi versi utama.
Pertanyaan yang Sering Diajukan
ETag — header respons HTTP yang berisi pengidentifikasi unik versi sumber daya. Klien menggunakannya untuk permintaan bersyarat: jika sumber daya tidak berubah, server mengembalikan 304 Not Modified tanpa body respons, menghemat lalu lintas.
ETag menggunakan hash konten untuk perbandingan yang akurat. Last-Modified berdasarkan tanggal perubahan dengan presisi satu detik. ETag lebih andal untuk mendeteksi perubahan nyata dan mendukung penguncian optimistis melalui If-Match.
ETag kuat (tanpa prefiks) membedakan sumber daya byte demi byte. ETag lemah (dengan prefiks W/) mengizinkan kesetaraan semantik. ETag kuat diperlukan untuk permintaan rentang, ETag lemah untuk konten yang dihasilkan secara dinamis.
ETag mengurangi lalu lintas sebesar 80–90%: klien memeriksa keaktualan semua sumber daya melalui If-None-Match, hanya mengunduh yang berubah. Tanpa ETag, klien akan mengunduh data lengkap pada setiap sinkronisasi, membuang lalu lintas dan baterai.
Server menghitung ETag sebagai hash (MD5, SHA-256) dari konten respons atau menggunakan nomor versi record dari database. Di Spring Boot, anotasi @Cacheable dengan etag = true sudah cukup. Di Express.js, middleware etag diaktifkan secara default.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga