회원가입 폼이나 엑셀에서 받은 데이터를 DB에 넣기 전에 형식을 걸러야 할 때, 매번 정규식을 새로 짜는 건 시간 낭비입니다. 자주 쓰는 패턴은 한곳에 모아 두고 꺼내 쓰는 게 낫습니다. 아래 패턴들은 자바스크립트 리터럴 형식(/패턴/)으로 적었습니다. PHP에서는 그대로 preg_match()의 첫 인자로, VB.NET에서는 앞뒤 슬래시를 떼고 Regex.IsMatch()에 넣으면 됩니다.

한글·영문·숫자처럼 "이 문자만 허용"하는 패턴

입력 칸 검증에서 제일 많이 쓰는 종류입니다. 모두 ^와 $로 앞뒤를 묶어서 문자열 전체가 조건에 맞아야 통과합니다. 이 두 기호를 빼먹으면 "한 글자라도 맞으면 통과"가 되어 버리니 복사할 때 꼭 확인하세요.

광고
용도 패턴
숫자만 (공백 불가) /^[0-9]+$/
영문만 /^[a-zA-Z]+$/
영문과 공백 /^[a-zA-Z\s]+$/
영문과 숫자 /^[a-zA-Z0-9]+$/;
한글만 (공백 불가) /^[가-힣]+$/
한글과 공백 /^[가-힣\s]+$/
한글과 영문 /^[가-힣a-zA-Z]+$/;

한글 패턴의 가-힣은 완성형 글자 범위라서 'ㄱㄴㄷ'이나 'ㅏㅑ' 같은 자모만 따로 입력하면 걸러집니다. 이름 칸처럼 자음만 치고 넘어가는 장난 입력을 막을 때 오히려 쓸모가 있습니다.

연락처·이메일·주민번호

// 전자우편 주소 (소문자 기준)
/^[a-z0-9_+.-]+@([a-z0-9-]+\.)+[a-z0-9]{2,4}$/

// 이메일 형식 (조금 더 너그러운 버전)
/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/

// 전화번호 - 123-123-2344, 123-1234-1234 등
/(\d{3}).*(\d{3}).*(\d{4})/

// 전화번호 000-0000-0000 형태만 허용
/^[0-9]{2,3}-[0-9]{3,4}-[0-9]{4}$/

// 주민등록번호 (하이픈 포함)
/^(?:[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[1,2][0-9]|3[0,1]))-[1-4][0-9]{6}$/

첫 번째 이메일 패턴은 대문자를 허용하지 않고 최상위 도메인도 4자까지만 받습니다. .company 같은 긴 도메인이나 대문자가 섞인 주소를 받아야 한다면 두 번째 패턴이 낫습니다. 전화번호 첫 번째 패턴은 사이에 아무 문자나 와도 되기 때문에 검증용이라기보다 "숫자 묶음을 뽑아내는" 용도에 가깝습니다. 폼에서 형식을 강제하려면 두 번째 패턴을 쓰세요.

주민번호 패턴은 생년월일 자리의 월(01~12)과 일(01~31) 범위까지 확인합니다. 다만 대괄호 안의 [1,2], [0,1]에 쉼표가 들어가 있어서 쉼표 문자도 허용 대상이 됩니다. 실제로 쉼표가 들어올 일은 드물지만 깔끔하게 하려면 [12], [01]로 쓰는 게 맞습니다. 그리고 이건 형식 검사일 뿐 끝자리 검증 공식까지 확인하는 건 아닙니다.

URL·도메인·파일명

// URL (프로토콜 필수)
/^(file|gopher|news|nntp|telnet|https?|ftps?|sftp):\/\/([a-z0-9-]+\.)+[a-z0-9]{2,4}.*$/

// 도메인 - http:// https:// 있어도 되고 없어도 됨
/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/

// 도메인 - http:// https:// 반드시 포함
/^((http(s?))\:\/\/)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/

// 도메인 - http:// https:// 포함하면 안 됨
/^[^((http(s?))\:\/\/)]([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/

// HTML 태그
/\<(/?[^\>]+)\>/

// jpg, gif, png 확장자 파일명
/([^\s]+(?=\.(jpg|gif|png))\.\2)/

여기에는 그대로 쓰면 곤란한 패턴이 두 개 있습니다. "포함하면 안 됨" 패턴의 [^(...)]는 "http로 시작하지 않는다"는 뜻이 아니라, 대괄호 안에 나열된 문자((, h, t, p, s, :, / 등) 중 하나가 아닌 문자 한 개로 시작한다는 뜻입니다. 그래서 site.com처럼 s로 시작하는 정상 도메인도 떨어집니다. 프로토콜이 없는 것만 받으려면 부정 전방탐색을 써서 ^(?!https?:\/\/) 로 시작하게 바꾸는 편이 정확합니다.

HTML 태그 패턴은 괄호 안의 /가 이스케이프되지 않아서 자바스크립트 리터럴로 쓰면 그 자리에서 정규식이 끝나 버립니다. JS에서는 \/로 바꿔 써야 하고, PHP에서 # 같은 다른 구분자를 쓸 때는 문제없습니다.

그 밖에 자주 찾는 것

// 날짜 - 3/28/2007, 3/28/07
/^\d{1,2}\/\d{1,2}\/\d{2,4}$/

// 1부터 50 사이의 숫자 (1과 50 포함)
/^[1-9]{1}$|^[1-4]{1}[0-9]{1}$|^50$/

// 16진수 색상 코드 (#fff, #ffffff)
/#?([A-Fa-f0-9]){3}(([A-Fa-f0-9]){3})?/

// 소문자·대문자·숫자를 각각 하나 이상 포함한 8~15자 (비밀번호 형식)
/(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,15}/

날짜 패턴은 미국식 월/일/년 순서라 우리가 흔히 쓰는 2007-03-28 형식에는 맞지 않습니다. 비밀번호 패턴은 앞뒤에 ^, $가 없어서 16자 이상이어도 앞부분 15자가 조건에 맞으면 통과합니다. 길이 제한을 엄격히 걸려면 ^와 $를 붙이세요.

패턴을 직접 고치려면 알아야 할 기본 문법

위 패턴을 손보려면 기호 몇 개만 알면 됩니다. 자주 쓰는 것만 추렸습니다.

기호 의미 예
^ 문자열의 시작 ^The → The로 시작
$ 문자열의 끝 of despair$ → of despair로 끝남
^abc$ 시작과 끝이 모두 abc 문자열 abc 자체
* 앞 문자 0개 이상 ({0,}) ab* → a, ab, abbb
+ 앞 문자 1개 이상 ({1,}) ab+ → ab, abbb
? 앞 문자 있거나 없거나 ({0,1}) ab? → a, ab
{n} 정확히 n개 ab{2} → abb
{n,} n개 이상 ab{2,} → abb, abbbb
{n,m} n개~m개 ab{3,5} → abbb ~ abbbbb
( ) 묶음 a(bc)* → a 뒤에 bc가 0번 이상
\| 또는 hi\|hello, (b\|cd)ef → bef 또는 cdef
. 아무 문자 하나 ^.{3}$ → 정확히 3글자
[ ] 괄호 안 문자 중 하나 [ab] = a\|b, [a-d] = a~d
[^ ] 괄호 안에 없는 문자 하나 %[^a-zA-Z]% → % 사이에 영문자가 없음

(a|b)*c처럼 조합하면 "a와 b가 섞여서 몇 번 나오고 끝에 c가 붙은" 문자열이 됩니다. ^[a-zA-Z]는 영문자로 시작하는 문자열, [0-9]%는 % 바로 앞에 숫자 하나가 있는 경우입니다.

특수문자 자체를 찾을 때는 앞에 역슬래시를 붙입니다. \^ \. \[ \$ \( \) \| \* \+ \? \{ \\ 가 그렇습니다. 대괄호 안에서는 대부분의 특수문자가 원래 의미를 잃고 일반 문자로 취급된다는 점도 알아 두면 좋습니다(위의 "포함하면 안 됨" 패턴이 틀린 이유가 바로 이것입니다).

기호 의미 반대
\w 알파벳, 숫자, 밑줄(_) \W
\s 공백 \S
\d 숫자 \D
\b 단어 경계 \B
\n / \r / \t 줄바꿈 / 캐리지 리턴 / 탭
\xnn 16진수 nn에 해당하는 문자

괄호로 잡은 부분을 치환에 다시 쓰기

괄호로 묶은 부분은 나중에 번호로 꺼내 쓸 수 있습니다. 치환 문자열에서는 $1, $2처럼, 패턴 안에서는 \1, \2처럼 씁니다. 파일 이름 앞뒤를 바꾸는 예가 이해하기 쉽습니다.

검색 : (.*) - (.*)\.mp3
치환 : $2 - $1.mp3

"제목 - 연주자.mp3"  →  "연주자 - 제목.mp3"

패턴 안에서 \1을 쓰면 "앞에서 잡은 것과 똑같은 내용"을 찾습니다. (.+)\1+는 어떤 문자열이 바로 뒤에 한 번 이상 반복되는 경우로, abab에서는 (.+)가 ab를 잡고 \1+가 뒤의 ab와 맞습니다. 중복 입력된 단어를 찾을 때 이런 식으로 응용합니다.

검색 방식을 바꾸는 변경자로 (?i)(대소문자 무시), (?-i)(대소문자 구분)도 있습니다. 다만 대소문자 무시가 기본값인 엔진은 거의 없고, (?g)/(?-g)로 greedy 모드를 바꾸는 문법은 일부 편집기 전용이라 자바스크립트나 PHP에서는 통하지 않습니다. 언어마다 지원 범위가 다르니 쓰기 전에 꼭 확인하세요. 탐욕적 매칭을 끄고 싶을 때는 +?, *?처럼 수량자 뒤에 ?를 붙이는 방식이 대부분의 언어에서 공통으로 됩니다.

언어별로 쓰는 법

// 자바스크립트: 정규식 객체의 test()
/^[0-9]+$/.test("12345");   // true
// PHP: preg_match()
if (preg_match('/^[0-9]+$/', $value)) {
    // 숫자만 입력됨
}
' VB.NET: 앞뒤 슬래시는 빼고 넣습니다
If System.Text.RegularExpressions.Regex.IsMatch(value, "^[0-9]+$") Then
    ' 숫자만 입력됨
End If

패턴을 고친 뒤에는 바로 코드에 넣지 말고 regexpal.com 같은 온라인 테스트 도구에 실제 데이터 몇 줄을 붙여 넣어 확인해 보세요. 통과해야 할 값과 떨어져야 할 값을 함께 넣어 보면 위에서 짚은 것 같은 실수를 금방 찾을 수 있습니다. 그리고 클라이언트(자바스크립트) 검증은 사용자 편의용일 뿐이니, 같은 패턴을 서버(PHP) 쪽에서도 한 번 더 거는 걸 잊지 마세요.

참고: Developer Factory - 자주 쓰이는 정규식