main-logo

정규표현식, 복잡하지 않습니다!

문득 보면 어려워 보이는 정규표현식, 하나씩 천천히 살펴보자!

profile
nocturne9no1
2023년 02월 25일 · 0 분 소요

서론

웹 개발을 하다보면 유저가 입력한 텍스트에 대해 검증해야 하는 경우가 있습니다. 대표적인 예시로 회원 가입시 비밀번호 입력을 들 수 있습니다. ‘영문 대문자, 소문자, 특수기호로 이뤄져야 한다.’ 많이들 보시지 않았나요?? 그렇다면 프론트엔드에서는 이러한 검증 로직을 어떻게 구현하고 있을까요?? 이 물음에 대해 알아보며 정규 표현식의 편리함에 대해 알아보는 시간을 가져보려 합니다.

본론

정규 표현식이 왜 필요할까?

정규 표현식이 무엇인지에 대해서는 잠시 접어두고 텍스트를 검증하려면 어떻게해야 할 지 생각해봅니다. 간단하게 ‘알파벳으로만 이루어진 텍스트’인지를 검증하는 로직을 구현해봅시다.

‘abcdef1000ghi’ 라는 텍스트를 검증해보기 위해 반복문을 사용해 보겠습니다.

const validAlphabet = (str) => {
  let i;
  for (i = 0; i < str.length; i++) {
    if (!isNaN(parseInt(str[i]))) {
      return false;
    }
  }
  return true;
};

한 문자씩 순회하며 해당 문자가 숫자인지를 확인하며 하나라도 숫자라면 즉시 false 를 반환하여 마지막까지 도달했다면 모두 문자이므로 true를 반환하도록 하였습니다.

지금은 ‘숫자인지’ 하나만 검증하지만 만약에 특수문자, 글자 수 제한, 특정 패턴 추가 등이 들어간다면 검증 함수 하나만으로 수백줄의 코드를 작성해야 할 수도 있습니다. 수없이 많은 반복문과 조건문의 반복이죠… 하지만 정규표현식을 사용한다면 이 과정을 단 한줄로 사용할 수 있습니다!

그래서 어떻게 쓰죠?

정규 표현식 객체를 생성하려면 정규 표현식 리터럴이나 RegExp 생성자 함수를 사용해야합니다. 일반적으로는 정규 표현식 리터럴을 사용합니다.

/(패턴)/i

정규 표현식 리터럴은 위와 같이 /를 통해 시작과 종료를 나타내고 그 안에 패턴을 넣은 뒤 마지막으로 플래그를 넣으면 됩니다. 간단하게 사용해보죠.

const text = 'I am a boy.';

const regExp = /am/i;
// const regExp = new RegExp(/am/i); 와 같이 표현할 수도 있습니다!

regExp.test(text); // true;

변수 regExp에 정규표현식 객체를 생성하여 test 메소드를 통해 text 변수에 ‘am’ 이라는 텍스트가 들어있는 지에 대해 검사하였습니다. 여기에는 I am a boy 이기 때문에 true 를 반환하네요!

플래그

/am/ 까지는 알겠는데 뒤에 i는 그럼 뭔가요?

위와 같은 질문이 나올 타이밍인 것 같습니다.

위에서 패턴 이후에 마지막에 ‘플래그’가 나온다고 했었죠. 이 플래그의 역할은 정규 표현식의 검색 방식을 설정합니다. 플래그에는 총 여섯가지가 있습니다. 간단하게 살펴보죠

flag meaning deteail
i Ignore Casing 대소문자 구별 없이 패턴 검사
g Global 패턴과 일치하는 모든 문자열 전역 검색
s Dot All . (온점)이 개행 문자(\n)도 포함함
m Multiline 행이 바뀌어도 계속 검색
y Sticky 문자 내 특정 위치에서 검색을 시작
u Unicode 유니코드 전체 지원

플래그는 옵션입니다. 또한 순서와 상관없이 하나 이상의 플래그를 동시에 사용할 수도 있습니다.

패턴

패턴은 /로 열고 닫고 따옴표""는 생략합니다. 따옴표가 들어가면 따옴표까지도 패턴에 포함되어 검색해버립니다. 처음 살펴봤던 예제에서 /am/i 를 통해 대소문자 구분 없이 ‘am’을 탐색할 수 있었습니다. 패턴을 표현하는 방법은 다양합니다. 지금부터 패턴을 표현하는 방법에 대해 간단하게 살펴보겠습니다.

  • .

    • 임의의 문자 한 개를 의미합니다. 문자의 내용은 상관없습니다. 단 \ 는 불가능합니다.
    • const text = 'I am a boy.';

    const regExp = /../g;

    console.log(text.match(regExp)); // [ ‘I ’, ‘am’, ’ a’, ’ b’, ‘oy’ ]

    - 임의의 글자 수가 2개인 묶음의 배열을 반환하는 것을 볼 수 있습니다.
  • {}

    • 수량 패턴입니다. 대괄호에 들어가는 값에 따라 개수에 다른 의미를 부여할 수 있습니다.
    • 만약 숫자가 하나만 들어간다면 앞의 패턴이 그 수만큼 반복되는 문자열을 나타냅니다.
    • const text = '1 22 333 444';

    const regExp = /3{3}/g;

    console.log(text.match(regExp)); // [‘333’]

    - 숫자가 {Min,Max}의 형태로 들어갈 수도 있습니다. 이 경우 최소, 최대 반복 횟수를 결정할 수 있는 것입니다. 주의할 점은 Min,Max 사이에 공백이 없어야합니다.
    
    - ```js
    const text = '얍 얍얍얍 얍얍 얍 얍얍얍';
    
    const regExp = /얍{2,3}/g;
    
    console.log(text.match(regExp)); // [ '얍얍얍', '얍얍', '얍얍얍' ]
    • {Min,} 의 형태를 가진다면 최소 개수 이상의 반복되는 패턴을 의미합니다.
    • const text = '얍 얍얍얍 얍얍 얍 얍얍얍';

    const regExp = /얍{2,}/g;

    console.log(text.match(regExp)); // [ ‘얍얍얍’, ‘얍얍’, ‘얍얍얍’ ]

    
    
  • +

    • 최소 한번 이상 반복되는 문자열을 의미합니다. 위에 설명한 {} 에서 {1,} 과 같은 의미입니다.
    • const text = '얍 헐 얍얍 얍 얍얍얍';

    const regExp = /얍+/g;

    console.log(text.match(regExp)); // [ ‘얍’, ‘얍얍’, ‘얍’, ‘얍얍얍’ ]

    
    
  • []

    • 괄호안에 제시한 문자들을 범위로 한 문자열을 의미합니다.
    • 이를 응용하면 [a-zA-Z], [ㄱ-ㅎ가-힣] 등을 통해 알파뱃이나 한글 문자로 입력을 제한할 수 있습니다.
    • 문자 앞에 ^ 를 붙이면 특정 문자를 제외할 수 있습니다. 만약 [] 없이 사용한다면 특정 문자열로 시작하는 것을 의미합니다.
  • $

    • ^ 이 문자열의 시작을 의미한다면 $ 는 반대로 문자열의 끝날 시점을 의미합니다.

자주 사용하는 패턴

지금까지 간단하게 정규표현식을 사용하는 방법에 대해 알아보았습니다. 그렇다면 이런 정규표현식들은 어디에서 주로 쓰일까요?? 자주 쓰이는 용례를 통해 그 씀씀이를 살펴보겠습니다!

  • 웹사이트의 주소

    • 정규표현식: /https?:\/\/[\w\-\.]+/g
    • 분석
    • http로 시작하고 s?를 통해 http, https 둘다 문자열의 시작으로 판단합니다.
    • : 를 통해 http나 https 뒤에는 : 가 와야함을 의미합니다.
    • \/\/ 를 통해 : 다음에 //가 와야함을 의미합니다.
    • [\w\-\.]+ : \w 는 영어 알파벳, 숫자, 언더스코어를 의미합니다. 여기에 온점(.)을 더하여 포함된 문자열이 한개 이상 있음을 판단합니다.
    • /g 매칭되는 것을 모두 찾습니다.
  • 핸드폰 번호

    • 우리나라의 핸드폰 번호는 000-0000-0000의 형태를 가지고 있습니다.
    • {} 수량 패턴을 응용하여 정규표현식을 만들 수 있습니다.
    • 정규표현식: /\d{3}-\d{4}-\d{4}/g
    • 분석
    • \d 는 숫자를 의미합니다.
    • {3} 과 {4} 를 통해 숫자 패턴이 각 3개, 4개인 패턴을 찾아냅니다.
  • 이메일주소

    • 회원가입, 로그인 등에서 이메일 주소 패턴 파악은 널리 사용됩니다.
    • 이메일은 보통 {id}@{.이 포함된 주소} 로 이루어져 있습니다.
    • 정규표현식: /[\w\-\.]+\@[\w\-\.]+/g
    • 분석
    • [\w\-\.]+ : 온점(.)을 포함하여 알파벳, 숫자, 언더스코어 등으로만 이루어진 id 값을 구분합니다.
    • \@ id 의 뒤에는 @ 가 와야함을 의미합니다.
    • 다시 [\w\-\.]+ 를 사용하여 주소값을 분석합니다.

결론

정규표현식은 언뜻보면 복잡해보이지만 자주 사용하는 패턴 항목에서 보았듯이 하나하나 파악해보면서 그 의미를 안다면 코드의 가독성을 크게 향상시킬 수 있음을 알 수 있었습니다. 직접 작성하는 것이 처음에는 힘들 수도 있습니다. 하지만 걱정하지 마세요 이러한 고충을 인지하고 만들어진 좋은 테스트 사이트들이 있습니다. 마지막으로 정규표현식 테스트 사이트들을 추천드리며 간략하게 소개한 정규표현식 글을 마무리하고자 합니다. 부족한 글 읽어주셔서 감사합니다! 모두 행복한 코딩생활 되시기를 바라겠습니다!