지금까지의 여정을 통해 데이터가 물리적인 신호로 변환되고(1계층), MAC 주소를 통해 같은 동네 안에서 길을 찾고(2계층), IP 주소와 라우팅을 통해 전 세계적인 목적지 컴퓨터까지 도달하는(3계층) 과정을 살펴보았다. 하지만 데이터가 목적지 컴퓨터에 도착했다고 해서 임무가 끝난 것은 아니다. 마치 거대한 빌딩(컴퓨터)에 우편물이 도착했을 때, 이 우편물이 수많은 부서(애플리케이션) 중 정확히 어느 부서의 누구에게 전달되어야 하는지를 결정해야 하는 마지막 단계가 남아있다.
이 중요한 임무를 수행하는 것이 바로 4계층, 전송 계층(Transport Layer)이다. 전송 계층은 단순히 데이터를 목적지 컴퓨터로 보내는 것을 넘어, 출발지 컴퓨터의 특정 프로세스(애플리케이션)에서 목적지 컴퓨터의 특정 프로세스까지 데이터가 온전히 전달되도록 책임지는, 이른바 '종단 간(End-to-End)' 통신의 핵심 지휘자이다.
이 계층은 데이터 전송의 '품질'을 결정한다. 어떤 데이터는 한 글자도 빠짐없이 순서대로 도착해야 하고(TCP), 어떤 데이터는 약간의 손실이 있더라도 최대한 빨리 도착하는 것이 중요하다(UDP).
전송 계층은 하위 계층들이 제공하는 '호스트 대 호스트' 전달 서비스를 '프로세스 대 프로세스' 전달 서비스로 확장하며, 다음과 같은 핵심 기능을 수행한다.
프로세스 간 통신 (Port 번호): 하나의 컴퓨터에서는 웹 브라우저, 메신저, 게임 등 여러 프로그램이 동시에 네트워크를 사용한다. 전송 계층은 포트(Port) 번호라는 16비트 숫자를 사용하여 데이터를 수신할 정확한 애플리케이션을 식별한다. IP 주소가 '아파트 주소'라면, 포트 번호는 '동호수'에 해당한다.
다중화와 역다중화 (Multiplexing & Demultiplexing): 송신 측에서는 여러 애플리케이션(소켓)에서 오는 데이터를 모아 하나의 통로(네트워크 계층)로 보내는 다중화를 수행한다. 반대로 수신 측에서는 들어온 데이터 스트림을 포트 번호를 보고 각각의 올바른 애플리케이션(소켓)으로 분배하는 역다중화를 수행한다.
데이터 분할 및 재조립 (Segmentation): 응용 계층에서 받은 큰 데이터 덩어리를 하위 계층이 처리하기 쉬운 작은 단위인 세그먼트(Segment) 또는 데이터그램(Datagram)으로 분할하고, 각 조각에 순서 번호와 같은 제어 정보를 추가한다. 수신 측에서는 이 조각들을 다시 원래의 데이터로 재조립한다.
연결 제어 (Connection Control): TCP와 같은 연결 지향 프로토콜의 경우, 실제 데이터 전송 전에 양단 간에 논리적인 연결을 설정하고, 통신이 끝나면 이 연결을 해제하는 역할을 한다.
흐름 제어 (Flow Control): 수신 측의 데이터 처리 능력을 고려하여 송신 측의 데이터 전송 속도를 조절한다. 이를 통해 수신 버퍼가 넘쳐 데이터가 유실되는 것을 방지한다.
오류 제어 (Error Control): 전송 중 데이터가 손상되거나 유실되었는지 검사하고, 문제가 발생했을 경우 재전송을 통해 오류를 복구하여 데이터의 신뢰성을 보장한다.
TCP는 '신뢰성 있는 데이터 전송'을 보장하는 전송 계층의 핵심 프로토콜이다. 마치 중요한 서류를 보낼 때 사용하는 '등기우편'과 같다. 배송 전 수신자와 연락하여 보낸다는 사실을 알리고(연결 설정), 각 서류에 번호를 매겨 순서대로 도착했는지 확인하며(순서 보장), 잘 받았다는 확인 서명을 받고(응답 확인), 만약 중간에 분실되면 다시 보내주는(재전송) 모든 과정을 포함한다.
TCP의 신뢰성은 20바이트(옵션 제외) 크기의 헤더에 담긴 정교한 정보들을 통해 구현된다.
[출처: https://maker5587.tistory.com/4#google_vignette]
| 필드 | 크기 | 설명 |
|---|---|---|
| Source Port | 16 bits | 데이터를 보내는 애플리케이션의 포트 번호 |
| Destination Port | 16 bits | 데이터를 받는 애플리케이션의 포트 번호 |
| Sequence Number | 32 bits | 세그먼트에 포함된 데이터의 순서 번호. 데이터의 순차적 재조립과 유실 감지에 사용 |
| Acknowledgment Number | 32 bits | 수신 성공을 확인하고 다음에 수신할 데이터의 순서 번호를 요청하는 데 사용 |
| Data Offset (Header Length) | 4 bits | TCP 헤더의 전체 길이를 나타냄 (데이터의 시작 위치를 알려줌) |
| Reserved | 6 bits | 미래를 위해 예약된 필드 |
| Flags (Control Bits) | 6 bits | 연결 상태를 제어하는 6개의 비트 (URG, ACK, PSH, RST, SYN, FIN) |
| Window Size | 16 bits | 흐름 제어를 위해 수신 가능한 데이터의 양(버퍼 크기)을 송신 측에 알림 |
| Checksum | 16 bits | 헤더와 데이터의 오류를 검출하기 위한 값 |
| Urgent Pointer | 16 bits | URG 플래그가 설정되었을 때 긴급 데이터의 위치를 알림 |
TCP는 데이터를 보내기 전에 반드시 상대방과 논리적인 통신 회선을 수립하는 '연결 지향' 프로토콜이다. 이 과정은 세 번의 악수(Handshake)를 통해 이루어진다.
[출처: https://jaehyeon48.github.io/network/tcp-three-way-handshake/]
SYN: 클라이언트가 서버에게 연결을 요청하는 SYN(Synchronize) 패킷을 보낸다. 이때 클라이언트는 통신을 시작할 자신의 초기 순서 번호(ISN, Initial Sequence Number)를 함께 보낸다.
SYN+ACK: 요청을 받은 서버는 연결을 수락한다는 의미로 ACK(Acknowledgment) 패킷과, 자신도 통신을 시작하겠다는 SYN 패킷을 함께 보낸다. ACK 패킷에는 클라이언트의 ISN에 1을 더한 값을 담아 "당신의 요청을 잘 받았다"는 것을 알리고, SYN 패킷에는 자신의 ISN을 담는다.
ACK: 서버의 응답을 받은 클라이언트는 마지막으로 서버의 ISN에 1을 더한 값을 담은 ACK 패킷을 보낸다. 이 패킷을 받은 서버는 연결이 완전히 수립되었음을 확인하고, 이때부터 양측은 데이터를 주고받을 수 있는 ESTABLISHED(연결됨) 상태가 된다.
TCP 연결은 양방향 통신이므로, 한쪽이 연결을 끊고 싶다고 해서 바로 종료되지 않는다. 양쪽 모두가 "더 이상 보낼 데이터가 없다"고 합의해야만 연결이 완전히 종료된다.
[출처: https://jaehyeon48.github.io/network/tcp-three-way-handshake/]
FIN: 클라이언트가 데이터 전송을 마치고 연결을 종료하겠다는 FIN(Finish) 패킷을 보낸다.
ACK: 서버는 일단 클라이언트의 종료 요청을 받았다는 ACK를 보낸다. 이때 서버는 아직 보낼 데이터가 남아있을 수 있으므로, 연결은 바로 끊지 않고 CLOSE_WAIT 상태로 대기한다.
FIN: 서버도 자신의 모든 데이터 전송을 마치면, 이제 연결을 종료할 준비가 되었다는 FIN 패킷을 클라이언트에게 보낸다.
ACK: 클라이언트는 서버의 FIN 패킷을 받고, 마지막 확인 응답으로 ACK를 보낸다. 이 마지막 ACK가 유실될 경우를 대비해, 클라이언트는 TIME_WAIT 상태로 일정 시간(보통 2MSL, 최대 세그먼트 수명의 두 배) 동안 대기한 후 연결을 완전히 닫는다. 이 ACK를 받은 서버는 즉시 연결을 닫는다.
[출처: https://www.researchgate.net/figure/TCP-sliding-window-mechanism_fig1_331853081]오류 제어 (Sequence/Acknowledgment): 송신 측은 데이터를 보낼 때 각 바이트마다 고유한 순서 번호(Sequence Number)를 부여한다. 수신 측은 데이터를 받으면 순서 번호를 확인하여 데이터가 순서대로 왔는지, 중간에 빠진 부분은 없는지 확인한다. 그리고 다음에 받아야 할 데이터의 순서 번호를 Acknowledgment Number에 담아 응답한다. 만약 송신 측이 특정 데이터에 대한 ACK를 일정 시간 동안 받지 못하면(Timeout), 데이터가 유실된 것으로 간주하고 해당 데이터를 재전송한다.
혼잡 제어 (Congestion Control): TCP는 네트워크 전체의 혼잡 상황을 고려하여 전송 속도를 조절한다.
Slow Start: 연결 초기에는 전송 속도를 지수적으로 빠르게 증가시켜 네트워크의 가용 대역폭을 탐색한다.
AIMD (Additive Increase / Multiplicative Decrease): 일정 수준(임계값)에 도달하면 속도를 완만하게(덧셈 방식) 증가시키다가, 패킷 손실(혼잡)이 감지되면 전송 속도를 절반으로 확 줄여(곱셈 방식) 네트워크의 부담을 덜어준다.
UDP는 TCP와 정반대의 철학을 가진 프로토콜이다. 신뢰성보다는 속도와 효율성을 최우선으로 한다. '일반 우편'처럼, 일단 데이터를 보내고 나면 잘 도착했는지, 순서는 맞는지 전혀 신경 쓰지 않는다. 연결 설정(Handshake) 과정도 없기 때문에 '비연결형' 프로토콜이라고 불린다.
UDP의 헤더는 단 8바이트로, TCP에 비해 매우 간단하다.
[출처: https://maker5587.tistory.com/4#google_vignette]
| 필드 | 크기 | 설명 |
|---|---|---|
| Source Port | 16 bits | 데이터를 보내는 애플리케이션의 포트 번호 |
| Destination Port | 16 bits | 데이터를 받는 애플리케이션의 포트 번호 |
| Length | 16 bits | 헤더와 데이터를 포함한 전체 데이터그램의 길이 |
| Checksum | 16 bits | 데이터 오류 검출을 위한 값 (선택 사항) |
UDP는 약간의 데이터 손실이 있더라도 실시간성이 매우 중요한 서비스에 적합하다.
실시간 스트리밍: 동영상이나 음성 스트리밍에서 몇몇 프레임이 유실되더라도 전체 재생에 큰 영향을 주지 않지만, 지연은 치명적이다.
온라인 게임: 플레이어의 움직임을 빠르게 전달하는 것이 중요하며, 약간의 패킷 손실은 허용될 수 있다.
DNS: 도메인 이름을 IP 주소로 변환하는 과정은 매우 빨라야 하므로, 신뢰성보다 속도가 우선시된다.
전통적으로 4계층은 최종 사용자 장치(PC, 서버)의 운영체제 내에서 소프트웨어적으로 구현되는 프로토콜 계층이다. 하지만 현대 네트워크에서는 4계층 정보를 활용하여 트래픽을 지능적으로 관리하는 하드웨어 장비들이 널리 사용된다.
L4 스위치는 여러 대의 서버를 마치 한 대의 서버처럼 보이게 만들어주는 장비로, 로드 밸런서(Load Balancer)라는 이름으로 더 잘 알려져 있다. 웹 사이트 방문자가 급증할 때, 서버 한 대가 모든 요청을 감당하지 못하고 다운되는 것을 막기 위해 등장했다.
[출처: https://www.geeksforgeeks.org/system-design/what-is-load-balancer-system-design/]
L4 스위치는 외부로부터 쏟아져 들어오는 요청(트래픽)을 자신이 관리하는 여러 대의 서버(서버 팜 또는 서버 풀)에게 적절히 나누어주는 '교통정리 담당관' 역할을 한다. 이를 통해 특정 서버에만 부하가 몰리는 것을 방지하고, 전체 서비스의 안정성과 가용성을 높인다. L4 스위치의 핵심 동작 원리는 4계층 정보, 즉 TCP/UDP 포트 번호와 IP 주소를 기반으로 트래픽을 분산시키는 것이다.
가상 IP(VIP)로 요청 수신: 사용자(클라이언트)는 실제 서버의 IP 주소를 알지 못한다. 대신 로드 밸런서가 외부에 대표로 노출하고 있는 가상 IP 주소(VIP, Virtual IP)로 서비스 요청을 보낸다.
서버 선택: L4 스위치는 들어온 요청을 어떤 실제 서버(Real Server)에게 전달할지 결정한다. 이때 다양한 로드 밸런싱 알고리즘이 사용된다.
라운드 로빈(Round Robin): 서버들에게 순서대로 돌아가며 요청을 분배하는 가장 기본적인 방식이다.
최소 연결(Least Connection): 현재 연결(세션) 수가 가장 적은 서버에게 요청을 보내는 방식이다.
가중 라운드 로빈(Weighted Round Robin): 서버의 처리 성능이 다를 경우, 성능이 좋은 서버에 더 많은 요청을 보내도록 가중치를 설정하는 방식이다.
주소 변환(NAT): L4 스위치는 선택된 실제 서버로 요청을 보내기 위해 패킷의 목적지 IP 주소를 자신의 VIP에서 실제 서버의 실제 IP(Real IP)로 변경한다. 이 과정을 NAT(Network Address Translation)라고 한다.
응답 처리: 실제 서버가 요청을 처리한 후 응답을 보낼 때, 출발지 IP 주소는 실제 서버 자신의 IP가 된다. 이 응답 패킷이 다시 L4 스위치를 거치면서, 출발지 IP 주소가 L4 스위치의 VIP로 다시 변경되어 최종적으로 사용자에게 전달된다. 이 덕분에 사용자는 자신이 여러 대의 서버 중 하나와 통신하고 있다는 사실을 인지하지 못하고, 마치 하나의 거대한 서버와 통신하는 것처럼 느끼게 된다.
방화벽은 미리 정의된 규칙에 따라 네트워크 트래픽을 허용하거나 차단하는 핵심 보안 장비이다. 방화벽은 동작 방식에 따라 크게 두 종류로 나뉜다.
'패킷 필터링'이라고도 불리는 초기 형태의 방화벽으로, 주로 3계층에서 동작한다. 이 방화벽은 각 패킷을 독립적인 개체로 취급하며, 패킷 헤더에 있는 출발지/목적지 IP 주소와 포트 번호만을 보고 미리 설정된 규칙(ACL, Access Control List)과 일치하는지를 판단하여 허용 또는 차단 결정을 내린다.
장점: 구조가 단순하고 각 패킷만 검사하므로 처리 속도가 매우 빠르다.
단점: 통신의 전체적인 맥락이나 연결 상태를 전혀 고려하지 않기 때문에 정교한 공격에 취약하다. 예를 들어, 내부에서 시작된 요청에 대한 정상적인 응답 패킷과 외부에서 위장하여 들어오는 악의적인 패킷을 구분하지 못할 수 있다.
'상태 기반 방화벽' 또는 '동적 패킷 필터링'이라고 불리며, 4계층에서 동작한다. 이 방화벽은 단순히 개별 패킷만 보는 것을 넘어, 연결의 상태(State)와 맥락을 추적하고 기억하는 지능적인 방화벽이다.
[출처: https://www.fortinet.com/kr/resources/cyberglossary/stateful-firewall]
핵심 동작 원리 (상태 테이블): 스테이트풀 방화벽의 핵심은 '상태 테이블(State Table)' 또는 '연결 테이블(Connection Table)'을 유지하고 관리하는 것이다.
연결 시작: 내부 사용자가 외부 웹 서버로 접속하기 위해 SYN 패킷을 보낸다. 방화벽은 이 패킷이 보안 규칙에 따라 허용되면, 이 새로운 연결에 대한 정보(출발지/목적지 IP, 포트, TCP 순서 번호 등)를 자신의 상태 테이블에 기록한다.
상태 추적: 이후 해당 연결을 통해 오가는 모든 패킷들은 이 상태 테이블과 비교된다.
응답 패킷 처리: 외부 웹 서버에서 응답 패킷(SYN+ACK 등)이 방화벽으로 돌아오면, 방화벽은 이 패킷이 상태 테이블에 기록된 '유효한 연결'의 일부인지 확인한다.
동적 허용: 패킷이 기존 연결에 속한 정상적인 응답이라고 판단되면, 별도의 수신 규칙이 없더라도 동적으로 통과시켜 준다.
비정상 패킷 차단: 반면, 외부에서 아무런 요청 없이 갑자기 들어오는 패킷처럼 상태 테이블에 일치하는 연결 정보가 없는 비정상적인 접근은 즉시 차단한다.
장점: 연결의 전체 맥락을 이해하므로 IP 스푸핑이나 DoS 공격 등 더 정교하고 복잡한 공격을 효과적으로 방어할 수 있어 보안성이 훨씬 뛰어나다.
단점: 모든 연결 상태를 추적하고 기록해야 하므로 스테이트리스 방화벽보다 더 많은 메모리와 CPU 자원을 소모하며, 처리 속도가 상대적으로 느릴 수 있다.