Mendevelop Fitur Image Gallery

Setelah saya melakukan rewrite terhadap codebase inklusif, fitur yang selalu ingin saya prioritaskan adalah Image Gallery karena belakangan ini saya banyak bermain dengan Stable Diffusion dan ada banyak gambar yang ingin saya bagikan dan tidak mungkin saya embed menggunakan inline image.

Image Gallery sebetulnya adalah kumpulan gambar yang di-render dalam bentuk kolase namun tetap dapat dilihat secara individual dalam resolusi yang lebih besar.

Pemilihan Storage

Pertimbangan yang cukup memakan waktu pada saat planning fitur ini adalah pilihan storage. Sebelumnya saya terbiasa menggunakan SaaS seperti Cloudinary atau ImageKit, mungkin jika dalam context development blog pribadi atau website yang jumlah contentnya dapat saya control sudah pasti saya akan menggunakan Cloudinary atau ImageKit, tapi untuk web UGC ( User Generated Content ) seperti inklusif, menggunakan 3rd party service apalagi dari company asal US sudah pasti akan menjadi bom waktu bagi saya dari sisi cost nantinya. Lagipula, dimana serunya menggunakan SaaS? jadilah saya memutuskan untuk menggunakan on-prem storage dan mendevelop service sederhana sendiri.

Tentu, memilih untuk menggunakan on-prem storage dan in-house development tidak seindah jika saya menggunakan SaaS, tapi menurut saya ini worth it karena selain tidak ada tagihan baru, akhirnya saya akan dipaksa untuk belajar cara meng-handle gambar dengan proper, men-backup data dengan proper.

Design Architecture

Mendevelop fitur semacam ini sebenarnya bukanlah rocket science, lebih butuh kesabaran dibandingankan kecerdasan karena semua library dan underlying teknologinya sudah tersedia secara gratis dan open. karena inklusif belum mendukung mermaid, saya coba jelaskan secara high level dalam bentuk teks.

Data Layer

Ada dua jenis data yang disimpan untuk merepresentasikan gambar.

  1. Metadata dalam bentuk database table

  2. Raw Image dalam bentuk avif max 1400 width / 1400 height

Semua gambar yang diupload ke inklusif disimpan dalam bentuk table untuk kebutuhan browsing file dan mapping terhadap file system, pada table ini juga ada informasi tentang aspect-ratio, timestamp, dan mime-type. Hal yang perlu saya hightlight adalah aspect-ratio, data ini sangat penting untuk merender placeholder gambar saat initial render untuk menghidari Cumulative Layout Shift (CLS).

Folder Partition

Awalnya saya hanya menyimpan setiap gambar dalam satu folder dengan nama id dari user yang meng-upload, namun setelah saya konsolustasi kepada kawan, saya mendapat insight bahwa partisi itu sangat penting karena semakin banyak file dikumpulkan dalam satu folder yang sama, akan menyakiti file system, singkatnya tidak scale, maka dari itu saya memutuskan untuk mem-partisi menggunakan timestamp

[userId]/[year]/[month]/[imageId]

Dengan partisi diatas, ada beberapa benefit yang didapatkan

  1. Dapat melakukan incremental backup, misal backup data pertahun atau perbulan

  2. Data dengan usia yang lama misal > 5 tahun dapat dipindahkan ke cold-storage ( storage yang lebih murah )

  3. Jika mau, saya dapat men-apply volume limit per user, pertahun / perbulan

Service Layer

Tidak ada yang spesial pada layer ini karena heavy lifting part dihandle oleh library Sharp untuk kebutuhan compress, resize, conversion.

Serving Layer

Juga tidak ada yang spesial pada layar ini, hanya saja yang terpenting pada layer ini adalah untuk memastikan bahwa setiap image tidak di-load dalam bentuk full buffer ke memory melainkan menggunakan Stream. Jika menggunakan Node.js, pastikan load file gambar menggunakan fs.createReadStream kecuali server kita memiliki RAM unlimited :D

Kesimpulan

Tentu artikel ini bukan detailed technical document, bukan juga sebuah tulisan yang dapat dijadikan referensi teknis, melainkan showcase dari fitur Image Gallery, selamat mencoba!