본문 바로가기
dev/javascript

[javascript] 자바스크립트 이메일 검증 방법 (verify email with regexp)

by 최연탄 2022. 5. 30.
728x90
반응형

참고: https://stackabuse.com/validate-email-addresses-with-regular-expressions-in-javascript/

소개

웹 개발자에게 다양한 유형의 사용자 입력을 검증하는 것은 매우 중요합니다. 이는 클라이언트와 서버 사이에 전송되는 데이터의 시작점이 되기 때문에 모든 것이 올바른 발판 위에서 시작하도록 해야 합니다. 또한 사용자 입력은 악의적일 수 있기 때문에 보안도 고려해야합니다. 프론트 엔드에서 입력 유효성을 검사하여 문제를 최대한 피하는 것이 좋습니다. 이 글에서는 정규표현식(regular expression)을 사용하여 이메일 주소를 확인하는 방법을 살펴보겠습니다.

Javascript의 정규 표현식

정규 표현식에 익숙하지 않거나 가물가물한 기억을 상기시킬 내용이 여기에 있습니다.

정규식은 패턴을 나타내는 메타문자의 나열입니다. 이러한 패턴은 다양한 종류가 될 수 있는데 문자와 숫자, 특수문자,  심지어 다른 언어 문자의 혼합입니다. 정규식을 약어로 RegEx 또는 RegExp로 표현합니다. 정규식은 메타 문자, 수량자, 그룹 및 이스케이프 문자를 통해 거의 모든 패턴 을 표현할 수 있습니다. 예를 들어, 아래 표현식은 알파벳(소문자 및 대문자 모두) 또는 숫자 사이의 유효한 문자를 임의의 조합으로 가지는 일련의 문자를 표현합니다.

^([A-Za-z]|[0-9])+$

정규표현식을 사용하여 Javascript의 이메일 형식 검증

일단 가능한 모든 유효 이메일 주소와 일치하는 정규식은 존재하지 않습니다. 그러나 99.9% 일치하는 항목은 존재합니다. 이메일 또는 모든 입력의 유효성을 검사할 때 사용자가 RegEx와 일치하는지 어느 정도 보장할 수 있는 좋은 방법은 사용자 입력을 미리 제한하는 것입니다.

예를 들어 gmail.com 또는 yahoo.com 을 의무적으로 사용 하고 지원되지 않는 공급자를 입력하지 못하도록 미리 방어하는 것입니다. (하지만 이 접근 방식을 사용하면 확장성과 최신 상태를 유지에 문제가 발생합니다.) 그런데 여기서 또 다른 질문이 제기 됩니다. "이메일 형식이란 무엇인가?" 이는 우리가 곧 보겠지만 신기하게도 느슨한 정의로 간단히 규정할 수 있습니다. 이메일 유효성 검사는 다음 항목 "일반 이메일 검증"에서 보다 구체적으로 다룰 것 입니다.

소스코드를 보기 전에 우리가 알아보려하는 이메일 형식에 대해 미리 확인하겠습니다.

  • 일반 포멧 - (something)@(some_domain).(some_toplevel_domain)
  • 특정 호스트나 도메인 - 특정 도메인이나 탑레벨 도메인을 나타냅니다.
  • RFC 5322 - Internet Message Format으로 거의 99.9%의 이메일을 커버합니다.

일반 이메일 검증

엔지니어가 강력한 정규식으로 이메일 유효성을 검사하려는 수많은 도전을 하다가 결국은 오래도록 사용되어온 일반 형식으로 마음을 바꿉니다. 이것인 좋은 방법인지 아닌지는 논쟁의 여지가 있긴 하지만 말입니다.

이메일 주소에는 뭐가 들어갈까요? @ 기호가 있어야하고 앞에 오는 문자열과 그 뒤에 오는 문자열이 있어야 합니다. 또한 뒤의 문자열에는 점을 포함해야 하며 점 뒤에 2~3개의 문자가 추가로 포함됩니다. 결론적으로 대략 아래와 같은 모양이 됩니다.

(randomString)@(randomString2).(2-3 characters)

다음의 예 들이 일반적인 이메일의 예로 볼 수 있습니다.

someone@gmail.com
john.doe.1@yahoo.com
david@github.io

이를 염두하고 일반적인 이메일의 표현을 javascript RegExp 정규식으로 다음과 같이 변환합니다.

let regex = new RegExp('[a-z0-9]+@[a-z]+\.[a-z]{2,3}');

let testEmails = ["notanemail.com", "workingexample@email.com", "another_working@somethingelse.org", "notworking@1.com"];

testEmails.forEach((address) => {
    console.log(regex.test(address))
});

첫 번째 문자열에는 john.doe.1, workingemail 같은 소문자 영숫자 문자가 포함될 수 있습니다. 결과는 다음과 같습니다.

false
true
true
false

"이 코드가 항상 동작하는지?" 아닙니다. 이를 통과하는 일부 잘못된 형식의 이메일이 있습니다. 또한 이 정규식을 사용하여 스팸 감지를 할 수 없으므로 다음과 같이 딱봐도 스팸인 이메일 주소가 이 정규식을 통과합니다.

console.log(regex.test("aaa@aa.aa")); // true

가장 강렬하고 복잡한 이메일 유효성 검사 표현식도 이 이메일 주소는 통과합니다.

특정 이메일 주소 검증

이메일을 검증하려면 불확실성의 정도를 낮추는 것도 도움이 됩니다. 불확실성이 적을수록 표현식을 사용하여 부과해야 하는 제한이 줄어듭니다. 이렇게 하면 방금 본 것과 동일한 일반 형식을 사용하는 특정 이메일 주소 유효성 검사가 더 정확해집니다. 더이상 예외 사례를 다룰 필요가 없습니다. 도메인 및 최상위 도메인을 참조하는 몇 가지 일반적인 경우를 살펴보겠습니다.

1. Javascript로 이메일 주소 도메인 확인

예를 들어 tistory 라는 회사에서 일하고 있다고 가정합시다. 모든 직원에게는 @tistory.com으로 끝나는 이메일이 있으며 각 사용자 마다 앞 쪽 문자열이 변경됩니다. 대략적인 스케치는 다음과 같습니다.

(randomString)@tistory.com

이렇게 하면 도메인 이름 및 조직 유형과 같은 일부 변수가 고정되었으므로 작업이 훨씬 쉬워졌습니다. 도메인 이름은 매우 다양 하기 때문에  사용자 명과 도메인 이 두 가지는 일반적으로 문제를 가장 많이 일으키는 변수 입니다. 따라서 특정 도메인과 관련된 이메일 주소의 유효성을 검사하는 것은 RegExp를 활용하기 쉬운 작업이 됩니다.

let regex = new RegExp('[a-z0-9]+@tistory.com');

let testEmails = ["notanemail.com", "workingexample@tistory.com", "not_working@tistory.org"];

testEmails.forEach((address) => {
    console.log(regex.test(address))
});

이 결과:

false
true
false

이 접근 방식을 사용하면 필요에 따라 리터럴 문자열을 변경할 수 있습니다. 항상 그렇듯이 정규식의 첫 부분은 대문자와 대소문자를 일치시키도록 변경할 수 있으며 +또는 _와 같은 특수 문자를 포함할 수 있습니다.

2. Javascript에서 이메일 주소 최상위 도메인 확인

이 방법은 이메일의 마지막 2~3자를 제한한다는 점을 제외하고는 앞의 사례와 매우 유사합니다. 여기에 사용될 문자는 .com, .org, .edu, .eu, .us 등이 될 수 있습니다. 이제 example@yale.edu.com 같이 최상위 도메인에 .edu가 들어가는 이메일 정규식을 만들어 봅시다.

let regex = new RegExp('[a-z0-9]+@[a-z]+\.edu\.[a-z]{2,3}');

let testEmails = ["notanemail.com", "someone@tistory.com", "example@yale.edu.com"];

testEmails.forEach((address) => {
    console.log(regex.test(address))
});

결과:

false
false
true

yale 이메일 주소만 제외하고 나머지 이메일 주소에는 최상위 도메인에 .edu가 포함되어 있지 않기 때문에 유효한 형식의 이메일 이어도 검사를 통과하지 못합니다.

RFC 5322 형식

RFC 5322는 Internet Message Format(이메일 메시지의 기본 형식)입니다. RFC 5322에는 허용되어야 하는 항목만 기술되어 있지만 표현식은 아닙니다.  규칙을 구현 하는 여러 종류의 표현식이 있는데 이는 상당히 복잡합니다. 올바르게 구현된 경우 RFC 5322 호환 정규식은 유효한 이메일 주소의 99.99%를 검증할 수 있어야 합니다. 다음은 javascript RegExp로 표현한 예제 입니다.

let regex = new RegExp("([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\"\(\[\]!#-[^-~ \t]|(\\[\t -~]))+\")@([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\[[\t -Z^-~]*])");

추가 엣지 케이스를 허용하는 확장버전과 그림으로 시각화한 자료는 http://emailregex.com/ 에서 확인할 수 있습니다.

위의 정규식으로 이메일 테스트를 해보면:

let regex = new RegExp("([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\"\(\[\]!#-[^-~ \t]|(\\[\t -~]))+\")@([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\[[\t -Z^-~]*])");

let testEmails = ["notanemail.com", "workingexample@stackabuse.com", "example@yale.edu.com"];

testEmails.forEach((address) => {
    console.log(regex.test(address))
});

결과:

false
true
true

정리

정규식으로 이메일 주소를 검증하는 완벽한 방법은 없습니다. 하지만 발생할 수 있는 경우의 수는 최대한 커버해야 합니다. 그렇기 때문에 현존하는 대부분의 이메일 형식을 검증하려면 RFC 5322 형식을 사용하면 됩니다.

관련 글

자바스크립트 정규식으로 비밀번호 강도 확인

자바스크립트 정규식 비밀번호 강도 확인

반응형

댓글