
HTTP 통신 프로토콜에서 김영한님강의랑 책을보며 TCP, UDP에 대해서 공부했는데 더 상세히 적어보자!
그대로 옮기자면
TCP, UDP 둘다 전송계층에 속하는 프로토콜입니다.
그러나 트래픽을 전송하는 방식에 있어서 두 프로토콜은 큰 차이를 보이는데요,
우선 TCP의 경우 트래픽을 보낼 때 패킷이라는 단위를 사용하고 이 패킷은 전송 과정 전후로 연결을 맺고 끊는 과정이 포함되고, 전송 도중에도 올바르게, 그리고 순서대로 도착했는지 확인하는 과정이 있습니다.
그래서 패킷 전송시 신뢰성이 더 높습니다.
그러나 UDP는 트래픽을 보낼때 데이터그램이라는 단위를 사용하고 전송 도중 TCP처럼 확인하는 과정이 없습니다.
따라서 상대적으로 TCP보다 신뢰성은 낮지만 속도가 빠릅니다.
3-way는 연결을 맺을 때, 4-way는 연결을 끊을 때 사용된다.
둘의 단계 수 차이는 동작 방식과 목적이 다르기 때문
클라이언트와 서버가 신뢰성 있는 연결을 만들기 위해 필요한 절차야.
- SYN: 클라이언트 → 서버 (연결 요청)
- SYN-ACK: 서버 → 클라이언트 (요청 수락 + 나도 연결 요청할게)
- ACK: 클라이언트 → 서버 (수락 응답)
➡️ 이로써 양쪽 모두 "연결할 준비가 됐다!"는 걸 확인하고 연결이 성립돼.
🔌 TCP 4-way handshake (연결 해제)
연결을 끊을 때는 양방향으로 따로 끊어야 해서 4단계가 필요
왜냐하면, 데이터 전송이 완전히 끝났는지 확인해야 하거든.
FIN: 클라이언트 → 서버 (나 이제 데이터 다 보냈어. 끊을래.)
ACK: 서버 → 클라이언트 (알겠어. 너 보낸 건 잘 받았어.)
FIN: 서버 → 클라이언트 (나도 이제 다 보냈어. 끊을게.)
ACK: 클라이언트 → 서버 (응, 잘 받았어.)
➡️ 이렇게 해서 양쪽 모두 전송 완료를 확인하고 완전히 연결이 끊겨.
연결 설정(3-way): 동시에 연결 상태만 확인하면 OK.
연결 해제(4-way): 한쪽이 먼저 종료 요청, 반대쪽도 마무리하고 종료 → 양방향 해제 필요
TCP는 신뢰성과 순서를 보장하기 위해 이런 절차를 거쳐. 그래서 3-way/4-way는 각각 목적에 맞게 최적화된 handshake 방식이야!
정리하자면!
ISN은 initial Sequence number 즉 초기 순서 번호
이 번호는 TCP 통신 시작할때 데이터 전송 순서를 정하기 위해 첫 패킷에 포함되는 번호.
만약 ISN이 항상 0부터 시작하거나 예측 가능한 값이라면,
매번 ISN이 같다면 이전 연결과 새 연결이 구분 안될 수 있다.
데이터가 섞이고 충돌이 발생가능
➡️ 그래서 매번 다른 ISN을 생성해서 고유한 연결로 구분해.
완전히 다른 시점에 발생하는 시간초과 의미
Connection Timeout : 서버에 연결을 시도할 때까지 기다리는 시간
Read Timeout : 서버에 연결된 후, 응답(데이터)을 기다리는 시간
TCP 연결을 끊을 때, 클라이언트가 마지막으로 ACK를 보내고 나서 일정 시간 동안 대기하는 상태
TCP는 순서 있는 데이터 전송을 보장해.
만약 연결을 바로 재사용하면, 이전 연결의 늦게 도착한 패킷이 새 연결과 섞일 수 있어.
TIME_WAIT 동안 기다리면, 그런 늦은 패킷이 네트워크에서 다 사라지게 됨.
🧠 요점: 패킷이 섞이지 않게 안전 시간 확보!
4-way handshake에서 마지막 ACK는 "끊을게요"라는 신호야.
만약 그 ACK가 서버에 도착하지 못했다면?
서버는 FIN을 다시 보내게 되고, 클라이언트는 TIME_WAIT 상태에서 그걸 받고 다시 ACK를 보낼 수 있어야 해.
🧠 요점: 서버가 "응? 네가 진짜 종료했는지 모르겠는데?" 할 경우를 대비한 대기시간!
상황 | TCP의 처리 방식
순서가 꼬임 : 순서 번호로 재정렬(ISN)
순서가 빠짐 : ACK로 재전송 유도
너무 오래된 패킷 : 무시하거나 연결과 매칭 실패로 폐기
새로운 연결과 헷갈릴 경우 : TIME_WAIT로 구분 및 보호
FIN 플래그도 하나의 시그널이자 SEQ 번호를 갖는 패킷
시나리오:
서버가 데이터1 (SEQ=100)을 보냄 → 네트워크에서 지연되거나 유실됨
서버가 FIN (SEQ=200)을 보냄 → 먼저 도착함
클라이언트가 먼저 FIN을 받고, 나중에 데이터1을 받음
TCP는 모든 데이터 수신 전까지 애플리케이션에 FIN 전달 안 함
FIN을 받은 순간 바로 연결 종료 처리하지 않음.
그 전에 SEQ=100에 해당하는 데이터가 아직 도착 안 했으면,
FIN은 버퍼에 쌓아두고 데이터가 올 때까지 ACK는 보내면서 기다림.
유실되었을 경우엔?
클라이언트는 빠진 SEQ=100에 대한 ACK를 계속 보내면서 재전송을 유도함.
서버가 재전송해서 도착하면 → 그때 모든 데이터 수신 완료 → FIN 처리
즉
1. FIN도착하면 "연결종료의사있음"으로 인식하되, 이전 데이터가 없으면 종료 보류
2. 지연된 데이터 도착 : 순서에 맞게 재조립 후 애플리케이션에 전달
3. 모든 데이터 수신 완료 시 : 그제서야 연결 종료 처리
🔐 TCP는 "순서 보장 + 완전성 보장"이 원칙.
FIN이 먼저 와도, 이전 순서 데이터가 도착할 때까지 연결을 종료하지 않음.
"빠르고 단순한 전송"을 목표로 함
TCP와 달리 연결을 맺지 않고, 그냥 데이터그램을 던져버림 ("fire and forget")
그래서 신뢰성, 순서 보장, 재전송 같은 기능이 없음
속도가 중요한 경우 (신뢰성보다 실시간성이 더 중요할 때)
예시:
➡️ "조금 손실되더라도 빠른 게 낫다!"는 상황에 적합함
예: QUIC, RTP(Real-time Transport Protocol)
이들은 UDP 위에 순서, 재전송, 흐름 제어 등을 얹어서 사용함
애플리케이션이 필요한 것만 골라 쓰고 싶어서
어떤 앱은 순서 보장만 필요하고, 손실은 무시해도 됨
어떤 앱은 딱 1~2회 재전송만 해주면 충분
TCP는 모든 걸 자동으로 처리해서 커스터마이징이 어려움
➡️ 그래서 개발자들이 UDP 위에서 자기 앱에 맞는 방식으로 신뢰성 기능을 따로 구현하는 거야
🎮 예시: 게임, 실시간 스트리밍
FPS 게임: 위치 좌표 0.1초 늦게 오면 의미 없음. → 재전송 X
화상회의: 한두 프레임 유실 괜찮음 → 재전송보단 끊기지 않는 게 중요
이런 상황에서 TCP 쓰면 "재전송하면서 끊기거나 버벅임"이 발생
➡️ 그래서 UDP에 최소한의 신뢰성만 추가해서 처리하는 거야.