본문 바로가기
C.W.K.
Stream
Lesson 09 of 10 · published

정규식 쓰면 안 되는 자리

~10 min · limits, anti-patterns, html-parsing

Level 0패턴 호기심
0 XP0/90 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

그 유명한 Stack Overflow 답변

Stack Overflow에 "정규식으로 HTML을 파싱하는 법"을 물으면 "He comes."로 끝나는 과격한 명답이 따라와. 표현은 과하지만 교훈은 정확해. 정규식은 파서가 아냐.

정규식이 진짜 못 하는 것

중첩 구조. 깊이가 정해지지 않은 괄호의 짝을 맞추는 일은 정규 언어가 아냐. ((a))(((a)))를 구분하려면 깊이를 세어야 하고, 순수 정규식은 그 수를 기억하지 못해. 일부 PCRE 엔진은 재귀 (?R)를 추가해 흉내 내지만 이미 고전적인 정규식의 범위를 벗어난 기능이야.

HTML / XML / Markdown / JSON / YAML / 소스 코드. 모두 중첩 구조를 품고 있어. Python의 html.parser·lxml·json·yaml, JavaScript의 DOMParser·JSON.parse처럼 형식에 맞는 파서를 써.

의미 검증. 정규식은 모양은 확인하지만 의미는 판단하지 못해. \d{4}는 "9999"도 매칭해. 그 값이 유효한 연도인지는 일반 코드가 판단해야 해.

Unicode의 깊은 문제. 오른쪽에서 왼쪽으로 쓰는 문자 체계, 이모지 ZWJ 시퀀스, 결합 문자, 로캘별 대소문자 변환은 전용 라이브러리의 영역이야. 정규식이 \p{...}와 Unicode 플래그로 일부를 *건드릴* 수는 있지만 대개 알맞은 도구가 아니야.

위험 신호

패턴이 100자를 넘고, 그룹이 네 겹 이상 중첩되고, 후방 탐색으로 주변 맥락을 기억하려 한다면 멈춰. 매칭이 아니라 파싱을 시도하는 중일 가능성이 커. HTML 파서, YAML 라이브러리, 토크나이저, AST 순회 도구처럼 구조를 다루는 도구를 꺼내.

정규식은 모양을 감지해. 문제가 구조로 바뀌는 순간 다음 도구에 넘겨야 해.

Code

잘못된 도구, 옳은 도구·python
# 잘못된 도구 — HTML에서 정규식으로 <a href> 추출
import re
links = re.findall(r'<a\s+href="([^"]+)"', html)
# 작은따옴표, 속성 순서, 여러 줄 태그, 이스케이프된 따옴표,
# 주석, CDATA를 만날 때마다 깨져. 끝이 없어.

# 올바른 도구 — 진짜 HTML 파서
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
links = [a['href'] for a in soup.find_all('a', href=True)]
# 형식의 경계 사례는 파서가 맡아.

External links

Exercise

코드베이스에서 80자가 넘는 정규식 하나를 점검해. 모양을 감지하는지, 구조를 파싱하려는지 물어봐. 구조를 다룬다면 진짜 파서를 썼을 때 코드가 어떤 모양일지 스케치해. 오늘 바로 바꾸지 않더라도 그 경계는 정확히 알아둬.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.