Biar Gak Pusing Lagi Yuk Handle Error API Kita Secara Konsisten

Biar Gak Pusing Lagi Yuk Handle Error API Kita Secara Konsisten
Photo by Nong/Unsplash

Pernah gak sih kita lagi asik ngoding di tengah malam lalu tiba tiba aplikasi frontend langsung crash hanya karena endpoint backend ngirim response HTML error 500 yang panjang banget? Momen seperti itu pasti bikin pusing kepala dan bikin suasana ngoding langsung hancur seketika. Masalah error handling yang berantakan memang sering menjadi musuh utama bagi para developer. Ketika aplikasi kita tumbuh makin besar dan tim dev makin bertambah, cara kita mengelola kesalahan di sistem akan menentukan seberapa nyaman kita dalam bekerja. Jika setiap endpoint memiliki gaya error response yang berbeda beda, maka tim frontend akan terus menerus kebingungan saat melakukan integrasi data. Oleh karena itu, mari kita bahas cara mengelola error API secara konsisten agar proses development aplikasi kita menjadi jauh lebih rapi, cepat, dan pastinya menyenangkan.

Mengapa Error Handling API yang Konsisten Itu Penting Banget

Ketika kita membangun sebuah Web API atau RESTful API, fokus kita sering kali hanya tertuju pada fitur fitur utama yang berjalan sukses. Kita sangat semangat membuat endpoint registrasi, pengiriman data, hingga proses pembayaran. Namun kenyataan di lapangan menunjukkan bahwa aplikasi kita akan sering menghadapi situasi tidak terduga. Input dari user yang tidak sesuai format, database yang mendadak timeout, atau server pihak ketiga yang sedang mengalami gangguan adalah situasi yang sangat lumrah terjadi.

Jika kita tidak menyiapkan penanganan kesalahan yang matang, aplikasi kita akan merespon dengan cara yang tidak elegan. Frontend akan menerima pesan kesalahan yang asal asalan atau bahkan stack trace mentah dari server backend. Hal ini sangat berbahaya dari sisi keamanan informasi dan sangat menyulitkan teman ngoding kita di bagian frontend. Penanganan error yang rapi dan seragam akan membuat komunikasi antara frontend dan backend menjadi sangat lancar. Frontend dev bisa dengan mudah menangkap tipe error yang terjadi, lalu menampilkan pesan visual yang ramah kepada pengguna tanpa perlu membuat banyak pengkondisian yang rumit di kode mereka.

Selain memudahkan tim frontend, konsistensi ini juga membantu kita saat melakukan proses debugging di kemudian hari. Saat bug muncul di lingkungan produksi, kita tidak perlu menghabiskan waktu berjam jam hanya untuk mencari tahu arti dari sebuah error message. Kita bisa langsung melacak sumber masalah dengan melihat kode error internal yang sudah terdefinisi dengan jelas. Pengalaman ngoding kita pun akan terasa jauh lebih tenang dan teratur.

Standar HTTP Status Code yang Wajib Kita Pahami

Langkah pertama yang harus kita lakukan untuk menyatukan persepsi adalah memanfaatkan HTTP status code secara benar dan proporsional. Masih banyak project yang mengembalikan status code 200 OK padahal di dalam body JSON jelas jelas tertulis bahwa proses tersebut gagal. Praktik seperti ini sangat membingungkan karena membohongi sistem HTTP parser dan library client seperti Axios atau Fetch.

Mari kita bagi kelompok status code yang sering kita gunakan ke dalam kategori yang tepat.

Kelompok status 2xx menandakan bahwa request berhasil diproses dengan baik. Kita bisa menggunakan status 200 OK untuk response standar, status 201 Created saat berhasil menambahkan data baru ke database, dan status 204 No Content saat proses penghapusan data berhasil tanpa perlu mengembalikan payload data.

Kelompok status 4xx menandakan bahwa terjadi kesalahan dari sisi client. Jika client mengirimkan parameter data yang salah atau tidak lengkap, kita wajib mengembalikan status 400 Bad Request. Jika user belum melakukan login atau token JWT sudah kadaluarsa, kita kembalikan status 401 Unauthorized. Jika user sudah login tetapi tidak memiliki hak akses untuk fitur tertentu, status 403 Forbidden adalah pilihan yang sangat pas. Lalu jika data yang dicari tidak ditemukan di database, gunakanlah status 404 Not Found secara konsisten.

Kelompok status 5xx adalah area khusus untuk kesalahan yang berasal dari server kita sendiri. Jika terjadi panic pada aplikasi, koneksi database terputus, atau ada unhandled exception, kembalikan status 500 Internal Server Error. Jangan pernah melempar kesalahan sistem internal ini menjadi status 4xx hanya karena ingin menyembunyikan bug backend. Kejujuran dalam status code ini akan mempermudah pemantauan performa server kita secara keseluruhan.

Structuring Payload Error Response JSON yang Seragam

Setelah menentukan HTTP status code yang pas, langkah krusial berikutnya adalah menetapkan struktur JSON response yang konsisten untuk semua error. Kita tidak boleh membuat satu endpoint mengembalikan format JSON berupa string langsung, sementara endpoint lain mengembalikan JSON berupa object bertingkat.

Struktur standar yang baik idealnya memiliki beberapa properti penting. Properti pertama adalah status yang bernilai boolean false atau string error untuk memperjelas keadaan. Properti kedua adalah message yang berisi deskripsi singkat dan mudah dipahami oleh manusia. Properti ketiga adalah code atau errorCode yang berisi kode unik internal untuk identifikasi bug secara cepat. Properti keempat adalah timestamp yang mencatat waktu pasti kapan kesalahan tersebut terjadi di server.

Jika kesalahan tersebut disebabkan oleh validasi form, kita bisa menambahkan properti details atau errors yang berisi daftar spesifik field mana saja yang gagal divalidasi. Misalnya field email tidak boleh kosong atau password kurang dari delapan karakter. Dengan struktur yang teratur seperti ini, tim frontend hanya perlu membuat satu fungsi interceptor atau helper untuk menangani semua bentuk error di seluruh aplikasi. Kode frontend menjadi sangat bersih dan tidak dipenuhi oleh blok switch case yang melelahkan.

Memanfaatkan Global Exception Handler dalam Project Kita

Menulis blok try catch di setiap controller atau handler function adalah cara lama yang sangat melelahkan dan rentan membuat kode kita kotor. Jika kita lupa menuliskan try catch di satu endpoint saja, aplikasi bisa langsung crash atau memberikan response default dari framework yang bentuknya acak acakan.

Solusi paling elegan untuk masalah ini adalah dengan mengimplementasikan Global Exception Handler atau Error Handling Middleware. Hampir semua framework modern saat ini, seperti Express di Node.js, Spring Boot di Java, Laravel di PHP, maupun Gin di Go, mendukung mekanisme ini dengan sangat baik.

Dengan menggunakan Global Exception Handler, semua exception atau error yang terlempar di layer manapun, baik itu di service layer, repository layer, maupun controller, akan ditangkap di satu tempat terpusat. Di dalam middleware terpusat ini, kita bisa mengatur transformasi dari exception menjadi struktur JSON error yang sudah kita sepakati sebelumnya. Jika error tersebut adalah kustom exception buatan kita, kita tinggal membaca properti di dalamnya. Namun jika error tersebut adalah unexpected system error, middleware kita akan secara otomatis mengubahnya menjadi HTTP status 500 dengan pesan yang aman untuk konsumsi publik. Pendekatan ini membuat kode controller kita tetap ramping karena fokus sepenuhnya pada business logic utama.

Pentingnya Internal Error Code untuk Modern App

HTTP status code memang sangat bagus untuk memberikan gambaran umum tentang jenis kesalahan yang terjadi. Namun sering kali HTTP status code terasa kurang spesifik untuk kebutuhan aplikasi yang kompleks. Sebagai contoh, status 400 Bad Request bisa berarti saldo pengguna kurang, kuota voucher sudah habis, atau format nomor telepon tidak valid.

Di sinilah peran penting dari kustom internal error code. Kita bisa membuat penamaan unik berbentuk string atau angka khusus yang secara spesifik menjelaskan masalah tersebut. Contohnya kita bisa menetapkan kode ERRPAYMENTINSUFFICIENTBALANCE untuk masalah saldo, atau ERRAUTHTOKENEXPIRED untuk masalah token yang habis masa berlakunya.

Penggunaan internal error code ini memberikan fleksibilitas luar biasa bagi tim frontend dan mobile app. Mereka tidak lagi bergantung pada pencocokan string teks pesan error yang rentan berubah ketika ada lokalisasi bahasa. Tim frontend cukup memeriksa nilai dari internal error code ini, lalu menampilkan komponen UI atau dialog modul yang sesuai dengan kebutuhan pengguna secara tepat dan akurat.

Strategi Logging dan Keamanan Response API Kita

Satu hal yang tidak boleh kita lupakan saat menangani error adalah masalah keamanan dan privasi data. Sangat sering kita melihat aplikasi di lingkungan produksi melempar pesan error yang berisi query database SQL mentah, file path server, atau stack trace framework yang sangat detail.

Informasi detail seperti ini adalah emas bagi para hacker yang sedang melakukan investigasi celah keamanan sistem kita. Oleh karena itu, kita harus memisahkan antara informasi error yang ditampilkan ke user dengan informasi error yang dicatat ke sistem logging internal.

Pesan error yang dikembalikan dalam response API kepada pengguna harus selalu bersifat general, aman, dan sopan. Sementara itu, detail teknis seperti stack trace lengkap, variabel environment, dan query database yang gagal harus dikirim ke sistem log terpisah seperti Winston, Logstash, Sentry, atau CloudWatch. Pastikan juga proses logging kita menyaring data sensitif seperti password, nomor kartu kredit, dan API key agar tidak tersimpan secara mentah di file log server.

Menjaga Dokumentasi API Tetap Rapi dan Asik Dibaca

Membuat sistem error handling yang canggih tentu akan sia sia jika tidak diketahui oleh anggota tim developer lainnya. Dokumentasi adalah jembatan komunikasi yang akan membuat seluruh upaya perapikan kode ini berdampak nyata pada produktivitas tim.

Kita bisa memanfaatkan tools seperti OpenAPI atau Swagger untuk mencatat semua kemungkinan error response pada setiap endpoint. Dalam dokumentasi tersebut, tuliskan dengan jelas status code yang mungkin muncul, struktur JSON yang dikembalikan, serta daftar kustom internal error code yang berlaku.

Ketika ada endpoint baru yang dibuat, biasakan untuk langsung memperbarui dokumentasi tersebut. Proses ini akan membuat aktivitas onboarding developer baru menjadi sangat cepat dan asik. Developer baru tidak perlu terus menerus bertanya di grup chat hanya untuk menanyakan arti dari suatu error response.

Langkah Nyata Mulai Merapikan Error Handling API Kita

Setelah memahami semua konsep di atas, sekarang saatnya kita mengambil tindakan nyata untuk merapikan codebase yang ada. Kita tidak perlu langsung merombak seluruh aplikasi dalam satu hari jika memang kodenya sudah terlalu besar. Kita bisa memulainya secara bertahap dan terencana.

Langkah pertama, buat kesepakatan bersama seluruh tim mengenai format standar JSON error dan daftar internal error code yang akan digunakan. Langkah kedua, buatkan middleware global exception handler di project utama kita. Langkah ketiga, buat kustom exception class yang mewakili berbagai skenario kesalahan bisnis. Langkah keempat, mulailah menerapkan format baru ini pada endpoint endpoint baru yang sedang dikembangkan. Terakhir, lakukan refactoring secara bertahap pada endpoint lama setiap kali kita mendapatkan tugas maintenance atau penambahan fitur.

Dengan konsistensi yang terus kita jaga, kualitas codebase kita akan meningkat secara drastis. Aplikasi menjadi jauh lebih stabil, proses debugging terasa santai, dan kolaborasi antar tim menjadi sangat menyenangkan. Selamat mencoba dan mari kita buat pengalaman ngoding sehari hari menjadi lebih asik dan bebas pusing.