Bir soruyla başlayalım: tarayıcınızdaki adres hangi makineyi işaret ediyor ve o makineyi kim buluyor?
Cevaba geçmeden önce "ağ" kelimesini küçültmek gerekiyor. Kulağa büyük geliyor; akla veri merkezleri ve okyanus altından geçen kablolar geliyor. Ama en yalın hâliyle bir ağ, iki cihaz ve aralarındaki tek bir bağlantıdan ibaret. İki bilgisayarı bir kabloyla birleştirirseniz çalışan bir ağınız olur. Burada bulma problemi de yok, çünkü kablonun bir ucundan çıkan verinin gidebileceği tek bir yer var.
İnternet ise milyarlarca cihazın olduğu bir yer ve orada bulmak gerçek bir problem. Yazının kalanında bu problemin katmanlarını tek tek açacağım. Her kavram için iki şey yapacağım: onunla daha önce nerede karşılaştığınızı hatırlatacağım ve kendi makinenizde nasıl bakabileceğinizi göstereceğim. Çünkü bunların hiçbiri soyut değil. Hepsi bir hata mesajının ya da bir bekleme süresinin arkasında duruyor.
Adresleme
İlk dört kavram birlikte tek bir işi yapıyor: doğru makineyi ve o makinedeki doğru programı işaret etmek.
IP adresi
Bir ağdaki her cihazın bir adresi vardır ve bu adrese IP adresi denir. Diğer cihazların o cihazı bulabilmesi için buna ihtiyacı var.
Adreslerin iki sürümü var. Yaygın olanı IPv4: 93.184.216.34 gibi noktalarla ayrılmış, her biri 0 ile 255 arasında dört sayı. Bu yapı yaklaşık 4,3 milyar adres üretiyor ki internete bağlanan cihaz sayısı düşünüldüğünde bu uzun zaman önce yetmemeye başladı. IPv6 tam bu yüzden var. 2001:db8::4a2b:1f30:9c07 gibi görünüyor ve pratikte tükenmeyecek bir alan sunuyor.
Adresler ayrıca ya private ya public. Private olanlar 192.168. veya 10. ile başlar ve yalnızca kendi ağınızın içinde bir anlam taşır. Public bir adres ise sizi tüm internette temsil eder ve onu size internet servis sağlayıcınız verir.
Laptop 192.168.1.10 private
Telefon 192.168.1.24 private
Televizyon 192.168.1.31 private
↓
Router 88.245.13.7 public
Evinizdeki her cihazın kendi private adresi var; ama dışarı çıkarken hepsi router'ın public adresini kullanıyor. Yani bir sitenin loglarında görünen şey cihazınız değil, eviniz.
Bunu nerede gördünüz: telefonunuzun wifi ayarlarındaki 192.168.1.24 gibi bir sayı. Ya da sunucu loglarınızda bir ziyaretçi kaydının yanındaki IP kolonu.
Kendiniz deneyin: terminale ipconfig getifaddr en0 yazmak makinenizin private adresini gösterir. Windows'ta aynı işi ipconfig yapıyor. Public adresiniz için curl ifconfig.me yeterli. Bunu iki farklı cihazda çalıştırıp aynı cevabı almanıza şaşırmayın; nedenini biraz sonra göreceksiniz.
DNS
DNS, Domain Name System'in kısaltması. Kimse IP adreslerini akılda tutmak istemez. DNS, insanların yazdığı github.com gibi isimleri makinelerin kullandığı 140.82.121.4 gibi adreslere çeviren sistem.
Bu çeviri tek bir yerde olmuyor. Sırayla birkaç kapı çalınıyor. Önce tarayıcı kendi hafızasına bakıyor. Cevap orada yoksa işletim sistemine soruluyor. O da bilmiyorsa soru bir resolver'a gidiyor; genelde internet servis sağlayıcınızın ya da Google gibi bir public sağlayıcının işlettiği bir sunucu.
Resolver da bilmiyorsa hiyerarşiyi tırmanıyor: önce root sunucular, sonra .com gibi bir üst düzey alan adından sorumlu sunucu ve en sonunda o alan adının kayıtlarını gerçekten tutan authoritative sunucu.
Kulağa uzun geliyor ama pratikte sorguların çoğu bu yolun tamamını yürümüyor, çünkü her adımda bulunan cevap bir süre saklanıyor. Ne kadar süre saklandığını da kaydın TTL değeri söylüyor.
Bunu nerede gördünüz: alan adını yeni bir sunucuya yönlendirdikten sonra sitenizin hâlâ eski yerden açılması. Kod tarafında bir sorun yok; elinizdeki kayıt henüz yenilenmemiş. TTL dolduğunda kendi kendine düzeliyor.
Kendiniz deneyin: nslookup github.com yazmak ismin hangi adrese çözümlendiğini gösterir.
$ nslookup github.com
Name: github.com
Address: 140.82.121.4
IP ve DNS birlikte trafiği doğru makineye götürüyor. Ama bir makinede aynı anda birden fazla program çalışıyor olabilir. İstek hangisine gidecek?
Port
Cevap port numaralarında. Port, makineye gelen verinin hangi programa gideceğini belirleyen sayı. Adresi ve portu birlikte yazdığınızda hedef tam olarak belirlenmiş olur.
192.168.1.10:3000
192.168.1.10 → hangi makine
3000 → hangi program
Port numaraları 0 ile 65535 arasında değişiyor ve bazıları yaygın servislerle özdeşleşmiş durumda.
HTTP → 80
HTTPS → 443
PostgreSQL → 5432
Redis → 6379
Bunlar teknik zorunluluklar değil, herkesin üzerinde anlaştığı varsayılan değerler. Bir uygulamayı farklı bir portta çalıştırmanızın önünde bir engel yok.
Bunu nerede gördünüz: iki projeyi birlikte açtığınızda Next.js'in Port 3000 is in use, trying 3001 instead demesi. Numara boş değil, çünkü başka bir process onu dinliyor.
Kendiniz deneyin: lsof -i :3000 o portu hangi programın tuttuğunu adıyla ve PID'iyle gösterir. Kapanmak istemeyen bir process'i kill <PID> ile kapatabilirsiniz.
Buraya kadar doğru cihazı ve o cihazdaki doğru programı tanımlayabiliyoruz. Ama yerel ağdaki cihazları internete çıkarmak ayrı bir problem yaratıyor.
NAT
Evinizdeki veya ofisinizdeki cihazlar genelde private adresler kullanıyor.
Dizüstü 192.168.1.10
Telefon 192.168.1.11
Bu adresler yalnızca kendi ağınızın içinde bir anlam taşıyor. İnternete çıktığınızda ağınızdaki her cihaz tek bir public adres üzerinden görünüyor. Bu dönüşümü yapan mekanizmaya NAT deniyor.
Dizüstü
192.168.1.10
│
↓
Router
│
↓
Public IP
203.x.x.x
│
↓
İnternet
Router, yerel ağdaki adresleri dış dünyada kullanılan public adrese eşliyor ve cevap geldiğinde onu doğru cihaza yönlendiriyor. Aynı ağdaki onlarca cihazın tek bir public adres üzerinden internete erişebilmesi böyle oluyor.
Bunu nerede gördünüz: dev sunucunuzu başlatıp telefonunuzdan localhost:3000 denediğinizde hiçbir şey alamamanız. localhost her cihaz için "kendisi" anlamına geliyor, yani telefonunuz kendi içine bakıyor. Private IP'yi, 192.168.1.10:3000 girdiğinizde çalışıyor, çünkü artık doğru makineyi işaret ediyorsunuz.
Kendiniz deneyin: public IP'nizi dizüstünüzde ve telefonunuzda kontrol edip aynı cevabı almanız, NAT'ın işini yaptığının kanıtı.
Bu noktada adresleme problemini büyük ölçüde çözmüş olduk.
DNS isim → IP adresi
IP hangi makine
Port hangi program
NAT private adres ↔ public adres

Uç uca dizdiğinizde bu dördü tek bir zincir: isim bir adrese çözümlenir, adres makineyi tanımlar, port o makinedeki programı tanımlar ve NAT çıkışta göndereni yeniden yazar. Yanıt da aynı yoldan geri gelir.
Ama hedefi bilmek tek başına yetmiyor. Bir paket kaynak cihazdan hedefe giderken hangi yoldan gideceğini nasıl biliyor?
Routing
Bir cihazın IP adresini bilmek ona ulaşmak için yetmez, çünkü bir ağdaki cihazlar genelde birbirine doğrudan bağlı değildir. Paketler hedefe varmadan önce birkaç router'dan geçebilir.
Kaynak
↓
Router A
↓
Router B
↓
Router C
↓
Hedef
Routing, bir paketin hedefine ulaşmak için hangi yoldan gideceğine karar verme işi. Router'lar bu kararı, hangi hedef için hangi yöne gidileceğini tutan bir routing table üzerinden veriyor.
Çarpıcı olan kısmı şu: bir router'ın tüm yolu bilmesi gerekmiyor. Bir sonraki durağı bilmek genelde yeterli. Büyük ağlarda bu yol bilgisi routing protokolleri üzerinden paylaşılıyor; örneğin BGP, internetteki ayrı ağların birbirleriyle rota bilgisi alışverişi yapmasını sağlayan şey.
Temel fikir: IP hedefi tanımlar, routing oraya nasıl gidileceğini belirler.
Bunu nerede gördünüz: aynı ülkedeki iki siteden birinin diğerinden belirgin biçimde daha geç açılması. Coğrafi mesafe aynı olsa bile paketin geçtiği durak sayısı farklı olabilir.
Kendiniz deneyin: traceroute github.com çalıştırın. Windows'taki karşılığı tracert. Çıktıdaki her satır paketin uğradığı bir durak, yanındaki süre de oraya kadar ne kadar sürdüğü.
Cihazlar birbirini bulabiliyor ve paketler yol alabiliyor. Peki bu cihazlar hangi kurallarla konuşuyor?
Protokoller
Bir ağdaki cihazların birbirini anlaması için ortak kurallara ihtiyaçları var. Bu kurallar mesajların nasıl gönderileceğini ve nasıl yorumlanacağını tanımlıyor.
Farklı problemler için farklı protokoller kullanılıyor.
IP adresleme
TCP güvenilir taşıma
UDP hızlı taşıma
DNS isim çözümleme
HTTP web iletişimi
TLS güvenli iletişim
Bir ağda her şeyi tek bir protokol yapmak yerine birkaçı birlikte çalışıyor. Bir web geliştirici olarak en çok dokunduğunuz da bu listenin en üstündeki değil, HTTP.
HTTP
HTTP, web'de istemci ve sunucu arasındaki iletişimin kurallarını belirleyen protokol. Bir isteğin nasıl gönderileceğini ve sunucunun nasıl cevap vereceğini tanımlıyor.
İstemci
│
│ HTTP isteği
↓
Sunucu
│
│ HTTP yanıtı
↓
İstemci
Bir istek şöyle görünüyor:
GET /users HTTP/1.1
Host: example.com
Burada GET yapılmak istenen işlemi, /users istenen kaynağı, Host da isteğin hangi alan adına gittiğini belirtiyor. İşlemi adlandırmak için kullanılan GET, POST, PUT, PATCH ve DELETE gibi kelimelere method deniyor.
Sunucu isteği aldıktan sonra bir yanıt gönderiyor ve bu yanıtın içinde bir durum kodu bulunuyor.
HTTP/1.1 200 OK
Content-Type: application/json
200 OK
201 Created
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
500 Internal Server Error
Böylece istemci yalnızca cevabın içeriğini değil, işlemin sonucunu da anlıyor.
HTTP'nin bir diğer önemli özelliği stateless olması. Her istek kendi başına değerlendiriliyor; protokol öncekileri hatırlamıyor. Oturum bilgisi gibi şeyler cookie ya da session gibi ayrı mekanizmalarla ele alınıyor.
Bunu nerede gördünüz: DevTools'un Network sekmesinde bir isteğe tıkladığınızda açılan Headers paneli. Orada gördüğünüz şey tam olarak yukarıdaki yapı.
Kendiniz deneyin: curl -i https://example.com yanıtın hem header'larını hem gövdesini yazdırır. İlk satır durum kodu.
HTTP en üstte, yazdığınız kodun hemen altında duruyor. Peki onun altında ne var?
Katmanlar
Ağ iletişimi tek bir iş değil. Veriyi fiziksel olarak taşımak, bir bağlantıyı yönetmek ve uygulamanın anladığı bir formatta konuşmak birbirinden farklı problemler. Bu yüzden iletişim katmanlara ayrılıyor ve her katman üstündekine hizmet ediyor.
Uygulama
↓
Taşıma
↓
İnternet
↓
Ağ erişimi
Bu ayrımın en büyük faydası şu: bir katmanın içindeki bir detay değiştiğinde diğerlerinin yeniden yazılması gerekmiyor. HTTP'nin nasıl çalıştığını anlamak için Ethernet'in veriyi fiziksel olarak nasıl taşıdığını bilmeniz gerekmiyor.
Katmanları açıklamak için iki model kullanılıyor. OSI modeli iletişimi yedi katmana ayırıyor ve çoğunlukla kavramsal bir referans. TCP/IP modeli ise internetin gerçekten üzerinde çalıştığı protokolleri açıklamak için daha pratik.
Ağ erişimi: Ethernet, Wi-Fi ve MAC
En alt katman bir cihazın ağa fiziksel olarak nasıl bağlandığıyla ilgileniyor. MAC adresi, bir ağ arayüzünün yerel ağdaki fiziksel adresi. Ethernet ve Wi-Fi ise cihazların bu yerel ağ üzerinden iletişim kurmasını sağlayan teknolojiler. IP adresi hedefi tanımlıyor olabilir ama yerel ağın içinde teslimat asıl olarak MAC adresine yapılıyor.
Kendiniz deneyin: ifconfig çıktısında ether ile başlayan satır makinenizin MAC adresini gösterir. Windows'ta ipconfig /all çıktısındaki Physical Address da aynı şey.
Şimdi günlük hayatta en çok karşılaştığınız katmana bakalım: taşıma.
Taşıma
Paketler
Veri karşı tarafa tek parça hâlinde gitmiyor. Küçük parçalara bölünüyor, her parça kendi yoluna çıkıyor ve hedefte sıra numarasına göre yeniden birleştiriliyor. Bu parçalara paket deniyor.
Parçalar farklı rotalardan gidebilir, farklı bir sırayla varabilir ve bazıları hiç varmayabilir. Onları yeniden birleştirmek ve eksik olanı fark etmek alıcı tarafın sorumluluğu.
Bunu nerede gördünüz: zayıf bir bağlantıda bir görselin yukarıdan aşağıya bant bant belirmesi. İzlediğiniz şey paketlerin sırayla varması.
Kendiniz deneyin: ping google.com komutunu birkaç saniye çalıştırıp durdurun. Çıktının sonundaki özet satırı kaç paket gönderildiğini, kaçının geri döndüğünü ve kayıp oranını gösterir.
TCP ve UDP
Taşıma katmanı, iki cihazdaki programlar arasında verinin nasıl taşınacağını belirliyor. Burada iki temel yaklaşım var.
TCP güvenilir olan. Bir bağlantı kuruyor, gönderdiği parçaları takip ediyor, kaybolanları fark edip yeniden gönderiyor ve veriyi doğru sırada teslim ediyor. Web trafiği, API istekleri ve dosya transferleri bunu kullanıyor, çünkü eksik gelen bir yanıtın hiçbir faydası yok.
UDP hızlı olan. Bağlantı kurmayı ya da teslimi garanti etmeyi gerektirmiyor, dolayısıyla daha az ek yükle çalışıyor. Bir paket kaybolduğunda onu yeniden göndermek zorunda değil. Canlı görüşmelerde ve gerçek zamanlı uygulamalarda bu yüzden tercih ediliyor: iki saniye önce kaybolmuş bir kareyi yeniden istemenin bir anlamı yok.
TCP güvenilirlik
UDP hız ve düşük gecikme
Yani hangisinin daha iyi olduğuna dair tek bir cevap yok. Seçim uygulamanın neye ihtiyacı olduğuna bağlı.
Bunu nerede gördünüz: bağlantınız bozulduğunda bir sayfanın ya tamamen yüklenmesi ya da hiç yüklenmemesi, buna karşılık bir görüntülü görüşmede görüntünün kare kare bozulup konuşmanın devam etmesi. İkisi arasındaki fark tam olarak bu.
Kendiniz deneyin: curl -v https://example.com çalıştırdığınızda çıktının başındaki Connected to satırı, herhangi bir veri alışverişinden önce kurulan TCP bağlantısı.
Peki TCP bu bağlantıyı gerçekte nasıl kuruyor?
Handshake
Bir TCP bağlantısı tek hamlede kurulmuyor. İki taraf önce mesaj alışverişi yapıp bağlantıyı ayağa kaldırıyor. Adres HTTPS ise bunun üzerine bir de şifreleme anlaşması bindiriliyor. Yani verinin ilk baytı bir yere gitmeden önce iki taraf arasında birkaç gidiş dönüş çoktan gerçekleşmiş oluyor.
Bu gidiş dönüşlerin her biri mesafeye bağlı bir süreye mal oluyor. Sunucu ne kadar uzaktaysa kurulum o kadar pahalı. Kurulmuş bir bağlantının bir süre açık tutulup yeniden kullanılmasının nedeni de bu.
Bunu nerede gördünüz: bir siteye ilk girişinizin, ardından gelen tıklamalardan belirgin biçimde daha yavaş olması. İkinci istek kurulum maliyetini ödemiyor.
Kendiniz deneyin: DevTools'un Network sekmesinde bir isteğin Timing panelini açın. Initial connection ve SSL satırları tam olarak bu kurulum aşamaları.
Güvenlik: HTTPS ve TLS
Bağlantı kuruldu, kurallar belli. Ama bu hâliyle söylenen her şey yolda okunabilir durumda. TLS bu problemi çözüyor.
TLS iki iş yapıyor. Birincisi, aradaki trafiği okunamaz hâle getiriyor. İkincisi, bir sertifika üzerinden karşı tarafın gerçekten iddia ettiği kişi olduğunu doğruluyor. İkinci kısım en az birincisi kadar önemli, çünkü yanlış kişiyle şifreli konuşmanın size bir faydası yok.
HTTP + TLS = HTTPS
Bir HTTPS bağlantısında sıra şöyle: önce TCP bağlantısı kuruluyor, sonra TLS handshake gerçekleşiyor ve iki taraf güvenli iletişim için gerekenleri paylaşıyor. HTTP isteği ancak bundan sonra gönderiliyor. Adres çubuğundaki kilit simgesi size bu sürecin tamamlandığını söylüyor.
Bunu nerede gördünüz: süresi geçmiş sertifikaya sahip bir siteye girdiğinizde tarayıcının araya girip sayfayı hiç göstermemesi. O ekranı üreten şey TLS'in doğrulama tarafı.
Kendiniz deneyin: adres çubuğundaki kilit simgesine tıklayıp sertifika detaylarını açın. Sertifikayı kimin verdiğini ve ne zaman geçerliliğini yitireceğini göreceksiniz.

Diyagram ikisini yan yana koyuyor: düz HTTP üzerinde istek ve yanıt okunabilir metin olarak gidiyor, HTTPS ise öne bir handshake koyup sonrasındaki her şeyi şifreliyor. Yukarıdaki ikisinin yanına üçüncü bir garantiyi de adlandırıyor: bütünlük, yani verinin yolda fark edilmeksizin değiştirilememesi.
Karşı taraftaki makineye güvenli biçimde ulaştık. Ama ulaştığınız makine, sandığınız makine olmayabilir.
Altyapı
Reverse proxy ve load balancer
Modern bir sitede bir isteğin ilk konuştuğu şey genelde uygulamanın kendisi değil, onun önünde duran bir katman. Bu katman isteği alıyor, gerekirse arkadaki sunuculardan birine iletiyor, cevabı alıp size veriyor. Buna reverse proxy deniyor. Arkasında birden fazla sunucu varsa ve yük bunlar arasında paylaştırılıyorsa, bu işi yapan şeye load balancer deniyor.
Bu katman görünmez olduğu için varlığını genelde bir şey bozulduğunda fark ediyorsunuz.
Bunu nerede gördünüz: 502 Bad Gateway hatası. Bu hatayı uygulamanız üretmiyor, çünkü uygulamanıza baştan ulaşılamıyor. Onu size önündeki katman veriyor ve aslında dediği şu: arkamdakine sordum, cevap alamadım.
Kendiniz deneyin: curl -I https://example.com ile yanıt header'larına bakın. server gibi alanlar isteğinizi kimin karşıladığına dair bir ipucu verir.
CDN
Sunucunuz tek bir yerde duruyor ama kullanıcılarınız her yerde. Aradaki mesafe kaçınılmaz bir gecikme yaratıyor. CDN, sık kullanılan içeriği dünyanın farklı noktalarındaki sunuculara kopyalayarak bu mesafeyi kısaltıyor.
Bir görsel bir kez istendikten sonra en yakın noktada saklanıyor ve sonraki istekler o kopyadan yanıtlanıyor. Yani istek çoğu zaman gerçek sunucunuza hiç ulaşmıyor.

Haritadaki mantık bu: ortada bir origin sunucu, etrafına yayılmış edge sunucular ve her isteğin en yakın olana gitmesi. Sidney'deki bir kullanıcı için önemli olan origin'in nerede olduğu değil, Melbourne'deki kopyanın orada olması.
Bunu nerede gördünüz: bir sayfa ilk açıldığında görsellerin yavaş gelmesi, ikincisinde anında belirmesi.
Kendiniz deneyin: bir görselin header'larına curl -I ile bakın. age alanı içeriğin orada ne kadar süredir durduğunu, x-cache ve benzeri alanlar da isteğin bir kopyadan mı yoksa gerçek sunucudan mı karşılandığını söyler.
Performans: latency ve bant genişliği
İkisi de hız kelimesiyle anılıyor ama farklı şeyleri ölçüyorlar.
Latency, verinin gidip geri gelmesi için geçen süre. Bant genişliği ise bir seferde ne kadar veri taşınabildiği. Daha fazla bant genişliği büyük dosyaları daha hızlı indirmenizi sağlıyor ama uzaktaki bir sunucuya olan mesafeyi kısaltmıyor.
Bu yüzden bağlantınızı yükseltmek her problemi çözmüyor. Çok sayıda küçük istek yapan bir uygulamada darboğaz genelde bant genişliği değil, her istek için tekrar tekrar ödenen gidiş dönüş süresi.
Bunu nerede gördünüz: hızlı internetinize rağmen uzak bir bölgedeki bir API'nin yavaş cevap vermesi.
Kendiniz deneyin: sırayla yakın bir adrese ve uzak bir adrese ping atın. Milisaniye cinsinden fark, bant genişliğinizle hiçbir ilgisi olmayan saf mesafe maliyeti.
Toparlayalım
Adres çubuğuna bir şey yazdığınızda kabaca şunlar oluyor: yazdığınız isim DNS tarafından bir IP adresine çevrildi, isteğinizin adresi yerel ağdan çıkarken NAT tarafından yeniden yazıldı, paketler birkaç router üzerinden hedefe doğru yönlendirildi, o hedefle önce bir TCP bağlantısı sonra bir TLS anlaşması kuruldu, isteğiniz HTTP olarak gönderildi, sunucunun kendisi değil önündeki bir katman tarafından yanıtlandı ve yanıt büyük olasılıkla gerçek sunucuya hiç dokunmadan size yakın bir kopyadan geri geldi.
Bunların hepsi birkaç yüz milisaniyede oldu ve siz sadece sayfanın açılmasını izlediniz.
Bu kavramların hiçbirini ezberlemeniz gerekmiyor. Bir dahaki sefere bir 502 gördüğünüzde, bir sayfa beklenmedik biçimde yavaş açıldığında ya da alan adı değişikliğiniz bir türlü etkili olmadığında nereye bakacağınızı bilmeniz yeterli.
