Skip to content

네트워크 — TCP/IP와 OSI 7계층

개요 — 왜 네트워크 계층 모델을 알아야 하는가

Section titled “개요 — 왜 네트워크 계층 모델을 알아야 하는가”

게임 서버 개발자라면 클라이언트와 서버 간 데이터가 어떻게 전달되는지 이해해야 합니다.

  • 패킷 손실이 발생했을 때 어느 계층에서 재전송이 일어나는가
  • 실시간 게임에서 TCP보다 UDP가 유리한 이유는 무엇인가
  • 3-way handshake 비용이 게임 접속 지연에 미치는 영향
  • 방화벽, 프록시, NAT가 어느 계층에서 동작하는가

OSI 7계층과 TCP/IP 모델은 이러한 질문에 구조적으로 답할 수 있게 해주는 개념적 틀입니다.


OSI(Open Systems Interconnection) 모델은 네트워크 통신을 7개의 계층으로 추상화한 참조 모델입니다. 각 계층은 독립적인 역할을 가지며, 하위 계층의 서비스를 사용해 상위 계층에 서비스를 제공합니다.

계층이름역할대표 프로토콜/장비
7응용(Application)사용자 애플리케이션에 네트워크 서비스 제공HTTP, FTP, SMTP, DNS
6표현(Presentation)데이터 형식 변환, 암호화/복호화, 압축SSL/TLS, JPEG, ASCII
5세션(Session)통신 세션 수립·유지·종료 관리NetBIOS, RPC
4전송(Transport)종단 간 신뢰성 있는 데이터 전달, 흐름 제어TCP, UDP
3네트워크(Network)논리적 주소(IP) 기반 경로 결정(라우팅)IP, ICMP, 라우터
2데이터링크(Data Link)물리적 주소(MAC) 기반 프레임 전송, 오류 감지Ethernet, Wi-Fi, 스위치
1물리(Physical)비트 신호를 물리 매체로 전송케이블, 허브, NIC

송신 측에서는 상위 계층에서 하위 계층으로 내려갈수록 헤더(header)가 추가되고, 수신 측에서는 역순으로 헤더를 제거합니다.

[응용 계층] 데이터
[전송 계층] TCP 헤더 + 데이터 = 세그먼트(Segment)
[네트워크 계층] IP 헤더 + 세그먼트 = 패킷(Packet)
[데이터링크 계층] MAC 헤더 + 패킷 + FCS = 프레임(Frame)
[물리 계층] 비트 스트림으로 전송

실제 인터넷에서 사용하는 모델은 OSI 7계층보다 단순화된 TCP/IP 4계층입니다. OSI 모델은 개념적 참조 모델이고, TCP/IP는 실제 구현 모델입니다.

TCP/IP 계층대응하는 OSI 계층역할
응용(Application)5, 6, 7계층애플리케이션 프로토콜
전송(Transport)4계층TCP, UDP
인터넷(Internet)3계층IP 라우팅
네트워크 접근(Network Access)1, 2계층물리적 전송

게임 서버 설계에서 가장 중요한 선택 중 하나는 TCP를 사용할지 UDP를 사용할지입니다.

특징:

  • 연결 지향(Connection-oriented): 통신 전 3-way handshake로 연결 수립
  • 신뢰성 보장: 패킷 손실 시 자동 재전송
  • 순서 보장: 패킷 순서가 보장됨
  • 흐름 제어·혼잡 제어: 수신 측 처리 속도에 맞춰 전송량 조절

단점:

  • 연결 수립 오버헤드 (3-way handshake)
  • 재전송으로 인한 지연(Head-of-Line Blocking)
  • 상태 유지 비용

적합한 게임 데이터:

  • 채팅 메시지 (순서, 신뢰성 필요)
  • 로그인/인증 데이터
  • 아이템 구매, 퀘스트 완료 등 중요 게임 이벤트
  • 파일 다운로드 (패치, 에셋)

특징:

  • 비연결 지향(Connectionless): 연결 수립 없이 즉시 전송
  • 신뢰성 미보장: 패킷 손실·중복·순서 오류 가능
  • 낮은 오버헤드: 헤더 크기 8바이트 (TCP는 최소 20바이트)
  • 빠른 전송: 재전송 없음

적합한 게임 데이터:

  • 플레이어 위치, 회전 값 (최신 값이 중요, 이전 값 손실 무방)
  • 총알 발사, 이펙트 이벤트 (약간의 손실 허용)
  • 음성 채팅 (지연이 손실보다 나쁨)
  • 실시간 경쟁 게임의 입력 데이터
TCP 헤더 구조 (최소 20바이트):
[Source Port 16bit][Destination Port 16bit]
[Sequence Number 32bit]
[Acknowledgment Number 32bit]
[Data Offset][Flags][Window Size]
[Checksum][Urgent Pointer]
UDP 헤더 구조 (8바이트):
[Source Port 16bit][Destination Port 16bit]
[Length 16bit][Checksum 16bit]

TCP 연결 수립 과정인 3-way handshake는 클라이언트와 서버가 서로의 시퀀스 번호를 동기화하는 과정입니다.

클라이언트 서버
| |
|----[SYN, seq=x]--------->| 1단계: 클라이언트가 연결 요청
| |
|<---[SYN+ACK, seq=y, | 2단계: 서버가 요청 수락 및 자신의 SYN 전송
| ack=x+1]-------------|
| |
|----[ACK, ack=y+1]------->| 3단계: 클라이언트가 서버의 SYN 확인
| |
| [연결 수립 완료] |
| |
|<====[데이터 전송]========>|
클라이언트 서버
| |
|----[FIN]---------------->| 1단계: 클라이언트 종료 요청
|<---[ACK]-----------------| 2단계: 서버 확인
|<---[FIN]-----------------| 3단계: 서버 종료 요청
|----[ACK]---------------->| 4단계: 클라이언트 확인
| |
| [TIME_WAIT 상태 대기] | 클라이언트는 2MSL 동안 대기

TIME_WAIT 상태: 마지막 ACK가 서버에 도달하지 못했을 경우를 대비해 일정 시간(2 * MSL, 보통 60~120초) 대기합니다. 게임 서버에서 짧은 시간에 많은 연결/해제가 반복되면 TIME_WAIT 소켓이 포트를 점유해 문제가 될 수 있습니다.


IP 주소: 네트워크 상의 호스트를 식별 (3계층)
포트 번호: 같은 호스트의 어떤 프로세스/서비스인지 식별 (4계층)
예시: 192.168.1.100:7777
└─────┬─────┘ └┬─┘
IP 주소 포트

잘 알려진 포트 (Well-Known Ports):

  • 80: HTTP
  • 443: HTTPS
  • 22: SSH
  • 53: DNS
  • 게임 서버: 보통 1024~65535 범위의 사용자 지정 포트 사용

도메인 이름을 IP 주소로 변환하는 시스템입니다. UDP 53번 포트를 사용합니다.

game.example.com -> DNS 쿼리 -> 203.0.113.42

게임 서버에서는 서버 IP가 변경되어도 도메인만 유지하면 클라이언트 업데이트 없이 연결 가능합니다.

사설 IP 주소를 공인 IP 주소로 변환하는 기술입니다. P2P 게임에서 NAT Traversal(홀 펀칭)이 필요한 이유입니다.

[클라이언트 사설 IP: 192.168.1.100]
|
[NAT 라우터] <-- 공인 IP: 203.0.113.1
|
[인터넷]
|
[게임 서버]

// 실시간 위치 동기화: UDP 사용
// 패킷 손실 허용, 최신 상태만 중요
void SendPlayerPosition(const FVector& Position)
{
UDPPacket Packet;
Packet.Type = EPacketType::PlayerPosition;
Packet.PlayerId = LocalPlayerId;
Packet.Position = Position;
Packet.Timestamp = GetServerTime();
UDPSocket->Send(Packet); // 손실되어도 다음 프레임에 재전송
}
// 아이템 획득: TCP 사용
// 반드시 서버에서 확인 필요
void SendItemPickup(int32 ItemId)
{
TCPPacket Packet;
Packet.Type = EPacketType::ItemPickup;
Packet.ItemId = ItemId;
TCPSocket->Send(Packet); // ACK 받을 때까지 재전송 보장
}
RTT = 패킷을 보내고 응답을 받을 때까지의 시간
게임에서의 레이턴시 분류:
- < 50ms : 매우 좋음 (경쟁 게임 가능)
- 50~100ms: 양호 (일반 온라인 게임)
- 100~200ms: 보통 (캐주얼 게임)
- > 200ms : 나쁨 (실시간 반응 불가)
// Ping 측정 방식
클라이언트 -> [Ping 패킷, timestamp=T1] -> 서버
클라이언트 <- [Pong 패킷, timestamp=T1] <- 서버
RTT = 현재시간 - T1
// 공통 패킷 헤더
#pragma pack(push, 1) // 구조체 패딩 제거
struct PacketHeader
{
uint16_t PacketSize; // 전체 패킷 크기
uint16_t PacketType; // 패킷 종류 식별자
uint32_t Sequence; // 시퀀스 번호 (UDP 순서 보장에 활용)
uint32_t Timestamp; // 타임스탬프 (밀리초)
};
#pragma pack(pop)
// 위치 동기화 패킷
struct PositionPacket
{
PacketHeader Header;
uint32_t PlayerId;
float X, Y, Z; // 위치
float Yaw, Pitch; // 회전
float VelX, VelY, VelZ; // 속도 (예측에 활용)
};

OSI 7계층이란? 네트워크 통신을 7개의 추상화 계층으로 나눈 참조 모델로, 각 계층은 독립적인 역할을 수행하며 하위 계층 서비스를 사용해 상위 계층에 서비스를 제공합니다.

TCP와 UDP의 차이는? TCP는 연결 지향, 신뢰성 보장, 순서 보장을 제공하지만 오버헤드가 크고, UDP는 비연결 지향으로 신뢰성은 낮지만 빠른 전송이 가능합니다.

3-way handshake란? TCP 연결 수립 과정으로, SYN → SYN+ACK → ACK의 3단계를 통해 양측의 시퀀스 번호를 동기화하고 신뢰성 있는 연결을 수립합니다.

게임에서 UDP를 사용하는 이유는? 실시간 게임에서 위치 동기화 같은 데이터는 최신 값이 중요하고 약간의 손실은 허용됩니다. TCP의 재전송으로 인한 Head-of-Line Blocking은 오히려 게임 경험을 저하시킬 수 있어 UDP가 선호됩니다.