포트 vs 소켓
Source: Dev.to
번역을 진행하려면 번역이 필요한 원본 텍스트를 제공해 주세요. 텍스트를 알려주시면 그대로 마크다운 형식과 코드 블록, URL 등을 유지하면서 한국어로 번역해 드리겠습니다.
포트란 무엇인가?
포트는 머신에서 서비스를 식별하는 번호(0–65535)일 뿐입니다.
- IP 주소 → 머신을 식별합니다
- 포트 → 머신 내부의 애플리케이션을 식별합니다
일반적인 포트
22→ SSH80→ HTTP443→ HTTPS3306→ MySQL
192.168.1.10:443을 보면 다음을 의미합니다:
- 머신 IP =
192.168.1.10 - 서비스 = 포트
443에서 실행 중
포트 자체만으로는 연결이 존재한다는 의미는 아닙니다; 이는 단지 프로세스가 대기하고 있다는 뜻입니다.
소켓이란?
소켓은 전체 통신 엔드포인트입니다. 포함 항목:
- IP 주소
- 포트
- 프로토콜 (TCP/UDP)
실제 TCP 연결은 5‑튜플로 고유하게 식별됩니다:
Source IP + Source Port + Destination IP + Destination Port + Protocol
예시
- 클라이언트:
10.0.0.5:51512 - 서버:
192.168.1.10:443 - 프로토콜: TCP
이 5‑튜플이 하나의 고유한 연결을 정의합니다.
| 포트 | 소켓 |
|---|---|
| 단순한 숫자 | 전체 통신 엔드포인트 |
| 서비스를 식별 | 연결을 식별 |
| 트래픽 없이 존재 | 통신 중에 존재 |
Source: …
소켓은 어떻게 생성되나요?
클라이언트 측
브라우저가 HTTPS에 연결할 때:
-
socket()– 애플리케이션이 커널에 소켓 생성을 요청합니다.- 커널이 메모리에 소켓 구조체를 할당합니다.
- 파일 디스크립터를 반환합니다.
-
connect()– 커널이 임시 포트(예:51512)를 할당하고 TCP 3‑웨이 핸드셰이크를 시작합니다:SYN → SYN‑ACK → ACK핸드셰이크가 완료되면 연결 상태가 ESTABLISHED가 됩니다.
서버 측
Nginx가 시작될 때:
socket()– 리스닝 소켓을 생성합니다.bind()– 포트(예:443)를 예약합니다.listen()– 소켓을 리스닝 상태로 표시합니다.accept()– 클라이언트가 연결하면 커널이 해당 클라이언트를 위한 새로운 소켓을 만들고, 리스닝 소켓은 그대로 유지됩니다.
클라이언트당 하나의 새로운 소켓이 생성됩니다.
10,000명의 클라이언트가 연결하면 → 10,000개의 소켓이 생성됩니다.
소켓을 관리하는 주체는?
Linux 커널 TCP/IP 스택이 관리합니다:
- TCP 상태 (
SYN_SENT,ESTABLISHED,TIME_WAIT, …) - 송수신 버퍼
- 시퀀스 번호
- 혼잡 제어
- 메모리 할당
애플리케이션은 오직 다음만 수행합니다:
readwriteclose
그 외 모든 것은 커널의 책임입니다.
소켓이 파일 디스크립터를 사용하는 이유는?
소켓은 디스크에 쓰지 않지만, Unix/Linux에서는 “모든 것이 파일이다.” 라는 이유로 파일 디스크립터(FD)를 사용합니다.
Linux는 다음을 파일 디스크립터로 취급합니다:
- 파일
- 소켓
- 파이프
- 터미널
- 장치
epoll,eventfd등
파일 디스크립터란 실제로 무엇인가?
파일 디스크립터는:
- 단순히 정수
- 프로세스별 테이블의 인덱스
- 커널 객체를 가리킴
표준 디스크립터
| FD | 의미 |
|---|---|
0 | stdin |
1 | stdout |
2 | stderr |
3 | 첫 번째로 연 소켓/파일 |
예제 (C)
int fd = socket(AF_INET, SOCK_STREAM, 0);
커널:
- 소켓 객체를 생성한다.
- 프로세스의 FD 테이블에 저장한다.
- 작은 정수(핸들)를 반환한다.
그 정수는 단지 참조일 뿐이며, 디스크 파일을 의미하지 않는다.
파일 디스크립터 메커니즘을 재사용하는 이유는?
통합된 API를 제공합니다:
read(fd);
write(fd);
close(fd);
poll(fd);
epoll(fd);
동일한 시스템 호출이 파일, 소켓 및 파이프에서 모두 동작하므로 별도의 “네트워크 API”가 필요하지 않습니다. 이 추상화는 매우 강력합니다.
실제 시스템에서 이것이 중요한 이유
- 고 트래픽 서비스는 50,000개의 동시 연결 → 50,000개의 소켓 → 50,000개의 파일 디스크립터를 가질 수 있습니다.
- 오류 **“Too many open files”(파일을 너무 많이 열었습니다)**는 일반적으로 디스크 파일이 아니라 파일 디스크립터가 다 소진되었음을 의미합니다.
제한을 확인하려면:
ulimit -n
- 컨테이너와 Kubernetes 파드는 노드 커널을 공유하므로 노드 전체 FD 제한이 중요합니다.
- 소켓 고갈(예: 많은
TIME_WAIT상태)은 처리량을 크게 감소시킬 수 있습니다.
Visual Summary
| Concept | What It Represents |
|---|---|
| Port | 서비스 식별자 (활성 통신 없음) |
| Socket | 실시간 연결을 나타내는 커널 객체 (TCP 상태 및 버퍼 포함) |
| File Descriptor | 커널 객체를 가리키는 정수 핸들, 통합 I/O 추상화에 사용 |
최종 정신 모델
- IP = 건물
- Port = 문
- Socket = 두 문 사이의 활성 전화 통화
- File Descriptor = 운영 체제가 내부적으로 사용하는 호출 참조 번호