[그림으로 쉽게 이해하는 웹/HTTP/네트워크를 읽고 정리합니다.]
TCP
인터넷 통신을 담당하는 프로토콜 IP는 목적지까지 데이터를 정확하게 '배송'하는 역할만 한다.
데이터가 안전하게 전달되었는지, 주문한 순서대로 왔는지 등 '배송'을 제외한 나머지 부분은 TCP 프로토콜이 담당한다.
TCP(Transmission Control Protocol)는 신뢰성 있는 데이터 통신을 위한 프로토콜이다.
패킷 교환 방식의 문제점은 중간에 사라지는 패킷이 생긴다는 것이다.
패킷 교환 방식 이전의 회선 교환 방식이라면 데이터가 있거나, 없거나 둘 중 하나일 텐데
패킷 교환 방식을 사용하니 데이터를 받긴 했는데 이상한 데이터가 올 수도 있다는 문제점이 있었다.
따라서 TCP 프로토콜은 신뢰할 수 있는 데이터를 전달받기 위해 패킷마다 번호를 붙인다.
그리고 번호에 맞는 데이터가 정확히 목적지에 도착했는지 확인하기 위해 데이터를 주고 받을 때 하나의 절차를 추가한다.
그래서 서버 -> 클라이언트로 데이터를 보낸 후, 클라이언트는 데이터를 받고 잘 받았다는 메세지를 전달한다.
클라이언트에게 이런 메세지를 받지 못한다면 문제가 생겼다고 인지, 다시 데이터를 보내 클라이언트가 확실히 데이터를 받도록 한다.
즉, 클라이언트의 요청 -> 서버가 데이터 줌 -> 클라이언트가 잘 받았다고 함
TCP의 데이터 통신 과정은 위와 같이 진행된다.
클라이언트는 잘 받았다는 메세지를 어떻게 전달하고, 서버는 이를 어떻게 해석할까?
IP를 포함한 모든 프로토콜은 데이터 앞에 헤더라는 정보를 추가해 전송한다.
택배의 운송장처럼 수신자, 발신자, 운송장 번호 등 헤더에는 데이터를 전달할 때 필요한 정보들이 담겨 있다.
(TCP의 헤더는 데이터의 신뢰를 담당하다 보니 들어가야 할 정보가 많아 다른 프로토콜의 헤더보다 큰 편이다.)
패킷의 번호를 담는 공간(시퀀스 번호), 윈도 크기를 적는 공간을 비롯 패킷의 상태를 알리는 목적의 헤더 정보인 플래그(flag)가 담겨 있다.
플래그는 다른 기기에 신호를 전달하기 위한 용도로, 플래그의 활성화 여부에 따라 여러 의미를 전달할 수 있다.
URG | Urgent: 긴급 데이터
ACK | Acknowledgement: 응답 (앞서 받은 데이터를 잘 처리했음)
PSH | Push : 밀어 넣기
RST | Reset : 강제 연결 초기화
SYN | Sychronization : 동기화 (연결 요청)
FIN | Finish : 연결 종료 요청 (통신이 마무리 되어 연결 해제 요청)
이렇게 TCP 헤더의 플래그는 6개가 있는데, ACK/SYN/FIN을 주로 보면 된다.
각 플래그는 1비트로 이뤄져 있어 0과 1로 플래그의 활성화 여부를 체크할 수 있다.
핸드셰이크
TCP는 신뢰성 있는 통신이 주 목적인 프로토콜이다.
따라서 데이터를 주고받기 전 클라이언트와 서버가 서로 통신할 준비가 됐는지 확인해 연결 오류로 인한 데이터 유실을 방지한다.
이렇게 클라이언트와 서버가 서로 '연결'된 상태를 유지하며 데이터를 전달하기 때문에 TCP를 연결형 프로토콜이라고도 한다.
3-way handshake
TCP는 3방향 핸드셰이크로 연결을 수립한다.
3번의 메세지 교환으로 클라이언트와 서버가 서로 데이터를 주고받을 준비를 한다.
1. 클라이언트 P가 서버 Q쪽으로 SYN 패킷을 보낸다. (SYN 1, ACK 0)
클라이언트 P는 SYN_SENT로 상태를 바꾼다.
2. 서버 Q는 클라이언트 P의 요청에 대해 응답하는 ACK 패킷과 요청을 허락하는 SYN 패킷을 보낸다. (SYN 1, ACK 1)
서버 Q는 클라이언트 P의 요청을 받고 SYN_RECEIVED로 상태를 바꾼다.
3. 클라이언트 P는 서버 Q의 연결 허락에 대해 응답하는 ACK 패킷을 보낸다. (ACK 1)
클라이언트는 ESTABLISHED(연결됨)으로 상태를 바꾼다.
즉, 각각 연결 요청을 보내고 서로 확인했다는 응답을 받아야만 비로소 연결에 성공, 데이터를 주고 받을 수 있게 된다.
4-way handshake
더 이상 보낼 데이터가 없으면 3방향 핸드셰이크에서 한 단계 추가된 4방향 핸드셰이크로 연결을 끊는다.
전반적으로 3방향 핸드셰이크와 유사하다.
1. 클라이언트가 서버 쪽으로 연결을 종료한다는 의미의 FIN 플래그가 담긴 패킷을 보낸다.
종료를 기다리는 FIN_WAIT으로 상태를 변경한다.
2. 서버는 연결 종료 요청을 확인했다는 ACK 메세지를 보내고 미처 보내지 못한 패킷을 마저 보내며 자신의 통신이 끝날 때까지 기다린다.
이 때 CLOSE_WAIT으로 상태를 변경한다. (통신이 끝나길 기다린다)
3. 시간이 지나 서버도 연결을 종료할 준비가 됐다면 클라이언트에게 FIN 플래그를 전송한다.
서버는 마지막 ACK 플래그를 기다리는 상태인 LAST_ACK로 상태를 변경한다.
4. 서버의 FIN 답장을 받은 클라이언트는 ACK 플래그가 담긴 패킷을 보내 연결을 종료한다.
5. 클라이언트는 미처 받지 못한 패킷이 들어오는 등 혹시 모를 상황을 대비해 잠깐 기다렸다 연결을 종료한다.
따라서 TIME WAIT 상태에서 CLOSED로 변경된다.
4방향 핸드셰이크는 서버가 ACK, FIN을 따로 보내는 점,
클라이언트와 서버의 마지막 상태가 서로 다른 점에서 3방향 핸드셰이크와 차이가 있다.
흐름 제어
패킷은 순서대로 전송되고, 순서대로 조립되는 것이 매우 중요하다.
그러나 외부 상황으로 데이터가 유실되거나 순서가 잘못 수신되는 경우가 있을 수 있다.
이런 문제의 원인은 여러 가지가 있는데, 그 중 하나가 전송자와 수신자 간의 데이터 속도 차이다.
발신자의 데이터 처리 속도가 빨리 수신자가 데이터를 처리할 수 있는 용량을 초과하면,
이후 도착한 데이터는 손실될 위험이 있고, 이렇게 손실이 잦아지면 재전송할 패킷도 많아져 리소스가 낭비된다.
해결 방법은 보내는 쪽이 받는 쪽의 속도에 맞추면 된다.
이와 같은 방법을 흐름 제어(flow control)이라고 한다.
흐름 제어에는 2가지 방식이 있다.
1. 정지-대기 방식(stop and wait)
매번 전송한 패킷에 대해 확인 응답을 받은 뒤, 다음 패킷을 전송하는 방법
데이터 전송 -> 데이터 수신 후 ACK 플래그 전송 -> ACK 플래그 확인 후 데이터 전송
이러한 패턴으로 동작하기 때문에 가장 기본적이고 신뢰성이 높은 방법이다.
하지만 매 요청마다 확인 응답을 받아야 하고, 답장이 없으면 데이터를 전송할 수 없어 시간이 오래 걸리고 효율성이 떨어진다.
따라서 오늘날에는 잘 사용하지 않는 패턴이다.
2. 슬라이딩 윈도우(sliding window)
수신자가 받을 수 있는 만큼만 데이터를 보내는 방법
TCP 헤더에 있는 윈도우 크기는 수신자가 한 번에 처리할 수 있는 데이터의 크기를 나타낸다.
3방향 핸드셰이크 과정에서 이 윈도우 크기가 정해진다.
수신자가 한 번에 처리할 수 있는 데이터의 크기만큼 보내기 때문에 확인 응답 없이 패킷을 전송할 수 있다.
해서 정지-대기 방식보다 속도는 빠르고, 신뢰성(데이터가 유실/누락될 위험 없음)은 그대로 유지한 상태로 데이터를 전송할 수 있다.
윈도우 크기가 4고, 모든 데이터의 크기가 1일 때 1번부터 4번까지 데이터를 전달한다.
수신자는 받은 데이터를 처리하고 메세지 헤더 안에 마지막으로 받은 데이터의 번호를 ACK 패킷과 함께 전달한다.
마지막으로 받은 데이터의 번호를 확인해 그 다음부터 윈도우 크기만큼 데이터를 다시 전송한다.
이를 통해 매 전송마다 응답을 확인하지 않고도 적절하게 처리 속도를 제어할 수 있어 일반적으로 널리 사용된다.
혼잡 제어
전송자와 수신자 간의 처리 속도 차이 외에도 데이터 송수신에 문제를 주는 원인으로 '네트워크'가 있다.
한 네트워크에 데이터가 집중되면 해당 네트워크를 사용하는 데이터의 처리 속도는 떨어진다.
하지만 전송자와 수신자가 이를 모르는 상태일 때, 수신자는 전송자에게 다시 데이터를 보내달라고 한다.
전송자는 데이터가 느리게 가고 있는 것이 아니라 유실되었다고 판단, 다시 데이터를 재전송 하게 된다.
이러한 패턴이 반복되면서 네트워크에는 많은 데이터가 몰려 상황이 악화된다.
이처럼 네트워크 내 패킷의 수가 과도하게 증가하는 현상을 혼잡이라고 하며,
이를 제어하기 위한 기능을 혼잡 제어(congestion control)라고 부른다.
네트워트의 상황은 유동적으로 변하기 때문에 네트워크의 혼잡도는 단번에 파악할 수 없다.
따라서 혼잡 제어 방식의 대부분은 처음에는 데이터를 천천히 보내다가,
수신자가 데이터를 잘 받으면 점차 속도를 높이는 방식으로 제어한다.
여기서 속도를 얼만큼 높이는지, 혼잡을 감지할 때 속도를 얼만큼 줄이는지에 따라 혼잡 제어 방법을 구분한다.
합 증가/곱 감소 (AIMD, Additive Increase/Multiplicative Decrease)
처음에 전송자가 수신자에게 패킷을 1개씩 보낸 뒤 잘 도착했다는 응답을 받으면, 윈도우 크기를 1개씩 증가 시키면서 전송한다.
이 때 네트워크가 혼잡하다고 판단되면 윈도 크기를 '절반'으로 줄여서 네트워크가 안정되기 기다린다.
윈도 크기를 1개씩 늘려가기 떄문에 안전하게 네트워크를 사용할 수 있지만,
전송 속도가 천천히 증가하기 때문에 초기 전송 속도를 높이는데 시간이 걸린다는 단점이 있다.
느린 시작
처음에 윈도우 크기를 1로 시작해 서서히 개수를 2배씩 늘리며 전송한다.
네트워크가 혼잡하다고 판단되면 윈도우 크기를 1로 급격히 줄여버린다.
윈도우 크기가 2배씩 커지다 보니 시간이 지날 수록 많은 양의데이터를 전달할 수 있다는 특징이 있다.
합 증가/곱 감소와 느린 시작을 섞어 쓸 수도 있고, 이 외에도 여러 가지 방법이 있다.
UDP
TCP는 사실 전송 속도가 느리다는 단점이 있다.
데이터를 꼼꼼히 확인하기 위해 여러 중간 과정을 거치다 보니 느려질 수 밖에 없는데,
라이브 스트리밍이나 게임과 같이 실시간성이 중요한 콘텐츠가 많아지면서
이럴 해결하기 위해 UDP(User Datagram Protocol) 프로토콜이 탄생했다.
UDP는 TCP와 달리 전송자/수신자 간의 연결을 보장하지 않는다.
즉 전송자가 일방적으로 데이터를 전달하는 프로토콜이기 때문에 비연결형 서비스라고 할 수 있다.
그렇기 때문에 전송 순서를 보장하지도, 수신 여부를 확인하지도 않아 비교적 신뢰성이 낮다.
하지만 그렇기에 안정성을 확보하는 여러 정보가 빠져 데이터의 용량이 가볍고, 속도가 빠르다는 특징이 있다.
또 혼잡 제어와 같이 전송 속도를 제어하는 기능 없이, 일정한 속도로 데이터를 전달하는데
이로 인해 많이 사용하면 네트워크가 혼잡해질 수 있다는 여러 장단점이 공존하는 프로토콜이다.
따라서 UDP는 프레임 몇 개 정도 잠깐 안 보여도 괜찮으니 실시간으로 화면을 보여주는 게 중요한 경우 사용하면 좋다.
'🖥️ CS & Network & Web > 🕸️ Network' 카테고리의 다른 글
[Network] 7. HTTP 특징과 데이터 저장 방식 (0) | 2023.12.21 |
---|---|
[Network] 6. HTTP (1) | 2023.12.20 |
[Network] 4. IP (2) | 2023.12.19 |
[Network] 3. URL (0) | 2023.07.03 |
[Network] 2. 네트워크 개념 (0) | 2023.07.02 |