정규식 비밀번호 검증 패턴 완벽 정리 - 영문 숫자 특수문자 조합 검사하는 법
회원가입 폼에서 비밀번호 규칙을 한 줄로 검사하는 방법. 길이, 영문, 숫자, 특수문자 조건별 정규식 패턴과 자바스크립트 적용 예제까지 한번에 정리했습니다.
![]()
회원가입 폼을 만들 때 가장 자주 막히는 부분이 비밀번호 검증입니다. 영문과 숫자를 섞어야 하고, 특수문자도 넣어야 하고, 길이는 8자 이상이어야 하고. 요구사항은 많은데 이걸 코드로 어떻게 한 번에 검사할지 막막했던 경험이 다들 있으실 겁니다.
이럴 때 가장 깔끔한 해법이 정규식입니다. 조건 하나하나를 if문으로 나눠 검사할 수도 있지만, 잘 짜인 정규식 한 줄이면 복잡한 비밀번호 규칙을 간결하게 표현할 수 있습니다. 핵심 패턴만 이해하면 어떤 규칙이 와도 조합해서 만들 수 있습니다.
비밀번호 검증에 정규식을 쓰는 이유
비밀번호 규칙은 보통 여러 조건이 동시에 걸립니다. 예를 들어 영문 대소문자 포함, 숫자 포함, 특수문자 포함, 8자 이상이라면 조건이 네 개입니다. 이걸 일반 조건문으로 작성하면 검사 코드가 길어지고, 조건이 추가될 때마다 분기도 늘어납니다.
정규식은 이 조건들을 하나의 패턴 문자열로 묶어줍니다. 검증 로직이 한 곳에 모여 있어 유지보수가 쉽고, 프론트엔드와 백엔드에서 같은 패턴을 공유할 수도 있습니다.
비밀번호 검증의 핵심은 정규식 문법이 아니라 전방탐색(lookahead) 개념입니다. 이 한 가지만 이해하면 대부분의 비밀번호 규칙을 직접 만들 수 있습니다.
비밀번호 정규식 기본 구성 요소
비밀번호 검증에 쓰이는 핵심 문법은 생각보다 적습니다. 아래 요소만 알면 됩니다.
- ^ 와 $ - 문자열의 시작과 끝을 의미합니다. 전체 문자열을 검사하려면 반드시 양쪽에 붙입니다.
- (?=...) - 전방탐색입니다. "이 조건을 만족하는 문자가 어딘가에 있어야 한다"는 뜻으로, 비밀번호 검증의 핵심입니다.
- {8,} - 최소 8자 이상을 의미합니다. {8,20}처럼 쓰면 8자 이상 20자 이하가 됩니다.
왜 전방탐색이 필요할까요. 단순히 [A-Za-z0-9]+라고 쓰면 "영문과 숫자로 이루어진 문자열"이 되지만, "영문도 있고 숫자도 반드시 있어야 한다"는 조건은 표현하지 못합니다. 순서에 상관없이 특정 문자가 포함되어 있는지 확인하려면 전방탐색을 써야 합니다.
(?=.*\d)는 "문자열 어딘가에 숫자가 최소 하나 있다"는 의미입니다. .*는 앞쪽 아무 문자열이나 허용하고, \d가 숫자 하나를 확인합니다. 이 패턴을 조건 수만큼 나열하면 됩니다.조건별 정규식 패턴 모음
실무에서 가장 많이 쓰이는 비밀번호 규칙을 패턴별로 정리했습니다. 그대로 복사해서 쓰셔도 됩니다.
| 조건 | 정규식 패턴 |
|---|---|
| 8자 이상 | ^.{8,}$ |
| 영문 + 숫자 8자 이상 | ^(?=.*[A-Za-z])(?=.*\d).{8,}$ |
| 영문 + 숫자 + 특수문자 8자 이상 | ^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$ |
| 대문자 + 소문자 + 숫자 + 특수문자 | ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$ |
| 공백 불허, 8~20자 | ^(?=.*[A-Za-z])(?=.*\d)(?!.*\s).{8,20}$ |
특수문자 범위는 서비스마다 다르게 잡습니다. 위 예시는 [!@#$%^&*]만 허용했지만, 더 넓게 잡고 싶다면 ASCII 기호 영역 전체를 범위로 지정할 수 있습니다. 이때 특정 기호의 16진수 코드값을 확인하려면 진법 변환기로 ASCII 코드를 변환해 [\x21-\x2F] 같은 범위를 정확히 지정하면 됩니다.
\-로 이스케이프해야 범위 기호로 오해받지 않습니다. [!@#-]처럼 하이픈을 마지막에 두는 방식이 가장 안전합니다.언어별 적용 예제
자바스크립트
가장 많이 쓰는 환경입니다. 정규식 리터럴을 만들고 test()로 검사합니다.
const re = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/;
const valid = re.test(password);
파이썬
파이썬에서는 re.match를 씁니다. match는 문자열 시작부터 검사하므로 ^를 생략해도 되지만, 명확하게 붙여두는 편이 좋습니다.
import re
valid = bool(re.match(r'^(?=.*[A-Za-z])(?=.*\d).{8,}$', password))
HTML 입력 필드
별도 자바스크립트 없이 input 태그의 pattern 속성으로 1차 검증을 걸 수도 있습니다. 다만 브라우저 검증은 우회가 가능하므로 서버 검증을 반드시 함께 둬야 합니다.
자주 하는 실수와 주의점
정규식 비밀번호 검증에서 흔히 놓치는 부분이 있습니다.
- 한글 입력 허용 여부 -
.은 한글도 통과시킵니다. 영문/숫자/기호만 허용하려면.{8,}대신[A-Za-z\d!@#$%^&*]{8,}처럼 허용 문자 집합을 명시해야 합니다. - 최대 길이 누락 -
{8,}만 쓰면 길이 상한이 없습니다. 비정상적으로 긴 입력으로 인한 부하를 막으려면{8,64}처럼 상한을 두는 것이 안전합니다. - 이스케이프 누락 - 특수문자 클래스 안에서
],\,^(맨 앞),-는 위치나 이스케이프에 주의해야 합니다.
보안 관점에서도 짚어둘 점이 있습니다. 최근 보안 가이드라인은 복잡한 조합 강제보다 길이를 더 중요하게 봅니다. 무리하게 많은 조건을 강제하면 사용자가 예측 가능한 패턴(Password1!)을 쓰게 되어 오히려 보안이 약해질 수 있습니다. 조건은 적절히, 최소 길이는 넉넉하게 잡는 것이 실용적입니다.
적용 전 체크리스트
완성한 정규식을 서비스에 적용하기 전에 아래 항목을 확인하시기 바랍니다.
- 시작
^과 끝$가 모두 있는가 (부분 일치 방지) - 최소 길이뿐 아니라 최대 길이도 지정했는가
- 한글 등 허용하지 않을 문자가 통과되지 않는가
- 프론트엔드 검증과 동일한 규칙을 서버에서도 검사하는가
먼저 위 패턴 표에서 서비스에 맞는 조건을 골라 그대로 적용해보고, 특수문자 범위와 최대 길이만 서비스 정책에 맞게 조정하면 됩니다. 그다음 경계값 비밀번호로 직접 테스트해 의도대로 동작하는지 확인하시면 됩니다.