본문 바로가기

Development/Javascript

모던 자바스크립트 입문 - Chapter 12: 정규 표현식 💻

자바스크립트 개발을 하다 보면 텍스트 처리와 문자열 검증이 필수적입니다.

사용자가 입력한 이메일 주소가 올바른 형식인지 확인하거나, 특정 패턴의 문자열을 찾아 바꾸는 작업 등을 할 때 정규 표현식(Regular Expression)만큼 강력한 도구는 없습니다.

이번 포스트에서는 모던 자바스크립트에서 정규 표현식을 효과적으로 활용하는 방법들을 살펴보겠습니다.

 

📌 목차

  • 정규 표현식의 기본 개념과 사용법
  • 기본적인 정규 표현식 패턴 작성하기
  • 문자열 메서드를 활용한 패턴 매칭
  • RegExp 객체의 활용법
  • ES6+ 정규 표현식 새로운 기능들

📝 정규 표현식의 기본 개념과 사용법

정규 표현식은 문자열에서 특정 패턴을 찾거나 매칭하기 위한 강력한 도구입니다.

자바스크립트에서는 두 가지 방법으로 정규 표현식을 생성할 수 있습니다.

리터럴 방식

const regex1 = /hello/;
const regex2 = /hello/i; // 대소문자 구분 안함

생성자 방식

const regex3 = new RegExp('hello');
const regex4 = new RegExp('hello', 'i');

정규 표현식의 플래그들을 살펴보면:

  • i: 대소문자 구분 안함
  • g: 전역 검색 (모든 매치 찾기)
  • m: 다중 행 모드
  • s: 점(.)이 개행 문자도 매칭
  • u: 유니코드 모드
  • y: sticky 모드
const text = "Hello World! hello universe!";
const globalRegex = /hello/gi;
console.log(text.match(globalRegex)); // ["Hello", "hello"]

📝 기본적인 정규 표현식 패턴 작성하기

실제 개발에서 자주 사용되는 패턴들을 살펴보겠습니다.

문자 클래스와 메타 문자

// 숫자 매칭
const numberPattern = /\d+/; // 하나 이상의 숫자
console.log("abc123def".match(numberPattern)); // ["123"]

// 문자 매칭
const letterPattern = /[a-zA-Z]+/; // 하나 이상의 영문자
console.log("hello123".match(letterPattern)); // ["hello"]

// 공백 문자 매칭
const spacePattern = /\s+/; // 하나 이상의 공백
console.log("hello world".match(spacePattern)); // [" "]

수량 한정자

// 정확히 n번 반복
const exactPattern = /\d{3}/; // 정확히 3개의 숫자
console.log("12345".match(exactPattern)); // ["123"]

// n번 이상 반복
const minPattern = /\d{2,}/; // 2개 이상의 숫자
console.log("1234".match(minPattern)); // ["1234"]

// n번 이상 m번 이하 반복
const rangePattern = /\d{2,4}/; // 2~4개의 숫자
console.log("12345".match(rangePattern)); // ["1234"]

 


📝 패턴 매칭을 하는 문자열 메서드

자바스크립트 문자열 객체에서 제공하는 정규 표현식 관련 메서드들을 살펴보겠습니다.

match() 메서드

const text = "JavaScript는 2023년에도 인기 있는 언어입니다.";
const yearPattern = /\d{4}/g;
console.log(text.match(yearPattern)); // ["2023"]

// 그룹 캡처 활용
const datePattern = /(\d{4})-(\d{2})-(\d{2})/;
const dateString = "오늘은 2023-12-25입니다.";
const match = dateString.match(datePattern);
console.log(match[1]); // "2023" (년)
console.log(match[2]); // "12" (월)
console.log(match[3]); // "25" (일)

replace() 메서드

// 단순 교체
const text1 = "Hello World";
console.log(text1.replace(/World/, "JavaScript")); // "Hello JavaScript"

// 전역 교체
const text2 = "apple apple apple";
console.log(text2.replace(/apple/g, "orange")); // "orange orange orange"

// 그룹을 이용한 교체
const phoneNumber = "010-1234-5678";
const formatted = phoneNumber.replace(/(\d{3})-(\d{4})-(\d{4})/, "($1) $2-$3");
console.log(formatted); // "(010) 1234-5678"

search()와 split() 메서드

// search() - 첫 번째 매치 위치 반환
const text = "찾고 있는 패턴은 123입니다.";
console.log(text.search(/\d+/)); // 9

// split() - 패턴으로 문자열 분할
const csv = "apple,banana,cherry";
console.log(csv.split(/,/)); // ["apple", "banana", "cherry"]

const spaces = "word1   word2     word3";
console.log(spaces.split(/\s+/)); // ["word1", "word2", "word3"]

📝 RegExp 객체

RegExp 객체의 메서드와 속성을 활용하면 더 세밀한 제어가 가능합니다.

test() 메서드

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function validateEmail(email) {
    return emailRegex.test(email);
}

console.log(validateEmail("test@example.com")); // true
console.log(validateEmail("invalid-email")); // false

exec() 메서드

const text = "Price: $100, Discount: $20, Total: $80";
const pricePattern = /\$(\d+)/g;
let match;

while ((match = pricePattern.exec(text)) !== null) {
    console.log(`Found price: ${match[1]}`);
}
// Found price: 100
// Found price: 20
// Found price: 80

RegExp 속성 활용

const regex = /hello/gim;
console.log(regex.global); // true
console.log(regex.ignoreCase); // true
console.log(regex.multiline); // true
console.log(regex.source); // "hello"
console.log(regex.flags); // "gim"

📝 ECMAScript 6부터 추가된 정규 표현식의 새로운 기능

유니코드 플래그 (u)

// 유니코드 문자 매칭
const unicodeRegex = /^\u{1F600}$/u; // 😀 이모지
console.log(unicodeRegex.test("😀")); // true

// ES6 이전 방식으로는 제대로 동작하지 않음
const legacyRegex = /^\u{1F600}$/;
console.log(legacyRegex.test("😀")); // false

Sticky 플래그 (y)

const text = "abc123def456";
const stickyRegex = /\d+/y;

stickyRegex.lastIndex = 3; // 인덱스 3부터 시작
console.log(stickyRegex.exec(text)); // ["123"]
console.log(stickyRegex.lastIndex); // 6

console.log(stickyRegex.exec(text)); // null (연속된 위치에 패턴이 없음)

명명된 캡처 그룹 (ES2018)

const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = "2023-12-25".match(dateRegex);

console.log(match.groups.year); // "2023"
console.log(match.groups.month); // "12"
console.log(match.groups.day); // "25"

 


📚 마무리 정리

오늘 배운 내용들을 정리하면:

정규 표현식은 문자열 패턴 매칭의 강력한 도구로, 리터럴 방식과 생성자 방식으로 생성할 수 있습니다.

기본 메타 문자와 수량 한정자를 조합하여 복잡한 패턴을 만들 수 있으며, 문자열의 match(), replace(), split() 등의 메서드와 함께 사용하여 실용적인 텍스트 처리가 가능합니다.

RegExp 객체의 test()와 exec() 메서드를 활용하면 더 세밀한 제어가 가능하고, ES6+ 에서 추가된 유니코드 플래그, sticky 플래그, 명명된 캡처 그룹 등의 새로운 기능들로 더욱 강력한 패턴 매칭을 구현할 수 있습니다.

💡 오늘 새롭게 알게 된 것

  • 정규 표현식의 플래그들(i, g, m, s, u, y)이 각각 다른 매칭 동작을 제어한다는 점입니다
  • 명명된 캡처 그룹을 사용하면 매칭 결과를 더 명확하게 다룰 수 있다는 점입니다.
  • sticky 플래그(y)가 연속된 위치에서의 매칭을 강제한다는 점입니다.

🤔 어려웠던 점

  • 복잡한 패턴을 작성할 때 메타 문자들의 조합이 헷갈리는 것 같습니다.
  • 그룹 캡처와 백참조 개념을 이해하고 활용하는 부분입니다.
  • 성능을 고려한 정규 표현식 작성 방법입니다.

🎯 다음 학습 계획

다음 포스팅에서는 웹 브라우저의 객체에 대해 알아보겠습니다.