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

성능과 대안

~8 min · performance, alternatives

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

전후방 탐색에도 비용이 들어

각 전후방 탐색은 관련 위치에서 하위 패턴을 따로 평가해. 여러 조건을 겹치면 같은 텍스트를 반복해서 살필 수 있으므로 긴 입력에서는 캡처 후 검사하는 방식보다 느려질 수 있어.

탐욕적 수량자와 결합할 때

(?=.*X)(?=.*Y).*처럼 탐욕적 수량자와 겹치면 조건을 확인한 뒤 본 패턴에서 다시 백트래킹할 수 있어. ^$로 범위를 전체 입력에 고정하면 시작 위치를 여러 번 바꾸는 낭비는 줄일 수 있지만, 패턴 전체의 비용은 실제 입력으로 측정해야 해.

다른 도구가 더 나은 경우

  1. 문자를 실제로 소비해도 된다면 (?=[a-z]) 대신 [a-z]를 써.
  2. 정규식 하나가 지나치게 복잡해지면 넓게 매칭한 뒤 일반 코드에서 필터링해.
  3. Go, RE2, ripgrep 기본 엔진처럼 지원하지 않는 환경에서는 캡처 그룹과 후처리를 사용해.

선택 기준

분할 위치나 겹친 조건처럼 너비 0 검사가 꼭 필요할 때 전후방 탐색을 선택해. 값 추출만 필요하다면 캡처 그룹이 더 단순하고 호환성도 높을 수 있어.

Code

전후방 탐색과 대안·python
import re

# 전후방 탐색으로 대문자 앞에서 분할
re.split(r'(?=[A-Z])', 'CamelCaseString')
# ['', 'Camel', 'Case', 'String']

# 대안: 캡처한 뒤 다시 조립
parts = re.findall(r'[A-Z][a-z]*', 'CamelCaseString')
# ['Camel', 'Case', 'String']  — 때로는 이쪽이 더 간결해

# 후방 탐색으로 값 추출
re.findall(r'(?<=user_)\w+', 'user_alice user_bob')
# ['alice', 'bob']

# 같은 값을 캡처 그룹으로 추출 — 이식성이 더 좋아
m = re.findall(r'user_(\w+)', 'user_alice user_bob')
# ['alice', 'bob']  — 같은 결과이며 Go/RE2에서도 동작해

# 캡처 버전은 모든 정규식 엔진에서 동작해.
# 후방 탐색 버전은 Go에서 컴파일되지 않아.

External links

Exercise

7강의 비밀번호 검증기를 전후방 탐색 없이 넓게 캡처한 뒤 코드에서 조건을 검사하는 방식으로 다시 작성해. 두 해법의 길이, 읽기 쉬움, 엔진 호환성을 비교하고 현재 요구사항에 어느 쪽을 고를지 근거를 적어.

Progress

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

댓글 0

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

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