HooneyLog
© 2026 Seunghoon Shin. All rights reserved.
모든 게시글
javascript
2022. 4. 29.•
0

JavaScript 정규표현식: 생성자 함수(RegExp)로 동적 패턴 완벽하게 다루기

Seunghoon Shin
작성자 Seunghoon Shin풀스택 개발자

JavaScript 정규표현식: 생성자 함수(RegExp)로 동적 패턴 완벽하게 다루기

1. 문제의 배경

자바스크립트에서 문자열을 다룰 때 정규표현식(Regular Expression)은 빠질 수 없는 강력한 도구입니다. 보통 우리는 /pattern/gi와 같은 리터럴(Literal) 방식을 사용하여 정적 패턴을 정의하곤 하죠.

하지만 실무에서는 매칭해야 할 패턴이 코드 작성 시점이 아닌 런타임(Runtime)에 결정되는 경우가 많습니다. 예를 들어 사용자가 입력한 검색어를 하이라이팅하거나, 특정 파라미터로 넘어온 금칙어를 필터링해야 하는 상황입니다. 이때 많은 주니어 개발자들이 다음과 같은 실수를 하곤 합니다.

const text = "안a녕A하a세A요"; const letter = "A"; // ❌ 의도한 대로 작동하지 않습니다. // 변수 letter가 아닌 문자열 "letter" 자체를 찾으려고 시도합니다. const result = text.replace(/letter/gi, " ");

위 코드의 결과는 원본 문자열 그대로입니다. 리터럴 방식의 슬래시(/ /) 안에는 변수를 직접 넣을 수 없기 때문입니다.

2. 해결 방안 탐색

이 문제를 해결하기 위해서는 자바스크립트가 제공하는 정규표현식의 또 다른 생성 방식인 생성자 함수(new RegExp)를 사용해야 합니다.

리터럴 방식과 생성자 방식은 각각 장단점이 뚜렷합니다.

  • 리터럴 방식: 스크립트가 로드될 때 컴파일되므로 성능상 유리하고 가독성이 좋지만, 패턴이 고정되어야 합니다.
  • 생성자 방식: 실행 시점에 패턴이 컴파일되므로 동적인 변수를 사용할 수 있지만, 문자열 내의 역슬래시(``) 처리에 주의해야 합니다.

우리의 목적은 동적 패턴 생성이므로 생성자 함수를 선택하는 것이 타당합니다.

3. 핵심 개념 및 아키텍처

new RegExp(pattern, flags) 문법을 사용하면 첫 번째 인자로 문자열을 전달할 수 있습니다. 자바스크립트 엔진은 이 문자열을 평가하여 내부적인 정규식 객체를 생성합니다.

정규식 생성 프로세스 흐름

생성자 방식을 사용할 때 가장 중요한 포인트는 이스케이프(Escaping)입니다. 리터럴에서는 \d라고 쓰면 되지만, 문자열에서는 `` 자체가 특수문자이므로 "\\d"와 같이 두 번 써줘야 정규식 엔진에 정상적으로 전달됩니다.

4. 구현 및 트러블슈팅

이제 변수를 안전하게 전달하여 정규식을 처리하는 함수를 구현해 보겠습니다.

기본 구현 (TypeScript)

/** * 특정 문자를 동적으로 받아 공백으로 치환하는 함수 */ const replaceDynamicLetter = (text: string, letter: string): string => { // 변수 letter를 생성자의 첫 번째 인자로, 플래그를 두 번째 인자로 전달 const regex = new RegExp(letter, "gi"); return text.replace(regex, " "); }; const source = "안a녕A하a세A요a저a는A신a승A훈a입a니A다"; console.log(replaceDynamicLetter(source, "A")); // 결과: "안 녕 하 세 요 저 는 신 승 훈 입 니 다"

트러블슈팅: 특수문자가 포함된 변수 처리

만약 변수 letter에 . 이나 * 같은 정규식 특수문자가 들어온다면 의도치 않은 매칭이 발생할 수 있습니다. 이를 방지하기 위해 Regex Escape 유틸리티를 함께 사용하는 것이 시니어 레벨의 정석입니다.

const escapeRegExp = (str: string) => { return str.replace(/[.*+?^${}()|[]]/g, '\\$&'); // 특수문자 앞에 \ 추가 }; const safeReplace = (text: string, pattern: string) => { const safePattern = escapeRegExp(pattern); const regex = new RegExp(safePattern, "gi"); return text.replace(regex, " "); };

5. 결과 및 Trade-off

성과

  • 유연성 극대화: 사용자 입력이나 외부 API 데이터에 기반한 실시간 필터링 시스템을 구축할 수 있습니다.
  • 코드 중복 감소: 유사한 패턴을 가진 여러 정규식을 하나의 함수로 관리할 수 있습니다.

Trade-off 및 주의점

  • 성능 오버헤드: 반복문 내부에서 new RegExp를 남발하면 매번 컴파일이 발생하여 성능이 저하될 수 있습니다. 가능한 경우 컴파일된 객체를 재사용(Memoization)해야 합니다.
  • 가독성: 역슬래시를 두 번 써야 하는 특성상(\\w, \\s), 패턴이 복잡해질수록 가독성이 리터럴에 비해 떨어집니다.

6. 마치며

변수를 활용한 정규표현식 처리는 단순해 보이지만, 생성자 함수의 동작 원리와 문자열 이스케이프의 함정을 정확히 이해해야 버그 없는 견고한 코드를 짤 수 있습니다.

단순히 기능을 구현하는 것을 넘어, 보안과 성능까지 고려하는 시니어의 관점에서 동적 패턴을 다루어 보시길 바랍니다!

참고 자료:

  • MDN Web Docs: RegExp
  • JavaScript.info: RegExp Constructor
← 이전 글타입스크립트에서 여러 객체를 상속받을 수 있는 Mixin 패턴을 알아보자!
다음 글 →Interface type guard 하는 방법