[JS] 모던 자바스크립트 Deep Dive 31장

신지·2024년 5월 12일
post-thumbnail

* 모던 자바스크립트 Deep Dive을 토대로 공부한 것을 정리한 내용으로, 모든 인용문은 모던 자바스크립트 Deep Dive의 문구를 인용한 것입니다.

💡 31장. RegExp

💫 정규 표현식이란?

정규 표현식(regular expression)은 일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어다.

정규 표현식은 자바스크립트의 고유 문법이 아니며, 대부분의 프로그래밍 언어와 코드 에디터에 내장되어 있다.
정규 표현식은 패턴 매칭 기능을 제공한다. 패턴 매칭 기능이란 특정 패턴과 일치파는 문자열을 검색하거나 추출 또는 치환할 수 있는 기능을 말한다.

const tel = '010-1234-567팔';

cosnt regExp = /^\d{3}-\d{4}-\d{4}$/;

regExp.test(tel);	// false

위처럼 전화번호 패턴에 매칭하는 결과를 뽑아내고 싶을 때, 정규표현식을 사용하지 않는다면 수많은 반복문과 조건문을 사용해야 할 것이다.


💫 정규 표현식의 생성

정규 표현식 객체를 생성하기 위해서는 정규 표현식 리터럴과 RegExp 생성자 함수를 사용할 수 있다.

위와 같은 정규 표현식 리터럴이 더 일반적으로 사용되며, 정규 표현식 리터럴은 패턴과 플래그로 구성된다. 위처럼 정규 표현식 리터럴은 패턴과 플래그로 구성되어 있다.

아래에서 같은 정규 표현식을 정규 표현식 리터럴과 생성자 함수로 표현한 예제를 살펴보자.
아래는 패턴 is가 문장에 속해 있는지 매칭 결과를 반환하는 코드이다.

  • 정규 표현식 리터럴
const target = 'Is this all there is?';

// i(플래그) : 대소문자를 구분하지 않고 검색한다.
const regexp = /is/i;

regexp.test(target);	// true
  • 정규 표현식 객체
const target = 'Is this all there is?';

const regexp = new RegExp(/is/i);

regexp.test(target);

💫 RegExp 메서드

위의 예제에서 사용된 regexp.test의 test는 RegExp의 메서드 중 하나이다. 그렇다면 RegExp의 메서드를 알아보자!

🧐 RegExp.prototype.exec

exec 메서드는 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색하여 매칭 결과를 배열로 반환한다. 매칭 결과가 없는 경우 null을 반환한다.

🧐 RegExp.prototype.test

test 메서드는 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색하여 매칭 결과를 불리언으로 반환한다.

🧐 String.prototype.match

String 표준 빌트인 객체가 제공하는 match 메서드는 대상 문자열과 인수로 전달받은 정규 표현식과의 매칭 결과를 배열로 반환한다.

아래 예제를 통해 결과를 확인해보자!

const target = 'Is this all there is?';
const regExp = /is/;

regExp.exec(target);
// ["is", index: 5, input: "Is this all there is?", groups: undefined]

regExp.test(target);
// true

target.match(regExp);
// ["is", index: 5, input: "Is this all there is?", groups: undefined]

const regExp2 = /is/g;
target.match(regExp2);
// ["is", "is"]

이때 주의깊게 봐야 할 부분은, RegExp.prototype.execString.prototype.match는 같은 결과를 내놓지만 exec는 g 플래그를 지정해도 첫 번째 매칭 결과만을 반환하고 match는 g 플래그를 지정하면 모든 매칭 결과를 배열로 반환한다는 것이다.

밑에서 다시 설명하겠지만, g 플래그는 대상 문자열 내에서 패턴과 일치하는 모든 문자열을 전역 검색하는 플래그이다.

💫 플래그

정규 표현식의 플래그는 검색 방식을 설정하기 위해 사용된다. 교재에는 3개의 플래그가 있지만 나는 6개의 플래그를 살펴보고자 한다. 상단의 3개가 교재에 나온 플래그이다.

플래그의미설명
iignore case대소문자를 구분하지 않고 패턴을 검색한다.
gGlobal대상 문자열 내에서 패턴과 일치하는 모든 문자열을 전역 검색한다.
mMulti line문자열의 행이 바뀌더라도 패턴 검색을 계속한다.
ystickylastIndex 속성을 이용해 원하는 위치에서 검색을 시작한다.
uunicode유니코드 문자를 처리한다.
ssingle line개행 (\n)을 무시하고 단일 라인으로 취급하여 검색한다.

💫 패턴

정규 표현식은 "일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어"다.

  • 패턴은 /로 열고 닫으며 문자열의 따옴표는 생략한다.
  • 따옴표를 포함하면 따옴표까지도 패턴에 포함되어 검색된다.
  • 어떤 문자열 내에 패턴과 일치하는 문자열이 존재할 때 '정규 표현식과 매치한다'고 표현한다.

🧐 문자열 검색

정규 표현식의 패턴에 문자 또는 문자열을 지정하면 검색 대상 문자열에서 패턴으로 지정한 문자 또는 문자열을 검색한다. 밑의 예제를 통해 여러가지 패턴을 검색하는 법을 알아보자.

const target = 'Is this all there is?';

// 'is' 문자열과 매치하는 패턴. i 플래그를 추가했기 때문에 대소문자를 구분하지 않는다.
const regExp01 = /is/i;
target.match(regExp01);
// ["Is", index: 0, input: "Is this all there is?", groups: undefined]

// 'is' 문자열과 매치하는 패턴. ig 플래그를 추가했기 때문에 대소문자를 구분하지 않는 동시에 모든 문자열을 전역 검색한다.
const regExp02 = /is/ig;
target.match(regExp02);
// ["Is", "is", "is"]

🧐 임의의 문자열 검색

.은 임의의 문자 한 개를 의미한다. 문자의 내용은 무엇이든 상관없다. 아래의 예제는 .을 통해 패턴을 생성했으므로 문자의 내용과 상관없이 3자리 문자열과 매치한다.

const target = `Is this all there is?`;
cosnt regExp = /.../g;

target.match(regExp);
// ["Is ", "thi", "s a", "ll ", "the", "re ", "is?"]

🧐 반복 검색

  • {m, n}은 최소 m번, 최대 n번 반복되는 문자열을 의미한다. 이때, 콤마 뒤에 공백이 있으면 정상 동작하지 않는다.
  • {n}은 패턴이 n번 반복되는 문자열을 의미한다.
  • {n,}은 패턴이 최소 n번 이상 반복되는 문자열을 의미한다.
  • +는 패턴이 최소 한 번 이상 반복되는 문자열을 의미한다.
  • ?는 패턴이 최대 한 번(0번 이상) 반복되는 문자열을 의미한다.

말로만 보면 잘 와닿지 않으니 아래 예제를 통해 확인해보자.

const target = 'A AA B BB Aa Bb AAA';

//'A'가 최소 1번, 최대 2번 반복되는 문자열을 전역 검색한다.
const regExp01 = /A{1,2}/g;
target.match(regExp02); // ["A", "AA", "A", "AA", "AA"]

//'A'가 2번 반복되는 문자열을 전역 검색한다.
const regExp02 = /A{2}/g;
target.match(regExp02); // ["AA", "AA"]

//'A'가 최소 2번 이상 반복되는 문자열을 전역 검색한다.
const regExp03 = /A{2,}/g;
target.match(regExp03); // ["AA", "AAA"]

//'A'가 최소 1번 이상 반복되는 문자열을 전역 검색한다.
const regExp04 = /A+/g;
target.match(regExp04); // ["A", "AA", "A", "AAA"]


// colou?r은 'colo'다음 'u'가 최대 한 번 (0번 포함) 이상 반복된 후 'r'이 이어지는 문자열을 검색한다.
const tatget2 = 'color colour';

const regExp05 = /colou?r/g;

target.match(regExp05)	// ["color", "colour"]

🧐 OR 검색

|는 OR의 의미를 가진다.

const target = `A AA B BB Aa Bb`;
const regExp = /A|B/g;

target.match(regExp); // ["A", "A", "A", "B", "B", "B", "A", "B"]

🧐 NOT 검색

[...] 내의 ^은 NOT의 의미를 가진다.

const target = `A AA B BB Aa Bb`;

const regExp = /[^0-9]+/g;
target.match(regExp);	// ["AA BB ", " Aa Bb"]

🧐 시작 위치로 검색

[...] 밖의 ^ 문자열은 시작 의미를 가진다. 이때, [...] 내의 ^는 NOT의 의미를 가지므로 주의해야 한다.

const target = 'https://for_web_er.com';

const regExp = /^https/;
regExp.test(target);	// true

🧐 마지막 위치로 검색

$는 문자열의 마지막을 의미한다.

const target = 'https://for_web_er.com';

const regExp = /com$/;
regExp.test(target);	// true


리뷰

몰랐던 부분과 더 공부해보고 싶은 부분

부끄럽지만 사실 정규 표현식을 따로 공부해본 적이 없어서 필요할 때마다 검색해서 사용했었다... 이번 기회에 정규 표현식을 어떻게 사용하는지 알게 되었으니 다음에 전화번호 등 정규표현식이 필요할 일이 생기면 꼭 내 기억을 더듬어서 사용해보고 싶다!

공부하면서 든 생각

원래 32장 String을 하려고 했는데... 과제하다보니까 내가 정규표현식을 너무 모르는 것 같아서 이번 기회에 공부해보려고 선정했다!! 전화번호나 날짜 같은 거.... 특히 형식 검사 보니까 내가 너무 삶의 질이 떨어지는 개발을 하고 있던 것 같아서 반성했다...

3개의 댓글

comment-user-thumbnail
2024년 5월 13일

저도 정규표현식에 대해 다뤘는데! 마찬가지로 자스에서의 정규표현식이 익숙치 않아서 이 부분을 택했어요 ㅎㅎ. 저는 필요할 때 찾아보려는 목적으로 정리를 했는데, 신지님은 완전 학습 목적으로 원리를 다뤄주셔서 너무 좋네요.. 공부해서 적용하려는 생각보다 빠르게 복붙할 거리를 만들려고 했던 마음을 급 반성하고 갑니다 ㅎㅎㅎ.. 특히 RegExp.prototype.exec이랑 String.prototype.match를 비교해주신 부분이 인상깊네요..! match는 g 플래그 지정 시 모든 매칭 결과 "배열"반환.. 기억해두겠습니다!!! 좋은 아티클 감사해요! 오늘도 넘 깔끔하게 정리된 아티클 잘 읽구갑니다! 🥰

답글 달기
comment-user-thumbnail
2024년 5월 13일

아무래도 겹치지 않는 주제 선정에는 실패하신 거 같지만,,ㅋ ㅋ𐌅 ࠅ ヲ𐨛 𐌅 ࠅ ヲ𐨛𐌅 ࠅ 이번주도 꼼꼼한 아티클 감사합니다..!! 신지님만의 시각으로 담아주셔서 꼼꼼하게 해당 부분을 돌아볼 수 있었습니다..! 매번 느끼는 거지만, 신지님의 아티클은 처음 공부하는 사람이 봐도 손색이 없을 정도로 쉽고 꼼꼼하게 잘 담아주시는 거 같아요..!! 유용한 아티클 감사합니다💗

답글 달기
comment-user-thumbnail
2024년 5월 13일

ㅋㅋㅋㅋ 이번에도 겹치지 않는 주제 선정에는 실패하셨네요 ㅎ ㅎ저는 해당 부분은 어려워서 다 이해하지 못하고 넘어간 부분도 있었는데요,, 예제 위주로 잘 정리해주셔서 읽으면서 이해되지 않는 부분도 예제코드를 보며 잘 이해하고 넘어갈 수 있었던 것 같습니다! 깔끔한 정리 감사해요 ㅎㅎㅎ 신지님의 아티클은 매번 주제 선정 이유나 새롭게 알게 된 부분을 다뤄주셔서 좋은 것 같습니다. 또한 반성도 되네요..저는 과제를 구현하기 급급했었는데 저도 자주 검색하게 되는 부분은 따로 잘 공부를 해서 정리해두어야겠어요! 이번주도 고생하셨습니다~

답글 달기