TCP/IP 체크섬(Checksum) 내부 동작 원리

2026. 3. 23. 20:57·기술 학습

개요

TCP/IP 프로토콜 스택에서 체크섬(Checksum) 은 데이터가 전송 과정에서 손상되지 않았는지 검증하는 오류 검출 메커니즘이다.

오늘날 인터넷의 모든 패킷은 이 체크섬을 거쳐 전송된다.

 

체크섬은 TCP/IP 스택의 여러 계층에서 동작하며, 각 계층의 체크섬은 보호 범위와 목적이 다르다.

이번 정리에서는 체크섬의 내부 동작 원리를 세 계층으로 나누어 정리한다.

  • L2 데이터 링크 계층의 Ethernet CRC (32bit)
  • L3 네트워크 계층의 IP Header Checksum (16bit)
  • L4 전송 계층의 TCP/UDP Checksum (16bit)

1. 기반 원리 - 1의 보수 연산과 설계 배경

checksum에 대해 들어가기 전에 bit 세계에서 역수를 취하기 위한 보수 방법 2가지에 대해 알아보자.

1의 보수 vs 2의 보수

현대 컴퓨터는 음수를 표현할 때 2의 보수 방식을 사용한다.

  • 2의 보수는 모든 비트를 반전한 후 1을 더하는 방식으로, 0의 표현이 하나뿐이라는 장점이 있다.
    • 0000 -> 반전 -> 1111 -> +1 -> 1_0000 -> carry 버림 -> 0000
  • 반면에! 1의 보수는 모든 비트를 반전하는 방식이다. 단, +0(0000)과 -0(1111)이라는 두 개의 영(zero) 이 존재한다.

4비트 기준으로 비교하면 다음과 같다.

값 1의 보수 2의 보수 차이점
+5 0101 0101 동일
-5 1010 1011 1 차이
+0 0000 0000 동일
-0 1111 0000 1의 보수: 2개의 zero

TCP/IP 체크섬이 1의 보수를 선택한 이유

1의 보수 덧셈에는 핵심 속성 네 가지가 존재한다.

 

(P1) 교환법칙(Commutative)

  • 더하는 순서가 결과에 영향을 미치지 않는다. -> 패킷 내 16비트 워드를 어떤 순서로 합산해도 동일한 체크섬을 얻는다.

(P2) 항등원 존재

  • 1의 보수에는 +0과 -0 두 개의 항등원이 있다. -> 송신 측이 체크섬 필드에 0을 넣고 계산할 수 있다.
  • 덧셈에 항등원이 없다면 초기값을 설정하는것부터 어려워진다.
  • 초기값이 합산 결과에 영향을 주면 안되는데 항등원이 아닌 초기값이라면 영향을 주게 된다.

(P3) 역원 존재

  • 어떤 수에 대해 더하면 0이 되는 수가 존재한다. -> 수신 측이 전체 합산 후 결과가 0인지만 확인하면 검증이 완료된다.
  • 수정되지 않음을 증명하는 수에 대한 역원을 갖고 있다면 더해서 0이 되는지 확인하면 된다.

(P4) 결합법칙(Associative)

  • 어떤 순서로 묶어 더해도 결과가 같다. -> 체크섬 필드가 패킷 어디에 위치하든 문제없이 계산할 수 있고, 병렬 처리도 가능하다.

End-Around Carry와 Endian 독립성

1의 보수 덧셈에서 가장 특별한 점은 end-around carry 이다.

16비트 덧셈 결과가 17비트로 넘치면(carry 발생)

- 2의 보수에서는 초과된 비트를 버리지만,
- 1의 보수에서는 그 1을 최하위 비트에 다시 더해준다.

  FFFF
+ 0001
------
 10000  ← 17비트, carry 발생

2의 보수: carry 버림 → 0000 (0 + 1 = 0)?
1의 보수: carry 다시 더함 → 0000 + 1 = 0001 (0 + 1 = 1)

이 특성이 실용적으로 중요한 이유는 Endian 독립성 때문이다.

1980년대 인터넷은 Little Endian, Big Endian 등 바이트 순서가 다른 기종이 혼재했다.

1의 보수 합은 바이트 순서를 바꿔 계산해도 결과가 정확히 바이트만 뒤집힌 형태가 된다.

 

체크섬 최종 검증 시 `0xFFFF`인지만 확인하는데, 0xFFFF는 바이트를 뒤집어도 0xFFFF이므로

어떤 Endian 장비에서 검증하든 동일한 결과가 나온다.

 

반면 2의 보수에서는 carry를 버리는 순간 이 대칭성이 깨진다.

 

예시로 확인해 보자.

[Big Endian]
  0x 01FF
+ 0x FE01
---------
01 + FE =  FF (하위 바이트)    carry 없음
FF + 01 = 100 (상위 바이트)    carry 1 발생

   FF  |
+   100|
-------
= 10000 → 1 캐리 더함 → 0000 + 1 = 0001 (carry 더함)
= 10000 → 1 캐리 버림 → 0000 = 0000 (carry 버림)

1의 보수: 0001
2의 보수: 0000

[Litten Endian]
  0x FF01
+ 0x 01FE 
---------
FF + 01 = 00 (상위 바이트)    carry 1 발생
01 + FE = FF (하위 바이트)    carry 없음

  100  |
+    FF|
--------
= 100FF → 1 캐리 더함 → 0100 (carry 더함)
= 100FF → 1 캐리 버림 → 00FF (carry 버림)

1의 보수
=> 00|01, 01|00
- 정확히 바이트 swap 관계 성립 ✅

2의 보수
=> 00|00, 00|FF
- 대칭성 깨짐 ❌

 


2. IP Header Checksum

IP 헤더 구조와 체크섬의 위치

IPv4 헤더는 최소 20바이트(5개의 32비트 워드)로 구성된다.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|  IHL  |Type of Service|          Total Length         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Identification        |Flags|    Fragment Offset      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Time to Live |    Protocol   |       Header Checksum         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                     Source Address                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                  Destination Address                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 

IP 체크섬은 IP Header만 보호한다. 페이로드(데이터)는 포함하지 않는다.
TTL 같은 필드가 라우터를 지날 때마다 변경되므로, 페이로드까지 포함하면 매 홉마다 수십 KB의 데이터를 재합산해야 하는 부담이 발생하기 때문이다.

계산 과정 예시

다음 IPv4 헤더를 예로 들어 계산 과정을 따라가 보자.

Source IP는 192.168.0.1, Destination IP는 192.168.0.199, Protocol은 UDP(17)이다.

IP Header (hex): 4500 0073 0000 4000 4011 [0000] C0A8 0001 C0A8 00C7
                                          ^^^^^^ 체크섬 필드 (0으로 초기화)

 

Step 1: 모든 16비트 워드 합산

4500 + 0073 + 0000 + 4000 + 4011 + 0000 + C0A8 + 0001 + C0A8 + 00C7
= 2479C   ← 17비트, carry 발생!

 

Step 2: End-Around Carry 처리

479C + 0002 = 479E

상위 carry를 하위 16비트에 더한다.

 

Step 3: 1의 보수 (비트 반전)

NOT 479E = B861   ← 최종 체크섬 값

이 값 0x B861이 IP 헤더의 체크섬 필드에 삽입된다.

즉, IP Header의 구성요소 + 체크섬 = FFFF == 0000(Zero)이 되어야 하는것이다.

수신 측 검증

수신 측은 체크섬 필드를 포함한 전체 헤더를 동일하게 합산한다.

4500 + 0073 + 0000 + 4000 + 4011 + [B861] + C0A8 + 0001 + C0A8 + 00C7
= 2FFFD

carry 처리: FFFD + 2 = FFFF
1의 보수:   NOT FFFF = 0000  ← 결과가 0이면 오류 없음

-> 결과가 0이면 정상, 0이 아니면 패킷 폐기.

라우터에서의 증분 업데이트

라우터는 패킷을 포워딩할 때 TTL을 1 감소시키므로 IP 헤더 체크섬을 재계산해야 한다.

매번 헤더 전체를 다시 합산하는 것은 비효율적이므로, TTL이 1 감소한만큼 +1 증분 업데이트 방식을 사용한다.

변경된 필드의 차이만큼만 체크섬을 보정하면 되며, 이것이 가능한 이유는 1의 보수 덧셈의 결합법칙과 교환법칙 덕분이다.

IPv6에서의 제거

IPv6에서는 IP 헤더 체크섬 필드가 제거되었다.

매 홉마다 재계산하는 부담을 없애고, 오류 검출은 기존 링크 계층(Ethernet CRC)과 전송 계층(TCP/UDP 체크섬)에 위임한다.

단, 이 결정으로 인해 IPv6에서는 UDP 체크섬이 필수가 되었다.

IP 헤더 체크섬이 없으면 UDP까지 체크섬을 끌 경우 IP 주소 손상을 감지할 계층이 아예 없어지기 때문이다.

참고: IPv6에서 없어진 것은 IP 헤더 자체가 아니라, 헤더 안의 "Header Checksum" 필드이다.
출발지/목적지 주소는 오히려 128비트로 확장되었고, TTL은 이름만 "Hop Limit"으로 바뀌었을 뿐 기능은 동일하다.

 


3. TCP/UDP Checksum과 Pseudo Header

IP 체크섬과의 결정적 차이

IP 체크섬이 헤더만 보호하는 것과 달리, TCP/UDP 체크섬은 헤더 + 페이로드 전체를 보호한다.

비교 항목 IP Header Checksum TCP/UDP Checksum
보호 범위 헤더만 헤더 + 페이로드 전체
재계산 매 홉마다 없음 (end-to-end)
성격 라우팅 정보 무결성 end-to-end 데이터 무결성
IPv6 제거됨 유지 (UDP 필수화)
  • TCP는 end-to-end 프로토콜이므로 출발지에서 한 번 생성하고, 목적지에서 검증한다.
    중간 라우터는 TCP 체크섬을 건드리지 않는다.

Pseudo Header의 필요성

TCP/UDP 체크섬을 헤더와 페이로드만으로 계산하면 심각한 문제가 발생한다.

IP 헤더의 목적지 주소가 전송 중 손상되어 엉뚱한 호스트에 도착하더라도, TCP 헤더와 페이로드 자체는 손상되지 않았으므로
체크섬 검증을 통과해 버린다. -> 이것이 바로 misrouted segment 문제이다.

=> 이 문제를 해결하기 위해 Pseudo Header(의사 헤더)를 도입했다.

Pseudo Header 구조 (IPv4)

필드 크기 설명
Source Address 32비트 IP 헤더의 출발지 IP 주소
Destination Address 32비트 IP 헤더의 목적지 IP 주소
Zero + Protocol 16비트 8비트 예약(0) + Protocol(TCP=6, UDP=17)
TCP/UDP Length 16비트 TCP/UDP 헤더 + 데이터 길이

Pseudo Header의 각 필드 역할

  • Source/Destination Address:
    • IP 주소가 체크섬 계산에 포함된다. (뒤에서 얘기하겠지만 전송 계층에서 IP 주소를 보는건 엄밀히 규약 위반이다.)
    • 주소가 손상되어 엉뚱한 호스트에 도착하면 수신 측이 자기 IP로 Pseudo Header를 만들어 검증할 때 체크섬이 불일치한다.
  • Protocol: TCP 세그먼트가 실수로 UDP로 해석되거나 그 반대 상황을 방지한다.
  • TCP/UDP Length: 데이터가 잘리거나 뒤에 쓰레기 바이트가 붙는 경우를 잡아낸다.

핵심: Pseudo Header는 실제로 전송되지 않는다. 체크섬을 계산할 때만 임시로 만들어서 쓰고, 계산이 끝나면 버린다.
수신 측도 도착한 패킷의 IP 헤더에서 동일한 정보를 꺼내 Pseudo Header를 재구성해서 검증한다.

TCP 체크섬 계산 대상

┌─────────────────────────┐
│  Pseudo Header (12byte) │  ← 실제 전송 안 됨, 계산에만 사용
├─────────────────────────┤
│  TCP Header (20+byte)   │  ← 체크섬 필드는 0으로
├─────────────────────────┤
│  TCP Payload (가변)      │  ← 홀수 바이트면 끝에 0 패딩
└─────────────────────────┘
  • 계산 알고리즘은 IP Header Checksum과 완전히 동일하다 (16비트 1의 보수 합의 1의 보수).
  • 달라지는 것은 입력 데이터의 범위 뿐이다.

Pseudo Header의 계층 위반 논쟁

Pseudo Header는 엄밀히 말해 계층 위반(layer violation)이다. 전송 계층(L4, TCP)이 네트워크 계층(L3, IP)의 정보를 직접 참조해야 하기 때문이다.

 

실제 구현에서는 두 계층이 같은 소켓 구조체를 공유한다.

  • TCP 계층이 connect()/bind() 시점에 이미 결정된 주소 정보를 읽어오는 방식으로 동작한다.
  • "3계층이 먼저" 또는 "4계층이 먼저"가 아니라, 두 계층 모두 같은 소켓 컨텍스트를 참조하는 것이다.

이 커플링 때문에 IP가 변경되면 TCP 체크섬 계산도 함께 수정되어야 한다.

실제로 IPv6에서는 Pseudo Header 구조가 변경되었다 (12바이트 → 40바이트, 주소가 128비트로 확장).

UDP 체크섬의 특이점

UDP 체크섬은 TCP와 계산 방식이 동일하지만, IPv4에서는 선택사항(optional)이다.

체크섬 필드에 0x0000을 넣으면 "체크섬을 사용하지 않겠다"는 의미이다. 실시간 스트리밍처럼 약간의 오류보다 재전송 지연이 더 치명적인 경우를 위한 설계이다.

단, IPv6에서는 UDP 체크섬이 필수이다. 3계층에서 IP 헤더 체크섬이 제거되었으므로, UDP까지 체크섬을 끄면 IP 주소 손상을 감지할 계층이 아예 없어지기 때문이다.


4. 데이터 링크 계층: Ethernet CRC-32

CRC의 동작 원리

TCP/IP 체크섬이 덧셈 기반인 반면, Ethernet CRC는 다항식 나눗셈 기반이다.

  • 전송할 데이터를 하나의 거대한 이진수로 취급하고, 미리 약속된 생성 다항식으로 나눈 나머지가 CRC값이 된다.
  • CRC 계산의 핵심은 모듈로-2 연산(XOR 기반)이다.
    • 13 mod 5 = 3
    • 13/5 = 몫: 2, 나머지 3
  • 일반적인 산술 나눗셈과 달리 빌림이나 올림이 없어서 하드웨어에서 매우 효율적으로 구현된다.

FCS(Frame Check Sequence) 필드에 이 CRC 값이 들어간다.

계산 범위

  • Source/Destination MAC 주소
  • Type 필드
  • Payload
  • Padding

위 목록을 포함한 프레임 거의 전부이다.

CRC vs 1의 보수 합산 비교

특성 TCP/IP Checksum CRC-32

특성 TCP/IP Checksum CRC
수학적 기반 1의 보수 덧셈 GF(2) 다항식 나눗셈
출력 크기 16비트 32비트
워드 순서 변경 감지 불가능 가능
상쇄 오류 감지 불가능 거의 항상 감지
감지못할 확률 약 1/65,536 약 1/4,294,967,296
처리 주체 OS 커널 / NIC offload NIC 하드웨어

CRC 재계산의 사각지대

Ethernet CRC는 체크섬 성능이 높은 편이지만 한 가지 중요한 약점이 있다. 매 홉마다 재계산된다는 것이다.

- 라우팅마다 비용도 높아지고, 중간 과정에서 오류가 발생했을 때 감지가 안된다.

[Host A] ──CRC 정상──→ [스위치] ──CRC 정상──→ [Host B]
                           │
                      여기서 메모리 오류로
                      패킷 데이터 손상!
                           │
                      하지만 스위치가 나갈 때
                      CRC를 새로 계산해서 붙임
                           │
                      → 나가는 CRC는 정상 OK
                      → 하지만 데이터는 손상됨 Damage!

스위치나 라우터의 메모리 오류, 버스 오류, 펌웨어 버그 등으로 패킷 내용이 손상되더라도,

해당 장비가 나가는 프레임에 새 CRC를 붙이므로 수신 측에서 보면 CRC는 완벽하게 유효하다.

 

이런 오류를 잡아내는 마지막 방어선이 바로 TCP/UDP 체크섬이다.

  • TCP 체크섬은 출발지에서 한 번 생성되고 중간에 재계산되지 않으므로, 중간 장비에서 발생한 손상을 end-to-end로 감지할 수 있다.

5. 계층별 종합 비교

패킷 송수신 전체 흐름

송신 측에서는 체크섬이 TCP → IP → Ethernet 순서로 생성된다.

  1. TCP 계층이 Pseudo Header + TCP Header + Payload로 체크섬 계산
  2. IP 계층이 IP Header만으로 체크섬 계산
  3. NIC 하드웨어가 Ethernet CRC를 붙여 전송

수신 측에서는 정반대 순서(Ethernet → IP → TCP)로 검증한다.

중간 라우터 에서는 Ethernet CRC와 IP 체크섬만 검증/재계산한다.
TCP 체크섬은 건드리지 않으며, 이것이 end-to-end 무결성을 보장하는 핵심이다.

종합 비교표

  Ethernet CRC IP Header Checksum TCP/UDP Checksum
계층 L2 데이터 링크 L3 네트워크 L4 전송
알고리즘 CRC 다항식 나눗셈 1의 보수 합 1의 보수 합 (동일)
보호 범위 프레임 전체 IP 헤더만 Pseudo Header + 헤더 + Payload
보호 목적 물리적 전송 오류 라우팅 정보 무결성 end-to-end 데이터 무결성 + 오배송 방지
검증 위치 매 홉 매 홉 최종 목적지만
재계산 매 홉마다 새로 생성 매 홉 (TTL 변경) 없음
감지 강도 매우 강함 (32비트) 약함 (16비트) 약함 (16비트)
IPv6 유지 제거됨 유지 (UDP 필수화)

7. 결론

TCP/IP Checksum은 오랜기간 동안 네트워크 환경에서 사용되고 있는 단순하지만 효과적인 오류 검출 메커니즘이다.

1의 보수 합산이라는 단순한 연산으로 Endian 독립성, 빠른 연산 속도, 증분 업데이트 가능성을 동시에 확보한 설계이다.

 

각 계층의 체크섬은 서로 보완 관계에 있다.

  • Ethernet CRC-32: 물리적 전송 오류를 강력하게 감지하지만, 매 홉에서 재계산되는 약점이 있다.
  • IP Header Checksum: 라우팅 정보를 보호하지만 헤더만 커버한다.
  • TCP/UDP Checksum: 약하지만 유일하게 end-to-end로 동작하는 검증 메커니즘이다.
반응형
저작자표시 비영리 변경금지 (새창열림)

'기술 학습' 카테고리의 다른 글

MSA에서 CORS 문제를 해결하는 4가지 전략  (0) 2026.03.27
Java 기반 동기/비동기, 블로킹/논블로킹 정리  (0) 2026.03.23
ANSI Isolation Level vs MySQL Isolation Level: 같은 이름, 다른 보장  (0) 2026.03.15
MSA에서 ACID의 의미  (0) 2026.03.10
객체지향 설계 원칙 - SOLID  (0) 2026.03.08
'기술 학습' 카테고리의 다른 글
  • MSA에서 CORS 문제를 해결하는 4가지 전략
  • Java 기반 동기/비동기, 블로킹/논블로킹 정리
  • ANSI Isolation Level vs MySQL Isolation Level: 같은 이름, 다른 보장
  • MSA에서 ACID의 의미
구름뭉치
구름뭉치
구름의 개발일기장
    반응형
  • 구름뭉치
    구름 개발일기장
    구름뭉치
  • 전체
    오늘
    어제
    • ALL (290)
      • 프로젝트 (23)
        • 토스페이먼츠 PG 연동 시리즈 (12)
        • JWT 방식 인증&인가 시리즈 (6)
        • 스우미 웹 애플리케이션 프로젝트 (1)
        • 스프링부트 기본 보일러 플레이트 구축 시리즈 (2)
        • 마이크로서비스 아키텍쳐 시리즈 (1)
      • 스프링 (43)
        • 스프링부트 API 설계 정리 (8)
        • 스프링부트 RestAPI 프로젝트 (18)
        • 스프링부트 WebSocket 적용기 (3)
        • 스프링 JPA 정리 시리즈 (5)
        • 스프링 MVC (5)
        • 스프링 배치 (2)
        • 토비의 스프링 정리 (2)
      • 기술 학습 (6)
        • 아파치 카프카 (9)
        • 클린 코드 (4)
        • 디자인 패턴의 아름다움 (2)
        • 모던 자바 인 액션 (7)
        • JVM 스레드 딥다이브 (7)
      • Web (25)
        • 정리글 (20)
        • GraphQL 정리글 (2)
        • Jenkins 정리글 (3)
      • 취업 (6)
      • CS (77)
        • 네트워크 전공 수업 정리 (11)
        • OSI 7계층 정리 (12)
        • 운영체제 정리 (19)
        • 데이터베이스 정리 (5)
        • MySql 정리 (17)
        • GoF의 Design Pattern 정리 (12)
      • 알고리즘 (70)
        • 백준 (56)
        • 프로그래머스 (12)
        • 알고리즘 정리본 (1)
      • 기초 지식 정리 (2)
      • 일상 (8)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    크로아티아
    류블라냐
    부다페스트
    마우스
    레이저
    동유럽
    키보드 손목 받침대
    mx master s3 for mac
    마우스 패드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
구름뭉치
TCP/IP 체크섬(Checksum) 내부 동작 원리
상단으로

티스토리툴바