진지한 protocol 의 배관 속에는 반드시 compatibility 약속 이 하나 숨어 있어. 어떤 변화는 기존 client 를 안 깨고 그냥 해도 되고, 어떤 변화는 version 을 올려야 하는 breaking change 인지를 정해주는 약속이지. 이 약속의 모양이 protocol 주변에 ecosystem 이 자랄 수 있게 해줘. HTTP 도 SQL 도 MCP 도 다 그렇게 컸어.
어휘는 RFC 2119 에서 와: MUST, SHOULD, MAY. MUST 는 협상 불가 — 안 하면 규격 위반이고 그냥 깨져. SHOULD 는 '웬만하면 해야 하고, 안 하면 사람들이 불행해지지만, 당장 죽지는 않는다.' MAY 는 '해도 되지만, 남이 했다고 가정하면 안 된다.'
LLM 과 agent 를 만지는 protocol 에서는 패턴 세 개가 반복돼. 첫째, 필드는 더하지 이름을 바꾸지 않아. 새 revision 은 content 옆에 annotations 를 하나 더 놓지, content 의 뜻을 슬쩍 바꾸지 않아. 둘째, deprecation 은 긴 시간을 두고 굴러가. 필드는 최소 한 revision 이상 deprecated 로 표시된 뒤에야 사라지고, 새 필드는 옛 client 가 계속 돌아가도록 나란히 내보내. 셋째, capability negotiation 이 version 의 짐을 덜어줘. 양쪽이 handshake 때 뭘 지원하는지 서로 밝히면, protocol 이 모든 세부 사항을 하나의 전역 version 번호에 묶어둘 필요가 없어지거든.
Compatibility 약속은 '내 server 를 client 안 깨고 올릴 수 있나?' 를 물을 때 펼쳐보는 거야. 답이 'changelog 보고 기도해' 라면 — 그건 진짜 protocol 이 아니라, protocol 옷을 입은 움직이는 표적이야. 진짜 protocol 은 약속을 하고, 그걸 적어두고, 어긴 걸 bug 로 다뤄.