TCP/UDP와 포트: IP만으로 부족한 통신 이해하기 (NAPT, 포트포워딩, ICMP)

Murhyun2·2025년 4월 23일
0

네트워크

목록 보기
3/7


안녕하세요! 개발하다 보면 '어? 왜 데이터가 순서대로 안 오지?' 혹은 '분명 보냈는데 왜 응답이 없지?' 같은 네트워크 문제에 맞닥뜨릴 때가 있습니다. 우리가 당연하게 사용하는 인터넷 통신의 기반에는 IP(Internet Protocol)가 있지만, 이 IP라는 친구, 생각보다 단순하고 때로는 꽤나 무책임(?)합니다. 오늘은 IP 혼자서는 해결할 수 없는 문제들, 그리고 이를 해결하기 위해 등장한 전송 계층(특히 TCP/UDP), '포트(Port)'라는 개념, 그리고 곁다리로 알아두면 유용한 NAPT, 포트 포워딩, ICMP까지 한번 짚어보겠습니다.

1. IP: 빠르지만, 약속은 못 지켜요!

IP의 설계 철학은 '최선을 다하지만, 보장은 못 해(Best-Effort)'입니다. 일단 목적지 IP 주소 보고 패킷을 던지고 보는 거죠.

  • 신뢰성? 그게 뭔가요? (Unreliable): 패킷이 중간에 길을 잃거나, 순서가 뒤죽박죽 도착하거나, 내용이 깨져도 IP 자체는 크게 신경 쓰지 않습니다. '알아서 잘 받겠지!' 하는 셈이죠. 패킷이 제대로 갔는지 확인하는 절차도 없습니다.

  • 연결? 일단 보내! (Connectionless): 데이터를 보내기 전에 상대방과 '나 지금 보낸다?' 하고 미리 연결을 맺는 과정(Handshake)이 없습니다. 각 패킷은 앞뒤 사정 모르는 독립적인 존재로 전송됩니다.

🤔 왜 이렇게 만들었을까요?

바로 속도 때문입니다. 신뢰성을 챙기고 연결 상태를 관리하려면 이것저것 확인하고 기록해야 하는데, 이게 다 성능에는 부담(오버헤드)이거든요. IP는 일단 최대한 빠르고 효율적으로 데이터를 전달하는 데 집중하도록 설계된 겁니다.

2. IP의 빈틈을 메우는 해결사: 전송 계층 (Transport Layer)

IP만 믿고 통신하기엔 실제 애플리케이션(웹 브라우저, 메신저, 게임 등)을 만들기 너무 힘듭니다. 웹페이지 로딩하는데 이미지가 깨지고 글 순서가 엉망이면 사용자 경험이 엉망이 되겠죠? 여기서 등장하는 해결사가 바로 전송 계층입니다. IP 바로 위 계층에서 IP가 못하는 중요한 일들을 처리해주죠.

  • 꼼꼼한 해결사, TCP (Transmission Control Protocol):

    • 연결 지향 (Connection-Oriented): 데이터를 보내기 전에, 유명한 3-way handshake로 상대방과 미리 연결을 설정합니다. 통신이 끝나면 4-way handshake로 깔끔하게 연결을 해제하고요.

    • 신뢰성 보장 (Reliable): 데이터가 순서대로, 빠짐없이 도착하도록 흐름 제어, 오류 제어, 혼잡 제어 같은 기능들을 수행합니다. 만약 패킷이 중간에 사라졌다면? '어? 그거 다시 보내줘!' 하고 재전송을 요청해서 어떻게든 데이터를 제대로 전달하려고 노력합니다. 웹 통신(HTTP/HTTPS), 파일 전송(FTP) 등 데이터의 정확성이 중요한 대부분의 통신에 사용됩니다.

  • 빠른 해결사, UDP (User Datagram Protocol):

    • 비연결성, 비신뢰성: TCP와 달리 연결 설정이나 데이터 도착 확인 같은 절차가 없습니다. 그냥 IP처럼 '일단 보내고 보자!' 스타일이죠.

    • 속도 중시: 신뢰성을 포기한 대신 TCP보다 훨씬 빠릅니다. 실시간 영상 스트리밍, 온라인 게임처럼 약간의 데이터 손실이 있더라도 속도가 더 중요하거나, DNS 조회처럼 빠르고 가벼운 통신이 필요할 때 주로 사용됩니다.

  • 애플리케이션 구분: 전송 계층의 또 다른 중요한 역할! 한 컴퓨터에서 웹 브라우저, 메신저, 게임 등 여러 프로그램이 동시에 인터넷을 사용하는데, IP 주소만으로는 이들을 구분할 수 없습니다. 전송 계층은 이 프로세스들을 구분하는 역할도 하는데, 바로 '포트(Port)' 번호를 사용해서 해결합니다.

3. 내 컴퓨터 안의 특정 방문: 포트 (Port)

IP 주소가 아파트 동/호수라면, 포트 번호는 그 집 안의 '안방', '작은방', '서재'처럼 특정 애플리케이션(프로세스)으로 향하는 고유한 문(Gate)이라고 생각하면 이해하기 쉽습니다.

  • 16비트 숫자: 포트 번호는 0부터 65535까지 (총 65,536개)의 숫자를 사용합니다.

  • TCP/UDP 헤더에 포함: TCP와 UDP 헤더에는 출발지 포트(Source Port)와 목적지 포트(Destination Port) 정보가 담겨 있습니다. 운영체제는 이 포트 번호를 보고 도착한 데이터를 정확한 애플리케이션에게 전달해 줄 수 있죠.

  • 포트 번호의 종류 (암묵적인 약속):

    • 잘 알려진 포트 (Well-known Ports: 0 ~ 1023): 이건 거의 '공식 지정석'입니다. FTP(21), SSH(22), DNS(53), HTTP(80), HTTPS(443) 등 전 세계적으로 약속된 서비스들이 사용합니다. 함부로 다른 용도로 사용하면 안 되겠죠?

    • 등록된 포트 (Registered Ports: 1024 ~ 49151): 특정 애플리케이션들이 IANA에 등록하고 사용하는 번호입니다. 개발자들이 자주 보는 Oracle DB(1521), MySQL(3306), Tomcat(8080) 등이 여기에 해당합니다.

    • 동적/사설 포트 (Dynamic/Private Ports: 49152 ~ 65535): 특정 서비스에 고정되지 않고, 주로 클라이언트가 서버에 접속할 때 '저 잠시 이 번호 좀 쓸게요!' 하고 운영체제로부터 임시로 할당받는 번호들입니다.

결국, IP 주소:포트 번호 조합 (예: 203.0.113.10:443)은 인터넷 세상에서 특정 컴퓨터의 특정 애플리케이션 서비스를 가리키는 유일무이한 식별자가 됩니다.

4. 하나의 IP로 여럿이 인터넷 쓰기: NAPT (Network Address Port Translation)

집이나 사무실에서 흔히 쓰는 공유기는 보통 외부 인터넷망과는 공인 IP 하나로 연결되지만, 내부에는 여러 기기(노트북, 스마트폰 등)가 각자 사설 IP를 사용합니다. 이 사설 IP를 가진 기기들이 어떻게 외부 인터넷과 통신할 수 있을까요? 바로 공유기의 NAPT(또는 PAT) 기술 덕분입니다.

  • 단순히 IP 주소만 1:1로 바꾸는 NAT로는 공인 IP 주소 절약 효과가 미미합니다.

  • NAPT는 IP 주소뿐만 아니라 포트 번호까지 함께 변환합니다.

  • 공유기는 내부 기기가 외부로 통신을 시작할 때, 사설 IP:출발지 포트 조합을 공인 IP:새로운 출발지 포트 조합으로 매핑하고 이 정보를 테이블에 기록합니다.

  • 외부 서버에서 응답 패킷이 공인 IP:새로운 출발지 포트로 돌아오면, 공유기는 테이블을 참조하여 원래의 사설 IP:출발지 포트로 정확히 전달해 줍니다.

  • 이렇게 하면 하나의 공인 IP 주소로도 수많은 내부 기기들이 동시에 인터넷을 사용할 수 있게 됩니다. IP 주소 고갈 문제를 해결하는 핵심 기술이죠.

5. 내 서버를 세상에 공개하기: 포트 포워딩 (Port Forwarding)

NAPT 환경에서는 기본적으로 외부에서 내부 네트워크의 특정 기기로 먼저 접속 요청을 보내는 것이 차단됩니다 (공유기가 방화벽 역할도 하니까요). 그런데 만약 내 PC에 웹 서버나 게임 서버를 구축해서 외부 사용자들이 접속하게 만들고 싶다면 어떻게 해야 할까요? 이때 필요한 것이 포트 포워딩 설정입니다.

  • 포트 포워딩은 공유기 설정에서 "외부에서 이 공인 IP의 특정 포트(예: 80번)로 들어오는 요청은, 내부 네트워크의 저 PC(예: 192.168.0.100)의 특정 포트(예: 8080번)로 전달해줘!" 라고 미리 길을 지정해주는 기능입니다.

  • 이렇게 설정하면, 외부 사용자는 공인 IP:80으로 접속했지만 실제로는 내부 192.168.0.100:8080 서버와 통신하게 됩니다. 내 방구석 서버를 월드 와이드 웹에 공개하는 방법인 셈이죠!

6. 네트워크 문제 해결의 단서: ICMP (Internet Control Message Protocol)

IP가 신뢰성은 없지만, 통신 과정에서 발생하는 문제 상황을 아예 무시하는 것은 아닙니다. ICMP는 IP 계층에서 통신 중 발생하는 오류를 보고하거나, 네트워크 상태를 진단하기 위한 메시지를 전달하는 프로토콜입니다.

  • 오류 보고: 목적지에 도달할 수 없다(Destination Unreachable), 패킷이 네트워크를 너무 오래 떠돌아 폐기되었다(Time Exceeded) 등의 다양한 오류 상황을 원래 패킷을 보낸 출발지 호스트에게 알려줍니다.

  • 진단 정보: 우리가 네트워크 연결 상태를 확인할 때 가장 많이 사용하는 ping 명령어(상대방이 살아있는지 확인: Echo Request/Reply)나, 목적지까지 어떤 라우터들을 거쳐 가는지 경로를 추적하는 traceroute (Windows에서는 tracert) 명령어가 바로 ICMP 메시지를 활용합니다.

중요 포인트: ICMP는 어디까지나 '문제가 발생했음!'을 알려주는 메신저 역할일 뿐, IP 통신 자체의 신뢰성을 보장해주지는 못합니다. 심지어 ICMP 메시지 자체도 네트워크 상황에 따라 유실될 수 있다는 점! (ICMP는 IPv4용 ICMPv4와 IPv6용 ICMPv6가 있습니다.)

마치며

돌이켜보면, IP는 인터넷 통신의 뼈대를 제공하지만 그 자체로는 꽤나 투박합니다. 이 부족함을 채우기 위해 전송 계층의 TCP/UDP가 신뢰성 또는 속도를 더하고, 포트 번호가 정확한 애플리케이션을 찾아가도록 안내하며, NAPT와 포트 포워딩 같은 기술들이 IP 주소의 한계를 극복하고 유연한 네트워크 구성을 가능하게 합니다. 그리고 문제가 생겼을 때는 ICMP가 진단할 실마리를 제공하죠.

이렇게 여러 계층의 프로토콜과 기술들이 서로 맞물려 돌아가기에 우리가 매일 편리하게 코드를 짜고, 서비스를 이용하고, 소통할 수 있는 것 같습니다. 평소 당연하게 여기던 네트워크 통신 뒤에 숨겨진 원리들을 하나씩 알아가는 과정, 꽤 흥미롭지 않나요? 다음번에는 또 다른 재미있는 네트워크 이야기로 돌아오겠습니다. 😊

profile
왜?를 생각하며 개발하기

0개의 댓글