밥 칸과 TCP/IP: 앱을 지탱하는 보이지 않는 계층
밥 칸이 TCP/IP 설계에 어떤 기여를 했는지, 패킷 네트워킹이 왜 중요한지, 그리고 이 구조가 어떻게 여전히 앱·API·클라우드 서비스를 지탱하는지 알아보세요.

TCP/IP가 현대 소프트웨어의 숨은 기반인 이유
대부분의 앱은 ‘즉시 반응’하는 것처럼 느껴집니다: 버튼을 누르면 피드가 새로고침되고, 결제가 완료되고, 동영상이 재생됩니다. 보이지 않는 곳에서는 작은 데이터 조각들이 Wi‑Fi, 셀룰러, 가정용 라우터, 데이터센터—때로는 여러 나라를 가로질러—흐르며 중간의 복잡한 문제들을 신경 쓰지 않게 만들어 줍니다.
그 보이지 않음이 바로 TCP/IP가 제공하는 약속입니다. 단일 제품이나 클라우드 기능이 아니라, 장치와 서버가 서로 대화하게 하는 공통 규칙의 집합입니다. 네트워크가 시끄럽고 혼잡하거나 일부 실패하는 상황에서도 대부분의 경우 부드럽고 믿을 만한 경험을 제공합니다.
밥 칸은 그 가능성을 만든 핵심 인물 중 한 명입니다. Vint Cerf 같은 협력자들과 함께, 네트워크들이 공통으로 사용할 수 있는 언어와 응용프로그램이 신뢰할 수 있는 방식으로 데이터를 전달하는 방법을 설계했습니다. 과장이 아니라 이 작업은 불안정한 연결을 소프트웨어가 안정적으로 기반 삼을 수 있게 만들었기 때문에 중요했습니다.
바쁠 때 이해하기 쉬운 패킷 네트워킹
메시지를 하나의 연속된 흐름으로 보내는 대신, 패킷 네트워킹은 작은 조각들(패킷)로 나눕니다. 각 패킷은 다른 길을 통해 목적지로 갈 수 있는데, 마치 서로 다른 우체국을 통하는 여러 봉투와 같습니다.
이 글에서 배우게 될 것들
TCP가 어떻게 신뢰감(느낌)을 만들어 내는지, 왜 IP가 고의로 완벽을 약속하지 않는지, 그리고 계층화가 시스템을 이해하기 쉽게 유지하는 방법을 풀어보겠습니다. 끝까지 읽으면 앱이 API를 호출할 때 실제로 어떤 일이 일어나는지, 그리고 왜 수십 년 된 이 아이디어들이 여전히 현대 클라우드 서비스를 뒷받침하는지 그려볼 수 있을 것입니다.
TCP/IP가 해결해야 했던 문제
초기 컴퓨터 네트워크는 ‘인터넷’으로 태어나지 않았습니다. 대학용 네트워크, 군사용 네트워크, 연구소 네트워크처럼 특정 그룹과 목적을 위해 구축되었습니다. 각 네트워크는 내부적으로는 잘 작동했지만 하드웨어, 메시지 형식, 데이터 전송 규칙이 제각각이었습니다.
그 결과는 좌절이었습니다: 두 컴퓨터가 모두 ‘네트워크에 연결’되어 있어도 서로 정보를 교환하지 못할 수 있었습니다. 이는 선로의 폭이 다르고 신호 규약이 다른 여러 철도 시스템이 존재하는 것과 비슷합니다. 한 시스템 내에서 열차는 움직일 수 있지만 다른 시스템으로 건너가기는 번거롭고 비용이 많이 들거나 불가능할 수 있습니다.
인터네트워킹: 컴퓨터가 아니라 네트워크를 연결하기
밥 칸이 직면한 핵심 과제는 단순히 "컴퓨터 A와 컴퓨터 B를 연결하는 것"이 아니었습니다. 문제는 네트워크들을 서로 연결하여 트래픽이 여러 독립 시스템을 통과해 마치 하나의 더 큰 시스템인 것처럼 동작하게 만드는 방법이었습니다.
그것이 ‘인터네트워킹’의 의미입니다—서로 다르게 설계되고 서로 다른 기관이 관리하는 네트워크들을 데이터가 한 네트워크에서 다음 네트워크로 건너가게 만드는 방법을 구축하는 것.
왜 공유 규칙(프로토콜)이 중요했나
인터네트워킹을 규모 있게 작동시키려면 모든 참여자가 단일 네트워크의 내부 설계에 의존하지 않는 공통 규칙(프로토콜)이 필요했습니다. 그 규칙은 현실적인 제약도 반영해야 했습니다:
- 네트워크는 실패하거나 데이터를 버리거나 순서가 뒤바뀔 수 있다.
- 모든 연결을 중앙에서 세세히 관리할 수는 없다.
- 시간이 지남에 따라 새로운 네트워크가 계속 추가될 것이다.
TCP/IP는 실용적인 답이 되었습니다: 독립적인 네트워크들이 상호연결되어도 실제 응용에 충분히 신뢰성 있게 데이터를 옮길 수 있도록 해주는 공유 ‘합의’였습니다.
밥 칸의 기여를 쉽게 풀어 말하면
밥 칸은 인터넷의 ‘도로 규칙’ 설계자 중 한 사람으로 가장 널리 알려져 있습니다. 1970년대 DARPA에서 일하면서 그는 네트워킹을 단순한 연구 실험에서 하드웨어·배선·내부 설계 모두를 동일하게 강제하지 않고도 다양한 네트워크를 연결할 수 있는 실용적 시스템으로 옮기는 데 기여했습니다.
핵심 아이디어: 네트워크들이 서로 말하게 하라
ARPANET는 패킷 스위치 연결을 통해 컴퓨터들이 통신할 수 있다는 것을 증명했습니다. 그러나 무선 기반 시스템, 위성 링크, 추가 실험 네트워크 등 다양한 네트워크가 등장했고 각각 고유한 특성이 있었습니다. 칸의 초점은 상호운용성이었습니다: 메시지가 여러 네트워크를 건너갈 때 마치 하나의 네트워크를 통과하는 것처럼 보이게 만드는 것입니다.
완벽한 하나의 네트워크를 만드는 대신 그는 다음과 같은 접근을 밀었습니다:
- 각 로컬 네트워크는 자체 설계를 유지할 수 있다.
- 공통 프로토콜이 그 위에 놓여 네트워크 경계를 넘어 데이터를 이동시킨다.
- 이 ‘접착제’는 앞으로 누군가가 발명할지도 모르는 미래의 네트워크 위에서도 작동할 만큼 일반적이다.
Vint Cerf와 함께 일하며 칸은 TCP/IP로 발전한 설계를 공동 설계했습니다. 지속적인 결과 중 하나는 책임 분리의 깔끔한 구조였습니다: IP는 주소 지정과 네트워크 간 전달을 처리하고, TCP는 응용이 필요로 하는 신뢰성 제공을 맡습니다.
오늘날 개발자가 얻는 이익
API를 호출하거나 웹페이지를 불러오거나 컨테이너에서 모니터링 서비스로 로그를 전송한 적이 있다면, 당신은 칸이 지지한 인터네트워킹 모델에 의존하고 있는 것입니다. 패킷이 Wi‑Fi, 광섬유, LTE, 클라우드 백본을 가로지르는지를 신경 쓸 필요가 없습니다. TCP/IP는 그 모든 것을 연속된 하나의 시스템처럼 보이게 만들어 소프트웨어는 배선이 아니라 기능에 집중할 수 있습니다.
TCP/IP의 계층화 아이디어: 단순하지만 강력함
TCP/IP의 가장 영리한 아이디어 중 하나는 계층화입니다: 모든 것을 다 하는 하나의 거대한 시스템을 만드는 대신, 각 계층이 하나의 역할을 잘 수행하도록 작은 조각들을 쌓아 올립니다.
이것이 중요한 이유는 네트워크가 모두 동일하지 않기 때문입니다. 서로 다른 케이블, 라디오, 라우터, 서비스 제공자가 몇 가지 깔끔한 책임에 합의하면 상호운용이 가능합니다.
IP: 네트워크 간 주소 지정과 라우팅
**IP(인터넷 프로토콜)**는 ‘이 데이터는 어디로 가야 하고, 그곳에 더 가깝게 옮기려면 어떻게 할까?’라는 질문에 답합니다.
IP는 주소를 제공하고(머신을 식별), 기본 라우팅을 제공합니다(패킷이 네트워크에서 네트워크로 홉하는 방법). 중요한 점은 IP가 완벽을 시도하지 않는다는 것입니다. 경로가 바뀌어도 패킷을 한 단계씩 앞으로 보내는 데 집중합니다.
TCP: IP 위에서 신뢰성 있는 전달
그 위에 **TCP(전송 제어 프로토콜)**가 놓여 ‘이것을 어떻게 믿을 수 있는 연결처럼 느끼게 할까?’에 답합니다.
TCP는 응용프로그램이 보통 원하는 ‘신뢰성’ 작업을 처리합니다: 데이터의 올바른 순서 보장, 누락된 조각 감지 및 재시도, 송신자가 수신자나 네트워크를 압도하지 않도록 페이싱(속도 제어) 등을 수행합니다.
간단한 우편물 비유(과장 없이)
분할된 역할을 그리는 유용한 방식은 우편 시스템과 비교하는 것입니다:
- IP는 주소와 라우팅 네트워크로 도시와 우체국 사이에서 봉투를 이동시킵니다.
- TCP는 추적과 확인처럼 다중 파트 배송이 완전하고 올바른 순서로 도착하도록 합니다.
주소가 패키지의 도착을 보장해 주지는 않습니다; 그 보장은 위에 쌓아서 만듭니다.
이 ‘단순한 스택’이 강력하게 남은 이유
책임이 분리되어 있기 때문에 한 계층을 개선해도 모든 것을 재설계할 필요가 없습니다. 새로운 물리적 네트워크는 IP를 담을 수 있고, 응용프로그램은 라우팅이 어떻게 작동하는지 이해하지 않아도 TCP의 동작에 의존할 수 있습니다. 이러한 깔끔한 분리는 TCP/IP가 거의 모든 앱과 API의 보이지 않는 기반이 된 주요 이유입니다.
패킷 교환: 속도, 유연성, 그리고 혼돈
패킷 교환은 전용 회선을 예약하지 않고도 대규모 네트워크를 실용적으로 만든 아이디어입니다: 메시지를 작은 조각으로 쪼개 각 조각을 독립적으로 보냅니다.
‘패킷’이란 무엇인가(그리고 왜 조각이 유리한가)
패킷은 헤더(보낸이, 받는이, 라우팅 정보)와 콘텐츠의 일부를 담은 작은 데이터 묶음입니다.
데이터를 쪼개면 네트워크가 다음을 할 수 있습니다:
- 여러 사용자가 링크를 공유하게 한다(아무도 ‘선로’를 독점하지 않음).
- 느리거나 고장난 구간을 우회해 라우팅할 수 있다.
- 전체 파일이 아니라 잃어버린 부분만 재전송해 복구할 수 있다.
서로 다른 경로, 뒤섞인 도착 순서
여기서 ‘혼돈’이 시작됩니다. 동일한 다운로드나 API 호출의 패킷들이 그 순간 무엇이 바쁜지에 따라 다른 경로를 택할 수 있습니다. 따라서 순서가 뒤바뀌어 도착할 수 있습니다—예를 들어 12번 패킷이 5번 패킷보다 먼저 도착할 수 있습니다.
패킷 교환은 이를 막으려 하지 않습니다. 신속하게 패킷을 통과시키는 것을 우선하고 도착 순서가 엉망인 경우는 위 계층이 정리합니다.
패킷이 사라지는 이유
패킷 손실은 드물지 않으며 언제나 누군가의 잘못은 아닙니다. 일반적인 원인:
- 혼잡: 라우터의 버퍼가 가득 차 패킷을 버림
- 노이즈/간섭: 특히 무선 링크에서
- 장애 및 재라우팅: 링크가 중간에 실패하면 일부 패킷은 도착하지 못함
불완전함은 결함이 아니라 기능
핵심 설계 선택은 네트워크가 불완전하도록 허용하는 것입니다. IP는 전진에 집중하고 전달이나 순서를 약속하지 않음으로써 네트워크가 확장될 수 있게 합니다—그리고 이 때문에 상위 계층(예: TCP)이 혼란을 정리하도록 존재합니다.
TCP가 불안정한 네트워크를 신뢰할 수 있게 만드는 방법
IP는 패킷을 ‘최선 노력’으로 전달합니다: 일부는 늦게 도착하고, 순서가 바뀌고, 중복되거나 전혀 도착하지 않을 수 있습니다. TCP는 그 위에서 응용프로그램이 신뢰할 수 있는 단일, 정렬되고 완전한 바이트 스트림을 만들어 줍니다—파일 업로드, 웹페이지 로드, API 호출할 때 기대하는 그런 연결입니다.
평범한 말로 신뢰성
사람들이 TCP를 ‘신뢰할 수 있다’고 말할 때 보통 의미하는 것은:
- 정렬됨: 데이터가 전송한 순서대로 앱에 전달된다.
- 완전함: 누락된 조각은 감지되어 재전송된다.
- 틈이 없음: 앱은 흩어진 패킷이 아니라 연속된 스트림을 읽는다.
핵심 메커니즘(그리고 왜 작동하는가)
TCP는 데이터를 조각내어 시퀀스 번호를 붙입니다. 수신자는 받은 것을 확인하는 **ACK(확인 응답)**을 보냅니다.
송신자가 제때 ACK를 받지 못하면 무언가가 손실된 것으로 가정하고 재전송을 수행합니다. 이것이 핵심적인 ‘환상’입니다: 네트워크가 패킷을 버리더라도 TCP는 수신자가 확인할 때까지 계속 시도합니다.
플로우 제어 vs 혼잡 제어
소리가 비슷하지만 해결하는 문제는 다릅니다:
- 플로우 제어는 수신자를 보호합니다. “내가 바빠—버퍼가 넘치지 않게 천천히 보내.”
- 혼잡 제어는 네트워크를 보호합니다. “경로가 과부하 상태야—교통 체증을 악화시키지 않도록 속도를 줄여.”
둘은 함께 TCP가 빠르면서도 무모하지 않게 유지되도록 돕습니다.
적응하는 타임아웃
고정된 타임아웃은 느린 네트워크와 빠른 네트워크 모두에서 실패합니다. TCP는 왕복시간(RTT)을 측정해 타임아웃을 지속적으로 조정합니다. 상태가 악화되면 재전송 전 더 오래 기다리고, 빨라지면 더 민감해집니다. 이러한 적응 덕분에 TCP는 Wi‑Fi, 모바일 네트워크, 장거리 링크 전반에서 계속 작동합니다.
확장 가능한 설계 선택: 엔드투엔드 사고방식
TCP/IP의 가장 중요한 아이디어 중 하나는 엔드투엔드 원칙입니다: 네트워크의 ‘중간’은 비교적 단순하게 두고 ‘스마트한’ 동작은 끝단에 두라는 것.
끝단에 지능을 두기
끝단은 실제로 데이터에 관심 있는 장치와 프로그램입니다: 당신의 폰, 노트북, 서버, 그리고 그 위에서 돌아가는 운영체제와 애플리케이션. 네트워크 핵심(라우터와 중간 링크)은 주로 패킷을 전달하는 데 집중합니다.
모든 라우터를 완벽하게 만들려 하기보다는 TCP/IP는 중간이 불완전할 것을 받아들이고 끝단이 문맥이 필요한 부분을 처리하도록 합니다.
단순한 핵심이 성장 가능성을 만든 이유
핵심을 단순하게 유지하면 인터넷 확장이 쉬워집니다. 새로운 네트워크가 합류하더라도 모든 중간 장치가 모든 애플리케이션의 요구를 이해해야 할 필요가 없습니다. 라우터는 패킷이 비디오 통화의 일부인지 파일 다운로드의 일부인지 API 요청의 일부인지 알 필요 없이 단지 전달하면 됩니다.
무엇을 어디에 둘 것인가(예시와 함께)
끝단에서 보통 처리하는 것들:
- 신뢰성: 재전송, 순서 정리, 중복 제거(TCP)
- 보안: 암호화와 신원 확인(보통 TLS를 통한 애플리케이션/OS 수준)
- 앱 동작: 타임아웃, 재시도, 캐싱, 속도 제한
네트워크에서는 주로:
- 주소 지정과 전달(IP)
- 기본적인 패킷 처리와 혼잡 신호
트레이드오프
엔드투엔드 사고는 잘 확장되지만 복잡성을 밖으로 밀어냅니다. 운영체제, 라이브러리, 애플리케이션이 ‘문제를 해결’할 책임을 지게 됩니다. 이는 유연성에는 좋지만 버그, 잘못된 타임아웃 설정, 과도한 재시도가 실제 사용자 문제를 만들 수 있다는 뜻이기도 합니다.
IP의 '최선 노력' 모델이 기능인 이유
IP는 단순한 약속을 합니다: 패킷을 목적지로 옮기려고 시도하겠습니다. 그뿐입니다. 도착 여부, 중복 여부, 순서, 특정 시간 안에 도착 등은 보장하지 않습니다.
이것은 단점처럼 보일 수 있지만 인터넷이 전 세계적으로 성장하는 데 필요한 조건을 제공했습니다: 많은 작은 네트워크들이 서로 다른 조직에 의해 소유되고 끊임없이 변하는 환경에서 함께 작동해야 했습니다.
라우터의 역할(하고 하지 않는 것)
라우터는 IP의 ‘교통 지휘자’입니다. 주된 임무는 전달입니다: 패킷이 도착하면 라우터는 목적지 주소를 보고 지금 가장 적절해 보이는 다음 홉을 선택합니다.
라우터는 통화를 추적하는 전화 교환원처럼 대화를 관리하지 않습니다. 보통 용량을 예약하지 않고 패킷이 통과했는지 확인하려 기다리지도 않습니다. 라우터를 전달에 집중하게 함으로써 네트워크의 핵심은 단순하게 유지되고 엄청난 수의 장치와 연결로 확장할 수 있습니다.
'최선 노력'이 전 세계적 확장에 기여한 이유
보장(guarantees)은 비용이 큽니다. IP가 모든 패킷의 전달, 순서, 타이밍을 보장하려 했다면 지구상의 모든 네트워크가 긴밀히 조정되어야 하고, 많은 상태를 저장하고, 실패 복구를 동일하게 수행해야 합니다. 그러면 성장 속도가 느려지고 장애가 더 심각해집니다.
대신 IP는 엉망을 허용합니다. 링크가 실패하면 라우터는 다른 경로로 패킷을 보낼 수 있습니다. 경로가 혼잡하면 패킷이 지연되거나 버려질 수 있지만 다른 대체 경로로 트래픽이 계속될 수 있습니다.
결과는 복원력입니다: 일부가 고장나거나 바뀌어도 인터넷은 계속 작동할 수 있습니다—네트워크가 완벽할 필요 없이 유용할 수 있기 때문입니다.
앱과 API에서 패킷까지: 실제로 무슨 일이 일어나는가
당신이 fetch()로 API를 호출하거나 ‘저장’ 버튼을 누르거나 웹소켓을 열 때, 당신은 한 번에 매끄럽게 서버와 이야기하는 것이 아닙니다. 앱은 운영체제에 바이트를 넘기고 운영체제는 그것을 패킷으로 잘라 여러 네트워크를 통해 보냅니다—각 홉은 자체 결정을 내립니다.
개발자 행동 → TCP/IP 동작의 간단한 맵핑
- HTTP 요청 / API 호출: 앱이 바이트(HTTP 요청)를 씁니다. TCP가 그 바이트 스트림을 세그먼트로 나누고 번호를 매기며 확인 응답을 기대합니다. IP가 각 세그먼트를 패킷으로 감싸 라우팅합니다.
- 연결 열기: TCP 핸드셰이크가 공유 상태(시퀀스 번호, 윈도 크기)를 설정합니다. 이는 무료가 아니며 첫 유효 바이트 전의 시간이 추가됩니다.
- 파일 업로드: TCP에 충분한 처리량이 있어도 지연(latency)이 높으면 성능이 느리게 느껴질 수 있습니다.
지연 대 처리량(그리고 왜 앱이 느리게 느껴지는가)
- **지연(latency)**은 메시지가 왕복하는 데 걸리는 시간입니다. 채팅 같은 잦은 요청 패턴에 해롭습니다: 작은 요청을 많이 하거나 리디렉션이 많은 경우.
- **처리량(throughput)**은 초당 전달 가능한 데이터 양입니다. 대용량 전송(이미지, 백업, 비디오)에 영향을 줍니다.
흔한 놀라움: 처리량은 좋지만 왕복 시간이 길어 UI가 둔하게 느껴질 수 있습니다. 각 요청이 왕복을 기다리기 때문입니다.
재시도와 타임아웃: 앱이 왜 TCP가 이미 하는 일을 다시 하는가
TCP는 잃은 패킷을 재시도하지만 사용자 경험에서 ‘너무 오래’가 무엇인지 알 수는 없습니다. 그래서 애플리케이션은 추가로:
- 타임아웃: “2초 내에 응답이 없으면 오류를 보여주자.”
- 재시도: “한 번 더 시도하자.” 일시적 실패에 유용하지만 결제 같은 작업에는 요청이 멱등(idempotent)이어야 안전합니다.
‘버그’처럼 보이지만 사실은 네트워크 현실일 때
패킷은 지연되거나 순서가 바뀌거나 중복되거나 버려질 수 있습니다. 혼잡이 순간적으로 지연을 급증시킬 수 있습니다. 서버는 응답했지만 응답이 당신에게 도달하지 못할 수도 있습니다. 이런 현상은 플래키한 테스트, 무작위 504 응답, ‘내 환경에선 된다’는 증상으로 나타납니다. 많은 경우 코드가 문제가 아니라 기계 사이 경로가 문제입니다.
클라우드에서의 TCP/IP: 동일한 규칙, 더 큰 규모
클라우드 플랫폼은 완전히 새로운 종류의 컴퓨팅처럼 느껴질 수 있습니다—관리형 데이터베이스, 서버리스 함수, '무한' 확장 등. 그러나 그 아래에서 당신의 요청은 여전히 밥 칸이 시작한 동일한 TCP/IP 기반을 탑니다: IP는 네트워크를 가로질러 패킷을 이동시키고 TCP(또는 때로는 UDP)가 애플리케이션이 네트워크를 어떻게 경험하는지 형성합니다.
클라우드에서 바뀌는 것(주로 포장 방식)
가상화와 컨테이너는 어디 소프트웨어가 실행되고 어떻게 포장되는지를 바꿉니다:
- “서버”는 가상 머신, 컨테이너, 또는 단명 함수일 수 있습니다.
- 네트워크는 종종 소프트웨어 정의 네트워킹으로 제공자가 이어붙입니다.
하지만 이는 배포의 세부사항입니다. 패킷은 여전히 IP 주소 지정과 라우팅을 사용하고 많은 연결은 여전히 순서적이고 신뢰성 있는 전달을 위해 TCP에 의존합니다.
변하지 않는 것들(인식할 수 있는 패턴)
일반적인 클라우드 아키텍처는 친숙한 네트워킹 구성요소로 만들어집니다:
- 로드 밸런서는 클라이언트 TCP 연결(종종 HTTPS)을 받아 백엔드 서비스에 분산합니다.
- 서비스 간 호출은 클러스터 내부에서도 네트워크 호출입니다—HTTP/gRPC가 TCP 위에서 흔히 쓰입니다(사설 IP 간).
- 데이터베이스와 캐시는 표준 프로토콜을 통해 TCP 위에서 접근됩니다(예: 데이터베이스 드라이버가 TCP 세션을 유지).
IP 주소를 ‘보지 못’하더라도 플랫폼은 그들을 할당하고 패킷을 라우팅하며 연결을 추적합니다.
신뢰성은 여전히 공동의 책임
TCP는 패킷 손실을 복구하고, 배달 순서를 재정렬하며, 혼잡에 적응할 수 있지만 불가능한 것을 약속할 순 없습니다. 클라우드 시스템에서 신뢰성은 팀의 작업입니다:
- 네트워크: 라우팅, 용량, 패킷 손실, 일시적 실패
- OS/런타임: 소켓 버퍼, 타임아웃, DNS 캐싱, 연결 재사용
- 애플리케이션: 지수 백오프가 있는 재시도, 멱등성 보장, 합리적 타임아웃, 우아한 열화
이것이 Koder.ai 같은 ‘vibe-coding’ 플랫폼이 전체 스택 앱을 빠르게 생성해줘도, 그 앱이 API나 데이터베이스, 모바일 클라이언트와 통신할 때 다시 TCP/IP 영역으로 들어가는 이유입니다—연결, 타임아웃, 재시도 등 모든 문제가 그대로 적용됩니다.
TCP vs UDP 그리고 개발자들의 선택
‘네트워크’라고 말할 때 개발자들은 보통 두 가지 전통적 전송 수단: TCP와 UDP 중 하나를 선택합니다. 둘 다 IP 위에 있지만 매우 다른 절충을 합니다.
TCP: 신뢰성 있는 스트림(숨겨진 비용 포함)
TCP는 데이터가 순서대로, 틈 없이 도착해야 하고 기다릴 의사가 있을 때 적합합니다. 예: 웹페이지, API 호출, 파일 전송, 데이터베이스 연결.
그렇기 때문에 일상 인터넷의 많은 부분이 TCP 위에 올라갑니다—HTTPS는 TCP 위에서 동작(TLS를 통해)하고 대부분의 요청/응답 소프트웨어는 TCP의 동작을 전제로 합니다.
단점: TCP의 신뢰성은 지연을 추가할 수 있습니다. 한 패킷이 누락되면 이후 패킷들이 갭이 채워질 때까지 기다려야 할 수 있습니다(‘헤드 오브 라인 블로킹’). 인터랙티브한 경험에서는 이 기다림이 가끔의 결함보다 더 나쁘게 느껴질 수 있습니다.
UDP: 단순하고 빠르며 앱이 제어함
UDP는 ‘메시지를 보내고 도착하길 바란다’에 가깝습니다. UDP 자체에는 순서 보장, 재전송, 혼잡 처리 같은 것이 없습니다.
개발자들은 시기성이 완벽함보다 중요한 경우 UDP를 선택합니다: 실시간 오디오/비디오, 게임, 실시간 텔레메트리 등. 이러한 앱들은 사용자에게 실제로 눈에 띄는 부분에 따라 자체 경량 신뢰성 메커니즘을 만들거나 아예 만들지 않습니다.
현대적 주요 예: QUIC는 UDP 위에서 동작해 애플리케이션이 더 빠른 연결 설정을 얻고 일부 TCP 병목을 피할 수 있게 해줍니다—기저의 IP 네트워크를 변경할 필요 없이.
선택을 위한 실용적 지침
기준에 따라 고르세요:
- 신뢰성 요구: 모든 바이트가 순서대로 도착해야 하나? TCP 우선.
- 지연 민감도: ‘지금’이 ‘완벽’보다 더 중요? UDP 고려.
- 제어 수준: 재시도/스킵/복구를 앱이 직접 판단하길 원하나? UDP(또는 QUIC)가 더 많은 설계 공간을 줍니다.
‘신뢰성’이 여전히 보장하지 못하는 것들: 현실적 함정
TCP는 종종 ‘신뢰할 수 있는’ 것으로 묘사되지만, 그것이 당신의 앱이 항상 신뢰할 만하게 느껴진다는 의미는 아닙니다. TCP는 많은 네트워크 문제를 복구할 수 있지만 두 시스템 사이 경로가 불안정할 때 지연이 낮거나 일관된 처리량, 좋은 사용자 경험을 보장할 수는 없습니다.
여전히 마주치게 될 일반적 네트워크 문제
패킷 손실은 TCP로 재전송을 강제합니다. 신뢰성은 유지되지만 성능이 크게 떨어질 수 있습니다.
높은 지연(긴 왕복시간)은 패킷 손실이 없어도 모든 요청/응답 주기를 느리게 만듭니다.
**버퍼블로트(bufferbloat)**는 라우터나 OS 큐가 너무 많은 데이터를 쌓을 때 발생합니다. TCP는 손실을 줄일 수 있지만 사용자는 거대한 지연과 ‘버벅임’을 경험합니다.
잘못 설정된 MTU는 단편화나 블랙홀(너무 큰 패킷이 사라짐)을 일으켜 혼란스러운 실패를 초래합니다.
앱 내부에서 보이는 모습
명확한 ‘네트워크 오류’ 대신 보통 다음과 같은 증상으로 나타납니다:
- 보통 작동하던 API 호출의 타임아웃
- 빠르게 시작했다가 느려지는 업로드/다운로드
- 반복 재연결, 멈춘 스트림, 부분적으로 로드된 페이지 같은 ‘플래키’한 연결
이 증상들은 실제이며 코드 때문만은 아닙니다. 종종 TCP가 제 역할(재전송, 백오프, 대기)을 하는 동안 애플리케이션의 시계가 계속 흐르기 때문에 발생합니다.
실용적인 디버깅 시작점
먼저 문제를 손실(loss), 지연(latency), 또는 경로 변화(path changes) 중 어느 쪽인지 분류하세요.
- Ping 스타일 검사로 지연과 손실을 가늠할 수 있습니다(비록 ICMP가 차단될 수 있음).
- Traceroute 스타일 사고로 지연이나 손실이 어디서 시작되는지 추적하세요.
- 로그와 메트릭 추가: 요청 지속시간, 타임아웃 횟수, 재시도 횟수, 큐/백프레셔 신호 등.
Koder.ai 같은 환경에서 빠르게 서비스를 프로토타이핑하고 호스팅 및 커스텀 도메인으로 배포할 때, 이런 관찰 가능성(Observability) 기초를 초기 계획 체크리스트에 포함시키는 것이 가치가 있습니다—네트워킹 실패는 깔끔한 예외가 아니라 타임아웃과 재시도로 먼저 드러나기 때문입니다.
실패를 전제로 설계하라
네트워크가 잘못 동작한다고 가정하세요. 타임아웃, 지수 백오프가 포함된 재시도, 멱등성 보장을 사용해 재시도가 결제나 중복 생성으로 이어지지 않도록 설계하세요.
자주 묻는 질문
TCP/IP가 무엇이며 현대 앱에 왜 중요한가요?
TCP/IP는 서로 다른 네트워크들이 상호 연결되어도 예측 가능한 방식으로 데이터를 주고받을 수 있게 하는 공통 규칙들의 집합입니다.
이는 Wi‑Fi, LTE, 광섬유, 위성 같은 불안정하고 이질적인 링크들을 소프트웨어가 신경 쓰지 않고도 사용할 수 있게 해주기 때문에 중요합니다. 앱은 물리적 네트워크의 세부를 몰라도 바이트를 보내고 응답을 받을 수 있다고 가정할 수 있습니다.
밥 칸은 인터넷 설계에 어떤 핵심 기여를 했나요?
밥 칸은 ‘인터네트워킹’이라는 핵심 아이디어를 주도해 여러 서로 다른 네트워크들을 연결하는 방법을 제시했습니다. 즉, 각 네트워크가 내부 설계나 하드웨어를 공유하지 않아도 트래픽이 네트워크 경계를 넘어 전달되도록 한 것이죠.
그 결과는 Vint Cerf 등과 함께 만든 설계로 이어졌고, 여기서 IP는 주소 지정과 네트워크 간 전달을, TCP는 응용프로그램을 위한 신뢰성 제공을 분리해 맡게 되었습니다.
간단히 설명하면 패킷 교환이란 무엇이며 왜 사용되나요?
패킷 교환은 메시지를 작은 패킷으로 나누어 각 패킷이 독립적으로 전송되는 방식입니다.
장점:
- 링크를 다수 사용자가 공유하게 해 효율성이 높아짐
- 장애가 있는 구간을 우회해 라우팅 가능
- 전체 파일을 다시 보내지 않고 잃은 부분만 재전송하면 됨
왜 IP는 전달이나 순서를 보장하지 않나요?
IP는 한 가지 일에 집중합니다: 패킷을 목적지 주소 쪽으로 전달하려 시도합니다. 도착, 순서, 시간 보장 같은 것을 약속하지 않습니다.
이런 ‘best effort’ 모델은 전 세계적으로 확장 가능하게 만듭니다. 라우터들이 단순하고 빠르게 유지될 수 있어 링크가 실패하거나 경로가 바뀌어도 네트워크가 계속 작동할 수 있습니다.
TCP는 어떻게 불안정한 네트워크를 신뢰할 수 있게 만들나요?
TCP는 IP의 best-effort 패킷을 응용프로그램이 기대하는 정렬된 바이트 스트림으로 바꿉니다.
방법:
- 시퀀스 번호: 데이터의 순서를 알 수 있게 라벨링
- ACK(확인 응답): 수신된 부분을 확인
- 재전송: 누락된 부분을 다시 보냄
- 적응형 타임아웃: 네트워크 속도에 맞춰 타임아웃을 조정
TCP의 플로우 제어와 혼잡 제어는 어떻게 다른가요?
두 메커니즘은 다른 문제를 해결합니다:
- **플로우 제어(flow control)**는 수신자를 보호합니다(수신자가 처리할 수 있는 양을 알림).
- **혼잡 제어(congestion control)**는 네트워크 경로를 보호합니다(경로에 혼잡 신호가 보이면 송신자가 속도를 줄임).
좋은 성능을 위해서는 둘 다 필요합니다: 빠른 송신자는 수신자와 네트워크를 모두 존중해야 합니다.
개발자에게 TCP/IP의 '계층화'가 왜 중요한가요?
계층화(layering)는 각 구성요소가 한 가지 역할을 잘 하도록 나누는 설계 원칙입니다.
- 하위 계층은 바뀔 수 있습니다(새로운 Wi‑Fi 표준, 광장비, 클라우드 네트워크).
- 상위 계층은 그대로 동작합니다(예: TCP 동작, 응용 프로토콜).
개발자 입장에서는 네트워크 유형마다 앱을 다시 설계할 필요 없이 API와 서비스를 구축할 수 있다는 의미입니다.
엔드투엔드 원칙은 실제로 무엇을 의미하나요?
엔드투엔드 원칙은 네트워크의 중심부(라우터 등)는 비교적 단순하게 두고 실제 ‘스마트한’ 동작은 끝단(클라이언트와 서버)에 두라는 뜻입니다.
실무적 의미: 신뢰성, 타임아웃, 재시도, 암호화(종종 TLS)는 네트워크가 아니라 운영체제와 애플리케이션이 처리합니다. 네트워크 코어가 모든 애플리케이션 요구를 이해할 필요가 없어 확장성이 좋아집니다.
지연과 처리량이 API 성능에 각각 어떻게 영향을 주나요?
**지연(latency)**는 왕복 시간(RTT)으로 채팅형(작은 요청을 많이 하는) 패턴에 큰 영향을 줍니다.
**처리량(throughput)**은 초당 전송 가능한 바이트 수로 대용량 전송(이미지, 백업, 비디오)에 영향을 줍니다.
실용 팁:
- 연결 재사용(keep-alive/풀링)으로 핸드셰이크 비용 줄이기
- 가능한 요청 배치하기
- 사용자 경험에 맞게 타임아웃 설정하기(단순히 ‘TCP가 언젠가 전달할 것’에만 의존하지 않음)
개발자는 언제 TCP를 쓰고 언제 UDP를 골라야 하나요? QUIC는 어디에 해당하나요?
선택 기준:
- 신뢰성 필요도: 모든 바이트가 순서대로 도착해야 하나? 그렇다면 TCP.
- 지연 민감도: '지금'이 '완벽'보다 중요한가? 그렇다면 UDP.
- 제어 수준: 앱이 재시도, 누락 처리, 복구 방식을 직접 결정하길 원하나? UDP(또는 QUIC)는 더 많은 설계 자유를 줍니다.
QUIC는 UDP 위에서 동작해 연결 설정 시간을 줄이고 일부 TCP 병목을 피할 수 있어 HTTP/3 등에 사용됩니다. 요청/응답형이고 정확성이 우선이면 TCP(또는 HTTP/3의 QUIC)가 보통 출발점입니다.