# Aha Notes > 어려운 기술 개념을 일상의 비유로 풀어내는 블로그. "아~ 그래서 그렇구나!" 하는 순간을 모아둔 곳이에요. ## Docs - [Home](https://blog.nvim.me/index.md): 어려운 기술 개념을 일상의 비유로 풀어내는 블로그. 비개발자도, 개발자도 환영해요. - [Kafka는 어디부터 읽을까요?](https://blog.nvim.me/messaging/kafka/index.md): Kafka를 처음 접하는 독자가 record 하나의 흐름에서 출발해 topic, partition, consumer group, offset을 차례로 연결하는 입구예요. - [Kafka는 왜 메시지를 줄 세워 기록할까요?](https://blog.nvim.me/messaging/kafka/why-kafka-and-log-based-messaging-exist.md): 직접 호출과 전형적인 작업 큐만으로 풀기 어려운 시간 분리, 여러 독자의 독립적인 읽기, 과거 재생 문제에서 Kafka의 출발점을 찾아봐요. - [패킷이 뭐길래? 인터넷 택배 이야기](https://blog.nvim.me/network/basic/01-what-is-packet.md): 인터넷이 정보를 주고받는 기본 단위, '패킷(Packet)'을 비개발자도 이해할 수 있도록 친근하게 풀어봅니다. - [IP 주소와 라우팅 - 패킷은 어떻게 길을 찾을까?](https://blog.nvim.me/network/basic/02-ip-and-routing.md): 작은 패킷이 어떻게 지구 반대편 서버까지 정확히 도착하는지, IP 주소와 라우팅 개념을 비유로 풀어봅니다. - [TCP vs UDP - 꼼꼼한 친구와 빠른 친구는 뭐가 다를까요?](https://blog.nvim.me/network/basic/03-tcp-vs-udp.md): 패킷이 도착했는지 어떻게 확인하는지, TCP와 UDP의 차이를 일상 비유로 쉽게 풀어봅니다. - [DNS는 어떻게 이름을 IP 주소로 바꿀까요? 인터넷 안내 데스크 이야기](https://blog.nvim.me/network/basic/04-dns.md): 우리가 외우는 도메인 이름이 어떻게 실제 IP 주소로 바뀌는지, DNS의 동작을 일상 비유로 쉽게 풀어봅니다. - [포트와 소켓은 뭐가 다를까요? 같은 컴퓨터 안에서 길 찾기](https://blog.nvim.me/network/basic/05-ports-and-sockets.md): 같은 컴퓨터에 도착한 데이터가 어떻게 정확한 앱까지 찾아가는지, 포트와 소켓 개념을 일상 비유로 쉽게 풀어봅니다. - [HTTP와 HTTPS는 뭐가 다를까요? 브라우저와 서버의 대화 규칙](https://blog.nvim.me/network/basic/06-http-and-https.md): 브라우저가 서버에 어떤 형식으로 말을 거는지, HTTP와 HTTPS의 차이를 일상 비유로 쉽게 풀어봅니다. - [TLS, SSL, 인증서는 뭐가 다를까요? 브라우저는 어떻게 진짜 서버를 확인할까?](https://blog.nvim.me/network/basic/07-tls-ssl-and-certificates.md): HTTPS의 보호된 통로가 어떻게 준비되는지, TLS·SSL·인증서 개념을 일상 비유로 쉽게 풀어봅니다. - [OSI 7계층과 TCP/IP 모델, 왜 지도를 두 개나 그릴까요?](https://blog.nvim.me/network/basic/08-osi-and-tcp-ip-layers.md): 복잡한 네트워크 세계를 한눈에 보여주는 두 가지 지도, OSI와 TCP/IP 모델의 차이와 연결 고리를 알아봐요. - [TCP 3-way handshake는 왜 세 번이나 주고받을까요? 연결 전에 무슨 합의를 할까?](https://blog.nvim.me/network/basic/09-tcp-3-way-handshake.md): TCP가 데이터를 보내기 전에 SYN, SYN-ACK, ACK를 왜 주고받는지, sequence 번호와 acknowledgment 번호를 중심으로 쉽게 풀어봅니다. - [A, AAAA, CNAME... DNS 레코드는 왜 종류가 여러 갈래일까요?](https://blog.nvim.me/network/basic/10-dns-records.md): 도메인 이름 뒤에 숨은 A, AAAA, CNAME 레코드의 차이를 비유와 실제 예시로 친근하게 풀어봅니다. - [공인 IP, 사설 IP, 그리고 NAT는 왜 같이 나올까요? 집 안 주소와 바깥 주소의 비밀](https://blog.nvim.me/network/basic/11-public-private-ip-and-nat.md): 공인 IP와 사설 IP의 차이, 그리고 NAT가 왜 필요한지 집과 공유기 비유로 쉽게 풀어봅니다. - [패킷 캡처는 뭘 보는 걸까요? 같은 요청도 보는 자리마다 다르게 보이는 이유](https://blog.nvim.me/network/basic/12-packet-capture.md): 패킷 캡처가 무엇인지, 캡처 도구에서 TCP·DNS·NAT 흔적이 어떻게 보이는지 캡처 위치 중심으로 쉽게 풀어봅니다. - [공유기와 홈 네트워크, 우리 집 인터넷은 안에서 어떻게 흘러갈까요?](https://blog.nvim.me/network/basic/13-router-and-home-network.md): 모뎀, 공유기, 스위치, 와이파이, DHCP, 기본 게이트웨이까지 집 안 네트워크 구조를 한 장면으로 쉽게 풀어보는 글이에요. - [포트 포워딩과 들어오는 연결, 닫힌 우리 집 문을 어떻게 열까요?](https://blog.nvim.me/network/basic/14-port-forwarding-and-incoming-connections.md): 바깥에서 집 안 서버나 게임기로 직접 연결하고 싶을 때 쓰는 포트 포워딩, DMZ, 그리고 CGNAT 같은 함정까지 쉽게 풀어보는 글이에요. - [방화벽과 상태 기반 필터링, 열린 문 앞에서 누가 들어와도 되는지 어떻게 판단할까요?](https://blog.nvim.me/network/basic/15-firewall-and-stateful-filtering.md): 포트 포워딩으로 문을 열어둔 뒤에도 왜 방화벽이 필요한지, 그리고 상태 기반 필터링이 어떻게 정당한 답장만 들여보내는지 쉽게 풀어봐요. - [서브넷 마스크와 CIDR, 같은 동네인지 어떻게 판단할까요?](https://blog.nvim.me/network/basic/16-subnet-mask-and-cidr.md): IP 주소만 보고는 부족한 이유와 서브넷 마스크, CIDR, 같은 네트워크 범위 판단을 동네 비유로 쉽게 풀어봐요. - [DHCP, 우리 집 기기들은 자기 주소를 어떻게 자동으로 받을까요?](https://blog.nvim.me/network/basic/17-dhcp.md): 와이파이에 붙자마자 기기가 IP 주소, 게이트웨이, DNS를 자동으로 받는 이유를 DHCP와 임대 비유로 쉽게 풀어봐요. - [ARP와 로컬 전달, 주소는 알겠는데 진짜 목적지는 어떻게 찾을까요?](https://blog.nvim.me/network/basic/18-arp-and-local-delivery.md): IP 주소라는 숫자는 알지만, 같은 집 안에서 실제로 누구한테 패킷을 던져야 하는지 MAC 주소와 ARP의 관계를 통해 알아봐요. - [기본 게이트웨이와 첫 번째 도약, 패킷이 집을 나서는 순간엔 무슨 일이 벌어질까요?](https://blog.nvim.me/network/basic/19-default-gateway-and-first-hop.md): 게이트웨이 MAC 주소를 찾아 패킷을 맡긴 뒤, 공유기가 무엇을 보고 어디로 넘기는지 첫 번째 도약(First-hop)의 흐름을 알아봐요. - [ICMP, Ping, 그리고 Traceroute, 패킷이 어디까지 갔는지 어떻게 알아낼까요?](https://blog.nvim.me/network/basic/20-icmp-ping-and-traceroute.md): ICMP가 어떤 힌트를 주는지, ping은 무엇을 확인하는지, traceroute는 왜 중간 홉을 보여줄 수 있는지 쉽게 알아봐요. - [MTU, Fragmentation, 그리고 Path MTU, 패킷은 왜 길 위에서 쪼개지거나 멈출까요?](https://blog.nvim.me/network/basic/21-mtu-fragmentation-and-path-mtu.md): 패킷이 길을 따라가다가 너무 커서 문제가 생기는 상황과, 이를 해결하는 MTU와 Fragmentation의 원리를 알아봐요. - [TCP 재전송과 신뢰성 - 사라진 패킷을 끝까지 챙기는 법](https://blog.nvim.me/network/basic/22-tcp-retransmission-and-reliability.md): 중간에 패킷이 사라지면 TCP는 어떻게 그 사실을 알고 다시 보내줄까요? Sequence 번호와 ACK를 이용한 재전송 메커니즘을 알아봐요. - [TCP Teardown과 TIME-WAIT - 대화가 끝난 뒤의 깔끔한 마무리](https://blog.nvim.me/network/basic/23-tcp-teardown-and-time-wait.md): 데이터를 다 보낸 뒤에 연결을 어떻게 안전하게 닫을까요? FIN 신호와 TIME-WAIT 상태가 왜 필요한지 알아봐요. - [Proxy, Reverse Proxy, 그리고 Load Balancer - 서버 앞단의 교통정리](https://blog.nvim.me/network/basic/24-proxy-reverse-proxy-and-load-balancer.md): 사용자가 보는 서버와 실제로 일을 하는 서버가 왜 다를 수 있을까요? 프록시, 리버스 프록시, 로드 밸런서의 차이를 큰 그림부터 알아봐요. - [CDN, Cache, 그리고 Edge Delivery - 왜 사용자 가까이에 복사본을 둘까요?](https://blog.nvim.me/network/basic/25-cdn-cache-and-edge-delivery.md): CDN이 왜 필요한지, 캐시 히트와 미스가 무엇을 바꾸는지, 엣지에서 전달된다는 말이 실제로 무슨 뜻인지 차근차근 풀어봐요. - [End-to-End Request Debugging - 느린 요청은 어디서 막히고 있을까요?](https://blog.nvim.me/network/basic/26-end-to-end-request-debugging.md): 브라우저에서 시작한 요청 하나가 DNS, 연결, TLS, 프록시, 캐시, 오리진을 지나며 어디서 시간이 쓰이고 어디서 문제가 생기는지 차근차근 따라가봐요. - [네트워크 기본편은 어디부터 읽으면 좋을까요?](https://blog.nvim.me/network/basic/index.md): 패킷부터 End-to-End Request Debugging까지, 네트워크의 큰 흐름을 차근차근 따라가는 기본편 읽기 가이드예요. - [Wireshark Follow Stream은 왜 대화문처럼 읽힐까요?](https://blog.nvim.me/network/deep-dive/_wireshark-follow-stream.md): 흩어진 패킷 조각들을 하나의 대화문처럼 묶어서 보여주는 Wireshark의 Follow TCP Stream 기능을 실전 장면과 함께 읽어봐요. - [Cache Key와 Vary는 왜 같이 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/cache-key-and-vary.md): 같은 URL처럼 보여도 캐시가 다른 사본으로 나눠 저장하는 이유를 Cache Key, Vary, Accept-Encoding, Accept-Language, Cookie 신호로 같이 읽어봐요. - [캐시 오염 증상은 어디서부터 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/case-cache-poisoning-symptom.md): HIT인데 엉뚱한 언어, 사용자, CORS 헤더, 오래된 HTML이 보이는 캐시 오염 의심 장면을 Cache-Control, Age, Vary, cache key, 쿠키 신호로 나눠 읽어봐요. - [인증서 만료 장애는 어디서부터 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/case-cert-expired-incident.md): 갑자기 HTTPS 접속이 막히는 인증서 만료 장애를 브라우저, curl, openssl, 프록시 로그 신호로 나눠 읽고 갱신·배포·체인 문제를 좁혀봐요. - [DNS가 됐다 안 됐다 하는 장애는 TTL부터 어떻게 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/case-dns-flap-and-ttl.md): 어떤 사용자는 새 IP를 보고 어떤 사용자는 예전 IP를 보는 DNS 흔들림 장면을 권한 DNS, 재귀 리졸버 캐시, TTL, dig 출력으로 나눠 읽어봐요. - [한동안 조용한 뒤 첫 요청만 502가 나는 이유는 뭘까요?](https://blog.nvim.me/network/deep-dive/case-keepalive-mismatch-502.md): 앞단 프록시와 오리진의 keep-alive idle timeout이 어긋날 때, 재사용하려던 연결이 이미 닫혀 간헐적 502가 생기는 장면을 로그와 패킷 신호로 좁혀봐요. - [작은 요청은 되는데 큰 응답만 멈추는 이유는 뭘까요?](https://blog.nvim.me/network/deep-dive/case-mtu-blackhole.md): TCP 연결과 작은 요청은 성공하지만 큰 데이터 전송만 멈추는 MTU black hole 장애를 패킷 크기, DF, ICMP, 재전송 신호로 좁혀봐요. - [TIME-WAIT가 많을 때 정말 포트가 고갈된 걸까요?](https://blog.nvim.me/network/deep-dive/case-time-wait-port-exhaustion.md): 짧은 TCP 연결이 몰릴 때 TIME-WAIT가 쌓이고 새 연결이 실패하는 장면을 임시 포트 범위, 4-tuple, 연결 생성률, 운영체제 오류 신호로 좁혀봐요. - [CDN Cache Status 헤더는 어떻게 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/cdn-cache-status-headers.md): CF-Cache-Status, X-Cache, Cache-Status 같은 CDN 캐시 상태 헤더를 Cache-Control, Age, Vary, 요청 조건과 함께 읽으며 HIT, MISS, BYPASS, STALE을 오해하지 않게 정리해봐요. - [A/B/C 클래스 주소 체계는 왜 CIDR로 바뀌었을까요?](https://blog.nvim.me/network/deep-dive/classful-addressing-and-cidr-history.md): IPv4 주소를 예전에는 왜 A, B, C 클래스로 나눴고, 지금은 왜 /24, /20 같은 CIDR prefix 중심으로 읽는지 역사와 구조를 같이 풀어봐요. - [CNAME과 apex 도메인은 왜 같이 쓰기 어려울까요?](https://blog.nvim.me/network/deep-dive/cname-flattening-and-apex.md): CNAME이 편한 별명처럼 보이지만 루트 도메인에서는 왜 막히는지, CNAME flattening이 어떤 우회 방식인지 DNS 응답 장면으로 풀어봐요. - [Connection Pool Saturation은 왜 TTFB를 길게 만들까요?](https://blog.nvim.me/network/deep-dive/connection-pool-saturation.md): 앱 처리는 짧은데 브라우저 Waiting이 길어지는 장면에서 connection pool 포화, pending queue, upstream timing, p99를 함께 읽는 법을 정리해봐요. - [Connection reuse, Keep-Alive, Pooling은 왜 같이 봐야 할까요?](https://blog.nvim.me/network/deep-dive/connection-reuse-keepalive-and-pooling.md): HTTP 요청마다 새 연결을 여는 대신 연결을 재사용하는 이유와, Keep-Alive 설정·upstream connection pool·idle timeout mismatch가 지연과 502로 이어지는 장면을 같이 읽어봐요. - [Cookie와 캐시 가능성은 왜 같이 봐야 할까요?](https://blog.nvim.me/network/deep-dive/cookie-and-cacheability.md): Cookie, Set-Cookie, Authorization, private, no-store, Vary를 함께 읽으며 사용자별 응답이 공유 캐시에 섞이지 않게 판단하는 법을 정리해봐요. - [curl verbose와 timing은 어디부터 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/curl-verbose-and-timing.md): curl -v 출력과 --write-out timing 값을 DNS, TCP, TLS, 첫 바이트, 전체 시간으로 나눠 읽으며 느린 요청의 위치를 좁히는 방법을 같이 정리해봐요. - [dig 출력은 어디부터 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/dns-lookup-with-dig.md): DNS 조회 결과를 dig로 봤을 때 HEADER, QUESTION, ANSWER, AUTHORITY, ADDITIONAL 섹션을 어떤 순서로 읽으면 좋은지 실제 출력처럼 따라가요. - [DNS 메시지는 왜 질문 하나에 칸이 이렇게 많을까요?](https://blog.nvim.me/network/deep-dive/dns-message-format.md): DNS 요청과 응답이 실제로는 어떤 칸들로 나뉘는지, 12바이트 헤더와 Question·Answer·Authority·Additional 구조를 함께 읽어봐요. - [DNS 재귀 조회와 반복 조회는 뭐가 다를까요?](https://blog.nvim.me/network/deep-dive/dns-resolver-recursion-vs-iteration.md): 브라우저가 한 번 물어봤을 뿐인데 리졸버가 루트, TLD, 권한 서버를 대신 돌아다니는 이유를 재귀 조회와 반복 조회 관점에서 풀어봐요. - [DNS TTL과 캐시는 왜 바뀐 주소를 바로 안 보여줄까요?](https://blog.nvim.me/network/deep-dive/dns-ttl-and-cache-staleness.md): DNS 설정을 바꿨는데도 누군가는 예전 주소를 보는 이유를 TTL, 재귀 리졸버 캐시, 음성 캐시, 전환 순서 관점에서 풀어봐요. - [DNSSEC은 DNS 응답을 어떻게 믿게 만들어줄까요?](https://blog.nvim.me/network/deep-dive/dnssec-overview.md): DNSSEC이 DNS 응답에 서명을 붙이고, DS·DNSKEY·RRSIG 체인으로 답을 검증하는 흐름을 큰 그림부터 같이 읽어봐요. - [DoH와 DoT는 DNS 경로를 어디까지 숨겨줄까요?](https://blog.nvim.me/network/deep-dive/doh-dot-and-resolver-paths.md): DNS over HTTPS와 DNS over TLS가 평문 DNS와 무엇이 다르고, 리졸버 경로·암호화 구간·운영 신호를 어떻게 나눠 읽어야 하는지 같이 정리해봐요. - [EDNS0는 DNS 메시지 크기를 어떻게 넓혀줄까요?](https://blog.nvim.me/network/deep-dive/edns0-and-dns-message-size.md): DNS 응답이 512바이트를 넘을 때 TC 비트, OPT 의사 레코드, UDP payload size, TCP fallback이 어떻게 이어지는지 같이 읽어봐요. - [ETag와 조건부 요청은 어떻게 304를 만들까요?](https://blog.nvim.me/network/deep-dive/etag-and-conditional-requests.md): ETag, Last-Modified, If-None-Match, If-Modified-Since, 304 Not Modified를 함께 읽으며 캐시된 사본을 다시 내려받지 않고 확인하는 흐름을 정리해봐요. - [이더넷 프레임과 VLAN 태그 해부하기](https://blog.nvim.me/network/deep-dive/ethernet-frame-and-vlan.md): IP 패킷을 감싸서 로컬 네트워크로 실어 나르는 이더넷 프레임의 구조와, 그 사이에 끼어드는 VLAN 태그의 4바이트를 자세히 들여다봐요. - [HTTP/1.1 메시지는 왜 빈 줄 하나가 중요할까요?](https://blog.nvim.me/network/deep-dive/http1-message-grammar.md): HTTP/1.1 요청과 응답이 시작 줄, 헤더 필드, 빈 줄, 본문으로 어떻게 나뉘고 Content-Length와 Transfer-Encoding을 어떻게 읽어야 하는지 같이 해부해봐요. - [HTTP/2는 어떻게 여러 요청을 한 연결에 섞어 보낼까요?](https://blog.nvim.me/network/deep-dive/http2-frames-and-multiplexing.md): HTTP/2가 HTTP/1.1의 텍스트 메시지를 바이너리 프레임, 스트림, 멀티플렉싱으로 바꾸어 한 TCP 연결 안에서 여러 요청과 응답을 동시에 다루는 방식을 해부해봐요. - [HTTP/3는 QUIC 위에서 프레임을 어떻게 나눌까요?](https://blog.nvim.me/network/deep-dive/http3-and-quic-frames.md): HTTP/3가 HTTP/2와 비슷한 HEADERS, DATA 프레임 감각을 유지하면서도 QUIC 스트림, 제어 스트림, QPACK 위로 옮겨 타는 방식을 같이 해부해봐요. - [ICMP와 ICMPv6 Type은 어떻게 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/icmp-and-icmpv6-types.md): 기본편에서 ping과 traceroute의 힌트로 봤던 ICMP를, 이번엔 Type과 Code 칸 위에서 펼쳐보며 Echo, Time Exceeded, Destination Unreachable, Packet Too Big, IPv6 Neighbor Discovery까지 같이 읽어봐요. - [네트워크 심화편은 여기서 시작할게요](https://blog.nvim.me/network/deep-dive/index.md): 기본편에서 큰 그림을 본 뒤, 프로토콜 헤더 구조·패킷 캡처·브라우저 타이밍·캐시 헤더·장애 사례 같은 장면을 더 깊게 파고드는 심화편 입구예요. - [IPv4 헤더 한 줄 한 줄 읽기](https://blog.nvim.me/network/deep-dive/ipv4-header-anatomy.md): 기본편에서 카드 4개로만 봤던 IP 헤더를, 32비트 격자 위 13개 필드로 직접 펼쳐서 비트 단위로 읽어봐요. - [IPv6 헤더는 왜 딱 40바이트일까요?](https://blog.nvim.me/network/deep-dive/ipv6-header-anatomy.md): 기본편에서 AAAA와 IPv6를 이름 정도로만 봤다면, 이번엔 IPv6 기본 헤더를 32비트 격자 위에서 펼쳐보며 왜 더 길어졌는데 오히려 단순해졌는지 같이 읽어봐요. - [L4와 L7 로드 밸런서는 무엇을 보고 나눠 보낼까요?](https://blog.nvim.me/network/deep-dive/l4-vs-l7-load-balancer.md): 로드 밸런서가 IP와 포트만 보고 연결을 나누는지, HTTP Host와 path까지 보고 요청을 나누는지에 따라 L4와 L7 장면이 어떻게 달라지는지 읽어봐요. - [Longest Prefix Match는 왜 더 구체적인 길을 고를까요?](https://blog.nvim.me/network/deep-dive/longest-prefix-match-and-route-selection.md): 라우팅 테이블에 여러 경로가 동시에 맞을 때 라우터가 왜 더 긴 prefix를 고르는지, 기본 경로와 CIDR 요약 경로까지 함께 읽어봐요. - [네트워크 주소, 브로드캐스트 주소, 호스트 범위는 어떻게 나뉠까요?](https://blog.nvim.me/network/deep-dive/network-broadcast-and-host-range.md): 192.168.0.0/24 같은 범위에서 네트워크 주소, 브로드캐스트 주소, 실제 호스트 주소가 어떻게 갈라지는지 숫자로 읽어봐요. - [QUIC은 왜 UDP 위에서 돌아갈까요?](https://blog.nvim.me/network/deep-dive/quic-first-look.md): QUIC이 왜 굳이 UDP 위에 올라갔는지, TLS는 어디에 들어가는지, HTTP/3 장면은 어떻게 보이는지 큰 구조와 실제 흔적을 같이 읽어봐요. - [502, 503, 504는 어디서 만든 응답일까요?](https://blog.nvim.me/network/deep-dive/reading-502-503-504.md): 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout을 프록시와 오리진 경계에서 읽고, 헤더와 waterfall 신호로 응답의 출처를 좁혀봐요. - [브라우저 waterfall은 어디부터 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/reading-browser-waterfall.md): Chrome DevTools Network waterfall에서 Queueing, DNS, Initial connection, SSL, Waiting, Content Download를 나눠 읽으며 느린 요청의 위치를 좁히는 방법을 정리해봐요. - [Cache-Control과 Age 헤더는 어떻게 같이 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/reading-cache-control-and-age.md): Cache-Control, max-age, s-maxage, no-cache, no-store, private, public, Age 헤더를 함께 읽으며 지금 응답이 새 원본인지 오래된 사본인지 좁혀봐요. - [Server-Timing과 Request ID는 왜 같이 봐야 할까요?](https://blog.nvim.me/network/deep-dive/server-timing-and-request-id.md): 브라우저 waterfall의 긴 Waiting 구간을 Server-Timing, request id, trace id, 오리진 로그와 이어 붙이며 느린 요청의 안쪽 원인을 좁히는 방법을 정리해봐요. - [느린 upstream과 느린 render는 어떻게 구분할까요?](https://blog.nvim.me/network/deep-dive/slow-upstream-vs-slow-render.md): 브라우저의 긴 Waiting 구간을 서버 로그, Server-Timing, request id, 외부 API 시간, 렌더링 시간으로 나눠 읽으며 오리진 안쪽 병목을 좁혀봐요. - [SNI, ESNI, ECH는 뭐가 다를까요?](https://blog.nvim.me/network/deep-dive/sni-and-esni-ech.md): TLS가 시작되기 전에 왜 서버 이름이 먼저 필요하고, 평문 SNI가 왜 문제였는지, ESNI에서 ECH로 왜 바뀌었는지 같이 해부해봐요. - [ss와 netstat에서 TCP 상태는 어떻게 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/ss-and-netstat-state-reading.md): ss와 netstat 화면에 보이는 LISTEN, ESTABLISHED, TIME-WAIT, CLOSE-WAIT 같은 TCP 상태를 실제 장면과 함께 읽어봐요. - [stale-while-revalidate와 soft purge는 왜 같이 볼까요?](https://blog.nvim.me/network/deep-dive/stale-while-revalidate-and-soft-purge.md): stale-while-revalidate, stale-if-error, soft purge, background revalidation을 함께 읽으며 오래된 캐시 사본을 버리지 않고 안전하게 갱신하는 흐름을 정리해봐요. - [Sticky Session과 로드 밸런싱 방식은 왜 같이 봐야 할까요?](https://blog.nvim.me/network/deep-dive/sticky-sessions-and-load-balancing-modes.md): 라운드 로빈, least connections, hash 기반 분산, sticky session이 요청을 어떤 기준으로 같은 서버 또는 다른 서버에 보내는지 세션·배포·장애 관점에서 읽어봐요. - [서브넷 마스크와 CIDR은 실제로 어떻게 계산할까요?](https://blog.nvim.me/network/deep-dive/subnet-mask-and-cidr.md): 255.255.255.0과 /24가 같은 뜻인 이유, 네트워크 주소와 호스트 범위를 비트 단위로 읽는 법을 같이 풀어봐요. - [Tail Latency와 p99는 왜 평균보다 먼저 봐야 할까요?](https://blog.nvim.me/network/deep-dive/tail-latency-and-p99.md): 대부분의 요청은 빠른데 일부 요청만 느린 장면에서 평균, median, p95, p99, max를 나눠 읽으며 꼬리 지연을 디버깅하는 감각을 정리해봐요. - [TCP 혼잡 제어는 왜 흐름 제어와 따로 봐야 할까요?](https://blog.nvim.me/network/deep-dive/tcp-congestion-control.md): 받는 쪽 여유를 보는 Window와, 네트워크 길이 붐비는지를 보고 속도를 조절하는 congestion window가 어떻게 다른지 쉽게 풀어봐요. - [TCP 플래그는 어떻게 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/tcp-flags-cheatsheet.md): SYN, ACK, FIN, RST, PSH 같은 TCP 플래그를 캡처 화면에서 어떻게 읽어야 하는지, 자주 보는 조합과 헷갈리기 쉬운 해석을 같이 정리해봐요. - [tcpdump에서 TCP handshake는 어떻게 보일까요?](https://blog.nvim.me/network/deep-dive/tcp-handshake-in-capture.md): SYN, SYN-ACK, ACK가 실제 tcpdump 캡처에서는 어떤 줄로 보이는지, 어디를 먼저 읽어야 하는지, 어디서 끊기면 무엇을 의심해야 하는지 같이 정리해봐요. - [TCP 헤더는 왜 이렇게 칸이 많을까요?](https://blog.nvim.me/network/deep-dive/tcp-header-anatomy.md): 기본편에서 본 포트, sequence 번호, ACK, SYN/ACK 신호가 TCP 헤더의 몇 번째 칸에 들어가는지 32비트 격자 위에서 같이 펼쳐봐요. - [TCP 상태 머신: 연결의 탄생부터 소멸까지의 일대기](https://blog.nvim.me/network/deep-dive/tcp-state-machine.md): TCP가 SYN을 보내고 TIME-WAIT로 사라지기까지, 엔드포인트 내부에서 어떤 상태를 거치는지 RFC 9293 표준을 바탕으로 촘촘하게 해부해봐요. - [TCP 윈도우와 흐름 제어는 왜 같이 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/tcp-window-and-flow-control.md): 받는 쪽이 얼마나 더 받을 수 있는지 알려주는 Window 값이 ACK, 버퍼 여유, Window Scale과 함께 어떻게 움직이는지 쉽게 풀어봐요. - [tcpdump 한 줄은 어떻게 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/tcpdump-first-look.md): tcpdump를 처음 열었을 때 보이는 한 줄을 읽는 법부터, 자주 쓰는 옵션과 필터를 실전 감각으로 같이 정리해봐요. - [TLS 인증서 체인과 신뢰 오류는 어떻게 읽어야 할까요?](https://blog.nvim.me/network/deep-dive/tls-cert-chain-and-trust-errors.md): 인증서가 한 장이 아니라 체인으로 따라오는 이유와, 만료·이름 불일치·신뢰 실패 같은 TLS 경고를 실제 장면처럼 읽어봐요. - [TLS 핸드셰이크는 실제로 어떻게 한 단계씩 진행될까요?](https://blog.nvim.me/network/deep-dive/tls-handshake-step-by-step.md): TCP가 열린 뒤 TLS 핸드셰이크가 어떤 순서로 지나가고, 각 단계에서 무엇을 먼저 읽어야 하는지 장면처럼 따라가봐요. - [TLS 종료와 TLS 패스스루는 어디서 갈라질까요?](https://blog.nvim.me/network/deep-dive/tls-termination-vs-passthrough.md): HTTPS 요청을 앞단 프록시에서 풀어 읽는 TLS termination과, 암호화된 연결을 뒤쪽 서버까지 그대로 넘기는 TLS passthrough의 차이를 장애와 라우팅 관점에서 읽어봐요. - [TLS 1.3 핸드셰이크는 실제로 어떤 순서일까요?](https://blog.nvim.me/network/deep-dive/tls13-handshake-anatomy.md): ClientHello부터 ServerHello, EncryptedExtensions, Certificate, Finished까지, TLS 1.3 핸드셰이크의 큰 흐름과 각 메시지 역할을 같이 해부해봐요. - [TTFB와 Content Download는 어떻게 다르게 읽을까요?](https://blog.nvim.me/network/deep-dive/ttfb-vs-content-download.md): 브라우저 waterfall과 curl timing에서 첫 바이트 대기 시간과 본문 다운로드 시간을 나눠 읽으며, 서버 처리 문제와 전송 문제를 구분하는 감각을 정리해봐요. - [UDP 헤더는 왜 딱 8바이트일까요?](https://blog.nvim.me/network/deep-dive/udp-header-anatomy.md): 기본편에서 TCP보다 단순한 친구로만 봤던 UDP를, 이번엔 8바이트 헤더 위에서 펼쳐보며 포트·길이·체크섬이 어디 들어가는지 같이 읽어봐요. - [X-Forwarded 헤더에서 진짜 클라이언트 IP는 어떻게 읽을까요?](https://blog.nvim.me/network/deep-dive/x-forwarded-headers-and-client-ip.md): 리버스 프록시 뒤에서 앱이 보는 IP가 왜 프록시 주소가 되는지, X-Forwarded-For와 Forwarded 헤더를 신뢰 경계 기준으로 읽어봐요. - [AOP 프록시와 Annotation은 왜 기대와 다르게 동작할까요?](https://blog.nvim.me/spring-boot/aop-proxy-and-annotation-behavior.md): `@Transactional` 같은 Annotation이 단순한 표시가 아니라 프록시를 통과하는 호출에서 동작하는 이유와 self-invocation 함정을 살펴봐요. - [ApplicationContext와 Bean은 왜 Spring이 소유한 객체일까요?](https://blog.nvim.me/spring-boot/application-context-and-beans.md): ApplicationContext가 빈 정의를 모으고 실제 빈 객체를 만들고 연결하는 흐름을, 생명주기와 scope까지 이어서 살펴봐요. - [Application Event는 같은 앱 안에서 무엇을 느슨하게 만들까요?](https://blog.nvim.me/spring-boot/application-events-internal-messaging.md): ApplicationEventPublisher와 EventListener로 component를 분리하고, TransactionalEventListener의 실행 시점과 내부 event의 전달 한계를 함께 살펴봐요. - [스타터와 자동 설정은 왜 버전과 설정을 대신 맞춰줄까요?](https://blog.nvim.me/spring-boot/auto-configuration-and-starters.md): Spring Boot starter, BOM, dependency management, auto-configuration, 조건 평가 리포트를 통해 의존성 하나가 어떻게 실행 설정으로 이어지는지 살펴봐요. - [Spring Boot 4와 3은 무엇이 달라졌을까요?](https://blog.nvim.me/spring-boot/boot-4-and-boot-3-baseline-map.md): Spring Boot 4.x와 3.5.x의 기준선을 Java, Spring Framework, Jakarta EE, Servlet 컨테이너, starter, 테스트 의존성 관점에서 비교해요. - [컴포넌트 스캔과 Bean 등록은 왜 가끔 내 클래스를 못 찾을까요?](https://blog.nvim.me/spring-boot/component-scan-and-bean-registration.md): 컴포넌트 스캔, @Bean, 조건부 등록이 각각 어떤 방식으로 빈을 등록하는지 보고, Spring Boot가 클래스를 못 찾는 흔한 이유를 정리해요. - [application.yml과 profile은 설정을 어떻게 바꿔줄까요?](https://blog.nvim.me/spring-boot/configuration-properties-profiles-and-secrets.md): Spring Boot의 외부 설정, Config Data, profile, 환경 변수, Configuration Properties, 검증, secret 경계를 한 흐름으로 읽어봐요. - [데이터 접근은 JDBC, JPA, R2DBC 중 무엇을 골라야 할까요?](https://blog.nvim.me/spring-boot/data-access-map-jdbc-jpa-r2dbc.md): JDBC와 JdbcClient, Spring Data JDBC, JPA, Spring Data repository, R2DBC를 최신순이 아니라 문제 모양과 실행 모델로 고르는 법을 살펴봐요. - [의존성 주입은 실제 코드에서 어떻게 읽어야 할까요?](https://blog.nvim.me/spring-boot/dependency-injection-in-real-code.md): 생성자 주입, 선택적 의존성, 여러 빈 후보, 순환 의존성을 실제 서비스 코드 흐름으로 읽고 field injection이 오래 갈수록 불리해지는 이유를 살펴봐요. - [RestClient, WebClient, HTTP Interface는 언제 다르게 써야 할까요?](https://blog.nvim.me/spring-boot/http-clients-restclient-webclient-http-interface.md): 서버가 다른 서버를 호출할 때 RestClient, WebClient, HTTP Interface를 어떻게 고르고, timeout과 retry를 어디에 두어야 하는지 outbound API 경계로 읽어봐요. - [Spring Boot 글은 어디부터 읽으면 좋을까요?](https://blog.nvim.me/spring-boot/index.md): Spring과 Spring Boot를 처음 만날 때 헷갈리는 지점을, 객체 생성부터 자동 설정과 운영 흐름까지 한 줄로 이어서 읽는 입구예요. - [JPA Entity 상태와 영속성 컨텍스트는 왜 헷갈릴까요?](https://blog.nvim.me/spring-boot/jpa-entity-state-and-persistence-context.md): JPA Entity가 새 객체, 관리되는 객체, 분리된 객체, 삭제 예정 객체로 바뀌는 흐름을 영속성 컨텍스트, dirty checking, lazy loading, N+1, auditing과 함께 살펴봐요. - [JSON과 Jackson 3는 왜 API 호환성의 핵심일까요?](https://blog.nvim.me/spring-boot/json-jackson3-and-migration-from-jackson2.md): Spring Boot 4.x의 Jackson 3 기본 흐름, JsonMapper, Jackson 2 마이그레이션, 날짜와 enum과 unknown field가 API 계약에 주는 영향을 살펴봐요. - [JWT와 OAuth2 Resource Server는 왜 로그인 구현과 다를까요?](https://blog.nvim.me/spring-boot/jwt-oauth2-and-resource-server.md): JWT access token, OAuth2 login, resource server, issuer, JWK Set, scope, refresh token 경계를 Spring Security 요청 흐름으로 나누어 읽어봐요. - [main 메서드 하나가 어떻게 실행 중인 앱이 될까요?](https://blog.nvim.me/spring-boot/main-method-to-running-app.md): SpringApplication.run이 환경을 준비하고 ApplicationContext를 만들고 웹 서버를 띄우는 흐름을, 처음 읽는 사람도 따라갈 수 있게 단계별로 풀어봐요. - [Kafka와 RabbitMQ는 event를 어떻게 다르게 전달할까요?](https://blog.nvim.me/spring-boot/messaging-kafka-rabbitmq-and-events.md): Spring Boot에서 Kafka와 RabbitMQ로 process 밖에 message를 보내고, ordering, retry, dead-letter, idempotency를 함께 설계해야 하는 이유를 살펴봐요. - [Method Security와 도메인 권한은 어디에 둬야 할까요?](https://blog.nvim.me/spring-boot/method-security-and-domain-permission.md): URL 규칙만으로 부족해지는 소유권 검사, method security, @PreAuthorize, @PostAuthorize, 도메인 권한 판단을 service 경계에서 읽어봐요. - [Micrometer tracing과 correlation ID는 한 요청을 어떻게 찾을까요?](https://blog.nvim.me/spring-boot/micrometer-tracing-logs-and-correlation-id.md): 여러 Spring Boot service를 지난 요청 하나를 log, trace, trace ID, span ID, MDC로 연결하고 sampling과 context propagation 경계를 운영 관점에서 살펴봐요. - [MongoDB와 Elasticsearch는 왜 JPA보다 빠른 DB가 아닐까요?](https://blog.nvim.me/spring-boot/mongodb-elasticsearch-and-nosql-boundaries.md): MongoDB, Elasticsearch, document model, search index를 JPA 대체재가 아니라 서로 다른 데이터 문제를 푸는 도구로 나누어 읽어봐요. - [Actuator의 health와 metrics는 운영에서 무엇을 알려줄까요?](https://blog.nvim.me/spring-boot/observability-actuator-health-metrics.md): 배포된 Spring Boot 애플리케이션을 Actuator의 health, info, metrics, Prometheus endpoint로 관측하고 liveness와 readiness를 안전하게 나누는 기준을 살펴봐요. - [복잡한 query는 Querydsl과 Specification 중 무엇으로 풀어야 할까요?](https://blog.nvim.me/spring-boot/querydsl-specification-and-complex-query.md): Spring Data JPA에서 derived query method, @Query, Specification, Querydsl을 언제 나눠 쓰는지 검색 조건, join, pagination, sorting 경계로 살펴봐요. - [Redis cache와 session은 왜 성능을 올리면서 버그도 만들까요?](https://blog.nvim.me/spring-boot/redis-cache-and-session.md): Spring Boot에서 Redis cache와 Spring Session Redis를 같은 저장소처럼 보되, TTL, invalidation, key prefix, 분산 session 경계로 나누어 읽어봐요. - [REST API 설계와 에러 계약은 왜 컨트롤러 코드보다 먼저일까요?](https://blog.nvim.me/spring-boot/rest-api-design-and-error-contracts.md): DTO, request와 response 모양, Bean Validation, Problem Details, error code, API versioning을 클라이언트와 서버의 약속으로 읽어봐요. - [Schema migration은 왜 Flyway와 Liquibase로 관리할까요?](https://blog.nvim.me/spring-boot/schema-migration-flyway-liquibase.md): 테이블과 컬럼 변경을 서버 코드처럼 버전으로 남겨야 하는 이유를 Flyway, Liquibase, migration history, 배포 순서, rollback 기대까지 이어서 살펴봐요. - [Auth API는 실무 프로젝트처럼 어떻게 설계할까요?](https://blog.nvim.me/spring-boot/source-backed-auth-api.md): Spring Boot 4와 Java 21로 회원가입, Basic 자격 증명 교환, JWT Bearer 보호 API, refresh token 회전, JDBC 저장소, ProblemDetail, 15개 테스트를 처음부터 만들어요. - [Auth API에 metrics와 tracing을 실제로 어떻게 붙일까요?](https://blog.nvim.me/spring-boot/source-backed-observability-api.md): 기존 Auth API에 Actuator, Prometheus Counter, OpenTelemetry tracing, Jaeger, 작은 downstream을 붙이고 health부터 장애 추적까지 실행 결과로 확인해요. - [Todo API 첫 커밋은 어떻게 차근차근 만들까요?](https://blog.nvim.me/spring-boot/source-backed-todo-api-first-commit.md): Spring CLI로 Java 21, Gradle wrapper 기반 Todo API 프로젝트를 만들고, 생성된 파일 확인부터 controller, service, repository, validation, MockMvc 테스트까지 첫 커밋 흐름으로 따라가요. - [Spring Boot 프로젝트는 처음에 무엇을 만들어줄까요?](https://blog.nvim.me/spring-boot/spring-boot-init-and-project-shape.md): Spring Initializr와 spring init으로 만든 첫 프로젝트의 선택지, 빌드 파일, main 클래스, 패키지 구조, DevTools까지 처음 생성된 파일의 의미를 하나씩 봐요. - [Spring MVC와 WebFlux는 언제 다르게 선택해야 할까요?](https://blog.nvim.me/spring-boot/spring-mvc-vs-webflux.md): Spring MVC와 WebFlux를 단순한 구버전/신버전 관계가 아니라 blocking I/O, non-blocking I/O, thread model, 라이브러리 선택의 문제로 읽어봐요. - [Spring Security는 왜 filter chain부터 봐야 할까요?](https://blog.nvim.me/spring-boot/spring-security-filter-chain-first.md): Spring Boot에 Security starter를 넣었을 때 모든 요청이 왜 갑자기 잠기고, 인증과 인가와 CSRF와 CORS가 filter chain 안에서 어떻게 나뉘는지 살펴봐요. - [IoC, DI, AOP는 왜 Spring을 읽는 세 가지 기준점일까요?](https://blog.nvim.me/spring-boot/spring-three-principles-ioc-di-aop.md): 제어의 역전, 의존성 주입, 관점 지향 프로그래밍을 어려운 정의보다 먼저 코드 책임의 이동으로 보고, Spring Boot 코드에서 어디에 나타나는지 잡아봐요. - [Testcontainers와 WireMock은 무엇을 진짜로 바꿔줄까요?](https://blog.nvim.me/spring-boot/testcontainers-wiremock-and-contract-tests.md): 실제 PostgreSQL을 띄우는 Testcontainers, 외부 HTTP를 재현하는 WireMock, 서비스 사이 약속을 검증하는 contract test의 경계와 CI 운영법을 살펴봐요. - [테스트는 unit, slice, integration을 어떻게 나눠야 할까요?](https://blog.nvim.me/spring-boot/testing-map-unit-slice-integration.md): 빠른 unit test, 필요한 Spring 조각만 여는 slice test, 전체 bean graph를 연결하는 integration test가 각각 무엇을 증명하고 무엇을 놓치는지 살펴봐요. - [트랜잭션 경계와 롤백은 왜 Annotation 하나로 끝나지 않을까요?](https://blog.nvim.me/spring-boot/transaction-boundaries-and-rollback.md): `@Transactional`이 시작되는 위치, commit과 rollback이 결정되는 시점, propagation과 self-invocation이 기대를 흔드는 이유를 service 경계와 테스트까지 이어서 살펴봐요. - [웹 요청은 Spring MVC 안에서 어떤 순서로 지나갈까요?](https://blog.nvim.me/spring-boot/web-request-lifecycle-mvc.md): DispatcherServlet, HandlerMapping, argument resolution, validation, HttpMessageConverter, exception handling까지 Spring MVC 요청 흐름을 한 번에 따라가요. - [WebSocket과 STOMP는 언제 실시간 연결에 필요할까요?](https://blog.nvim.me/spring-boot/websocket-and-stomp.md): HTTP 요청-응답과 오래 열린 WebSocket 연결의 차이, STOMP destination, message broker, @MessageMapping, SockJS fallback을 Spring Boot 흐름으로 읽어봐요. - [왜 Spring과 Spring Boot가 필요했을까요?](https://blog.nvim.me/spring-boot/why-spring-and-boot-exist.md): 객체를 직접 만들고 연결하던 코드가 왜 Spring의 컨테이너로 옮겨갔는지, 그리고 Spring Boot가 어떤 설정 부담을 덜어주는지 첫 장면부터 풀어봐요. - [용어집](https://blog.nvim.me/tips/glossary.md): 약어, 서비스명, 도구 이름처럼 자주 보이지만 읽는 법과 뜻이 헷갈리는 단어를 한 페이지에서 찾을 수 있게 모아둔 글이에요.