EIP-706 DEVp2p 스내피 압축 (DEVp2p snappy compression)
최종 확정 · 네트워크·노드 · 원문 상태 Final · 2017-09-07 작성
이더리움 노드끼리 주고받는 모든 네트워크 메시지를 스내피(Snappy) 알고리즘으로 압축해 통신량을 줄입니다. 초기 동기화 기준으로 데이터 트래픽이 60~80% 감소합니다.
왜 필요한가
이더리움 노드들이 서로 통신할 때 쓰는 기본 네트워크 규약(DEVp2p)은 원래 아무 압축도 하지 않았습니다. 블록과 거래 데이터는 압축이 잘 되는 성질인데도 원본 그대로 주고받다 보니 네트워크 전체에서 막대한 대역폭이 낭비되고 처음 노드를 켜서 블록체인을 내려받는 초기 동기화도, 평소 운영도 느려집니다. 실제로 Geth 클라이언트로 메인 네트워크(블록 4,248,000 기준)를 패스트 싱크 방식으로 동기화하면 업로드 1.01GB, 다운로드 33.59GB가 필요했습니다. 메시지 내용물 수준에서 압축을 켜면 같은 동기화의 다운로드가 13.46GB로 줄고 린케비 테스트 네트워크에서는 다운로드 2.51GB가 463.65MB로 줄어듭니다. 하위 프로토콜(eth, les, bzz)마다 따로 압축을 구현하는 대신 그 아래층인 DEVp2p에서 한 번에 처리하면 모든 프로토콜이 수정 없이 혜택을 받습니다.
무엇이 바뀌나
지금
- 노드 간 메시지를 압축 없이 원본 그대로 전송합니다
- 메인넷 패스트 싱크에 다운로드 33.59GB가 필요합니다(블록 4,248,000 기준)
- 압축을 원하면 eth 같은 각 하위 프로토콜이 따로 구현해야 합니다
EIP-706 이후
- 핸드셰이크 이후 모든 메시지 내용물을 스내피로 압축해 전송합니다
- 같은 조건의 메인넷 다운로드가 13.46GB로 줄어듭니다
- eth, les, bzz 등 모든 하위 프로토콜이 수정 없이 압축 혜택을 받습니다
- 구버전(v4) 노드와는 기존 방식 그대로 통신해 호환성이 유지됩니다
누구에게 영향이 있나
- 노드 운영자: 초기 동기화와 평상시 운영에 드는 네트워크 사용량이 크게 줄어듭니다. 특히 다운로드 트래픽이 60~80% 감소합니다.
- 클라이언트 팀: DEVp2p 버전을 5로 올리고 압축·해제 단계를 넣어야 하며 v4만 지원하는 상대와는 기존 방식으로 통신해야 합니다.
- 하위 프로토콜 개발자: eth, les, bzz 같은 프로토콜은 아무 변경 없이 전송 계층에서 압축을 얻으므로 각자 트래픽 최적화를 고민할 필요가 줄어듭니다.
- 일반 사용자: 프로토콜 동작은 그대로이므로 체감 변화는 없지만 노드를 직접 돌리는 문턱이 낮아져 네트워크 건강에 도움이 됩니다.
심층 설명
버전 협상: v4에서 v5로
광고하는 DEVp2p 버전 번호를 4에서 5로 올립니다. 핸드셰이크에서 상대가 버전 4만 지원한다고 알리면 기존 프로토콜을 그대로 돌리고 상대가 버전 5 이상을 알리면 압축을 활성화합니다. 공통 버전을 협상하는 수단인 핸드셰이크 메시지 자체는 절대 압축하지 않습니다. 이 구조 덕분에 업그레이드한 클라이언트와 구버전 클라이언트가 섞여 있어도 네트워크가 깨지지 않는 완전한 하위 호환이 성립합니다.
송수신 경로에 끼워 넣는 압축 단계
송신 시에는 DEVp2p 메시지를 암호화하기 직전에 스내피 압축 단계를 넣습니다. 메시지는 {Code, Size, Payload}로 구성되는데, 원본 Payload를 스내피로 압축해 같은 필드에 저장하고 Size를 압축된 길이로 갱신한 뒤, 기존과 동일하게 암호화해 전송합니다. 수신 시에는 복호화 직후에 대칭적으로 해제 단계를 넣어 Payload를 풀고 Size를 원본 길이로 되돌립니다. 암호화·복호화 로직은 압축 여부를 전혀 모르는 채(oblivious) 동작하므로 기존 전송 코드 변경이 최소화됩니다. DEVp2p가 이미 메시지 단위 프로토콜이므로 스내피 프레이밍 포맷은 쓰지 않습니다.
DoS 방지: 해제 후 크기도 16MB로 제한
DEVp2p 메시지 길이는 24비트로 제한되어 최대 16MB입니다. 압축이 도입되면 작은 압축본이 풀었을 때 훨씬 커질 수 있어 받은 메시지를 무턱대고 해제하면 메모리 고갈 공격에 노출됩니다. 스내피 스트림은 맨 앞에 압축 해제 후 길이를 리틀엔디언 varint로 담고 있어(최대 2^32 - 1), 실제로 메모리에 풀지 않고도 결과 크기를 알 수 있습니다. 제안은 해제 후 크기에도 기존과 같은 16MB 한도를 적용해 초과 메시지를 버리는 것입니다. 이렇게 하면 기존 DEVp2p가 주던 보장이 그대로 유지되어 상위 응용 프로토콜에 돌발 상황이 생기지 않습니다.
왜 eth가 아니라 DEVp2p 계층인가
eth 같은 개별 프로토콜에 압축을 넣는 안은 언제 압축할지 더 정밀하게 최적화할 수 있다는 장점이 있지만 전송 계층 인코딩이 응용 계층 로직에 섞이고 메시지 명세가 압축 세부사항으로 복잡해지며 eth·les·shh·bzz 프로토콜마다 클라이언트 간 조율을 반복해야 해서 폐기되었습니다. xyz-compressed처럼 압축판 프로토콜을 따로 알리는 안은 조율 없이 끼워 넣을 수 있지만 네트워크에 클라이언트별 프로토콜 광고가 난립하고 결국 상호운용을 위해 EIP 명세가 필요해 역시 폐기되었습니다. 압축 전 크기만 제한하고 해제 후 크기를 제한하지 않는 안도 상위 프로토콜이 큰 메시지를 직접 검사해야 하고 지연 해제가 필요해 버려졌습니다.
벤치마크와 구현, 테스트 벡터
메인 네트워크(블록 4,248,000)는 업로드 1.01GB / 다운로드 33.59GB에서 1.01GB / 13.46GB로, 린케비 테스트넷(블록 852,000)은 55.89MB / 2.51GB에서 46.21MB / 463.65MB로 줄었습니다. 참조 구현은 go-ethereum 풀 리퀘스트 15106에 있습니다. 스내피는 같은 입력에 대해 유효한 인코딩이 하나가 아니어서 구현마다 압축 결과가 조금씩 다를 수 있지만 서로 교차 해제가 가능해야 하며 린케비 블록 #272621의 RLP(약 3MB)를 Go와 Python 스내피 라이브러리로 각각 약 70KB로 압축한 테스트 벡터가 제공됩니다. 스내피는 최대 4GB의 비압축 리터럴도 지원하므로 이미 압축되거나 암호화된 데이터는 그대로 담는 최적화 여지도 남아 있습니다.
상태: Final
이 EIP는 2017년 9월 7일에 제안되어 Final 상태로 확정되었습니다. DEVp2p 버전 5의 일부로 이미 네트워크에 적용되어 있는 완결된 명세이며, 더 이상 내용이 바뀌지 않습니다.