UDP와 TCP는 전송계층에서 사용되는 네트워크 통신 프로토콜이다. 각 차이점을 알아보며 특징을 이해해보도록 하자.
UDP
UDP는 비 연결형 통신 프로토콜이다. 비 연결형 통신 프로토콜이란, 서버와 클라이언트 간의 연결 없이 데이터를 주고 받는다는 의미이다.
연결 없이 데이터를 주고받는다는 뜻은 클라이언트에서 서버를 향해 데이터를 보낼 수는 있으나, 그 반대로 서버에서 클라이언트로 데이터를 보낼 수는 없다는 뜻이다.
왜? 서버는 대상이 특정되어 있지만, 클라이언트는 불특정 다수이므로 대상을 특정할 수 없다. => 서버에서도 특정 클라이언트의 정보를 안다면 데이터를 보낼 수도 있다.
서버와 클라이언트가 연결되어 있지 않기 때문에, 각 패킷들은 서로 다른 경로로 이동하여 목적지에 도착하게 된다. 각 패킷의 경로가 다른 이유로, 패킷의 전송 시간이 일정하지 않아 보내는 순서와 도착하는 순서가 다를 수가 있다. => 데이터의 신뢰성이 보장되지 않는다.
클라이언트에서 A,B,C의 순서로 패킷을 서버로 보내면, 서버에서는 A,B,C의 순서로 패킷을 수신해야 하지만 UDP 통신의 경우 A,C,B 나 B,A,C 등 클라이언트가 송신한 순서와 다소 다를 가능성이 생긴다.
그렇다면, 데이터를 신뢰성있게 보내지도 못하는 프로토콜이 무슨 의미가 있을까? UDP의 장점은 바로 속력에 있다. 데이터를 송수신하는데 있어서 고려하지 않는 것들이 많아 빠른 처리가 가능하기 때문에 네트워크에 부하를 적게 주며, 신뢰성은 낮더라도 연속성은 높은 통신을 할 수 있게 된다.
이러한 이유로 UDP는 비디오 스트리밍과 같이 신뢰성보다 연속성이 중요한 서비스에 주로 사용된다. (비디오 스트리밍의 경우 중간 1프레임정도 문제가 발생하더라도 크게 눈치채지 못하지만, 느린 송수신으로 인해 화질이 저하되거나 프레임이 낮아지는 것은 쉽게 알아차릴 수 있다.)
TCP
TCP는 연결형 통신 프로토콜이다. 연결형 통신 프로토콜이란, 클라이언트와 서버가 논리적으로 연결된 상태로 데이터를 주고 받는다는 의미이다.
클라이언트와 서버가 서로 이어져 있기 때문에, 양방향 통신이 가능하다. 클라이언트에서 서버로 데이터를 보낼 수 있으며, 서버에서도 클라이언트로 데이터를 보낼 수 있다.
TCP 통신에서 클라이언트와 서버를 연결하는 이유는 신뢰성 있는 데이터의 송수신을 위해서이다. 서로 연결되어 있기 때문에, 데이터의 순서와 무결성을 보장할 수 있다. 또한, 유실된 패킷이 존재할 경우 클라이언트에 재송신을 요청할 수도 있게 된다.
TCP 통신에서 클라이언트와 서버의 연결, 해제에는 특별한 방법이 사용된다. 바로, 3 Way - Handshake 와 4 Way - Handshake 이다.
3 Way - Handshake
3Way - Handshake 란, TCP 통신에서 클라이언트와 서버가 서로 연결하기 위해 사용하는 방식이다. 이 때, SYN과 ACK라는 두개의 플래그를 사용한다. (구체적로는 더 많은 플래그가 사용되는 것으로 안다.)
SYN : 무작위 난수를 담아, 상대방에게 보낸다. (응답을 요청하는 신호) ACK : 상대가 보낸 SYN에 담긴 난수에 1을 더해, 상대방에게 보낸다. (SYN에 대한 응답 신호)
먼저, 클라이언트가 서버에 SYN을 보낸다. 서버는 SYN을 수신한 뒤, SYN에 대한 ACK와 함께 새로운 SYN을 보낸다. 클라이언트는 서버에서 보낸 SYN에 대한 ACK를 다시 서버에 보내고, 서버가 ACK를 수신한 뒤 서로 연결이 확립된다.
이는 신뢰성 있는 통신을 위해, 서로 데이터를 송신하고 수신할 수 있는 준비가 되어있는지 사전에 확인하는 과정이다.
4 Way - Handshake
4Way - Handshake 란, TCP 통신에서 클라이언트와 서버가 안정적으로 연결을 해제하기 위해 사용하는 방식이다. 이 때는, FIN과 ACK라는 두개의 신호를 사용한다.
FIN : 연결을 종료하겠다는 신호 ACK : FIN에 대한 응답 신호
서버에 연결을 시도하는 것은 클라이언트로부터 시작되지만, 접속을 해제하는 것은 서버가 먼저 시도할 수도 있다. 그러므로, 서버와 클라이언트가 아니라 A와 B로 표현할 것이다. A는 먼저 연결 해제를 요청하는 쪽이며, B는 해제를 요청받는 쪽이다.
먼저, A는 B에게 FIN을 보낸다. B는 FIN을 수신한 뒤 A에 ACK를 송신하고, 잠시 대기 상태에 머문다. (대기상태에 머무는 이유는 A가 보낸 패킷중 도달하지 않은 것이 있을 수 있기 때문에 이를 기다리는 것이다.)
B에서 충분히 대기했다고 판단하면, A에 FIN신호를 보낸다. A는 FIN을 수신한 뒤, B에 ACK를 송신하고 잠시 대기상태에 머문다. (역시나, B에서 보낸 패킷중 아직 도착하지 않은 것이 있을 수 있기 때문이다.)
B는 ACK를 수신받은 뒤, 소켓을 닫는다. (이 때, A는 아직 소켓을 닫지 않았으므로 송신중인 패킷이 있다면 수신할 수 있다.)
A는 충분한 대기시간을 거친 뒤, 최종적으로 소켓을 닫는다.
이러한 과정을 통해, 연결 해제로 인해 데이터의 유실이 발생하거나 데드락에 빠지는 것을 방지할 수 있다.
TCP는 이처럼, 연결과 해제 과정에서도 여러 과정을 거치지만 패킷을 송수신할 때, 데이터의 신뢰성을 보장하기 위한 여러 절차를 거치기 때문에 UDP에 비해 상대적으로 느린 속력을 보인다.
TCP의 경우는 속도보다 신뢰성에 무게를 둔 프로토콜인만큼, 파일을 다운로드 받는 등의 서비스에 이용된다.
DNS : 웹 사이트의 문자열 주소(도메인)를 IP로 변경하거나, IP를 문자열 주소(도메인)로 변경해주는 시스템
우리는 일반적으로, 어떠한 웹사이트에 접속하기 위해 문자열로 된 주소를 입력한다. www.naver.com www.google.com www.daum.net 이런 영문과 특수기호로 이루어진 문자열을 주소창에 입력하면 웹사이트에 접속이 된다. 하지만, 실제로는 영문 문자열이 아니라 IP주소를 알아야 웹 사이트에 접속할 수 있다.
구글에 PING을 한 번 보내보자.
[2404:6800:4005:814::2004] 라는 IPv6 주소를 확인할 수 있다. www.google.com이라는 문자열은 어떠한 과정을 거쳐서 [2404:6800:4005:814::2004]라는 IP주소로 변환이 되고, 우리는 그 IP주소를 통해 웹 서버에 접속할 수 있게 되는 것이다.
이 때, 문자열 주소(도메인)를 IP로 변환하는 역할을 담당하는 것이 DNS이다.
복잡하고 직관적이지 않은 IP주소를 사이트 별로 모두 외우는 것은 유저 입장에서 접근성이 상당히 떨어지는 일이기 때문에, 쉽고 간편하게 접근할 수 있는 문자열 주소를 사용할 수 있게 도와주는 셈인 것이다.
DNS의 과정
1. Local DNS에 IP주소 요청
Local DNS란, 기지국의 DNS서버이다. 모든 PC는 인터넷 가입시, 해당 통신사 기지국의 DNS 서버를 등록하게 된다. 어떠한 도메인의 IP를 찾기 위해, PC는 Local DNS에 해당 도메인의 IP를 요청하게 된다.
2.Local DNS에서 Root Name Server에 IP주소 요청
기지국의 DNS 서버는 요청받은 도메인의 IP주소를 Root Name Server라는 DNS 서버에 요청하게 된다.
DNS서버는 트리 구조로 이어져있다고 한다. 해당 트리의 루트 노드가 바로 Root Name Server인 것이다. 해당 Root Name Server에 IP주소를 요청하면, Root Name Server는 TLD 네임 서버의 주소를 반환해준다.
3.Local DNS에서 TLD 네임 서버에 IP요청
TLD 네임 서버란, 최상위 도메인(TLD)의 네임 서버이다. 도메인 주소를 보면, 닷(.)으로 분류되어 있는 것을 볼 수 있다. www.naver.com 의 경우, www와 naver과 com으로 분류되어 있다. 이중 가장 뒤에 있는 com이 최상위 도메인이다. www.daum.net 의 경우, net이 최상위 도메인이 된다.
우리가 Local DNS에 www.naver.com 의 IP를 요청했다면, Root Name Server에선 com의 DNS 서버를 알려주게 된다. Local DNS는 Root Name Server로부터 제공받은 com의 DNS 서버에 다시 IP를 요청하게 된다. 최상위 도메인 naver.com의 DNS 서버를 찾아서 다시 local DNS에 반환해준다.
4.Local DNS에서 최종적인 IP를 받을 때까지 재귀적으로 IP요청
예를 들어, 요청한 주소가 A.B.C.D.E.F.G.com 이라고 해보자. (물론 이런 주소는 실제로는 없겠지만) 그렇다면, Root Name Server가 TLD DNS 서버를 제공해주고, 다시 TLD DNS 서버에 IP를 요청하면, G.com의 DNS 서버를 제공해줄 것이며, G.com의 DNS 서버는 F.G.com의 DNS 서버를 제공해줄 것이다. local DNS는 A.B.C.D.E.F.G.com의 IP주소를 반환 받을 때까지 이 과정을 재귀적으로 반복하게 된다. 최종적으로 IP를 알게 되면, Local DNS는 해당 IP주소를 PC에 알려주게 된다.
DNS 캐싱
DNS는 이처럼 상당히 번거로운 과정을 거치고 있다. 하지만, 항상 저 모든 과정을 거치는 것은 아니다. 왜냐하면, 각 DNS는 최근에 탐색된 IP주소를 캐싱 하기 때문이다. 캐싱이란, 별도의 공간에 IP를 저장 해놓는 것이다.
예를 들어, Local DNS에 www.naver.com 의 아이피 주소가 캐싱되어 있다면, Root Name Server에 IP를 요청할 필요 없이 캐싱된 IP를 바로 PC에 반환해줄 수 있는 것이다. (컴퓨터에 사용되는 캐시 메모리와 동일한 기능이라고 생각하면 된다.)
어떠한 DNS 서버에서 캐싱된 IP주소를 발견할 수 있다면, 끝까지 재귀적 탐색을 하지 않고 중간에 종료하여 IP 주소를 얻어낼 수 있는 것이다. 그리고 이렇게 얻어낸 IP 주소는 각 DNS 서버에만 캐싱되는 것이 아니라 우리 PC에도 캐싱된다. (cmd에 ipconfig /displaydns 를 입력하면, 캐싱된 데이터를 볼 수 있다.)
하지만, PC에 캐싱된 IP정보는 모종의 이유로 변조될 수 있다고 한다. (바이러스, 해킹 등...) www.naver.com을 을 쳤는데 다른 IP 주소로 접속이 되는 보안 취약점이 발생할 수 있다는 것이다. 그러므로, PC에 저장된 DNS 캐시는 주기적으로 정리해주는 것이 좋다고 한다. (물론, 개인 PC 뿐만이 아니라 각 DNS 서버에서도 발생할 수 있는 문제이긴 하다.)