본문 바로가기
C.W.K.
Stream
Lesson 11 of 12 · published

정규식 대신 다른 도구를 고를 때

~8 min · limits, tooling, judgment

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

도구를 바꿀 때가 됐다는 신호

정규식은 문자열의 모양을 찾고 바꾸는 데 강하지만 모든 구조를 파싱하는 도구는 아니야. 다음 신호가 보이면 전용 파서나 라이브러리가 더 알맞은지 다시 판단해.

  1. 패턴이 100자를 넘고 계속 자라. 길이는 절대 기준이 아니지만, 예외를 하나 붙일 때마다 다른 사례가 깨진다면 파싱 문제를 밀어 넣고 있다는 강한 신호야.
  2. 따옴표나 주석 안팎처럼 상태를 추적해야 해. 이스케이프 규칙까지 포함한 렉서나 파서가 더 분명할 수 있어.
  3. 깊이가 정해지지 않은 중첩을 다뤄야 해. 괄호, 객체, 태그의 구조를 이해하는 파서를 우선 검토해.
  4. 재귀 같은 엔진별 확장에 의존해야 해. 이식성과 유지보수 비용을 전용 도구와 비교해.
  5. 정규식 단계를 세 번 이상 연결하고 있어. 절대 기준은 아니지만 중간 상태를 설명하기 어렵다면 이름 붙은 처리 단계나 작은 파서가 더 읽기 쉬울 수 있어.
  6. 허용되는 공백이나 속성 순서가 조금만 달라져도 깨져. 형식의 문법을 아는 도구가 필요한 신호야.
  7. 패턴을 소리 내어 설명하기 어려워. 성공과 실패 조건을 테스트로도 설명하기 어렵다면 패턴을 더 늘리기 전에 문제의 경계를 다시 정의해.

중첩 구조에는 파서를 사용해

  • HTML과 XML → BeautifulSoup, lxml, DOMParser 같은 형식별 파서
  • JSON → json.loads, JSON.parse
  • YAML → PyYAML, js-yaml
  • 소스 코드 → Python ast, Babel 파서 같은 AST 도구
  • 사용자 정의 언어 → PLY, Lark, nom, ANTLR 같은 렉서와 파서 도구

알려진 형식에는 전용 라이브러리를 사용해

  • URL → urllib.parse, new URL()
  • 날짜 → datetime, dateutil, date-fns
  • 전화번호 → libphonenumber
  • IP 주소 → ipaddress, net.ParseIP
  • 버전 → packaging.version, SemVer 라이브러리

정규식과 전용 도구의 역할을 나눠

정규식으로 후보를 빠르게 찾고 전용 도구로 실제 구조와 값을 검증하는 조합도 좋아. 핵심은 더 영리한 패턴을 만드는 것이 아니라, 실패 방식과 유지보수 비용까지 포함해 가장 작은 믿을 만한 해결책을 고르는 거야.

Code

옳은 도구 비교·python
# JSON 구조를 정규식으로 추측하는 방식
import re
re.findall(r'"name":\s*"([^"]+)"', '{"name": "pippa", "data": {"name": "x"}}')
# ['pippa', 'x'] — 두 필드의 구조적 차이를 구분하지 못해

# JSON 파서로 구조를 보존하는 방식
import json
data = json.loads('{"name": "pippa", "data": {"name": "x"}}')
print(data['name'])          # 'pippa'
print(data['data']['name'])  # 'x'

# 날짜 모양만 나누는 정규식
re.match(r'(\d{4})-(\d{2})-(\d{2})', '2026-05-04')
# 존재하는 날짜인지 확인하려면 별도 검증이 필요해

# 날짜 파서로 검증과 변환을 함께 처리
from datetime import datetime
dt = datetime.strptime('2026-05-04', '%Y-%m-%d')

# 소스 코드에서 함수처럼 보이는 문자열 찾기
re.findall(r'def\s+(\w+)\(', code)
# 주석과 문자열 안의 텍스트도 구분하지 못할 수 있어

# AST로 실제 함수 정의만 순회
import ast
tree = ast.parse(code)
for node in ast.walk(tree):
    if isinstance(node, ast.FunctionDef):
        print(node.name)

External links

Exercise

코드베이스에서 긴 정규식 하나를 찾아 모양 감지와 구조 파싱 중 어느 일을 하는지 분류해 봐. 구조를 파싱하고 있다면 사용할 수 있는 전용 라이브러리나 파서의 입력과 출력을 간단히 스케치하고, 현재 패턴과 실패 방식을 비교해.

Progress

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

댓글 0

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

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