JavaScript에서 다음 RegExp.prototype.test 구문을 이용하여 정규표현식을 검증하려 할 때가 있습니다.
const regex = /hello/g; console.log(regex.test('hello')); console.log(regex.test('hello'));
위 예시에서 정규표현식의 내용과 확인할 문자열이 모두 같기 때문에 두 로그의 값은 true
가 나와야 할 것입니다. 하지만 실제 결과는 다음과 같이 표시됩니다.
true false
아이러니하게도 두번째 실행 결과가 false
로 나타났습니다.
원인과 해결 방법
이 문제는 정규표현식에 g
플래그를 달았을 때 발생하는 문제입니다. 간단하게 g플래그를 제거하면 문제가 해결됩니다.
const regex = /hello/; console.log(regex.test('hello')); // true console.log(regex.test('hello')); // true
정규표현식의 g
플래그는 표현식을 만족하는 하나 이상의 값을 찾습니다. 즉 문자열에서 일치하는 값을 찾게 된 시점의 포지션(lastIndex)을 기억하고 있으며, 다음 검증 시 해당 인덱스로부터 검색을 수행합니다.
const regex = /hello/g; console.log(regex.test('hello')); // true console.log(regex.lastIndex); // 5 console.log(regex.test('hello')); // false console.log(regex.lastIndex); // 0 console.log(regex.test('hello')); // true console.log(regex.lastIndex); // 5
위 예시에서 확인할 수 있듯이 처음 검색을 수행한 후에는 마지막 인덱스 위치가 5를 가리키고 있는 것을 확인할 수 있습니다. 이제 다음 검색은 lastIndex의 값으로부터 검색을 수행하는데, 이 때 정규식에 일치하는 값이 없으므로 false를 반환하게 됩니다. false가 반환되면 다시 lastIndex값은 0으로 초기화됩니다.
결국 이로인해 동일하지 않은 값이 반복되어 나타나게 되는 것입니다. 단순히 여러 문자열을 하나씩 정규식을 통해 검증하려면 g
플래그를 사용하지 않아야 합니다.
아니면 아래와 같이 매 과정 마다 lastIndex를 0으로 초기화해도 됩니다.
const regex = /hello/g; console.log(regex.test('hello')); // true regex.lastIndex = 0; console.log(regex.test('hello')); // true regex.lastIndex = 0;
이렇게하면 매번 처음 문자열의 포지션부터 검색을 수행하기 때문에 원하는 결과를 얻을 수 있게 됩니다.