시스템 엔지니어가 서버를 운영하다 보면 반드시 네트워크 문제를 만나게 된다.
서버의 CPU와 메모리는 정상이고 디스크에도 문제가 없는데 애플리케이션 접속이 되지 않는 경우가 있다.
웹 서버 프로세스도 정상적으로 실행되고 있고 포트도 열려 있는데 외부에서 접속할 수 없을 수도 있다.
반대로 서버 자체에는 문제가 없는데 방화벽이나 라우팅 문제 때문에 서비스가 장애처럼 보이는 경우도 있다.
예를 들어 다음과 같은 상황을 생각해보자.
사용자
|
| HTTP/HTTPS
v
Internet
|
v
Firewall
|
v
Load Balancer
|
v
Web Server
|
v
Application Server
|
v
Database Server
사용자가 웹사이트에 접속하지 못한다면 어디부터 확인해야 할까?
CPU를 확인해야 할까?
메모리를 확인해야 할까?
웹 서버 프로세스를 확인해야 할까?
방화벽을 확인해야 할까?
DNS를 확인해야 할까?
라우팅을 확인해야 할까?
이 문제를 해결하려면 서버뿐만 아니라 네트워크 전체의 흐름을 이해해야 한다.
이번 글에서는 네트워크의 기본 개념부터 시작해서 시스템 엔지니어가 네트워크를 왜 알아야 하는지, 그리고 앞으로 어떤 내용을 학습해야 하는지를 정리한다.
네트워크(Network)는 간단하게 말하면 여러 장치가 서로 데이터를 주고받을 수 있도록 연결된 구조다.
여기서 장치는 매우 다양하다.
PC
서버
스마트폰
스토리지
라우터
스위치
방화벽
프린터
IoT 장비
가상머신
컨테이너
이 장치들이 서로 데이터를 주고받기 위해서는 일정한 규칙이 필요하다.
이러한 규칙을 **프로토콜(Protocol)**이라고 한다.
예를 들어 우리가 웹사이트에 접속할 때 사용하는 대표적인 프로토콜이 HTTP와 HTTPS다.
Client
|
| HTTP / HTTPS
v
Web Server
파일을 전송할 때는 FTP나 SFTP와 같은 프로토콜을 사용할 수 있다.
서버에 원격 접속할 때는 SSH를 사용한다.
관리자 PC
|
| SSH
v
Linux Server
즉 네트워크는 단순히 케이블을 연결하는 것이 아니라,
장치
+
주소
+
통신 규칙
+
전송 경로
+
보안 정책
이 결합된 구조라고 이해하면 된다.
컴퓨터 한 대만 사용하는 환경이라면 네트워크가 없어도 된다.
하지만 실제 IT 환경에서는 대부분 여러 시스템이 서로 연결되어 있다.
예를 들어 기업의 일반적인 시스템을 생각해보자.
Internet
|
Firewall
|
Load Balancer
|
+-------+-------+
| |
Web01 Web02
| |
+-------+-------+
|
App Server
|
DB Server
|
Storage
Web Server는 Application Server와 통신해야 한다.
Application Server는 Database Server와 통신해야 한다.
Database Server는 Storage와 연결될 수 있다.
관리자는 SSH를 통해 서버에 접속한다.
모니터링 서버는 각 서버의 상태 정보를 수집한다.
백업 서버는 서버의 데이터를 가져간다.
즉 시스템 엔지니어가 관리하는 대부분의 시스템은 네트워크를 통해 서로 연결된다.
시스템 엔지니어가 네트워크를 몰라도 서버 자체를 관리하는 것은 가능하다.
하지만 실제 장애 상황에서는 매우 큰 한계가 생긴다.
예를 들어 다음과 같은 장애가 발생했다고 생각해보자.
웹사이트 접속 불가
서버에 로그인해보니 다음과 같다.
systemctl status nginx
결과:
active (running)
Nginx는 정상이다.
포트도 확인한다.
ss -lntp
결과:
LISTEN 0 511 0.0.0.0:80
LISTEN 0 511 0.0.0.0:443
서비스도 정상이다.
그런데 사용자는 접속할 수 없다.
이때 서버만 계속 확인하면 원인을 찾지 못할 수 있다.
실제 원인은 다음과 같을 수 있다.
DNS 문제
↓
Gateway 문제
↓
Routing 문제
↓
Firewall 문제
↓
Load Balancer 문제
↓
VLAN 문제
↓
Switch 문제
↓
Server NIC 문제
↓
Server Firewall 문제
↓
Application 문제
따라서 시스템 엔지니어는 최소한 다음 질문에 답할 수 있어야 한다.
내 서버의 IP는 무엇인가?
어떤 네트워크에 연결되어 있는가?
Gateway는 무엇인가?
DNS는 정상인가?
목적지까지 Routing이 존재하는가?
목적지 Port는 열려 있는가?
Firewall이 차단하고 있는가?
TCP 연결이 만들어지고 있는가?
Application이 정상적으로 응답하고 있는가?
이것이 시스템 엔지니어가 네트워크를 배워야 하는 가장 중요한 이유다.
네트워크를 공부하기 전에 먼저 몇 가지 핵심 용어를 알아야 한다.
NIC(Network Interface Card)는 컴퓨터를 네트워크에 연결해주는 장치다.
물리 서버에서는 실제 네트워크 카드가 존재한다.
Linux에서 다음 명령어로 확인할 수 있다.
ip link
또는
ip addr
예를 들어:
ens160
eth0
eno1
ens192
등의 인터페이스가 보일 수 있다.
구조를 단순화하면 다음과 같다.
Server
|
+-- NIC
|
+-- Network Cable
|
+-- Switch
가상머신에서는 실제 물리 NIC가 아니라 가상 NIC가 사용될 수도 있다.
네트워크 인터페이스에는 MAC Address라는 고유한 주소가 존재한다.
예:
00:50:56:AA:BB:CC
MAC Address는 일반적으로 Layer 2에서 사용된다.
Linux에서는 다음과 같이 확인할 수 있다.
ip link
예:
2: ens160:
link/ether 00:50:56:aa:bb:cc
여기서
00:50:56:aa:bb:cc
가 MAC Address다.
다만 시스템 엔지니어 입장에서는 MAC Address 자체를 외우는 것보다 IP Address와 MAC Address가 서로 어떤 관계를 가지고 있는지 이해하는 것이 더 중요하다.
이 부분은 이후 ARP에서 자세하게 다룬다.
IP Address는 네트워크에서 장치를 식별하고 통신하기 위한 주소다.
IPv4의 대표적인 형태는 다음과 같다.
192.168.0.10
예를 들어 서버가 다음과 같은 설정을 가지고 있다고 생각해보자.
IP : 192.168.0.10
Netmask : 255.255.255.0
Gateway : 192.168.0.1
이를 간단하게 표현하면:
Server
IP: 192.168.0.10
|
|
v
Gateway
192.168.0.1
|
v
Other Network
IP Address는 네트워크를 이해하기 위한 가장 기본적인 개념 중 하나다.
앞으로 네트워크 학습에서는 IP Address뿐만 아니라 Subnet Mask, CIDR, Gateway, Routing까지 함께 이해해야 한다.
서버가 다음과 같이 구성되어 있다고 생각해보자.
Server A
192.168.1.10/24
Server B
192.168.1.20/24
두 서버는 같은 네트워크에 있다.
192.168.1.0/24
+----------------------+
| |
| Server A |
| 192.168.1.10 |
| |
| Server B |
| 192.168.1.20 |
| |
+----------------------+
반면 다음과 같이 되어 있다면:
Server A
192.168.1.10/24
Server B
192.168.2.20/24
서로 다른 네트워크다.
Network A
192.168.1.0/24
|
| Router
|
Network B
192.168.2.0/24
이때 두 네트워크 사이의 통신에는 일반적으로 Router와 Routing이 필요하다.
이 개념은 나중에 Subnet과 Routing을 공부할 때 매우 중요하게 사용된다.
Switch는 여러 네트워크 장치를 연결하는 장비다.
간단하게 생각하면 다음과 같다.
Switch
+------+------+------+
| | | |
PC Server NAS Printer
스위치는 MAC Address를 기반으로 데이터를 전달한다.
예를 들어:
Server A
MAC: AA:AA:AA:AA:AA:01
Server B
MAC: BB:BB:BB:BB:BB:02
Switch는 어느 포트에 어떤 MAC Address가 연결되어 있는지 학습한다.
이를 MAC Address Table이라고 한다.
MAC Address Port
--------------------------------
AA:AA:AA:AA:AA:01 Gi1/0/1
BB:BB:BB:BB:BB:02 Gi1/0/2
CC:CC:CC:CC:CC:03 Gi1/0/3
따라서 Switch는 목적지 MAC Address를 확인하고 해당 포트로 Frame을 전달한다.
Router는 서로 다른 네트워크 사이에서 패킷을 전달하는 장비다.
예를 들어:
Network A
192.168.1.0/24
|
|
Router
|
|
Network B
192.168.2.0/24
Server A:
192.168.1.10
Server B:
192.168.2.20
Server A에서 Server B로 통신하려면 Router를 통해 다른 네트워크로 이동해야 한다.
이때 중요한 개념이 Gateway다.
Gateway는 다른 네트워크로 이동하기 위한 출입구라고 생각하면 이해하기 쉽다.
예를 들어:
Server
192.168.1.10
|
| Default Gateway
v
192.168.1.1
|
v
Other Network
Linux에서 Routing 정보를 확인하면:
ip route
예:
default via 192.168.1.1 dev ens160
192.168.1.0/24 dev ens160 proto kernel scope link src 192.168.1.10
여기서:
default via 192.168.1.1
이 기본 Gateway를 의미한다.
즉 서버가 목적지를 직접 알지 못하면 기본 Gateway를 통해 패킷을 전달한다.
사람은 다음과 같은 주소를 사용하기 편하다.
www.example.com
하지만 네트워크 통신에서는 IP Address가 필요하다.
www.example.com
|
v
DNS
|
v
93.184.xxx.xxx
DNS는 도메인 이름과 IP Address 등의 정보를 조회하는 시스템이다.
Linux에서는 다음과 같이 테스트할 수 있다.
nslookup www.example.com
또는:
dig www.example.com
실제 서버 장애에서 DNS 문제는 매우 중요하다.
예를 들어:
ping IP → 정상
ping Domain → 실패
라면 서버 자체의 네트워크 연결과 DNS 이름 해석을 구분해서 확인해야 한다.
IP Address가 컴퓨터의 주소라면 Port는 그 컴퓨터에서 실행되는 서비스를 구분하는 번호라고 이해할 수 있다.
예를 들어:
192.168.1.10:22
192.168.1.10:80
192.168.1.10:443
같은 서버라도 Port가 다르다.
대표적인 예:
| Port | 일반적인 서비스 |
|---|---|
| 22 | SSH |
| 53 | DNS |
| 80 | HTTP |
| 443 | HTTPS |
| 3306 | MySQL/MariaDB |
| 5432 | PostgreSQL |
| 6379 | Redis |
예를 들어 Linux 서버에서:
ss -lntp
를 실행하면:
LISTEN 0 128 0.0.0.0:22
LISTEN 0 128 0.0.0.0:80
LISTEN 0 128 0.0.0.0:443
처럼 현재 열려 있는 TCP Port를 확인할 수 있다.
여기서 중요한 것은 Port가 열려 있다는 것과 외부에서 접근할 수 있다는 것은 반드시 같은 의미가 아니라는 점이다.
예를 들어:
Application
|
| LISTEN :8080
v
Server
|
| Firewall BLOCK
v
Network
Application은 정상인데 방화벽 때문에 외부에서는 접속할 수 없다.
네트워크 통신에서는 여러 종류의 전송 방식이 사용된다.
대표적으로:
TCP
UDP
가 있다.
TCP는 연결 지향적인 통신 방식이다.
Client
|
| Connection
v
Server
데이터 전달의 신뢰성과 순서 등을 중요하게 관리한다.
UDP는 TCP보다 단순한 구조로 데이터를 전달한다.
Client
|
| Datagram
v
Server
대표적으로 DNS, 실시간 스트리밍, 일부 게임 등의 환경에서 UDP가 사용될 수 있다.
TCP와 UDP의 자세한 차이는 이후 별도의 글에서 다룬다.
이제 간단한 예를 들어보자.
사용자가 브라우저에서 다음 주소를 입력한다.
https://www.example.com
아주 단순화하면 다음과 같은 과정이 발생한다.
1. DNS 조회
|
v
2. 서버 IP 확인
|
v
3. Routing
|
v
4. TCP 연결
|
v
5. TLS 연결
|
v
6. HTTPS 요청
|
v
7. Web Server 응답
조금 더 자세히 보면:
Browser
|
| DNS Query
v
DNS Server
|
| IP Address
v
Browser
|
| TCP Connection
v
Web Server
|
| TLS Handshake
v
HTTPS
|
| HTTP Request
v
Application
|
| Response
v
Browser
실제 환경에서는 중간에 더 많은 장비가 존재할 수 있다.
Client
|
Router
|
ISP
|
Internet
|
Firewall
|
Load Balancer
|
Reverse Proxy
|
Web Server
|
Application
|
Database
따라서 네트워크 장애를 해결하려면 통신의 전체 경로를 단계별로 나누어서 확인하는 능력이 필요하다.
네트워크 장애가 발생하면 무작정 장비를 확인하면 안 된다.
가능하면 계층적으로 확인하는 것이 좋다.
예를 들어 서버 접속 장애가 발생했다면 다음과 같이 접근할 수 있다.
ip link
NIC가 UP 상태인지 확인한다.
state UP
인지 확인한다.
ip addr
IP가 정상적으로 설정되어 있는지 확인한다.
ip route
기본 Gateway와 목적지 Routing을 확인한다.
ping 192.168.1.1
Gateway까지 통신이 되는지 확인한다.
nslookup example.com
또는:
dig example.com
이름 해석이 정상인지 확인한다.
nc -zv 192.168.1.10 443
또는:
telnet 192.168.1.10 443
목적지 Port에 연결할 수 있는지 확인한다.
systemctl status nginx
또는:
ps -ef | grep nginx
Application이 정상적으로 실행되고 있는지 확인한다.
필요하다면:
tcpdump -i ens160 port 443
를 이용해서 실제 패킷이 들어오고 나가는지 확인할 수 있다.
이 단계까지 내려가면 단순히 "네트워크가 안 된다"가 아니라,
Client
|
| Packet 없음
X
Server
인지,
Client
|
| SYN
v
Server
|
X
| SYN-ACK 없음
인지,
TCP 연결 정상
|
v
HTTP 응답 오류
인지 구분할 수 있다.
이것이 네트워크 장애 분석의 기본이다.
네트워크를 공부할 때 명령어만 외우면 오래 기억하기 어렵다.
중요한 것은 패킷이 어디에서 어디로 이동하는지 생각하는 것이다.
예를 들어 다음 명령어를 외우는 것보다:
ping
traceroute
ss
ip
tcpdump
각 명령어가 어떤 질문에 답하기 위한 것인지 이해하는 것이 중요하다.
| 명령어 | 확인 목적 |
|---|---|
ip addr |
IP/NIC 확인 |
ip link |
NIC 상태 확인 |
ip route |
Routing 확인 |
ping |
ICMP 기반 연결 확인 |
traceroute |
경로 확인 |
ss |
TCP/UDP Socket 확인 |
nslookup |
DNS 확인 |
dig |
DNS 상세 확인 |
nc |
Port 연결 확인 |
tcpdump |
실제 Packet 확인 |
curl |
HTTP/HTTPS 통신 확인 |
예를 들어 웹 서버 장애라면:
ping 192.168.1.10
만으로 끝내면 안 된다.
다음처럼 단계적으로 접근해야 한다.
IP 통신
↓
Routing
↓
TCP Port
↓
TLS
↓
HTTP
↓
Application
현대의 서버는 혼자 동작하지 않는다.
예를 들어 Kubernetes 환경을 생각해보자.
Internet
|
Ingress
|
+------+------+
| |
Service Service
| |
Pod Pod
| |
+------+------+
|
Redis
|
PostgreSQL
여기에서도 네트워크가 핵심이다.
Pod 간 통신
Service 통신
Ingress 통신
DNS
Load Balancing
Network Policy
외부 API 통신
Database 연결
모두 네트워크와 관련되어 있다.
Docker에서도 마찬가지다.
Host
|
+-- Container A
|
+-- Container B
|
+-- Container C
Container Network가 존재하고 Container 간 통신이 발생한다.
즉 Linux 서버를 배우고 Docker와 Kubernetes까지 공부했다면 이제 네트워크를 제대로 이해할 필요가 있다.
시스템 엔지니어가 자주 하는 실수 중 하나는 장애 원인을 너무 빨리 서버 자체에서 찾는 것이다.
예를 들어:
사용자:
"서버 접속이 안 됩니다."
이 말을 들으면 바로 서버에 로그인해서:
top
df -h
free -m
ps -ef
systemctl status
부터 확인할 수 있다.
물론 중요한 점검이다.
하지만 다음과 같은 상황일 수도 있다.
Server
|
| 정상
|
Firewall
|
X 443 차단
|
Client
이 경우 서버의 CPU, Memory, Disk를 아무리 확인해도 원인을 찾을 수 없다.
따라서 시스템 엔지니어는 항상 다음 질문을 해야 한다.
"어디에서 어디로 통신하는가?"
그리고:
출발지
↓
목적지
↓
경로
↓
Port
↓
Protocol
↓
Application
순서로 생각하는 습관을 만들어야 한다.
이번 네트워크 교육에서는 단순한 이론보다 실제 시스템 엔지니어가 장애를 해결할 수 있는 수준을 목표로 한다.
전체 학습 과정은 다음과 같이 진행할 수 있다.
네트워크 기본 개념
↓
OSI 7 Layer
↓
TCP/IP
↓
Ethernet / MAC
↓
IPv4
↓
Subnet / CIDR
↓
Gateway
↓
Routing
↓
ARP
↓
TCP / UDP
↓
TCP 3-Way Handshake
↓
TCP 4-Way Termination
↓
DNS
↓
DHCP
↓
HTTP / HTTPS
↓
TLS
↓
Port / Socket
↓
Firewall
↓
NAT
↓
VLAN
↓
Routing
↓
Packet Analysis
↓
Network Troubleshooting
최종적으로는 다음과 같은 장애를 스스로 분석할 수 있는 것이 목표다.
"서버 접속이 안 됩니다."
↓
NIC 확인
↓
IP 확인
↓
Subnet 확인
↓
Gateway 확인
↓
Routing 확인
↓
ARP 확인
↓
Firewall 확인
↓
Port 확인
↓
TCP 연결 확인
↓
DNS 확인
↓
HTTP 확인
↓
Packet Capture
↓
Application 확인
이런 방식으로 문제를 좁혀 나갈 수 있다면 네트워크 장애 대응 능력이 크게 달라진다.
네트워크는 단순히 컴퓨터와 컴퓨터를 연결하는 기술이 아니다.
시스템 엔지니어 관점에서는 서버와 서버, 사용자와 서버, 애플리케이션과 데이터베이스 등 시스템 간의 통신을 가능하게 만드는 전체 구조라고 이해하는 것이 좋다.
이번 편에서 기억해야 할 핵심은 다음과 같다.
NIC
↓
MAC Address
↓
IP Address
↓
Subnet
↓
Gateway
↓
Routing
↓
Port
↓
TCP / UDP
↓
Application
그리고 장애가 발생했을 때는 무작정 서버부터 확인하는 것이 아니라:
출발지
↓
네트워크
↓
라우팅
↓
방화벽
↓
목적지 Port
↓
Protocol
↓
Application
이라는 흐름으로 생각해야 한다.
특히 시스템 엔지니어에게 가장 중요한 질문은 다음과 같다.
"이 데이터는 어디에서 출발해서 어떤 경로를 거쳐 어디로 전달되는가?"
이 질문에 답할 수 있게 되면 네트워크 문제를 훨씬 체계적으로 분석할 수 있다.