정규표현식 (Regular Expressions)
정규표현식 (Regular Expressions)
JMeter는 텍스트 패턴 매칭에 Apache Jakarta ORO 소프트웨어를 사용해요. 패턴 매칭은 Perl의 그것과 아주 비슷해요. 특히 Response Assertion과 Regular Expression Extractor에서 정규표현식이 어떻게 동작하는지 이해하면 어서션과 응답 추출을 훨씬 강력하게 쓸 수 있어요. 여기서는 contains와 matches의 차이, 추출 예시, 메타문자, 수정자(modifier)를 알아볼게요.
본문
21.1 개요 (Overview)
JMeter는 패턴 매칭 소프트웨어 Apache Jakarta ORO를 포함해요. JMeter 5.5부터는 jmeter.regex.engine JMeter 프로퍼티를 oro가 아닌 다른 값으로 설정하면 Regex 구현을 ORO에서 JDK 기반으로 전환할 수 있어요. 패턴 매칭은 Perl의 패턴 매칭과 매우 비슷해요. Response Assertion 테스트 요소에서 쓰이는 "contains"와 "matches"의 차이를 짚고 넘어갈 필요가 있어요.
- "contains" — 정규표현식이 대상의 적어도 일부와 매치했음을 의미해요. 'alphabet'은 'ph.b.'를 "contains"해요. 정규표현식이 부분 문자열 'phabe'와 매치하니까요.
- "matches" — 정규표현식이 대상 전체와 매치했음을 의미해요. 'alphabet'은 'al.*t'에 "matched"돼요. 이 경우 정규표현식을 ^ 와 $ 로 감싼 것과 동등해요, 즉 '^al.*t$' 따위요.
하지만 항상 그런 건 아니에요. 예를 들어 정규표현식 'alp|.lp.*'는 'alphabet'에 "contained"되지만 'alphabet'을 "match"하지는 않아요. 왜냐하면 패턴 매처가 'alphabet'에서 'alp' 시퀀스를 찾으면 다른 조합을 시도하는 걸 멈추기 때문이에요. 'alp'는 'alphabet'과 같지 않아요('habet'이 없으니까요). Perl과 달리 정규표현식을 // 로 감쌀 필요가 없어요(감싸지 마세요). 그럼 뒤에 / 가 없다면 ismx 같은 수정자는 어떻게 쓸까요? 해결책은 확장 정규표현식을 쓰는 거예요, 즉 /abc/i 는 (?i)abc 가 돼요. 수정자 위치(Placement of modifiers)는 아래에서 다룰게요.
21.2 예시 (Examples)
단일 문자열 추출 (Extract single string) — 웹페이지의 다음 부분을 매치하고 싶다고 해볼게요.
name="file" value="readme.txt">
이때 readme.txt를 추출하고 싶어요. 적절한 정규표현식은 다음과 같아요.
name="file" value="(.+?)">
위의 특수 문자는: ( 와 ) 는 반환할 매치 문자열의 부분을 감싸고, . 는 어떤 문자든 매치하며, + 는 한 번 이상, ? 는 탐욕적이지 않게(첫 매치가 성공하면 멈춤). ? 가 없으면 .+ 가 첫 번째 "> 를 지나 마지막 가능한 "> 를 찾을 때까지 계속 가는데, 보통 의도한 바가 아니에요. 위 표현식도 동작하지만 더 효율적인 표현식이 있어요.
name="file" value="([^"]+)">
여기서 [^"] 는 " 를 제외한 무엇이든 매치한다는 뜻이에요. 이 경우 매칭 엔진은 첫 " 를 보는 즉시 멈출 수 있고, 앞선 경우에서는 "> 를 찾았는지 " > 와 같은지를 확인해야 해요.
여러 문자열 추출 (Extract multiple strings) — 다음 웹페이지 부분을 매치하고 file.name과 readme.txt를 모두 추출하고 싶다고 해볼게요.
name="file.name" value="readme.txt"
적절한 정규표현식은 다음과 같아요.
name="([^"]+)" value="([^"]+)"
이건 2개의 그룹을 만들고, JMeter Regular Expression Extractor 템플릿에서 $1$ 와 $2$ 로 사용할 수 있어요. JMeter Regex Extractor는 그룹 값을 추가 변수로 저장해요. 예를 들어 다음을 가정해볼게요.
Reference Name: MYREF
Regex: name="(.+?)" value="(.+?)"
Template: $1$$2$
정규표현식을 / / 로 감싸지 마세요. 그러면 다음 변수가 설정돼요: MYREF=file.namereadme.txt, MYREF_g0=name="file.name" value="readme.txt", MYREF_g1=file.name, MYREF_g2=readme.txt. 이 변수들은 나중에 테스트 계획에서 ${MYREF}, ${MYREF_g1} 등으로 참조할 수 있어요.
21.3 라인 모드 (Line mode)
패턴 매칭은 multi-line과 single-line 수정자 설정에 따라 약간씩 다르게 동작해요. single-line과 multi-line 연산자는 서로 관련이 없고, 독립적으로 지정할 수 있어요.
싱글라인 모드 (Single-line mode) — '.' 메타문자가 어떻게 해석되는지에만 영향을 줘요. 기본 동작은 '.' 가 newline을 제외한 어떤 문자든 매치하는 거예요. single-line 모드에서는 '.' 가 newline도 매치해요.
멀티라인 모드 (Multi-line mode) — '^' 와 '$' 메타문자가 어떻게 해석되는지에만 영향을 줘요. 기본 동작은 '^' 와 '$' 가 문자열의 맨 앞과 맨 끝에서만 매치하는 거예요. Multi-line 모드를 쓰면 '^' 메타문자는 각 줄의 시작에서, '$' 메타문자는 각 줄의 끝에서 매치해요.
21.4 메타문자 (Meta characters)
정규표현식은 특정 문자를 메타문자로 사용하는데, 이런 문자는 RE 엔진에 특별한 의미를 가져요. 이 문자를 일반 문자로 다루려면 \ (백슬래시)를 앞에 붙여 이스케이프해야 해요. 메타문자와 그 의미는 다음과 같아요(의심되면 ORO 문서를 확인하세요).
- ( 와 ) — 그룹화
- [ 와 ] — 문자 클래스
- { 와 } — 반복
- *, +, ? — 반복
- . — 와일드카드 문자
- \ — 이스케이프 문자
- | — 대안
- ^ 와 $ — 문자열 또는 줄의 시작·끝
ORO는 \Q 와 \E 메타문자를 지원하지 않는다는 점에 유의하세요. [다른 RE 엔진에서는 RE의 일부를 인용해 메타문자가 그 자체를 나타내도록 쓸 수 있어요.] ${__escapeOroRegexpChars(valueToEscape)} 함수로 동등한 작업을 할 수 있어요. ORO가 지원하는 Perl5 확장 정규표현식은 다음과 같아요.
- (?#text) — 텍스트를 무시하게 하는 내장 주석
- (?:regexp) — "()"처럼 그룹화하되 그룹 매치를 저장하지 않음
- (?=regexp) — 제로 폭 긍정 전방 탐색(positive lookahead). \w+(?=\s) 는 공백 뒤에 오는 단어와 매치하되 MatchResult에 공백은 포함하지 않아요.
- (?!regexp) — 제로 폭 부정 전방 탐색(negative lookahead). foo(?!bar) 는 "bar"가 뒤따르지 않는 "foo"의 모든 출현과 매치해요. 제로 폭 어서션이라 a(?!b)d 는 ad 와 매치한단 걸 기억하세요.
- (?imsx) — 하나 이상의 내장 패턴 매치 수정자. i 는 대소문자 무시, m 은 멀티라인 처리, s 는 싱글라인 처리, x 는 확장 공백 주석을 활성화해요. (?<=regexp) 후방 탐색(lookbehind)은 지원되지 않아요.
21.5 수정자 위치 (Placement of modifiers)
수정자는 정규식 어디든 위치할 수 있고, 그 지점부터 적용돼요. [ORO 버그로 정규식 맨 끝에는 쓸 수 없는데, 어차피 거기선 효과가 없어요.] single-line (?s) 와 multi-line (?m) 수정자는 보통 정규식 시작에 둬요. 대소문자 무시 수정자 (?i) 는 정규식의 일부에만 유용하게 적용할 수 있어요. 예를 들면
Match ExAct case or (?i)ArBiTrARY(?-i) case
이 정규식은 "Match ExAct case or arbitrary case"와 "Match ExAct case or ARBitrary case"는 매치하지만 "Match exact case or ArBiTrARY case"는 매치하지 않아요.
21.6 정규표현식 테스트 (Testing Regular Expressions)
JMeter 2.4부터 View Results Tree 리스너에 RegExp Tester가 포함되어 샘플러 응답 데이터에서 직접 정규표현식을 테스트할 수 있어요. Java 정규표현식을 테스트하는 사이트도 있어요. 또 다른 접근법은 간단한 테스트 계획으로 정규표현식을 테스트하는 거예요. Java Request 샘플러로 샘플을 생성하거나 HTTP Sampler로 파일을 로드할 수 있어요. Debug Sampler와 Tree View 리스너를 추가하면 외부 서버에 접근하지 않고도 정규표현식 변경을 빠르게 테스트할 수 있어요.
더 알아보기
- Elements of a Test Plan — 어서션과 응답 검증
- Component Reference — Response Assertion, Regular Expression Extractor
- Functions — ${__escapeOroRegexpChars(...)}