그 유명한 Stack Overflow 답변
SO 에 "정규식으로 HTML 파싱하는 법" 물으면, "He comes." 로 끝나는 그 유명한 unhinged-but-correct 답변이 와. 가르치는 교훈은 진짜야: 정규식은 파서가 아냐.
정규식이 진짜 못 하는 것
중첩 구조. 임의 깊이의 균형 잡힌 괄호 매칭은 정규 언어가 아냐. ((a)) vs (((a))) 는 카운팅이 필요하고, 순수 정규식은 못 세. 일부 PCRE 엔진이 recursion ((?R)) 추가해서 흉내내지만, 그건 이미 정규식 이론을 떠난 거.
HTML / XML / Markdown / JSON / YAML / 소스 코드. 다 중첩 구조. 파서 써. Python 은 html.parser, lxml, json, yaml. JavaScript 는 DOMParser, JSON.parse. 모든 언어가 모든 진짜 포맷에 대해 진짜 파서를 가지고 있어.
의미 검증. 정규식은 모양 체크는 하지만 의미는 못 봐. \d{4} 는 "9999" 매칭해 — 근데 9999 가 유효한 연도야? 코드가 필요해.
Unicode 깊은 자리. 우횡서 (RTL) 스크립트, emoji ZWJ 시퀀스, combining 글자, locale 별 케이싱. 정규식이 \p{...} 와 Unicode 플래그로 *건들* 수는 있지만 거의 항상 잘못된 도구.
스멜 테스트
패턴이 100자 넘거나, 중첩 그룹 4개 이상, lookbehind 로 컨텍스트 추적 흉내내고 있으면 — 멈춰. 매칭이 아니라 파싱하려는 거야. 옳은 도구로 손 뻗어: HTML 파서, YAML 라이브러리, 손으로 쓴 토크나이저, AST walker.
정규식은 모양 감지. 문제가 구조적으로 변하는 순간, 넘겨.