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

최적화 기법

~8 min · performance, optimization

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

먼저 정확성과 시간을 측정해

최적화하기 전에 패턴이 올바른 결과를 내는지 테스트하고 실제 입력으로 실행 시간을 재. 느려 보이는 문제가 잘못된 범위나 과도한 매칭에서 비롯된 정확성 문제일 수도 있어.

1. 재사용할 패턴에 이름 붙이기

re.compile로 만든 패턴 객체는 여러 호출에서 재사용하기 쉽고 의도도 드러내. Python의 모듈 수준 함수도 최근 패턴을 캐시하므로 명시적 컴파일이 언제나 더 빠른 것은 아니야. 반복 경로에서 차이가 중요한지는 측정해.

2. 검색 범위를 정확히 표현하기

입력 시작에서만 매칭해야 한다면 ^를 사용하고, 전체 문자열을 검증한다면 fullmatch 같은 API를 사용해. 불필요한 시작 위치를 시도하지 않게 할 수 있지만, 원래 의도한 매칭 범위를 바꾸지 않는지 먼저 확인해야 해.

3. 한 글자 선택은 문자 클래스로 쓰기

a|b|c처럼 한 글자 대안만 나열한다면 [abc]가 뜻을 더 직접적으로 보여 줘. 엔진이 둘을 비슷하게 최적화할 수도 있으므로 속도 차이는 가정하지 말고 가독성을 먼저 봐.

4. 종료 문자를 문자 클래스로 표현하기

종료 표식이 한 글자라면 .*?X보다 [^X]*X가 어디까지 허용하는지 더 분명하게 드러낼 수 있어. 종료 표식이 여러 글자라면 부정형 문자 클래스 하나로 같은 뜻을 표현할 수 없어. 문자열 검색이나 파서, 의미를 테스트한 다른 패턴을 사용해. 원자 그룹도 백트래킹 선택지를 없애므로 결과가 같다는 검증이 필요해.

5. 왼쪽에 구체적인 단서를 두기

패턴 초반에 고정 문자열이나 좁은 문자 클래스가 있으면 엔진이 맞지 않는 위치를 일찍 버릴 수 있어. 반대로 .*처럼 넓은 시작은 후보 범위를 크게 만들 수 있어. 엔진마다 최적화 방식이 다르므로 실제 입력으로 확인해.

6. 작업에 맞는 엔진과 도구 선택하기

큰 파일을 검색할 때는 선형 시간 보장을 목표로 하는 ripgrep의 기본 정규식 엔진이 유리할 수 있어. 전후방 탐색이나 역참조가 필요하면 다른 엔진을 선택해야 할 수도 있어. 필요한 문법과 입력 크기를 함께 고려해.

7. 대표 입력과 나쁜 입력을 함께 측정해

짧고 정상적인 예시에서 빠른 패턴도 긴 실패 입력에서는 느려질 수 있어. 실제 데이터의 대표 표본과 의도적으로 까다로운 입력을 함께 벤치마크해.

Code

최적화 예시·python
import re
from timeit import timeit

# 1. 재사용할 패턴에 이름 붙이기
DATE = re.compile(r'\d{4}-\d{2}-\d{2}')
# DATE.findall(text)를 여러 곳에서 재사용

# 2. 전체 문자열 검증은 fullmatch로 의도를 표현
bool(re.fullmatch(r'\d+', '12345'))  # True

# 3. 한 글자 대안은 문자 클래스로 간결하게
re.findall(r'[abcde]', 'abcdef' * 1000)

# 4. 같은 뜻인지 테스트한 뒤 시간을 비교
text = '"hello" world ' * 1000
lazy = lambda: re.findall(r'".*?"', text)
negated = lambda: re.findall(r'"[^"]*"', text)
assert lazy() == negated()
print(timeit(lazy, number=100))
print(timeit(negated, number=100))

# 5. 고정된 시작 단서로 후보를 좁히기
LOG_LINE = re.compile(r'^ERROR:\s+(.+)$', re.MULTILINE)

# 6. 큰 파일 검색에는 필요한 문법을 지원하는 도구 선택
# rg 'pattern' bigfile.log

External links

Exercise

코드에서 자주 실행되는 정규식 하나를 골라 정상 입력과 긴 실패 입력으로 시간을 측정해. 의미를 보존하는 변경 하나를 적용한 뒤 결과 집합이 같은지 먼저 확인하고 다시 측정해. 속도 차이가 없거나 중요하지 않았다는 결과도 그대로 기록해.

Progress

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

댓글 0

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

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