포스텔의 법칙

Postel's Law

보낼 때는 엄격하게, 받을 때는 관대하게 — 인터페이스는 다양한 입력을 받아들이고 정돈된 결과만 내보내야 한다는 원칙.

다른 이름: Robustness principleBe liberal in what you accept
···
html
<div class="stage">
  <div class="pane"><div class="tag">A</div>
    <div class="inp" id="ia">010-1234-5678</div>
    <svg class="ico bad" id="xa" viewBox="0 0 24 24"><path d="M5 5l14 14M19 5L5 19" stroke-width="3" fill="none" stroke-linecap="round"/></svg>
  </div>
  <div class="pane"><div class="tag">B</div>
    <div class="inp" id="ib">010-1234-5678</div>
    <svg class="ico ok" id="ok" viewBox="0 0 24 24"><path d="M4 13l5 5L20 6" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
    <div class="norm" id="norm">010-1234-5678</div>
  </div>
</div>
css
.stage{width:94%;height:88%;display:flex;gap:6%}
.pane{position:relative;flex:1;border-radius:14px;border:1px solid var(--line);background:var(--surface);display:grid;place-items:center;gap:10px;overflow:hidden}
.tag{position:absolute;top:8px;left:10px;font:700 11px/1 monospace;color:var(--muted)}
.inp{font:700 clamp(11px,2.6vmin,15px)/1 monospace;color:var(--fg);padding:8px 12px;border-radius:8px;border:1px solid var(--line);background:var(--bg)}
.ico{width:24px;height:24px}
.ico path{stroke:currentColor}
.bad{color:var(--accent-2);opacity:.85;animation:pulsebad 2s ease-in-out infinite}
.ok{color:var(--accent-3);opacity:.85;animation:pulseok 2s ease-in-out infinite}
@keyframes pulsebad{0%,100%{opacity:.85;transform:scale(1)}20%,45%{opacity:1;transform:scale(1.25)}}
@keyframes pulseok{0%,100%{opacity:.85;transform:scale(1)}30%,60%{opacity:1;transform:scale(1.25)}}
.norm{font:700 11px/1 monospace;color:var(--accent-3);opacity:.9}
js
const variants = ['010-1234-5678', '01012345678', '010 1234 5678'];
const ia = document.getElementById('ia'), ib = document.getElementById('ib');
let i = 0;
setInterval(() => {
  i = (i + 1) % variants.length;
  ia.textContent = variants[i];
  ib.textContent = variants[i];
}, 2000);

1980년 존 포스텔(Jon Postel)이 TCP 명세(RFC 761)에 쓴 문장에서 나왔습니다. 원래는 네트워크 프로토콜 설계 원칙이었지만 폼 입력 설계에 그대로 적용됩니다.

전화번호를 "010-1234-5678" 형식으로만 받는 폼은 사용자가 "01012345678"이나 "010 1234 5678"을 입력할 때마다 튕겨냅니다. 관대한 폼은 숫자만 추출해 내부에서 정규화하고, 사용자에게는 "이해했다"는 확인만 보여줍니다.

관대함이 무제한이라는 뜻은 아닙니다 — 받아들이는 범위는 넓히되, 저장·전송하는 값은 항상 하나의 정돈된 형식으로 맞춰야 나중에 파싱 지옥을 피할 수 있습니다.

데모의 A는 형식이 조금만 달라도 거부를 반복하고, B는 세 가지 다른 입력을 모두 받아 같은 정규화된 번호로 통일합니다.

언제 쓰나

전화번호·날짜·URL처럼 사용자가 여러 형식으로 입력할 수 있는 필드에서. 정규식으로 막기 전에 "정말 이 형식만 유효한가"를 먼저 물어보세요.