[CS 기초 #5] 네트워크: OSI 7계층과 TCP/IP 완벽 이해
[CS 기초 #5] 네트워크: OSI 7계층과 TCP/IP 완벽 이해
네트워크의 기본 원리를 배워봅시다! 브라우저에 URL을 입력하면 전 세계를 거쳐 데이터가 도착합니다. OSI 7계층과 TCP/IP의 마법을 이해해봅시다.
🎯 이 글을 읽고 나면
- OSI 7계층 모델과 각 계층의 역할을 설명할 수 있습니다
- TCP와 UDP의 차이점을 이해합니다
- HTTP/HTTPS와 DNS의 동작 원리를 알게 됩니다
- IP 주소, 서브넷, 라우팅 개념을 파악합니다
- 네트워크 보안 기초를 학습합니다
📚 사전 지식
- 기본 인터넷 사용: 웹 브라우징, 이메일 정도면 충분합니다
- 컴퓨터 구조: 이전 글: 컴퓨터 구조 참고
- 프로그래밍 경험: 어떤 언어든 괜찮습니다
💡 핵심 개념 미리보기
네트워크는 컴퓨터들이 데이터를 주고받기 위한 체계입니다. OSI 7계층은 네트워크를 7개 논리적 계층으로 나눈 표준 모델이고, TCP/IP는 실제 인터넷에서 사용하는 4계층 프로토콜입니다. 데이터는 패킷으로 나뉘어 라우터를 거쳐 목적지로 전달되며, TCP는 신뢰성 있는 전송을, UDP는 빠른 전송을 담당합니다!
🌐 들어가며: 인터넷은 어떻게 동작하는가?
브라우저에 URL을 입력하면 어떤 일이 일어날까요? 전 세계 컴퓨터가 어떻게 서로 통신할 수 있을까요?
오늘은 인터넷의 기반이 되는 네트워크 프로토콜과 OSI 7계층, TCP/IP 등 네트워크의 핵심 개념을 알아보겠습니다. 이 지식은 웹 개발, 클라우드 아키텍처, 보안의 기초가 됩니다!
📡 네트워크의 기본 개념
네트워크 구성 요소
graph TB
subgraph "네트워크 구성"
PC1[PC] --> Switch[스위치]
PC2[PC] --> Switch
Switch --> Router[라우터]
Router --> Internet[인터넷]
Server[서버] --> Switch2[스위치]
Switch2 --> Router2[라우터]
Router2 --> Internet
end
subgraph "통신 과정"
A[송신자] --> B[패킷 생성]
B --> C[라우팅]
C --> D[전송]
D --> E[수신자]
end
IP 주소와 포트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import socket
import struct
class NetworkBasics:
"""네트워크 기본 개념 시연"""
@staticmethod
def ip_to_binary(ip_address):
"""IP 주소를 이진수로 변환"""
octets = ip_address.split('.')
binary_octets = [format(int(octet), '08b') for octet in octets]
return '.'.join(binary_octets)
@staticmethod
def subnet_mask_info(ip_address, subnet_mask):
"""서브넷 정보 계산"""
# IP를 정수로 변환
ip_int = struct.unpack('>I', socket.inet_aton(ip_address))[0]
mask_int = struct.unpack('>I', socket.inet_aton(subnet_mask))[0]
# 네트워크 주소
network = ip_int & mask_int
network_addr = socket.inet_ntoa(struct.pack('>I', network))
# 브로드캐스트 주소
broadcast = network | ~mask_int & 0xFFFFFFFF
broadcast_addr = socket.inet_ntoa(struct.pack('>I', broadcast))
# 호스트 수
host_bits = 32 - bin(mask_int).count('1')
max_hosts = 2 ** host_bits - 2 # 네트워크와 브로드캐스트 제외
return {
'network': network_addr,
'broadcast': broadcast_addr,
'max_hosts': max_hosts
}
@staticmethod
def port_categories():
"""포트 번호 분류"""
return {
'Well-known Ports': (0, 1023),
'Registered Ports': (1024, 49151),
'Dynamic/Private Ports': (49152, 65535),
'Common Services': {
'HTTP': 80,
'HTTPS': 443,
'FTP': 21,
'SSH': 22,
'SMTP': 25,
'DNS': 53,
'MySQL': 3306,
'PostgreSQL': 5432
}
}
# 네트워크 기본 개념 테스트
nb = NetworkBasics()
# IP 주소 이진 변환
ip = "192.168.1.100"
print(f"IP 주소: {ip}")
print(f"이진수: {nb.ip_to_binary(ip)}")
# 서브넷 정보
subnet_info = nb.subnet_mask_info("192.168.1.100", "255.255.255.0")
print(f"\n서브넷 정보:")
print(f"네트워크 주소: {subnet_info['network']}")
print(f"브로드캐스트 주소: {subnet_info['broadcast']}")
print(f"최대 호스트 수: {subnet_info['max_hosts']}")
# 포트 정보
port_info = nb.port_categories()
print(f"\n주요 서비스 포트:")
for service, port in port_info['Common Services'].items():
print(f" {service}: {port}")
🏗️ OSI 7계층 모델
OSI(Open Systems Interconnection) 모델은 네트워크 통신을 7개 계층으로 나눈 표준 모델입니다.
graph TD
subgraph "OSI 7계층"
L7[7. Application<br/>응용 계층<br/>HTTP, FTP, SMTP]
L6[6. Presentation<br/>표현 계층<br/>암호화, 압축]
L5[5. Session<br/>세션 계층<br/>연결 관리]
L4[4. Transport<br/>전송 계층<br/>TCP, UDP]
L3[3. Network<br/>네트워크 계층<br/>IP, 라우팅]
L2[2. Data Link<br/>데이터링크 계층<br/>이더넷, 스위치]
L1[1. Physical<br/>물리 계층<br/>케이블, 허브]
L7 --> L6
L6 --> L5
L5 --> L4
L4 --> L3
L3 --> L2
L2 --> L1
end
subgraph "데이터 캡슐화"
Data[데이터]
Segment[세그먼트]
Packet[패킷]
Frame[프레임]
Bits[비트]
Data --> Segment
Segment --> Packet
Packet --> Frame
Frame --> Bits
end
각 계층의 역할과 프로토콜
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class OSIModel:
"""OSI 7계층 모델 시뮬레이션"""
def __init__(self):
self.layers = {
7: {'name': 'Application', 'protocols': ['HTTP', 'HTTPS', 'FTP', 'SMTP', 'DNS']},
6: {'name': 'Presentation', 'functions': ['암호화', '압축', '인코딩']},
5: {'name': 'Session', 'functions': ['세션 설정', '유지', '종료']},
4: {'name': 'Transport', 'protocols': ['TCP', 'UDP']},
3: {'name': 'Network', 'protocols': ['IP', 'ICMP', 'ARP']},
2: {'name': 'Data Link', 'protocols': ['Ethernet', 'PPP', 'Wi-Fi']},
1: {'name': 'Physical', 'components': ['케이블', '허브', '리피터']}
}
def encapsulation(self, data):
"""데이터 캡슐화 과정"""
encapsulated = data
headers = []
# 각 계층을 거치며 헤더 추가
for layer in range(7, 0, -1):
layer_name = self.layers[layer]['name']
if layer == 7: # Application
headers.append(f"[HTTP Header]")
elif layer == 4: # Transport
headers.append(f"[TCP Header: Port, Seq#]")
elif layer == 3: # Network
headers.append(f"[IP Header: Src IP, Dst IP]")
elif layer == 2: # Data Link
headers.append(f"[Ethernet Header: MAC]")
if headers and layer <= 4:
encapsulated = f"{headers[-1]} {encapsulated}"
print(f"Layer {layer} ({layer_name}): {encapsulated}")
return encapsulated
def decapsulation(self, frame):
"""데이터 디캡슐화 과정"""
print("\n디캡슐화 과정:")
layers_data = [
"[Ethernet Header: MAC]",
"[IP Header: Src IP, Dst IP]",
"[TCP Header: Port, Seq#]",
"[HTTP Header]"
]
current = frame
for layer in range(1, 8):
layer_name = self.layers[layer]['name']
if layer <= 4 and layers_data:
header = layers_data.pop(0)
current = current.replace(header + " ", "")
print(f"Layer {layer} ({layer_name}): {current}")
return current
# OSI 모델 시연
osi = OSIModel()
print("데이터 캡슐화 과정:")
print("=" * 60)
original_data = "Hello, World!"
frame = osi.encapsulation(original_data)
print("\n" + "=" * 60)
osi.decapsulation(frame)
🔗 TCP/IP 프로토콜 스택
TCP/IP는 인터넷의 기반이 되는 프로토콜 스위트입니다.
TCP vs UDP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import time
import random
class TCPSimulator:
"""TCP 통신 시뮬레이션"""
def __init__(self):
self.seq_num = 0
self.ack_num = 0
self.window_size = 5
self.congestion_window = 1
def three_way_handshake(self):
"""TCP 3-way handshake"""
print("TCP 3-Way Handshake:")
print("-" * 40)
# SYN
self.seq_num = random.randint(1000, 9999)
print(f"1. Client → Server: SYN (SEQ={self.seq_num})")
# SYN-ACK
server_seq = random.randint(1000, 9999)
self.ack_num = self.seq_num + 1
print(f"2. Server → Client: SYN-ACK (SEQ={server_seq}, ACK={self.ack_num})")
# ACK
self.seq_num = self.ack_num
self.ack_num = server_seq + 1
print(f"3. Client → Server: ACK (SEQ={self.seq_num}, ACK={self.ack_num})")
print("연결 설정 완료!\n")
return True
def send_with_flow_control(self, data_segments):
"""흐름 제어를 포함한 데이터 전송"""
print("TCP 데이터 전송 (흐름 제어):")
print("-" * 40)
for i, segment in enumerate(data_segments):
if i < self.window_size:
print(f"전송: Segment {i+1} (SEQ={self.seq_num + i})")
time.sleep(0.1)
else:
print(f"대기: Window full (size={self.window_size})")
print("ACK 수신 후 계속...")
self.window_size += 1 # 간단한 윈도우 증가
print("모든 세그먼트 전송 완료\n")
def congestion_control(self):
"""혼잡 제어 (Slow Start)"""
print("TCP 혼잡 제어 (Slow Start):")
print("-" * 40)
threshold = 8
max_window = 16
while self.congestion_window < max_window:
print(f"CWND: {self.congestion_window} segments")
if self.congestion_window < threshold:
# Slow Start: 지수적 증가
self.congestion_window *= 2
print(" → Slow Start: 윈도우 2배 증가")
else:
# Congestion Avoidance: 선형 증가
self.congestion_window += 1
print(" → Congestion Avoidance: 윈도우 +1")
# 패킷 손실 시뮬레이션
if random.random() < 0.1: # 10% 확률로 손실
print(" ⚠️ 패킷 손실 감지!")
threshold = self.congestion_window // 2
self.congestion_window = 1
print(f" → Threshold={threshold}, CWND=1로 리셋")
time.sleep(0.2)
if self.congestion_window >= max_window:
break
class UDPSimulator:
"""UDP 통신 시뮬레이션"""
def send_datagram(self, data):
"""UDP 데이터그램 전송"""
print("UDP 데이터그램 전송:")
print("-" * 40)
print(f"전송: {data}")
print("(연결 설정 없음, ACK 없음)")
print("전송 완료 (신뢰성 보장 X)\n")
# 패킷 손실 시뮬레이션
if random.random() < 0.2: # 20% 손실률
return None
return data
# TCP 시뮬레이션
tcp = TCPSimulator()
tcp.three_way_handshake()
tcp.send_with_flow_control(['Data1', 'Data2', 'Data3', 'Data4', 'Data5', 'Data6'])
tcp.congestion_control()
# UDP 시뮬레이션
print("\n" + "=" * 60)
udp = UDPSimulator()
for i in range(3):
result = udp.send_datagram(f"UDP Packet {i+1}")
if result:
print(f"수신 확인: {result}")
else:
print("⚠️ 패킷 손실!")
TCP/IP 계층별 헤더 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
class PacketAnalyzer:
"""패킷 분석기"""
def ethernet_header(self, src_mac, dst_mac):
"""이더넷 헤더 (14 bytes)"""
return {
'dst_mac': dst_mac, # 6 bytes
'src_mac': src_mac, # 6 bytes
'type': '0x0800 (IPv4)' # 2 bytes
}
def ip_header(self, src_ip, dst_ip):
"""IP 헤더 (20 bytes minimum)"""
return {
'version': 4, # 4 bits
'header_length': 20, # 4 bits
'tos': 0, # 1 byte
'total_length': 40, # 2 bytes
'identification': 12345, # 2 bytes
'flags': '010', # 3 bits
'fragment_offset': 0, # 13 bits
'ttl': 64, # 1 byte
'protocol': 6, # 1 byte (6=TCP)
'checksum': '0x1234', # 2 bytes
'src_ip': src_ip, # 4 bytes
'dst_ip': dst_ip # 4 bytes
}
def tcp_header(self, src_port, dst_port, seq_num, ack_num):
"""TCP 헤더 (20 bytes minimum)"""
return {
'src_port': src_port, # 2 bytes
'dst_port': dst_port, # 2 bytes
'seq_num': seq_num, # 4 bytes
'ack_num': ack_num, # 4 bytes
'data_offset': 5, # 4 bits (5 * 4 = 20 bytes)
'flags': { # 9 bits total
'NS': 0, 'CWR': 0, 'ECE': 0,
'URG': 0, 'ACK': 1, 'PSH': 0,
'RST': 0, 'SYN': 0, 'FIN': 0
},
'window': 65535, # 2 bytes
'checksum': '0x5678', # 2 bytes
'urgent_pointer': 0 # 2 bytes
}
def analyze_packet(self):
"""패킷 분석"""
print("패킷 구조 분석:")
print("=" * 60)
# 헤더 생성
eth = self.ethernet_header("AA:BB:CC:DD:EE:FF", "11:22:33:44:55:66")
ip = self.ip_header("192.168.1.100", "93.184.216.34")
tcp = self.tcp_header(54321, 80, 1000, 2000)
# 이더넷 헤더
print("이더넷 헤더 (Layer 2):")
for key, value in eth.items():
print(f" {key}: {value}")
# IP 헤더
print("\nIP 헤더 (Layer 3):")
for key, value in ip.items():
if key != 'flags':
print(f" {key}: {value}")
# TCP 헤더
print("\nTCP 헤더 (Layer 4):")
for key, value in tcp.items():
if key == 'flags':
flags_str = ', '.join([f for f, v in value.items() if v == 1])
print(f" flags: {flags_str if flags_str else 'None'}")
else:
print(f" {key}: {value}")
# 총 헤더 크기
total_header_size = 14 + 20 + 20 # Ethernet + IP + TCP
print(f"\n총 헤더 크기: {total_header_size} bytes")
# 패킷 분석
analyzer = PacketAnalyzer()
analyzer.analyze_packet()
🌍 응용 계층 프로토콜
HTTP/HTTPS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class HTTPSimulator:
"""HTTP 프로토콜 시뮬레이션"""
def http_request(self, method, url, headers=None):
"""HTTP 요청 생성"""
request = f"{method} {url} HTTP/1.1\r\n"
default_headers = {
'Host': 'www.example.com',
'User-Agent': 'Mozilla/5.0',
'Accept': 'text/html,application/json',
'Accept-Language': 'ko-KR,ko;q=0.9,en;q=0.8',
'Connection': 'keep-alive'
}
if headers:
default_headers.update(headers)
for key, value in default_headers.items():
request += f"{key}: {value}\r\n"
request += "\r\n" # 헤더 끝
return request
def http_response(self, status_code, status_text, body):
"""HTTP 응답 생성"""
response = f"HTTP/1.1 {status_code} {status_text}\r\n"
headers = {
'Date': 'Sat, 24 Aug 2024 10:00:00 GMT',
'Server': 'Apache/2.4.41',
'Content-Type': 'text/html; charset=UTF-8',
'Content-Length': len(body),
'Connection': 'keep-alive'
}
for key, value in headers.items():
response += f"{key}: {value}\r\n"
response += "\r\n" # 헤더 끝
response += body
return response
def status_codes(self):
"""HTTP 상태 코드"""
return {
'1xx': 'Informational',
'100': 'Continue',
'2xx': 'Success',
'200': 'OK',
'201': 'Created',
'204': 'No Content',
'3xx': 'Redirection',
'301': 'Moved Permanently',
'302': 'Found',
'304': 'Not Modified',
'4xx': 'Client Error',
'400': 'Bad Request',
'401': 'Unauthorized',
'403': 'Forbidden',
'404': 'Not Found',
'5xx': 'Server Error',
'500': 'Internal Server Error',
'502': 'Bad Gateway',
'503': 'Service Unavailable'
}
# HTTP 시뮬레이션
http = HTTPSimulator()
# HTTP 요청
print("HTTP 요청:")
print("-" * 60)
request = http.http_request('GET', '/api/users/123')
print(request)
# HTTP 응답
print("HTTP 응답:")
print("-" * 60)
response = http.http_response(200, 'OK', '{"id": 123, "name": "John Doe"}')
print(response)
# 상태 코드
print("\nHTTP 상태 코드:")
print("-" * 60)
codes = http.status_codes()
for code, meaning in codes.items():
if 'xx' not in code:
print(f" {code}: {meaning}")
DNS (Domain Name System)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import socket
class DNSSimulator:
"""DNS 시뮬레이션"""
def __init__(self):
self.dns_cache = {}
self.root_servers = ['a.root-servers.net', 'b.root-servers.net']
self.dns_records = {
'www.example.com': {
'A': '93.184.216.34',
'AAAA': '2606:2800:220:1:248:1893:25c8:1946',
'MX': 'mail.example.com',
'TXT': 'v=spf1 include:_spf.example.com ~all'
}
}
def dns_lookup(self, domain):
"""DNS 조회 과정"""
print(f"DNS 조회: {domain}")
print("-" * 40)
# 1. 로컬 캐시 확인
if domain in self.dns_cache:
print(f"1. 캐시 히트: {self.dns_cache[domain]}")
return self.dns_cache[domain]
print("1. 캐시 미스")
# 2. 재귀적 조회 시뮬레이션
print("2. DNS 서버에 재귀적 조회 요청")
print(f" → Root 서버: {self.root_servers[0]}")
print(" → TLD 서버: .com")
print(f" → 권한 서버: ns1.example.com")
# 3. 응답
if domain in self.dns_records:
ip = self.dns_records[domain]['A']
print(f"3. 응답 수신: {ip}")
# 캐시 저장
self.dns_cache[domain] = ip
print(f"4. 캐시 저장 (TTL: 3600)")
return ip
else:
print("3. NXDOMAIN (도메인 없음)")
return None
def reverse_dns(self, ip_address):
"""역방향 DNS 조회"""
print(f"역방향 DNS 조회: {ip_address}")
# 실제 역방향 조회 시뮬레이션
for domain, records in self.dns_records.items():
if records['A'] == ip_address:
print(f" → {ip_address} = {domain}")
return domain
print(f" → PTR 레코드 없음")
return None
# DNS 시뮬레이션
dns = DNSSimulator()
# 정방향 조회
ip = dns.dns_lookup('www.example.com')
print()
# 캐시된 조회
ip = dns.dns_lookup('www.example.com')
print()
# 역방향 조회
domain = dns.reverse_dns('93.184.216.34')
🔒 네트워크 보안
방화벽과 NAT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
class NetworkSecurity:
"""네트워크 보안 시뮬레이션"""
def __init__(self):
self.firewall_rules = []
self.nat_table = {}
def add_firewall_rule(self, action, protocol, src_ip, dst_ip, dst_port):
"""방화벽 규칙 추가"""
rule = {
'action': action, # ALLOW or DENY
'protocol': protocol,
'src_ip': src_ip,
'dst_ip': dst_ip,
'dst_port': dst_port
}
self.firewall_rules.append(rule)
def check_packet(self, protocol, src_ip, dst_ip, dst_port):
"""패킷 필터링"""
for rule in self.firewall_rules:
if (rule['protocol'] == protocol or rule['protocol'] == 'ANY') and \
(rule['src_ip'] == src_ip or rule['src_ip'] == 'ANY') and \
(rule['dst_ip'] == dst_ip or rule['dst_ip'] == 'ANY') and \
(rule['dst_port'] == dst_port or rule['dst_port'] == 'ANY'):
return rule['action']
return 'DENY' # 기본 정책
def nat_translation(self, private_ip, private_port):
"""NAT 변환"""
# PAT (Port Address Translation)
public_ip = '203.0.113.1'
public_port = 50000 + len(self.nat_table)
# NAT 테이블에 매핑 저장
key = f"{private_ip}:{private_port}"
self.nat_table[key] = f"{public_ip}:{public_port}"
return public_ip, public_port
def setup_dmz(self):
"""DMZ 설정"""
print("DMZ (Demilitarized Zone) 구성:")
print("-" * 40)
zones = {
'External': '0.0.0.0/0',
'DMZ': '192.168.100.0/24',
'Internal': '192.168.1.0/24'
}
rules = [
"External → DMZ: HTTP(80), HTTPS(443) 허용",
"DMZ → External: 모든 트래픽 허용",
"Internal → DMZ: 모든 트래픽 허용",
"DMZ → Internal: 데이터베이스(3306) 제한적 허용",
"External → Internal: 모든 트래픽 차단"
]
for zone, subnet in zones.items():
print(f"{zone}: {subnet}")
print("\n방화벽 규칙:")
for rule in rules:
print(f" • {rule}")
# 네트워크 보안 시뮬레이션
security = NetworkSecurity()
# 방화벽 규칙 설정
security.add_firewall_rule('ALLOW', 'TCP', 'ANY', 'ANY', 80)
security.add_firewall_rule('ALLOW', 'TCP', 'ANY', 'ANY', 443)
security.add_firewall_rule('DENY', 'TCP', 'ANY', 'ANY', 23) # Telnet 차단
# 패킷 검사
print("방화벽 패킷 필터링:")
print("-" * 40)
packets = [
('TCP', '192.168.1.100', '93.184.216.34', 80),
('TCP', '192.168.1.100', '93.184.216.34', 23),
('TCP', '192.168.1.100', '93.184.216.34', 443)
]
for protocol, src, dst, port in packets:
result = security.check_packet(protocol, src, dst, port)
print(f"{src} → {dst}:{port} ({protocol}): {result}")
print()
# NAT 변환
print("NAT 변환:")
print("-" * 40)
private_ip = '192.168.1.100'
private_port = 12345
public_ip, public_port = security.nat_translation(private_ip, private_port)
print(f"내부: {private_ip}:{private_port} → 외부: {public_ip}:{public_port}")
print()
security.setup_dmz()
🚀 웹 요청의 전체 과정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
def web_request_journey():
"""웹 요청의 전체 여정"""
steps = [
{
'step': 1,
'action': 'URL 입력',
'detail': '사용자가 브라우저에 www.example.com 입력'
},
{
'step': 2,
'action': 'DNS 조회',
'detail': 'DNS 서버에서 도메인의 IP 주소 조회 (93.184.216.34)'
},
{
'step': 3,
'action': 'TCP 연결',
'detail': '3-way handshake로 서버와 TCP 연결 설정'
},
{
'step': 4,
'action': 'TLS 핸드셰이크',
'detail': 'HTTPS의 경우 TLS 암호화 연결 설정'
},
{
'step': 5,
'action': 'HTTP 요청',
'detail': 'GET / HTTP/1.1 요청 전송'
},
{
'step': 6,
'action': '서버 처리',
'detail': '서버가 요청을 처리하고 HTML 생성'
},
{
'step': 7,
'action': 'HTTP 응답',
'detail': '200 OK와 함께 HTML 콘텐츠 반환'
},
{
'step': 8,
'action': '브라우저 렌더링',
'detail': 'HTML 파싱, CSS 적용, JavaScript 실행'
},
{
'step': 9,
'action': '추가 리소스',
'detail': '이미지, CSS, JS 파일 추가 요청'
},
{
'step': 10,
'action': '페이지 완성',
'detail': '모든 리소스 로드 후 페이지 표시 완료'
}
]
print("웹 페이지 요청의 전체 과정:")
print("=" * 60)
for item in steps:
print(f"\nStep {item['step']}: {item['action']}")
print(f" → {item['detail']}")
# 각 단계별 프로토콜
if item['step'] == 2:
print(" 프로토콜: DNS (UDP port 53)")
elif item['step'] == 3:
print(" 프로토콜: TCP")
elif item['step'] == 4:
print(" 프로토콜: TLS 1.3")
elif item['step'] in [5, 7]:
print(" 프로토콜: HTTP/HTTPS")
web_request_journey()
🎯 핵심 정리
꼭 기억해야 할 5가지
- OSI 7계층은 네트워크 통신을 계층별로 추상화
- TCP는 신뢰성, UDP는 속도를 우선시
- IP 주소는 네트워크 식별, 포트는 프로세스 식별
- DNS는 도메인을 IP 주소로 변환
- HTTP는 웹의 기반 프로토콜
실무 활용 팁
- 네트워크 문제 해결 시 계층별로 접근
- Wireshark 같은 패킷 분석 도구 활용
- 방화벽 규칙은 최소 권한 원칙 적용
- HTTPS 사용으로 보안 강화
📚 추가 학습 자료
추천 도서
- “Computer Networking: A Top-Down Approach” - Kurose & Ross
- “TCP/IP Illustrated” - Stevens
- “HTTP: The Definitive Guide”
실습 프로젝트
- 간단한 HTTP 서버 구현
- 패킷 스니퍼 만들기
- 채팅 프로그램 (TCP/UDP)
🚀 다음 시간 예고
다음 포스트부터는 자료구조편이 시작됩니다! 배열과 연결 리스트부터 시작하여 스택, 큐, 트리, 그래프까지 다룰 예정입니다.
✅ 이 글에서 배운 것
스스로 확인해보세요! 각 항목을 설명할 수 있다면 체크하세요.
개념 이해
- OSI 7계층 모델의 각 계층 역할
- TCP/IP 4계층 구조
- IP 주소와 서브넷 마스크의 개념
- TCP와 UDP의 차이점
- HTTP와 HTTPS의 차이
실용적 이해
- DNS가 도메인을 IP로 변환하는 과정
- 3-way handshake를 통한 TCP 연결 수립
- 라우팅과 패킷 전송 원리
- 네트워크 보안의 기초 (암호화, 인증)
- 포트 번호와 소켓의 역할
실습 완료
- IP 주소 변환 예제를 실행했다
- 패킷 구조 시뮬레이션을 이해했다
- HTTP 요청/응답 예제를 테스트했다
- DNS 조회 과정을 확인했다
📌 시리즈 네비게이션
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.
