폼 검증
휴대폰 번호, 우편번호, 날짜 형식, 비밀번호 강도 — 강좌 22–24단계의 패턴 셋은 프런트엔드 폼에 바로 쓸 수 있습니다. 앵커를 잊지 말고 「2월 30일」 같은 의미 검사는 코드에 맡기세요.
Guide
정규식 강좌는 25단계 인터랙티브 튜토리얼입니다. 단계마다 테스트 텍스트 한 토막과 목표(「이것들은 매칭하고 저것들은 매칭하지 않기」 또는 「일부를 캡처해 내기」)가 주어지고, 입력 상자에서 식을 고치면 오른쪽에 모든 매칭과 그룹이 실시간으로 강조되며 판정기가 목표 달성 여부를 항목별로 알려 줍니다. 판정은 전부 브라우저 내장 JavaScript 정규식 엔진으로 하며 텍스트를 업로드하지 않습니다.
2026-09-09 업데이트4 sources9 min read
정규식 강좌는 25단계 인터랙티브 튜토리얼입니다. 단계마다 테스트 텍스트 한 토막과 목표(「이것들은 매칭하고 저것들은 매칭하지 않기」 또는 「일부를 캡처해 내기」)가 주어지고, 입력 상자에서 식을 고치면 오른쪽에 모든 매칭과 그룹이 실시간으로 강조되며 판정기가 목표 달성 여부를 항목별로 알려 줍니다. 판정은 전부 브라우저 내장 JavaScript 정규식 엔진으로 하며 텍스트를 업로드하지 않습니다.
강좌는 난이도 순으로 나아갑니다. 먼저 리터럴, 점, 이스케이프 같은 「문자 찾기」 기초, 다음으로 문자 클래스와 범위, 미리 정의된 클래스 \d \w \s, 네 가지 수량자, 이어서 앵커와 단어 경계, 선택자, 세 가지 그룹과 역참조, 탐욕과 게으름, 그다음 전방·후방 단언과 플래그, 마지막으로 실전 패턴 셋(중국 본토 휴대폰 번호, 이메일, 날짜)으로 종합 연습하고 「치명적 백트래킹」 단계로 마무리합니다. 엔진을 멈춰 세우는 식을 직접 써 보고 고쳐 보는 단계입니다.
다 마치려면 60분쯤 걸립니다. 정규식을 한 번도 써 본 적 없거나 「베끼기는 하는데 고치지는 못하는」 사람에게 맞습니다. 이미 익숙한 독자는 17단계 이후의 룩어라운드와 함정 부분으로 바로 건너뛰어도 됩니다.
?lesson=n이 붙은 링크를 복사하며 열면 그 단계로 바로 들어갑니다. 「진행 초기화」는 이 강좌의 모든 기록을 지웁니다.이 페이지 위쪽이 곧 강좌 본체입니다. 왼쪽 목차에서 단계를 고르고, 가운데에 정규식을 입력하면 판정이 바로 나옵니다.
14단계 「캡처 그룹」의 목표는 2026-09-09에서 연도를 꺼내는 것입니다. 통과 과정 하나를 기록하면 다음과 같습니다.
테스트 텍스트 게시일: 2026-09-09, 마감일: 2027-01-31
1차 시도 \d+
매칭 2026 09 09 2027 01 31 ← 6곳 매칭, 캡처 그룹 없음
판정 ✕ 온전한 날짜 두 개만 매칭해야 함 ✕ 그룹 1은 연도여야 함
2차 시도 (\d{4})-\d{2}-\d{2}
매칭 2026-09-09 2027-01-31 ← 2곳 매칭
그룹 1 2026 2027
판정 ✓ 매칭 수 2 ✓ 그룹 1 = 2026 / 2027 → 통과
25단계 「치명적 백트래킹」은 반대 방향입니다. 먼저 ^(a+)+$ 같은 중첩 수량자 패턴을 쓰게 하고 aaaaaaaaaaaaaaaaaaaaaaaaaaaa! 문자열로 테스트하면 페이지가 시도 횟수가 지수적으로 늘어난다고 보고합니다. 그다음 ^a+$ 같은 동등한 식으로 바꿔 통과해야 합니다.
정규 표현식(regular expression)은 「어떤 문자열이 어떻게 생겼는지」를 작은 기호 세트로 서술합니다. 영문자와 숫자는 대개 자기 자신을 뜻하고, 열몇 개의 메타 문자(. * + ? ^ $ | ( ) [ ] { } \)는 특별한 뜻을 갖습니다. 엔진은 패턴을 들고 텍스트를 왼쪽에서 오른쪽으로 훑으며 위치마다 매칭을 시도하고, 찾으면 위치와 길이를 알려 줍니다. 이 강좌는 JavaScript(ECMAScript) 문법을 쓰며, Python, Java, Go의 정규식과 기본 문법은 거의 같고 차이는 룩어라운드, Unicode 속성, 일부 플래그에 몰려 있습니다.
cat은 c, a, t 세 문자가 연달아 있는 것을 매칭합니다. 점 .은 줄바꿈을 뺀 임의의 문자 하나를 매칭하므로 c.t는 cat, cut, c9t를 잡습니다. 정말로 마침표를 찾고 싶을 때(예: 파일 확장자 앞의 점)는 \.라고 씁니다. 백슬래시가 메타 문자를 원래의 글자 뜻으로 되돌립니다. 모든 메타 문자를 이렇게 이스케이프할 수 있고, 문자 클래스 안에서는 ] \ ^ -만 이스케이프하면 됩니다.
대괄호 안에 후보 문자를 나열합니다. [aeiou]는 모음 하나를 매칭하고, [a-z], [0-9]는 하이픈으로 범위를 나타내며 [A-Za-z0-9_]처럼 이어 쓸 수 있습니다. 맨 앞에 ^를 붙이면 반대가 되어 [^0-9]는 숫자가 아닌 아무 문자나 매칭합니다. 자주 쓰는 미리 정의 클래스 셋은 그 축약형입니다.
| 클래스 | 같은 표현 | 설명 |
|---|---|---|
\d |
[0-9] |
숫자(전각 숫자는 포함하지 않음) |
\w |
[A-Za-z0-9_] |
「단어 문자」, 한자는 포함되지 않음 |
\s |
[ \t\n\r\f\v…] |
공백, 전각 공백 포함 |
대문자 버전 \D \W \S는 각각의 반대입니다. \w에 한자가 들어가지 않는 것은 중국어 사용자가 가장 자주 밟는 함정입니다. 한자를 매칭하려면 [\u4e00-\u9fa5]라고 쓰거나 u 플래그에서 \p{Script=Han}을 씁니다. 같은 이유로 한글도 \w에 들어가지 않습니다.
수량자는 원자(문자 하나, 문자 클래스, 그룹) 뒤에 붙어 그 원자가 몇 번 반복되는지 정합니다.
*는 0번 이상, +는 1번 이상, ?는 0번 또는 1번입니다.{n}은 정확히 n번, {n,}은 n번 이상, {n,m}은 n번에서 m번입니다.\d{4}는 \d\d\d\d보다 읽기 좋고 \d{11}은 휴대폰 번호 자릿수입니다. 수량자는 바로 앞의 원자 하나에만 작용합니다. ab+는 a 뒤에 b가 하나 이상이고, ab 전체를 반복하려면 (ab)+라고 써야 합니다.
^와 $는 문자를 매칭하지 않고 위치만 매칭합니다. 문자열의 시작과 끝(멀티라인 모드에서는 각 줄의 시작과 끝)입니다. 폼 검증에는 거의 항상 ^…$를 붙여야 합니다. 그렇지 않으면 \d{11}이 12자리 번호의 앞 11자리를 「매칭」해 버립니다. \b는 단어 경계로, \w와 \W(또는 문자열의 양 끝) 사이의 위치입니다. \bcat\b는 a cat을 매칭하고 concatenate는 매칭하지 않습니다. 마찬가지로 \w에 한자가 없으므로 \b는 한자 텍스트에서 거의 쓸모가 없습니다.
|는 「또는」이고 우선순위가 가장 낮습니다. cat|dog은 두 단어 중 하나를 매칭하고, 범위를 제한하려면 괄호를 씁니다(gr(a|e)y). 괄호는 동시에 캡처 그룹을 만듭니다. 매칭에 성공하면 번호로 그룹 안 텍스트를 꺼내거나(match[1]) 치환 문자열에서 $1로 참조할 수 있습니다. 정규식에서 가장 생산적인 기능 중 하나로, 2026-09-09를 09/09/2026으로 바꾸는 일도 replace 한 번이면 됩니다.
(?<year>\d{4})는 이름 있는 그룹이고 groups.year로 읽습니다. 숫자 번호보다 패턴을 고칠 때 어긋날 위험이 적습니다. (?:…)는 비캡처 그룹으로 그룹만 만들고 번호를 차지하지 않아, 수량자나 선택에 범위만 주고 싶을 때 맞습니다. \1은 역참조로, 여기서 1번 그룹이 잡은 내용이 다시 나와야 한다는 뜻입니다. (\w)\1은 ll, oo 같은 겹글자를 매칭하고 <(\w+)>.*?</\1>은 짝이 맞는 HTML 태그를 매칭합니다.
수량자는 기본이 탐욕입니다. 최대한 많이 먹고, 먹은 것을 토해 냅니다. "a" and "b"에 ".+"를 쓰면 첫 따옴표부터 마지막 따옴표까지 전부 한 번에 매칭합니다. 수량자 뒤에 ?를 붙이면 게으름이 되어 ".+?"는 최소한만 먹고 "a"와 "b" 두 매칭을 얻습니다. 더 정확한 방법은 부정 문자 클래스 "[^"]+"입니다. 역추적에 기대지 않아 보통 더 빠릅니다.
룩어라운드(lookaround)는 앵커처럼 위치만 매칭하지만 조건이 「옆에 어떤 패턴이 있는가」입니다.
(?=…) 전방: 뒤에 …가 있어야 합니다. \d+(?=원)은 100원에서 100을 매칭하고 원은 매칭에 넣지 않습니다.(?!…) 부정 전방: 뒤에 …가 오면 안 됩니다.(?<=…) 후방: 앞에 …가 있어야 합니다. (?<=₩)\d+는 가격 숫자만 매칭하고 통화 기호는 포함하지 않습니다.(?<!…) 부정 후방.JavaScript는 ES2018부터 후방 단언을 지원하고 Safari 16.4 이후에 완전히 쓸 수 있게 되었습니다. Python의 후방 단언은 길이가 고정되어야 합니다. 비밀번호 강도 검사는 룩어라운드의 대표적인 용례입니다. ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$는 전방 단언 셋으로 같은 위치에서 「숫자 포함, 소문자 포함, 대문자 포함」을 각각 확인하고 .{8,}가 문자열 전체를 소비합니다.
플래그는 패턴 바깥에 씁니다. i는 대소문자를 무시하고, g는 첫 번째가 아니라 모든 매칭을 찾으며(강좌의 강조는 항상 g 사용), m은 ^ $가 각 줄을 매칭하게 합니다. s는 .이 줄바꿈까지 매칭하게 하고, u는 Unicode 모드를 켜서 .이 UTF-16 코드 단위가 아니라 코드 포인트 단위로 매칭되게 하므로 이모지가 한 문자로 셉니다. y는 붙임(sticky) 매칭으로 lastIndex 자리에서 곧바로 매칭해야 합니다.
중국 본토 휴대폰 번호: ^1[3-9]\d{9}$ — 1로 시작하고 두 번째 자리가 3–9, 모두 11자리입니다. 통신사별 번호 대역을 일일이 나열하려 하지 마세요. 대역은 매년 늘어납니다.
이메일: RFC 5322를 완전히 따르는 정규식은 수천 자에 이르고 실용적이지도 않습니다. 폼에 쓸 만한 현실적인 식은 ^[^\s@]+@[^\s@]+\.[^\s@]+$입니다. @가 정확히 하나, 양쪽이 비어 있지 않음, 도메인 부분에 점이 하나 이상 있어야 합니다. 진짜 검증은 확인 메일을 보내는 것으로 합니다.
날짜: ^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$는 월을 01–12, 일을 01–31로 제한할 수 있지만 2월이 며칠인지는 알지 못합니다. 문법 검증은 정규식에, 의미 검증은 코드에 맡기세요.
JavaScript, Python, Java, PCRE의 정규식 엔진은 모두 백트래킹 방식입니다. 나눌 방법이 여러 개면 하나를 먼저 시도하고 실패하면 되돌아와 다음 방법을 시도합니다. 중첩 수량자는 나눌 방법 수를 지수적으로 늘립니다. ^(a+)+$가 a 30개에 ! 하나를 상대로 실패를 선언하려면 을 넘는 분할을 시도해야 하고, 브라우저 탭이 몇 초에서 몇 분까지 멈춥니다. 이런 패턴이 사용자 입력을 받으면 서비스 거부 공격(ReDoS)이 됩니다.
피하는 원칙은 이렇습니다. 이웃한 두 수량자가 같은 문자를 매칭할 수 있게 두지 않습니다((a+)+, (\w+\s?)+, (.*)* 모두 위험 신호). 게으른 .*? 대신 부정 문자 클래스를 쓰고, 입력 길이 상한을 둡니다. Go와 Rust의 정규식 라이브러리는 Thompson NFA / DFA 구현이라 선형 시간을 보장하지만, 대신 역참조와 룩어라운드를 지원하지 않습니다. Russ Cox의 글에서 두 구현의 차이를 가장 명확하게 설명합니다.
중첩 구조 매칭(괄호 짝 맞추기, HTML 전체), 「개수 세기」가 필요한 일(왼쪽 괄호와 오른쪽 괄호 수가 같은지 판정), 문맥 의미에 의존하는 판단(이 숫자가 실제로 존재하는 날짜인지)은 정규식이 못 하거나 매우 어렵습니다. 정규식은 어휘 층의 도구입니다. 토큰 찾기, 자르기, 간단한 검증, 일괄 치환은 정규식이 대체 불가능합니다.
(?i) 인라인 수정자, Python의 (?P<name>), Java의 \p{javaLowerCase} 같은 문법 차이와 POSIX 문자 클래스 [[:alpha:]]는 다루지 않습니다.u 플래그를 플래그 단계에서 짧게 소개하고, \p{…} 속성 이스케이프와 v 플래그의 집합 연산은 강좌 범위 밖입니다.\w가 한자를 매칭한다」: 매칭하지 않습니다. \w는 ASCII 영문자, 숫자, 밑줄뿐입니다. 한자는 [\u4e00-\u9fa5]나 \p{Script=Han}(u 플래그 필요)을 씁니다..이 아무 문자나 매칭한다」: 기본은 줄바꿈을 매칭하지 않습니다. 줄을 넘게 하려면 s 플래그를 켜거나 [\s\S]를 쓰세요.\d{11}이라고 썼으니 11자리만 받는다」: 앵커가 없으면 더 긴 숫자열 안에서 11자리를 찾아냅니다. 검증에는 반드시 ^…$를 붙이세요.[A-z]는 모든 글자」: ASCII에서 대문자 Z(90)와 소문자 a(97) 사이에 [ \ ] ^ _ \`` 여섯 기호가 더 있어 함께 매칭됩니다. [A-Za-z]`라고 써야 합니다.ab+는 b만 반복합니다. ab{2}는 abb를 매칭하고 abab는 매칭하지 않습니다.>, 주석 때문에 정규식이 무너지므로 DOM 파서를 쓰세요.휴대폰 번호, 우편번호, 날짜 형식, 비밀번호 강도 — 강좌 22–24단계의 패턴 셋은 프런트엔드 폼에 바로 쓸 수 있습니다. 앵커를 잊지 말고 「2월 30일」 같은 의미 검사는 코드에 맡기세요.
VS Code, Sublime, JetBrains 계열의 찾기·바꾸기가 정규식과 $1 참조를 지원합니다. 그룹 단원을 마치면 2026-09-09를 한 번에 09/09/2026으로 바꾸거나 모든 console.log( 앞에 접두사를 붙일 수 있습니다.
수만 줄 로그에서 IP, 상태 코드, 소요 시간을 뽑습니다. (\d+\.\d+\.\d+\.\d+).*?" (\d{3}) (\d+)ms 같은 패턴에 이름 있는 그룹을 붙이면 몇 줄짜리 스크립트로 통계를 낼 수 있습니다.
(\w+\s?)+$, (.*a)+, (a|aa)+ 같은 중첩·중복 수량자가 사용자 입력을 처리하는 자리에 보이면 고쳐 쓰거나 길이 제한을 요구해야 합니다.
판정은 쓰는 방식이 아니라 결과를 봅니다. 매칭해야 할 것이 모두 걸리고 매칭하면 안 되는 것이 모두 비어 있으며 캡처 그룹 내용이 같으면 통과입니다. 참고 답은 여러 방식 중 하나일 뿐입니다.
보통 「매칭하면 안 되는」 조각까지 매칭되었거나, 매칭 범위가 목표보다 한 문자 더 많기 때문입니다(구두점을 삼킨 경우 등). 결과 표시줄에서 ✕가 붙은 항목을 보세요.
1–18단계의 문법은 주요 언어에서 그대로 통합니다. 룩어라운드 단계의 후방 단언은 Python에서 길이가 고정되어야 하고, 이름 있는 그룹은 Python에서 (?P<name>…)입니다. 플래그 표기는 언어마다 다릅니다.
현재 브라우저의 localStorage에 있고 업로드되지 않습니다. 브라우저를 바꾸거나 사이트 데이터를 지우면 사라집니다. 「이 단계 공유」 링크로 어디까지 배웠는지 기록해 둘 수 있습니다.
시연은 단계 수를 세는 시뮬레이션이고 임계값을 넘으면 「치명적 백트래킹」으로 판정합니다. 진짜로 실행하면 탭 전체가 응답하지 않게 되어 아무 피드백도 줄 수 없습니다.
강좌는 완전히 브라우저 로컬에서 돕니다. 입력한 식과 테스트 텍스트는 브라우저 내장 정규식 엔진에만 전달되고 어떤 서버로도 전송되지 않습니다. 진행 상황은 이 기기의 localStorage에 저장되며 페이지를 닫으면 입력 내용이 해제됩니다.
2026-09-09 업데이트
25단계 인터랙티브 정규식 튜토리얼: 리터럴, 문자 클래스, 수량자, 그룹, 룩어라운드부터 백트래킹 함정까지, 식을 바꾸면 즉시 매칭 확인
이 도구는 아직 완전히 번역되지 않아 일부 내용이 원문 또는 대체 언어로 표시됩니다.
목표cat을 포함하는 모든 단어와 일치하는 표현식을 작성하세요.
가장 간단한 정규식은 일반 문자의 연속입니다. cat은 텍스트에서 연속적인 c, a, t를 검색합니다. 기본적으로 정규 표현식은 "같음"이 아닌 "포함"을 의미합니다. concat 및 category에는 고양이가 포함되어 있으므로 둘도 일치합니다. 문자, 숫자, 공백 및 CJK 문자는 모두 리터럴입니다. 약 12개의 기호만이 특별하며 다음 강의에서는 하나씩 다룹니다.