İçeriğe Atla
Mustafa Erbay
Yaşam · 11 dk okuma · görüntülenme Read in English

Uygulama Boyutu: Her Kilobyte Mücadelesi mi, İşlevsellik Önceliği mi?

Uygulama boyutunun geliştirme süreçlerindeki önemini, mobil, web ve backend perspektiflerinden inceliyor; işlevsellik ve optimizasyon arasındaki dengeyi kendi…

100%

Yazılım geliştirme hayatımda, yıllardır hem sistem hem de yazılım tarafında sürekli bir denge arayışında oldum. Bu denge noktalarından biri de uygulamanın boyutu meselesi. Bir tarafımda “Her kilobyte önemlidir, her fazlalık maliyettir” diyen bir mühendislik içgüdüsü varken, diğer tarafımda “Kullanıcıya değer katacak işlevselliği en hızlı şekilde sunmak esastır” diyen pragmatik bir bakış açısı var. Bu iki uç arasında gidip gelmek, kariyerimin önemli bir parçası oldu.

Peki, gerçekten her kilobyte için mücadele etmeli miyiz? Yoksa işlevselliği mi ön planda tutmalıyız? Bu, projenin bağlamına, hedef kitlesine ve hatta deployment modeline göre değişen, gri bir alan. Deneyimlerimde bu sorunun net bir cevabı olmadığını, ancak doğru soruları sorarak ve bilinçli trade-off’lar yaparak en iyi sonuca ulaşılabileceğini gördüm. Bu yazıda, bu konudaki düşüncelerimi ve farklı alanlardaki gözlemlerimi paylaşacağım.

Mobil Dünyada Boyutun Acı Gerçekleri

Mobil uygulamalarda boyutun önemi tartışılmaz. Özellikle Türkiye gibi mobil internetin yaygın olduğu ancak her zaman hızlı veya sınırsız olmadığı pazarlarda, uygulama boyutu doğrudan indirme oranlarını, kullanıcı deneyimini ve hatta uygulamanın cihazda kalma süresini etkiliyor. Yıllar önce kendi Android spam uygulamamı geliştirirken bu gerçeği defalarca tecrübe ettim. Uygulamayı ne kadar küçültürsem, indirme ve yükleme oranları o kadar artıyordu.

Örneğin, bir dönem uygulamamın ana paketi epeyce şişmişti. Birkaç optimizasyon turundan sonra (gereksiz kaynakları temizleme, ProGuard ile kod sıkıştırma, native kütüphaneleri optimize etme) bu boyutu kabaca yarısına kadar düşürmeyi başardım. Bu belirgin düşüş, Play Store’daki indirme istatistiklerime doğrudan yansıdı. Özellikle düşük bant genişliğine sahip bağlantılarda veya kotalı mobil veri kullanan kişiler için bu fark çok kritikti. Hatta bazı kullanıcılar, sırf boyutu büyük olduğu için uygulamayı indirmekten vazgeçtiklerini geri bildirimlerde belirtmişlerdi.

Bir diğer etki de güncelleme süreçlerinde ortaya çıkıyor. Kullanıcılar, her yeni sürümde büyük boyutlu güncellemeler indirmek istemiyorlar. Bu, uygulama içi güncellemelerin ertelenmesine veya tamamen iptal edilmesine yol açabiliyor. Benim Android uygulamamda bir özellik eklediğimde, eğer bu özellik yeni bir büyük kütüphane gerektiriyorsa, bunu modüler bir şekilde yüklemeyi veya sadece Premium kullanıcılara sunmayı düşündüğüm oldu. Çünkü her kullanıcının bu boyutu indirmesini istemiyordum. Bu durum, mobil geliştiricilerin sürekli olarak işlevsellik ile boyut arasında bir denge kurmasını gerektiriyor. Uygulamanın açılış süresi (cold start time) de doğrudan boyuttan etkilenir; daha büyük uygulamalar, genellikle daha yavaş başlar.

Web ve Kurumsal Yazılımlarda Farklı Dinamikler

Web dünyasında, özellikle modern SPA (Single Page Application) mimarileriyle birlikte, JavaScript bundle boyutları ciddi bir sorun haline geldi. Kullanıcıların tarayıcısına indirilmesi gereken JavaScript, CSS ve diğer kaynakların toplam boyutu, sitenin yüklenme hızını doğrudan etkiliyor. Yıllar önce, bir müşteri projesinde React tabanlı bir dashboard uygulaması geliştirirken, ilk bundle boyutumuzun fahiş bir rakama ulaştığını gördük. Bu, kötü bir ilk yükleme deneyimi anlamına geliyordu.

Durumu düzeltmek için agresif optimizasyonlara gittik:

  1. Code Splitting / Lazy Loading: Ana sayfa için sadece gerekli bileşenleri yükledik, diğer rotaları ve modülleri kullanıcı ihtiyaç duyduğunda indirilmek üzere böldük.
  2. Tree Shaking: Kullanılmayan kodları bundle’dan atmak için Webpack yapılandırmasını optimize ettik.
  3. Görsel Optimizasyonu: WebP gibi modern formatlara geçtik ve görselleri sıkıştırdık.
  4. CDN Kullanımı: Statik varlıkları küresel CDN’ler üzerinden dağıttık.

Bu adımlar sonucunda başlangıç bundle boyutunu kat kat aşağı çekmeyi başardık. Bu, kullanıcıların siteyi algıladıkları hızda ciddi bir iyileşme sağladı. Ölçümlerimize göre, ilk anlamlı içerik yüklenme süresi (Largest Contentful Paint) belirgin biçimde kısaldı. Web projelerinde bu tür bir optimizasyon, SEO performansını bile etkileyebilir. Web performans optimizasyonları ve SEO ilişkisi

Kurumsal yazılımlarda ise durum biraz daha farklı. Son kullanıcı genellikle kurumsal ağ içinden eriştiği için bant genişliği mobil kadar kısıtlı olmayabilir. Ancak burada da deployment süreleri ve bağımlılık yönetimi öne çıkıyor. Bir üretim firmasının ERP’sini geliştirirken, yeni bir modülün devreye alınması bazen saatler sürebiliyordu. Bunun bir nedeni, tek bir büyük JAR dosyasının (monolith) tüm bağımlılıklarıyla birlikte tekrar tekrar deploy edilmesiydi.

# Örnek bir monolith uygulamanın JAR boyutu ve deployment akışı
# Tüm bağımlılıklarıyla birlikte şişmiş tek bir JAR, sadece bir versiyon
# değişikliği için bile baştan kopyalanıp yeniden başlatılmak zorundaydı.
# (çıktı ortama göre değişir)
$ ls -lh my-erp-monolith-1.2.3.jar

$ time scp my-erp-monolith-1.2.3.jar user@erp-server:/opt/erp/

$ time systemctl restart erp-application.service
# Uygulamanın tamamen ayağa kalkıp servise girmesini bekle

Bu tür durumlarda, boyutun doğrudan performanstan ziyade operasyonel hıza ve çevikliğe etkisi oluyor. Bağımlılıkları yönetmek, farklı modüllerin ayrı ayrı deploy edilebilmesini sağlamak (mikroservis mimarisine doğru bir geçişle), hem boyut sorununu hafifletiyor hem de geliştirme ve operasyonel süreçleri hızlandırıyor.

Backend ve Altyapıda Boyutun Dolaylı Etkileri

Backend uygulamalarında veya altyapı bileşenlerinde boyut, genellikle doğrudan son kullanıcıya yansımadığı için daha az önemsenir. Ancak burada da dolaylı maliyetler ve operasyonel yükler ortaya çıkar. Özellikle container teknolojileriyle çalışmaya başladığımdan beri, Docker imaj boyutlarının ne kadar kritik olabileceğini bizzat tecrübe ettim.

Bir Docker imajının boyutu, deployment süresini, disk kullanımını, ağ trafiğini ve hatta güvenlik açıklarını doğrudan etkileyebilir. Örneğin, bir uygulamayı Ubuntu tabanlı bir imajda (yaklaşık 100MB temel boyut) çalıştırmak yerine Alpine Linux tabanlı bir imajda (yaklaşık 5MB temel boyut) çalıştırmak, her yeni dağıtımda kaydedilen ağ trafiği ve depolama alanında ciddi farklar yaratır.

# Ubuntu tabanlı, daha büyük bir imaj örneği
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3 python3-pip && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python3", "app.py"]

# Alpine tabanlı, daha küçük bir imaj örneği
FROM python:3.9-alpine
COPY requirements.txt .
RUN pip install -r requirements.txt --no-cache-dir
COPY . .
CMD ["python", "app.py"]

Bu iki Dockerfile arasındaki fark, nihai imaj boyutunda yüzlerce megabyte’a varan farklılıklar yaratabilir. Kendi bir yan ürünümün backend’inde, sürekli CI/CD pipeline’ından geçen servislerimde Alpine tabanlı imajlar kullanarak deployment sürelerini belirgin biçimde kısalttığımı gördüm. Bu, özellikle her gün onlarca kez deploy yapılan bir ortamda önemli bir kazançtır. Container imaj optimizasyon teknikleri

Disk yangını konusu da burada devreye giriyor. Bir sunucuda birden fazla container çalıştırırken, her birinin logları, geçici dosyaları ve imaj katmanları zamanla diski doldurabilir. Özellikle journald’nin varsayılan ayarlarıyla çalıştığı bir ortamda, logların boyutu bazen kontrolden çıkabiliyor. Benzer şekilde, CI/CD süreçlerinde build cache’leri veya ara imajlar da diskte gereksiz yer kaplayarak performansı düşürebilir. Bir keresinde kendi self-hosted CI/CD runner’ımda, Docker build cache’lerinin diski tamamen doldurması nedeniyle pipeline’ların durduğunu gördüm. Bu, boyutun sadece son kullanıcıya değil, operasyonel maliyetlere de doğrudan etki ettiğinin somut bir örneğiydi.

İşlevsellik ve Hız Arasındaki İnce Çizgi

Uygulama geliştirme sürecinde, yeni bir özellik eklemek genellikle yeni bir kütüphane veya daha fazla kod anlamına gelir. Bu da kaçınılmaz olarak uygulamanın boyutunu artırır. Burada asıl soru, bu boyut artışının getirdiği işlevsel kazancın, oluşan maliyeti haklı çıkarıp çıkarmadığıdır. Bazen, çok küçük bir işlevsellik için çok büyük bir kütüphane eklediğimizi fark ederiz.

Örneğin, bir projede PDF oluşturma ihtiyacı doğduğunda, piyasadaki popüler bir PDF kütüphanesini (örneğin Java’da iText veya Python’da ReportLab) projeye dahil etmek, paketin boyutunu onlarca megabyte artırabilir. Eğer bu PDF özelliği sadece belirli raporlar için ve nadiren kullanılıyorsa, bu büyük kütüphaneyi ana pakete dahil etmek yerine, ayrı bir mikroservis olarak çalıştırmak veya sunucu tarafında oluşturup istemciye sadece çıktıyı göndermek gibi alternatifler düşünülebilir.

Bu durum, özellikle hızlı teslimat baskısı altındayken daha da belirginleşir. Bir özelliği “hızlıca devreye almak” adına, mevcut en kolay çözüme (genellikle boyutu en büyük olan kütüphaneye) yönelmek cazip gelebilir. Ancak bu, teknik borç biriktirir ve gelecekteki optimizasyonları daha zor hale getirir. Benim deneyimimde, bu “hızlı çözüm”lerin orta ve uzun vadede genellikle daha fazla maliyete yol açtığını gördüm. Başlangıçta 50KB’lık bir kütüphane eklemek önemsiz görünse de, bu tür eklemelerin zamanla birikmesi, uygulamanın genel performansını ve bakımını ciddi şekilde etkileyebilir. Bu, yazılım mimarisinin sadece kod yazmak değil, aynı zamanda organizasyonel akışları ve gelecekteki olası büyüme senaryolarını öngörmek olduğunu bir kez daha kanıtlıyor.

Pragmatik Yaklaşım: Nerede Ne Kadar Optimize Etmeli?

Uygulama boyutu optimizasyonunda “her şeyden vazgeç” veya “hiçbir şeyi umursama” gibi uç yaklaşımlar genellikle işe yaramaz. Önemli olan, projenin ve hedeflenen kullanıcı kitlesinin ihtiyaçlarına göre pragmatik bir denge kurmaktır. Bu dengeyi bulmak için kendime sorduğum bazı sorular var:

  • Hedef kitlem kim? Gelişmekte olan ülkelerdeki mobil kullanıcılar mı, yoksa yüksek bant genişliğine sahip kurumsal ağdaki profesyoneller mi?
  • Uygulama ne sıklıkla indiriliyor/güncelleniyor? Tek seferlik bir indirme mi, yoksa sürekli güncellenen bir SaaS ürünü mü?
  • Optimizasyonun getirisi ne olur? 1MB küçültme, kaç saniye kazandırır, kaç kullanıcıyı memnun eder?
  • Optimizasyonun maliyeti ne olur? Geliştirme süresi, bakım zorluğu, okunabilirlik kaybı?

Bu soruların cevapları, beni farklı stratejilere yönlendirdi. Örneğin, bir tüketiciye yönelik mobil uygulamada her kilobyte için savaşırken, dahili bir kurumsal yönetim panelinde daha büyük bundle boyutlarını tolerans gösterebilirim. Burada önemli olan, bilinçli bir karar vermek ve bu kararın arkasında durmaktır.

Bir bankanın iç platformunu geliştirirken, frontend bundle boyutunun 10MB olması bile pek sorun teşkil etmiyordu. Çünkü kullanıcılar platforma sabit bir ağdan, güçlü bilgisayarlarla erişiyordu ve ilk yüklemeden sonra tarayıcı cache’i devreye giriyordu. Ancak, kendi yan ürünümün finansal hesaplayıcıları için, sayfanın hızlı açılması kritikti. Bu yüzden her JavaScript ve CSS dosyasını sıkıştırdım, görsel optimizasyonuna gittim ve hatta bazı dinamik içerikleri sunucu tarafında render ettim.

// Webpack ile code splitting ve lazy loading örneği
// Bu sayede ana bundle'a sadece ana sayfa bileşenleri yüklenir,
// diğer modüller kullanıcı gerektiğinde indirilir.
import React, { Suspense, lazy } from 'react';

const Dashboard = lazy(() => import('./Dashboard'));
const Reports = lazy(() => import('./Reports'));

function App() {
  return (
    <div>
      <Suspense fallback={<div>Yükleniyor...</div>}>
        {/* Router bazlı lazy loading */}
        {window.location.pathname === '/dashboard' && <Dashboard />}
        {window.location.pathname === '/reports' && <Reports />}
      </Suspense>
    </div>
  );
}

Bu tür stratejileri uygularken, elde ettiğim performansı sürekli ölçtüm. Lighthouse skorları, Core Web Vitals metrikleri ve kendi özel telemetri sistemlerimle değişikliklerin etkilerini gözlemledim. Örneğin, bir görsel sıkıştırma algoritması uyguladığımda, sayfa boyutunun gözle görülür şekilde azaldığını ve LCP (Largest Contentful Paint) değerinin belirgin biçimde iyileştiğini gördüm. Bu ölçümler, optimizasyon çabalarımın boşa gitmediğini gösteriyordu.

Sonuç

Uygulama boyutu meselesi, mühendislikte sıkça karşılaştığımız bir trade-off döngüsünün iyi bir örneği. “Her kilobyte için mücadele mi, işlevsellik önceliği mi?” sorusunun cevabı, siyah ya da beyaz değil, projenin bağlamına göre değişen bir gri tonudur. Benim net pozisyonum, her zaman “bilinçli denge”den yana oldu.

Mobil platformlarda veya düşük bant genişliğine sahip ortamlarda, boyut optimizasyonu hayati önem taşır. Web’de, özellikle ilk yükleme hızının kritik olduğu sitelerde, yine boyutun önemi büyüktür. Backend ve altyapıda ise boyut, daha çok operasyonel maliyetlere ve deployment hızına etki eder. Her durumda, geliştirici olarak bizim görevimiz, kullanıcıya en iyi deneyimi sunarken, operasyonel verimliliği de göz ardı etmemektir. Bu, bazen fazladan birkaç kilobyte’ı tolere etmek anlamına gelirken, bazen de saatler süren optimizasyon çalışmalarıyla her bir byte’ı sıkıştırmak anlamına gelebilir. Önemli olan, bu kararları verilerle desteklemek ve projenin genel hedefleri doğrultusunda hareket etmektir.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

Sıkça Sorulanlar

Bu makale ile ilgili okurların sorduğu yaygın sorular.

Uygulamamın boyutunu küçültmeye nereden başlamalıyım?
Ben önce uygulamanın paket yapısını analiz ederek en büyük dosya ve kütüphaneleri tespit ettim. Android Studio’nun “APK Analyzer”ı, .apk içindeki her bir .dex, resim ve native .so dosyasının boyutunu gösterdiği için ilk durak noktasıdır. Sonra gereksiz manifest izinlerini, debug kodlarını ve kullanılmayan kaynakları temizledim. Ardından ProGuard/R8 ile kod sıkıştırması yaptım ve sık kullanılan kütüphaneleri “implementation” yerine “api” ya da “runtimeOnly” gibi daha hafif varyantlarla değiştirdim. Bu adımları birer kontrol listesi gibi tutmak, her adımda boyut farkını ölçerek ilerlemeyi sağlar.
ProGuard ve native kütüphane optimizasyonu arasında ne gibi trade‑off’lar var?
Ben ProGuard (veya R8) kullandığımda kodun okunabilirliği kaybolur ve hata ayıklama zorlaşır; özellikle reflection kullanan kütüphaneler yanlışlıkla kaldırılabilir, bu yüzden keep‑rules dosyasını titizlikle oluşturmak gerekir. Native .so dosyalarını küçültmek ise CPU mimarileri (armeabi‑v7a, arm64‑v8a) arasında denge kurmayı gerektirir; sadece bir mimariyi paketlerseniz uygulama daha küçük olur, fakat bazı cihazlarda çalışmaz. Ben iki stratejiyi birleştirerek, kritik platformları tutup geri kalanını “split APK” olarak sunmayı tercih ettim; bu sayede toplam indirme boyutu düşerken cihaz uyumluluğu korunur.
Boyut optimizasyonu sırasında beklenmedik hatalar alırsam nasıl debug yapmalıyım?
Ben önce “gradle assembleDebug” ile derleyip, “adb logcat” üzerinden runtime hatalarını izledim; ProGuard sonrası oluşan “ClassNotFoundException” genellikle eksik keep‑rule’dan kaynaklanır. Ardından “-dontobfuscate” bayrağını geçici olarak açıp, hatanın kaynağını izole ettim. Native kütüphane hatalarında “ndk‑stack” ve “readelf” araçlarıyla .so dosyasının sembollerini kontrol ettim. Sorun hâlâ çözülmezse, bir önceki stabil build’e geri dönüp adım adım değişiklik ekleyerek regresyon testleri yaptım. Bu yaklaşım, hangi optimizasyonun hataya yol açtığını net bir şekilde ortaya koyar.
Her kilobyte için mücadele etmek her zaman en iyi strateji midir, yoksa işlevselliği önceliklendirmek mi daha mantıklı?
Ben 20 yıllık deneyimimde, bağlamı göz önünde bulundurmadığım sürece “her kilobyte” taktiği aşırıya kaçabilir. Eğer hedef kitle düşük bant genişliğine sahip bir pazarda ise, indirme süresi ve depolama sınırlamaları kritik olduğu için boyut optimizasyonu öncelik kazanır. Ancak kurumsal bir web servisinde ya da masaüstü uygulamasında, yeni özellik eklemek ve performans iyileştirmeleri sağlamak daha yüksek bir değer taşıyabilir. Ben her projede bir “boyut‑fayda” matrisi oluşturarak, kullanıcı beklentisi, cihaz profili ve iş hedeflerini karşılaştırıyorum; bu sayede gereksiz küçültme çabalarından kaçınıp, işlevselliği koruyarak optimum dengeyi yakalıyorum.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

✉️ Ücretsiz · Spam yok · İstediğin an çık

Yeni yazılardan haberdar olun

Yeni içerikler ve teknik notlar e-postanıza gelsin.

  • 📌
    Haftanın en iyisi Sadece okumaya değer tek yazı
  • 🔧
    Alet çantası Bu hafta kullandığım araçlar
  • 🧠
    Perde arkası Blog'a girmeyen notlar

Spam yapmıyoruz. İstediğiniz zaman ayrılabilirsiniz. · Sadece Umami (self-hosted, Google yok) ile takip.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar