정규표현식 실전 패턴 — 매번 검색하는 것들 총정리

게시일: 2025년 11월 21일 · 14분 읽기

정규표현식은 매번 새롭다. 이메일 검증을 할 때도, URL을 파싱할 때도 매번 검색한다. 내가 자주 쓰는 패턴만 모아서 이 글에 정리했다. 이제부터는 이 글을 북마크하고 필요할 때 찾아쓰면 된다.

기본 패턴

이메일 주소

완벽한 RFC 5322 정규표현식은 너무 복잡하다. 실무에서는 대부분 이 정도면 충분하다.


^[^\s@]+@[^\s@]+\.[^\s@]+$

더 엄격하게 하려면:


^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

하지만 이것도 완벽하지 않다. 실제로는 정규표현식보다 확인 이메일을 보내는 것이 더 안전하다.


const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
console.log(emailRegex.test('user@example.com'));  // true
console.log(emailRegex.test('invalid.email'));     // false

URL


^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$

또는 더 간단하게:


^https?:\/\/.+$

전화번호 (한국)


^01[0-9]-?\d{3,4}-?\d{4}$

이 패턴은 010-1234-5678, 01012345678 등을 모두 허용한다.


const phoneRegex = /^01[0-9]-?\d{3,4}-?\d{4}$/;
console.log(phoneRegex.test('010-1234-5678'));  // true
console.log(phoneRegex.test('01012345678'));    // true

IP 주소 (IPv4)


^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$

이 패턴은 0-255 범위의 4개 옥텟을 검증한다.


const ipRegex = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
console.log(ipRegex.test('192.168.1.1'));  // true
console.log(ipRegex.test('256.1.1.1'));    // false

로그 파싱

타임스탐프 파싱

흔한 로그 포맷 (2026-02-26 14:30:45):


^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}

또는 구조화된 파싱을 위해 그룹을 사용:


^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})

const logLine = '2026-02-26 14:30:45 [ERROR] Connection failed';
const regex = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}) \[(\w+)\] (.+)$/;
const match = logLine.match(regex);

if (match) {
  const [, year, month, day, hour, minute, second, level, message] = match;
  console.log({ year, month, day, hour, minute, second, level, message });
}

로그 레벨 추출


\[(ERROR|WARN|INFO|DEBUG)\]

고급 패턴

Lookahead와 Lookbehind

Lookahead는 특정 문자 앞에 있는 것을 찾는다.


\w+(?=@)  // @앞의 모든 단어 문자

const email = 'user@example.com';
const username = email.match(/\w+(?=@)/)[0];
console.log(username);  // 'user'

Lookbehind는 특정 문자 뒤에 있는 것을 찾는다. (모던 JavaScript에서 지원)


(?<=@)\w+  // @뒤의 모든 단어 문자

const email = 'user@example.com';
const domain = email.match(/(?<=@)[\w.]+/)[0];
console.log(domain);  // 'example.com'

Named Groups (명명된 그룹)

정규표현식이 복잡해지면 그룹을 이름으로 참조하는 것이 좋다.


const dateRegex = /(?\d{4})-(?\d{2})-(?\d{2})/;
const match = '2026-02-26'.match(dateRegex);

console.log(match.groups.year);   // '2026'
console.log(match.groups.month);  // '02'
console.log(match.groups.day);    // '26'

Non-greedy 매칭

기본적으로 정규표현식은 greedy하다. 즉, 가능한 한 많이 매칭한다.


const text = '

Hello

World

'; // Greedy (잘못된 결과) const greedy = text.match(/

.*<\/p>/); console.log(greedy[0]); // '

Hello

World

' // Non-greedy (올바른 결과) const nonGreedy = text.match(/

.*?<\/p>/g); console.log(nonGreedy); // ['

Hello

', '

World

']

*?, +?, ?? 등을 사용해서 non-greedy 매칭을 한다.

일반적인 실수

Catastrophic Backtracking

복잡한 정규표현식은 매우 느릴 수 있다. 특히 텍스트가 패턴과 거의 맞지만 마지막에 실패하는 경우가 문제다.


// ❌ 위험: 백트래킹이 매우 많다
(a+)+b

// 이 텍스트는 프로세스를 한없이 계속할 것이다
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaac

// 직접 테스트하지 말 것! 브라우저가 멈칠 수 있다.
// const regex = /(a+)+b/;
// const text = 'a'.repeat(30) + 'c';
// regex.test(text);  // 매우 오래 걸림

이를 피하려면 중첩된 quantifier를 피해야 한다.


// ✅ 안전한 버전
a+b

성능 최적화 팁

  1. Anchors를 사용하자 (^ 와 $)
  2. 구체적인 패턴을 먼저 작성하자
  3. character class를 사용하자 ([a-z] vs a|b|c)
  4. 불필요한 그룹을 피하자

실무 활용 팁

입력 검증


const validators = {
  email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
  phone: /^01[0-9]-?\d{3,4}-?\d{4}$/,
  url: /^https?:\/\/.+$/,
  ipv4: /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
  username: /^[a-zA-Z0-9_]{3,20}$/
};

function validate(field, value) {
  return validators[field].test(value);
}

console.log(validate('email', 'user@example.com'));  // true
console.log(validate('phone', '01012345678'));       // true

문자열 변환


// camelCase를 snake_case로
const camelCase = 'getUserData';
const snakeCase = camelCase.replace(/([A-Z])/g, '_$1').toLowerCase();
console.log(snakeCase);  // 'get_user_data'

// 연속된 공백 제거
const text = 'Hello    world';
const cleaned = text.replace(/\s+/g, ' ');
console.log(cleaned);  // 'Hello world'

// URL에서 쿼리 파라미터 추출
const url = 'https://example.com?name=John&age=30';
const params = {};
url.replace(/[?&]([^=]+)=([^&]*)/g, (match, key, value) => {
  params[key] = value;
});
console.log(params);  // { name: 'John', age: '30' }

정규표현식 체크리스트

패턴 용도 정규표현식
이메일 기본 검증 ^[^\s@]+@[^\s@]+\.[^\s@]+$
URL URL 검증 ^https?:\/\/.+$
한국 전화번호 전화번호 ^01[0-9]-?\d{3,4}-?\d{4}$
IPv4 IP 주소 ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
타임스탐프 로그 파싱 ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$

정규표현식은 강력하지만 복잡할 수 있다. 이 글의 패턴들을 기억하고, 더 복잡한 경우에는 정규표현식 테스터(regex101.com 등)를 사용하자. 그리고 항상 성능을 고려하자.

iL
ian.lab

실무 개발자입니다. 현장에서 겪은 문제와 해결 과정을 기록합니다. 오류 제보는 연락처로 보내주세요.