728x90
반응형
Regex ( Regular Expression )
- 문자열에서 패턴을 검색하거나 대체할 때 사용되는 강력한 도구입니다.
- 수십 줄의 조건문을 정규식 한 줄로 표현 가능할 정도로 짧고 간결한 코드 구성에 용이합니다.
- 문자 검색, 그룹 추출, 치환, 분리까지 전부 처리 가능합니다.
- JavaScript, Python, Java, PHP 등 거의 모든 언어에서 동일한 문법으로 다양한 언어에서 사용 가능합니다.
기본 패턴
패턴 | 설명 | 예시 |
`.` | 아무 문자 1개 (줄바꿈 제외) | `/a.b/`은 "acb", "a#b" 등 |
`^` | 문자열의 시작 | `/^a/`는 "apple"과 매치, "banana"는 X |
`$` | 문자열의 끝 | `/e$/`는 "apple"에 매치 |
`*` | 0개 이상 반복 | `/lo*/`는 "lo", "loo", "looo" 등 |
`+` | 1개 이상 반복 | `/lo+/`는 "lo", "loo", "looo" 등 (0개는 X) |
`?` | 0개 또는 1개 | `/lo?/`는 "l", "lo" |
`{n}` | 정확히 n번 반복 | `/a{3}/`는 "aaa" |
`{n,}` | n번 이상 반복 | `/a{2,}/`는 "aa", "aaa", "aaaa" 등 |
`{n,m}` | n~m번 반복 | `/a{2,4}/`는 "aa", "aaa", "aaaa" |
`[]` | 문자 집합 | `/[abc]/`는 "a", "b", "c" 중 하나 |
`[^]` | 제외한 문자 집합 | `/[^abc]/`는 "a", "b", "c" 아닌 것 |
`( )` | 그룹화 | `/(ab)+/`는 "ab", "abab" 등 |
특수 문자
문자 | 의미 |
`\d` | 숫자 (0 ~ 9) |
`\D` | 숫자가 아닌 문자 |
`\w` | 워드 문자 (알파벳, 숫자, 언더스코어) |
`\W` | 워드 문자가 아닌 것 |
`\s` | 공백 문자 (스페이스, 탭 등) |
`\S` | 공백이 아닌 문자 |
`\b` | 단어 경계 |
`\B` | 단어 경계가 아님 |
`\` | 이스케이프 문자 |
플래그 옵션
플래그 | 의미 |
`g` | 전역 검색 (일치하는 모든 결과를 찾음) |
`i` | 대소문자 구분 없이 검색 |
`m` | 여러 줄 검색: `^`와 `$`가 줄의 시작/끝에 작동 |
`s` | `.`이 줄바꿈 문자(`\n`)도 포함하게 함 |
`u` | 유니코드 지원 (💡 이모지나 특수문자용) |
`y` | lastIndex부터 정확하게 일치하는 위치에서만 검색 (고급 기능) |
관련 메서드
매서드 | 설명 |
`test()` | 패턴이 있는 지 확인합니다. ex) `/abc/.test('abcdef'); // true` |
`exec()` | 첫 매치 결과를 객체로 반환 |
`match()` | 문자열에서 매치되는 부분 추출 ex) `'abc abc'.match(/a./g); // ["ab", "ab"]` |
`replace()` | 문자열 바꾸기 ex) `'abc123'.replace(/\d+/g, ''); // "abc"` |
`split()` | 정규식을 기준으로 문자열 나누기 ex) `'a,b;c.d'.split(/[;,.]/); // ["a", "b", "c", "d"]` |
사용시 주의사항
- 정규식 한 줄로 표현 가능할 정도로 짧고 간결한 코드 구성에 용이하나, 정규식이 복잡해질수록 읽기 어렵고 유지보수가 어렵습니다.
- 에러가 나도 어떤 부분이 문제인지 찾기 힘들기 때문에, 디버깅의 난이도를 높힙니다.
- 잘못된 정규식은 성능 문제를 일으킬 수 있습니다. ( ReDoS 공격 )
- ReDoS 공격 : 공격자가 의도적으로 긴 입력을 넣으면 서버 성능이 마비될 수도 있음
알아두면 좋아요!!
1. 정규식 캐싱
- JavaScript 엔진은 RegExp 객체로 만들면, 내부적으로 파싱해서 AST (추상 구문 트리)로 변환합니다. 그 후, 이를 NFA 기반의 엔진으로 컴파일합니다.
- 이 컴파일된 정규식은 캐싱되어, 같은 정규식을 반복해서 쓰면 재사용합니다. 단, 생성자 방식 new RegExp()는 매번 새 객체를 생성하기 때문에 캐싱되지 않아요!
// 이건 캐시됨 (리터럴 방식)
const re1 = /abc/;
// 이건 매번 새로 생성됨 (컴파일 비용↑)
const re2 = new RegExp('abc');
// ❌ 이렇게 하면 매번 새로 컴파일됨
function isValidEmail(email) {
return new RegExp('^.+@.+$').test(email);
}
// ✅ 이렇게 하면 성능 훨씬 좋음
const emailRegex = /^.+@.+$/;
function isValidEmail(email) {
return emailRegex.test(email);
}
2. ^ , $ 을 적극 활용하여 더 빠른 매치 판단을 내릴 수 있어요.
// ❌ 문자열 어디에 있어도 매치됨 (느림)
/\d{3}-\d{4}/
// ✅ 정확히 시작과 끝 지정 (더 빠름)
const regex = /^\d{3}-\d{4}$/;
3. RegExp.prototype.sticky 플래그 활용 (y)
const str = 'abc abc';
const re = /\w+/y;
re.lastIndex = 4;
console.log(re.exec(str)); // "abc" (index 4에서 정확히 시작해야 함)
// y 플래그는 정확한 위치에서만 매칭을 시도하므로, 불필요한 탐색을 줄일 수 있음
// 이는 큰 문자열을 처리할 때 유용합니다.
728x90
반응형
'javascript' 카테고리의 다른 글
알아두면 유용한 Regex 리스트와 match, matchAll (0) | 2025.04.16 |
---|---|
Single Thread와 Javascript (0) | 2025.03.31 |
Scope Closure Currying (0) | 2025.03.30 |