Transport Layer
- 전송 계층은 OSI 7계층과 TCP/IP 참조 모델 모두에 존재
- 양 끝단 사이에서 신뢰성 있는 데이터 전송을 담당
- 신뢰성: 데이터를 순차적, 안정적으로 전달
- 전송: 포트 번호에 해당하는 프로세스에 데이터를 전달
- 상위 계층이 데이터 전달의 유효성이나 효율성을 신경 쓰지 않도록, 오류 제어 / 순서 제어 / 흐름 제어 등의 기능을 제공
- 연결 지향형인 TCP / 비연결형인 UDP
- 전송 계층에서 다루는 패킷을 일반적으로 세그먼트 라고 부름 / UDP 에서는 데이터그램 이라고 부르기도 함
- 포트 번호를 사용해 프로세스를 식별하며, 필요에 따라 신뢰성, 순서 보장, 흐름 제어 등의 기능을 담당
Transport Layer 가 없다면
- 데이터의 순차 전송이 원할하지 않음 (1, 2, 3 → 1, 3, 2)
- Flow (흐름 문제): 송수신자 간의 데이터 처리 속도 차이 (수신자가 처리할 수 있는 데이터량을 초과)
- Congestion (혼잡 문제): 네트워크의 데이터 처리 속도 (네트워크가 혼잡할 때)
TCP 와 UDP
TCP (Transmission Control Protocol)
- 인터넷에서 데이터를 메시지 형태로 전송할 때 IP와 함께 사용하는 전송 계층 프로토콜
- 신뢰성있는 데이터 통신을 가능하게 해주는 프로토콜
- TCP는 3-way handshaking으로 연결을 설정하고 4-way handshaking으로 연결을 해제
- 이 과정에서 흐름 제어와 혼잡 제어를 수행해 높은 신뢰성을 보장한다.
- Flow Control (흐름 제어), Congestion Control (혼잡 제어), Error Detection (오류 감지)
- 일반적으로 TCP와 IP는 함께 사용되며, IP는 목적지까지의 전달과 라우팅을 담당하고 TCP는 세그먼트(패킷)의 분할, 추적, 재전송, 재조립을 담당
- 매번 Connection을 연결해서 시간 손실 발생 (3-way handshake)
- 패킷을 조금만 손실해도 재전송 / 이 때문에 UDP에 비해 상대적으로 전송 속도가 느림
- 전이중(Full-duplex) / 점대점(Point-to-Point) 방식의 통신을 제공
UDP (User Datagram Protocol)
- 데이터를 데이터그램 단위로 처리하는 전송 계층 프로토콜
- 연결 설정 / 해제 절차가 없는 비연결형 프로토콜
- 정보를 주고받을 때 별도의 신호 절차를 거치지 않음
- 논리적인 연결 경로를 유지하지 않고 각 패킷이 서로 다른 경로로 전송될 수 있음
- UDP 헤더의 CheckSum 필드를 통해 최소한의 오류만 검출하므로 신뢰성이 낮고 패킷 손실이나 순서 뒤바뀜이 발생할 수 있음
- 순서 보장 / 재조립 / 흐름 제어 / 혼잡 제어를 수행하지 않아 오버헤드가 적고 전송 속도가 빠름
- 이런 특성 때문에, 연속성이 더 중요한 실시간 서비스(스트리밍, VoIP, WebRTC 미디어 전송 등)에 적합
TCP vs UDP
- UDP와 TCP는 각각 독립된 포트 주소 공간을 가지므로, 두 프로토콜에서 동일한 포트 번호를 사용하더라도 서로 다른 포트로 취급됨
- 따라서 같은 호스트에서 TCP 80포트와 UDP 80포트를 동시에 사용하는 것이 가능
- 또한 동일 프로토콜 내에서도 클라이언트가 여러 연결을 동시에 맺는 경우, 동적 포트가 자동으로 할당되어 각 연결을 구분함
| 구분 | TCP (Transmission Control Protocol) | UDP (User Datagram Protocol) |
| 연결 방식 | 연결 지향형 (3-way handshake) | 비연결형 (바로 던짐) |
| 신뢰성 | 높음 (순서 보장, 재전송 있음) | 낮음 (순서 보장 없음, 유실 가능) |
| 속도 | 상대적으로 느림 (오버헤드 발생) | 매우 빠름 (가벼운 헤더) |
| 통신 방식 | 1:1 (Unicast) | 1:1, 1:N, N:N 모두 가능 |
| 데이터 단위 | Segment | Datagram |
| 사용 사례 |
3-Way Handshake와 4-Way Handshake
3-Way Handshake 는 TCP의 접속, 4-Way Handshake는 TCP의 접속 해제 과정이다.
포트 상태 정보
- CLOSED: 포트가 닫혀 있어, 연결이 존재하지 않는 상태
- LISTEN: 서버가 포트를 열어두고, 클라이언트의 연결 요청(SYN)을 기다리는 상태
- SYN_SENT: 클라이언트가 서버에 연결 요청(SYN)을 보내고, 이에 대한 응답(SYN+ACK 또는 ACK)을 기다리는 상태
- SYN_RCV: 클라이언트의 SYN을 받은 뒤, SYN+ACK를 보내고 클라이언트의 최종 ACK를 기다리는 상태
- FIN_WAIT_1: 연결을 종료하기 위해 먼저 FIN 패킷을 보낸 측이, 상대방의 ACK 또는 FIN/ACK 응답을 기다리는 상태
- ESTABLISHED: 3-Way Handshake가 완료되어, 양쪽 모두 연결이 설정된 상태로 데이터 송수신이 가능한 상태
TCP 플래그 정보
TCP 헤더에는 Control Bit(Flag Bit) 가 있으며, 전통적으로 6개의 주요 플래그(URG, ACK, PSH, RST, SYN, FIN)를 많이 언급한다. 각 비트가 1이면, 해당 플래그 역할을 하는 패킷이라는 의미다.
- SYN (Synchronize Sequence Number)
- 연결 설정 요청 플래그
- 세션을 생성할 때, 초기 Sequence Number를 설정하여 상대에게 전달한다.
- ACK (Acknowledgement)
- 응답(수신 확인)을 의미하는 플래그
- 이 비트가 1이면, Acknowledgement Number 필드가 유효함을 의미한다.
- 실제 데이터 전송이 시작된 이후에는, 최초 연결 설정 과정에서의 첫 세그먼트를 제외한 대부분의 세그먼트가 ACK 비트를 1로 가진다고 볼 수 있다.
- FIN (Finish)
- 연결 종료 요청 플래그.
- 더 이상 전송할 데이터가 없음을 의미하며, 세션을 종료하는 데 사용된다.
TCP의 3-Way Handshake
- TCP 통신으로 데이터를 전송하기 위해, 네트워크 연결을 설정하는 과정이다.
- 양쪽 모두 데이터 전송 준비가 되었음을 서로 확인하고, 실제 데이터가 오가기 전에 서로의 상태를 동기화한다.
3-way handshake의 기본 메커니즘: PAR
TCP는 PAR(Positive Acknowledgement with Re-transmission) 방식을 사용해 신뢰성을 보장한다.
- PAR을 사용하는 장치는 ACK를 받을 때까지 같은 세그먼트를 재전송한다.
- 수신 측은 세그먼트가 손상되었음을 체크섬으로 감지하면 해당 세그먼트를 폐기하고, 송신 측은 해당 세그먼트에 대한 긍정 응답(ACK) 을 받지 못했기 때문에 다시 전송한다.
이렇게 동작하는 과정에서, 연결을 설정할 때 클라이언트와 서버 사이에서 3개의 세그먼트(SYN, SYN+ACK, ACK) 가 오간다. 이 3단계 세그먼트 교환이 바로 3-Way Handshake의 기본 메커니즘이다.
Handshake에 사용되는 플래그
- SYN (Synchronize)
- 연결 요청, 세션을 설정하는 데 사용되며 초기 시퀀스 번호(ISN) 를 보낼 때 사용된다.
- ACK (Acknowledgement)
- 상대가 보낸 시퀀스 번호에 대해 “여기까지 잘 받았다”는 의미로, 다음에 기대하는 시퀀스 번호를 ACK 필드에 담아 보낸다.
- 클라이언트 ISN이 x라면, 서버는 ACK = x + 1을 보낸다.
- 서버 ISN이 y라면, 클라이언트는 ACK = y + 1을 보낸다.
3단계 동작 방식
여기서는 먼저 연결을 시작한 쪽을 Client(Host P), 요청을 받은 쪽을 Server(Host Q) 로 본다.
Step 1: SYN (Client → Server)
클라이언트가 서버와 커넥션을 맺기 위해 SYN 세그먼트를 전송한다. (Seq = x)
- 클라이언트는 최초 전송 시 임의의 초기 시퀀스 번호 x 를 선택하고, SYN 플래그를 1로 설정해 전송한다.
- 포트 상태
- Client: CLOSED → SYN_SENT
- Server: LISTEN 상태에서 대기 중
Step 2: SYN + ACK (Server → Client)
서버는 클라이언트의 SYN(x)을 받고, SYN과 ACK가 설정된 세그먼트를 응답으로 보낸다. (Seq = y, ACK = x + 1)
- 서버는 접속 요청을 수락하고, 자신의 초기 시퀀스 번호 y를 담은 SYN과, 클라이언트 ISN x에 대한 ACK = x + 1 을 함께 보낸다.
- 포트 상태
- Client: 여전히 SYN_SENT (서버 응답 대기)
- Server: SYN_RECEIVED
Step 3: ACK (Client → Server)
클라이언트는 서버의 SYN(y), ACK(x+1)를 받은 뒤, ACK(y+1)를 서버로 보낸다.
- 클라이언트는 서버 ISN y에 대해 ACK = y + 1 을 담은 ACK 세그먼트를 전송한다.
- 이 단계에서 전송할 데이터가 있다면, ACK와 함께 데이터를 실어 보내는 것도 가능하다.
- 포트 상태
- Client: ESTABLISHED
- Server: SYN_RECEIVED → 클라이언트의 ACK 수신 후 ESTABLISHED
이로써 양쪽 모두 연결이 설정되고, 본격적인 데이터 송수신이 시작된다.
Full-duplex 통신과 3-Way Handshake
- Step 1, 2에서는 Client → Server 방향에 대한 연결 파라미터(클라이언트의 시퀀스 번호 x)를 설정하고 승인한다.
- Step 2, 3에서는 Server → Client 방향에 대한 연결 파라미터(서버의 시퀀스 번호 y)를 설정하고 승인한다.
이렇게 양 방향의 초기 시퀀스 번호를 서로 교환·승인함으로써, TCP는 full-duplex(양방향 동시 통신) 연결을 구축한다.
TCP의 4-Way Handshake
- 4-Way Handshake는 TCP 연결을 해제 하는 과정이다.
- 이때 주로 FIN 플래그가 사용된다. (FIN: “더 이상 보낼 데이터가 없다”는 뜻으로 세션 종료 의사를 전달)
연결 해제 방식 두 종류
TCP는 다른 connection-oriented 프로토콜과 마찬가지로 두 가지 연결 해제 방식을 지원한다.
- Graceful connection release (정상적인 연결 해제)
- 양쪽이 각자의 전송 방향을 순서대로 닫으면서, 남은 데이터를 모두 주고받은 뒤 연결을 종료한다.
- Abrupt connection release (갑작스러운 연결 해제)
- 한쪽에서 RST 세그먼트를 보내 양 방향을 한 번에 강제로 닫는 방식이다.
Abrupt termination (RST를 이용한 강제 종료)
RST(TCP reset) 세그먼트가 전송되면 갑작스러운 연결 해제가 수행된다. RST는 보통 아래와 같은 상황에서 전송된다.
- 존재하지 않는 TCP 연결에 대해 비-SYN 세그먼트가 수신된 경우
- 열린 연결에서, 일부 구현에서 잘못된 헤더를 가진 세그먼트가 수신된 경우 (공격 방지 차원에서 해당 연결을 즉시 종료)
- 기존 TCP 연결을 더 이상 유지할 수 없을 때 (리소스 부족, 원격 호스트 미응답 등)
Graceful termination과 Half-close 기법
Graceful termination에서는 양쪽이 각자 “내 쪽 전송은 끝”이라는 FIN을 보내며, TCP가 half-close 를 지원하기 때문에 송신만 닫고 수신은 열어둘 수 있다.
4-Way Handshake 단계별 동작
보통 능동적으로 먼저 종료를 요청한 쪽을 Client, 이를 받은 쪽을 Server라고 보면 이해하기 쉽다.
STEP 1: FIN(+ACK) (Client → Server)
- 클라이언트가 close() (또는 이에 준하는 동작)를 호출하여 연결 종료를 요청하고, 서버에게 FIN 세그먼트를 전송한다.
- Half-close 때문에, 이 FIN은 “내가 보낸 쪽 데이터는 여기까지”라는 의미이며, 그 이전까지의 데이터에 대한 ACK 의미도 포함한다고 볼 수 있다.
- 상태 변화
- Client: ESTABLISHED → FIN_WAIT_1
- Server: 여전히 ESTABLISHED
STEP 2: ACK (Server → Client)
- 서버는 클라이언트의 FIN을 받고, 이를 잘 받았다는 ACK 세그먼트를 클라이언트로 보낸다.
- 서버는 아직 보낼 데이터가 남아 있을 수 있으므로, CLOSE_WAIT 상태에서 애플리케이션 레벨의 전송을 마저 수행한 뒤 close()를 호출한다.
- 클라이언트는 ACK를 받은 뒤, 서버의 FIN을 기다리는 FIN_WAIT_2 상태가 된다.
STEP 3: FIN (Server → Client)
- 서버가 남은 데이터를 모두 전송한 후, 연결 종료에 동의한다는 의미로 클라이언트에게 FIN 세그먼트를 보낸다.
- 이때 서버는 자신의 FIN에 대한 ACK를 기다리는 LAST_ACK 상태로 들어간다.
STEP 4: ACK (Client → Server)
- 클라이언트는 서버의 FIN을 수신하고, 이를 확인하는 ACK 세그먼트를 서버에 전송한다.
- 클라이언트는 이후 TIME_WAIT 상태에 머무르며, 일정 시간 동안 대기한 뒤 최종적으로 CLOSED 상태가 된다.
- TIME_WAIT은 지연되거나 중복된 FIN/ACK 세그먼트가 네트워크 상에 남아 있을 가능성을 고려해, 마지막 ACK가 유실되었을 때 재전송 FIN을 처리하고, 이전 연결의 패킷이 새 연결에 섞이지 않도록 하기 위함이다.
- 서버는 클라이언트의 마지막 ACK를 받은 뒤 소켓을 닫고 CLOSED 상태가 된다.