트랙
/
JavaScript
JavaScript
/
학습 과정
/
정규 표현식
정규

정규 표현식 에서 JavaScript

9개의 연습 문제

정규 표현식 소개

JavaScript의 정규 표현식

정규 표현식(또는 정규식)은 문자열의 특정 요소를 찾아 조작할 때 사용할 수 있는 문자들의 나열이에요. 그래서 다음과 같은 일을 할 수 있어요:

  • 문자열에서 텍스트 검색하기
  • 문자열의 부분 문자열 바꾸기
  • 문자열에서 정보 추출하기

이 개념은 JavaScript에서 정규 표현식을 사용하는 데 초점을 맞춰요. 정규 표현식을 작성하는 방법을 배우고 싶다면 Eloquent JavaScript가 좋은 자료가 될 거예요.

💡 JavaScript의 정규식 문법은 이 언어의 ECMA-262 표준에 포함돼 있어요. 따라서 브라우저별 호환성을 걱정할 필요가 없어요.

정규 표현식 만드는 방법

JavaScript에서 정규 표현식은 주로 /pattern/modifiers 형식으로 작성해요. 여기서 'pattern'은 핵심 정규식이고, 'modifiers'는 특별한 옵션(초능력 같은)을 나타내기 위해 덧붙일 수 있는 문자들이에요.

그래도 정규 표현식을 만드는 방법은 두 가지가 있어요:

  1. 정규 표현식 리터럴:
const regex = /[a-z]/;
  1. RegExp 생성자:
const regex = new RegExp('[a-z]');

두 경우 모두 JavaScript는 정규식으로 객체를 만들어요. 기본적으로는 리터럴로 불변 패턴을 사용하는 걸 권장해요.

RegExp 생성자는 정규식이 바뀌거나 아직 무엇인지 모르는 경우(예: 입력값)에 사용할 수 있어요.

🏴‍☠️ 플래그

정규 표현식에는 flags라는 선택적 초능력이 있어서 추가 기능을 사용할 수 있어요. 이 플래그들은 따로 또는 함께, 순서에 상관없이 사용할 수 있고, 정규 표현식의 일부로 포함돼요.

널리 쓰이는 것들은 다음과 같아요:

  • /g - 전역 검색
  • /i - 대소문자 구분 없음
  • /m - 여러 줄 검색

간단한 예를 볼까요:

const re = /home/gi;
const str = 'Home, sweet home.';

str.match(re);

// => ["Home", "home"]

g 문자는 문자열 안의 가능한 모든 일치 항목을 찾아낼 수 있게 해줘요. 이 기능이 없으면 JavaScript는 첫 번째 Home 일치만 추출해요.

대소문자 구분 없음 플래그 /i는 패턴을 찾을 때 유연하게 해줘요. 덕분에 찾는 대상이 UPPERCASE이든 lowercase이든 상관없어요.

RegExp 생성자를 사용할 때는 플래그를 추가하는 문법이 달라요. 이 경우에는 플래그를 두 번째 인자로 전달하면 돼요.

자주 사용하는 함수

정규 표현식을 JavaScript의 내장 함수와 함께 사용하면 문자열을 조작하고 데이터를 가져오는 강력한 방법을 얻게 돼요.

test() 메서드는 주어진 문자열 안에 찾는 값이 있는지 검색해서 알아내는 좋은 방법이에요. 이렇게 해서 불리언 값인 true 또는 false를 반환해요.

match() 메서드는 주어진 문자열에서 정규 표현식 일치를 추출해요. 정보와 일치 항목들을 담은 배열을 반환해요.

언제 어떤 것을 써야 할까요? 문자열 안에 값이 있는지 빠르게 확인하고 싶다면 test()를 쓰고, 그 값을 사용해야 하거나 일치 항목에 대한 더 많은 정보가 필요하다면 match()를 써요.

Test

test() 메서드는 정규 표현식과 지정된 문자열 사이의 일치를 검색해요. true 또는 false를 반환해요.

const str = 'It is difficult to test if you have a virus';
const result = /virus$/.test(str);

console.log(result);

// => true

Match

그런데 정규 표현식 검색의 실제 값들을 얻고 싶다면 어떨까요?

match() 메서드는 단순히 불리언을 반환하는 대신, 찾은 일치 항목의 존재 여부에 따라 내용이 달라지는 유용한 배열을 반환해요.

이렇게 해서 어떤 문자열에서든 정보를 검색하고 추출할 수 있어요. 예를 들어:

const funnyQuote =
  'If you see someone crying, ask if it is because of their haircut.';
const regex1 = /someone/;
const regex2 = /happy/;

funnyQuote.match(regex1);
// => ["someone", index: 3, input: "If you see someone crying, ask if it is because of their haircut.", groups: undefined]

funnyQuote.match(regex2);
// => null

전역 검색 플래그 /g가 있으면, 인덱스나 입력값 같은 유용한 정보와 함께 일치 항목 하나만 얻는 대신, 배열에 있는 모든 발생을 반환해요:

const funnyQuote =
  'If you see someone crying, ask if it is because of their haircut.';

const regex3 = /if/gi;

funnyQuote.match(regex3);
// => ["If", "if"];

Replace

JavaScript의 replace() 메서드는 주어진 문자열에서 값을 검색하고, 새 값으로 바꿀 수 있게 해줘요.

string.replace(searchValue, newValue);

바꿀 대상을 검색하는 패턴은 단일 문자열일 수도 있고 정규 표현식일 수도 있어요.

let string = 'I like dogs!';
let result = string.replace('dogs', 'cats');

let string = 'I would love to travel to Japan';
let result = string.replace(/Japan/g, 'Hawaii');

게다가 각 값에 추가 변경을 가하기 위해 바꾸는 자리에 함수를 적용할 수도 있어요.

let text = 'Say hello to the chatbot.';
let result = text.replace(/chatbot|hello/gi, function (word) {
  return word.toUpperCase();
});
// => "Say HELLO to the CHATBOT"

💡 결국 정규 표현식과 replace() 메서드를 함께 사용하면 요소를 바꾸는 더 유연한 방법이 돼요. 단일 문자열을 사용하는 건 한계가 있을 수 있어요.

Split

JavaScript의 split() 메서드는 정규 표현식으로 문자열을 사용하고 조작하는 또 다른 방법이에요.

이렇게 해서 패턴을 인식해 주어진 문자열을 나누기 위해 정규식을 사용해요. 예를 들어 str.split(/[,.\s]/)처럼요. 이 패턴은 separator로 사용돼요.

const str = 'hello,user.how are.you';

const result = str.split(/[,.\s]/);

console.log(result);
// => ['hello', 'user', 'how', 'are', 'you']

성능

성능과 관련해서, 둘 다 RegExp 객체를 만들어요. 주요 차이는 정규식이 컴파일되는 빈도예요:

  • Regular Expression Literal을 사용하면: 최초 코드 파싱과 컴파일 시 한 번만 컴파일돼요
  • RegExp() 문법을 사용하면: 새로운 객체가 만들어질 때마다 컴파일돼요.

리터럴 문법을 사용하는 것이 성능뿐만 아니라 단순함과 가독성 면에서도 더 나은 선택일 수 있어요. 자세한 내용은 이 Stackoverflow 토론을 참고해요.

  1. 더 짧고, 클래스 같은 생성자 관점으로 생각하도록 강요하지 않아요.
  2. RegExp() 생성자를 사용할 때는 따옴표를 이스케이프하고 백슬래시를 두 번 이스케이프해야 해요. 이는 본래 읽고 이해하기 어려운 정규 표현식을 더더욱 어렵게 만들어요.
GitHub에서 편집 링크가 새 창이나 탭에서 열려요

정규 표현식 배우기