BuNa_
IT Story
BuNa_
전체 방문자
오늘
어제
  • 분류 전체보기 (117)
    • CS (14)
      • 운영체제 (8)
      • 네트워크 (0)
      • Design Pattern (1)
      • OOP (4)
    • 대외활동 (24)
      • 우아한테크코스 (14)
      • DND 동아리 (4)
      • UMC 동아리 (5)
      • 해커톤 (1)
    • Android (29)
      • MVVM (2)
      • 스터디 (11)
      • Compose (3)
      • Unit Test (1)
    • Project (5)
      • 어따세워 (5)
      • DnD 과외 서비스 (0)
    • Programming (11)
      • Kotlin (4)
      • 파이썬 (7)
    • Git (1)
    • 인공지능 (22)
    • 백준 (8)
    • 기타 (3)
      • IntelliJ (1)
      • 일상 (0)

블로그 메뉴

  • 홈

공지사항

인기 글

태그

  • Ai
  • 우테코 5기
  • External fragmentation
  • Baekjoon
  • 다이나믹 프로그래밍
  • Compose
  • k-means++
  • 인공지능 분류
  • 우아한테크코스
  • 안드로이드
  • MVVM
  • 어따세워
  • 파이썬
  • 셀레니움
  • 컴공선배
  • 객체지향 생활체조
  • 우테코
  • 운영체제
  • K-means
  • ViewModel
  • RecyclerView
  • 우테코 프리코스
  • 원시값 포장
  • 외부 단편화
  • 선형회귀
  • 백준
  • UMC
  • 딥러닝
  • 인공지능
  • Android

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
BuNa_

IT Story

[Android] 자바 코틀린 (Pattern, Matcher)정규식을 사용하여 패스워드 조건을 만들어보자
Android

[Android] 자바 코틀린 (Pattern, Matcher)정규식을 사용하여 패스워드 조건을 만들어보자

2022. 2. 5. 19:47


동아리 프로젝트 중, 비밀번호 변경을 구현하는 단계에서 정규식을 사용할 일이 생겼습니다.

조건은 '영문, 숫자, 특수문자 중 2개를 사용하여 최소 8자리 이상'의 비밀번호를 입력해야 합니다.

 

 자바와 코틀린에서는 기본적으로 Pattern과 Matcher라는 정규식 라이브러리 클래스를 제공합니다.

이번 포스팅에서는 해당 클래스의 사용방법에 대해 알아보고 직접 비밀번호에 적용해보도록 하겠습니다.

 


 

Pattern

- Pattern 클래스 주요 메서드

compile(String regex) : 주어진 정규표현식으로부터 패턴을 만듭니다.
matcher(CharSequence input) : 대상 문자열이 패턴과 일치할 경우 true를 반환합니다.
asPredicate() : 문자열을 일치시키는 데 사용할 수있는 술어를 작성합니다.
pattern() : 컴파일된 정규표현식을 String 형태로 반환합니다.
split(CharSequence input) : 문자열을 주어진 인자값 CharSequence 패턴에 따라 분리합니다.


- Parttern 플래그 값 사용(상수)

Pattern.CANON_EQ : None표준화된 매칭 모드를 활성화합니다.
Pattern.CASE_INSENSITIVE : 대소문자를 구분하지 않습니다. 
Pattern.COMMENTS : 공백과 #으로 시작하는 주석이 무시됩니다. (라인의 끝까지).
Pattern.MULTILINE : 수식 ‘^’ 는 라인의 시작과, ‘$’ 는 라인의 끝과 match 됩니다.
Pattern.DOTALL : 수식 ‘.’과 모든 문자와 match 되고 ‘\n’ 도 match 에 포함됩니다.
Pattern.UNICODE_CASE : 유니코드를 기준으로 대소문자 구분 없이 match 시킵니다.
Pattert.UNIX_LINES : 수식 ‘.’ 과 ‘^’ 및 ‘$’의 match시에 한 라인의 끝을 의미하는 ‘\n’만 인식됩니다.

 

Matcher

- Matcher 클래스 주요 메서드

matches() : 대상 문자열과 패턴이 일치할 경우 true 반환합니다.
find() : 대상 문자열과 패턴이 일치하는 경우 true를 반환하고, 그 위치로 이동합니다.
find(int start) : start위치 이후부터 매칭검색을 수행합니다.
start() : 매칭되는 문자열 시작위치 반환합니다.
start(int group) : 지정된 그룹이 매칭되는 시작위치 반환합니다.
end() : 매칭되는  문자열 끝 다음 문자위치 반환합니다.
end(int group) : 지정되 그룹이 매칭되는 끝 다음 문자위치 반환합니다.
group() : 매칭된 부분을 반환합니다.
group(int group) : 매칭된 부분중 group번 그룹핑 매칭부분 반환합니다. 
groupCount() : 패턴내 그룹핑한(괄호지정) 전체 갯수를 반환합니다.

 

MetaCharacter

표현식                                              설명
^ 문자열의 시작
$ 문자열의 종료
. 임의의 한 문자 (문자의 종류 가리지 않음,  단, \ 는 넣을 수 없음)
* 앞 문자가 없을 수도 무한정 많을 수도 있음
+ 앞 문자가 하나 이상
? 앞 문자가 없거나 하나있음
[] 문자의 집합이나 범위를 나타내며 두 문자 사이는 - 기호로 범위를 나타낸다. []내에서 ^가 선행하여 존재하면 not 을 나타낸다.
{} 횟수 또는 범위를 나타낸다.
() 소괄호 안의 문자를 하나의 문자로 인식 
| 패턴 안에서 or 연산을 수행할 때 사용
\s 공백 문자
\S 공백 문자가 아닌 나머지 문자
\w 알파벳이나 숫자
\W 알파벳이나 숫자를 제외한 문자
\d 숫자 [0-9]와 동일
\D 숫자를 제외한 모든 문자
\ 정규표현식 역슬래시(\)는 확장 문자. 역슬래시 다음에 일반 문자가 오면 특수문자로 취급하고 역슬래시 다음에 특수문자가 오면 그 문자 자체를 의미
(?i) 앞 부분에 (?i) 라는 옵션을 넣어주면 대소문자를 구분하지 않음

 

 

정규식 패턴

분류 정규식 패턴
숫자 ^[0-9]*$
영문자 ^[a-zA-Z]*$
한글 ^[가-힣]*$
영어&숫자 ^[a-zA-Z0-9]*$
비밀번호 (숫자, 문자 포함의 6~12자리 이내) ^[A-Za-z0-9]{6,12}$
비밀번호 (숫자, 문자, 특수문자 포함 8~15자리 이내) ^.*(?=^.{8,15}$)(?=.*\d)(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$
이메일 ^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$
휴대전화 ^\\d{3}-\\d{3,4}-\\d{4}$
일반전화 ^\\d{2,3}-\\d{3,4}-\\d{4}$
주민등록번호 \d{6} \- [1-4]\d{6}
파일확장자 ^\\S+.(?i)(txt|pdf|hwp|xls)$
이중 파일확장자 (.+?)((\\.tar)?\\.gz)$

 

 

위에 정리된 메서드와 표를 바탕으로 정규식을 만들어보겠습니다.

 

1. 영문과 숫자가 섞인 8 ~ 20자의 문자를 입력받기

val pwPattern1 = "^(?=.*[A-Za-z])(?=.*[0-9])[A-Za-z[0-9]]{8,20}$" // 영문, 숫자 8 ~ 20자 패턴
val password1 = "abcd1234" // 임의의 패스워드 1 (영문+숫자)
val password2 = "1234@$!*" // 임의의 패스워드 2 (숫자+특수문자)

val pattern = Pattern.compile(pwPattern1) // 패턴 컴파일

val matcher1 = pattern.matcher(password1) // 비교를 위한 Matcher 인스턴스 생성
val matcher2 = pattern.matcher(password2) // 비교를 위한 Matcher 인스턴스 생성

Log.d("Match", matcher1.find().toString()) // 패턴 비교 결과 출력
Log.d("Match", matcher2.find().toString()) // 패턴 비교 결과 출력


True
False

 

2. 영문과 특수문자가 섞인 8 ~ 20자의 문자를 입력받기

val pwPattern2 = "^(?=.*[A-Za-z])(?=.*[$@$!%*#?&.])[A-Za-z$@$!%*#?&.]{8,20}$" // 영문, 특수문자 8 ~ 20자 패턴
val password1 = "1234@$!*" // 임의의 패스워드 1 (숫자+특수문자)
val password2 = "abcd@$!*" // 임의의 패스워드 2 (영문+특수문자)

val pattern = Pattern.compile(pwPattern2) // 패턴 컴파일

val matcher1 = pattern.matcher(password1) // 비교를 위한 Matcher 인스턴스 생성
val matcher2 = pattern.matcher(password2) // 비교를 위한 Matcher 인스턴스 생성

Log.d("Match", matcher1.find().toString()) // 패턴 비교 결과 출력
Log.d("Match", matcher2.find().toString()) // 패턴 비교 결과 출력


False
True

 

3. 숫자와 특수문자 섞인 8 ~ 20자의 문자를 입력받기

val pwPattern3 = "^(?=.*[0-9])(?=.*[$@$!%*#?&.])[[0-9]$@$!%*#?&.]{8,20}$" // 숫자, 특수문자 8 ~ 20자 패턴
val password1 = "abcd1234" // 임의의 패스워드 1 (영문+숫자)
val password2 = "1234@$!*" // 임의의 패스워드 2 (숫자+특수문자)

val pattern = Pattern.compile(pwPattern3) // 패턴 컴파일

val matcher1 = pattern.matcher(password1) // 비교를 위한 Matcher 인스턴스 생성
val matcher2 = pattern.matcher(password2) // 비교를 위한 Matcher 인스턴스 생성

Log.d("Match", matcher1.find().toString()) // 패턴 비교 결과 출력
Log.d("Match", matcher2.find().toString()) // 패턴 비교 결과 출력


False
True

 

위와 같은 코드를 바탕으로 비밀번호의 패턴을 만들어낼 수가 있습니다.

 

저희 프로젝트의 패스워드 조건은 이 3가지를 모두 혼합해야 만들어낼 수 있습니다.

즉, 영문+숫자+특수문자 중 2가지를 입력받아야 하며, 글자 수는 8자 이상이어야 합니다.

해당 조건을 구현한 코드는 아래와 같습니다.

 

private fun isRegularPW(password: String): Boolean {
    val pwPattern1 =
        "^(?=.*[A-Za-z])(?=.*[0-9])[A-Za-z[0-9]]{8,20}$" // 영문, 숫자
    val pwPattern2 =
        "^(?=.*[0-9])(?=.*[$@$!%*#?&.])[[0-9]$@$!%*#?&.]{8,20}$" // 숫자, 특수문자
    val pwPattern3 =
        "^(?=.*[A-Za-z])(?=.*[$@$!%*#?&.])[A-Za-z$@$!%*#?&.]{8,20}$" // 영문, 특수문자
    val pwPattern4 =
        "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[$@$!%*#?&.])[A-Za-z[0-9]$@$!%*#?&.]{8,20}$" // 영문, 숫자, 특수문자

    val pattern = Pattern.compile(pwPattern1)
    val matcher = pattern.matcher(pwPattern1)
    Log.d("Match", matcher.find().toString())

    return (Pattern.matches(pwPattern1, password) ||
            Pattern.matches(pwPattern2, password) ||
            Pattern.matches(pwPattern3, password) ||
            Pattern.matches(pwPattern4, password))
}

 

 

TextWatcher를 통해 EditText의 입력값을 감지하고, 정규식을 통해 패스워드 조건이 일치한다면 완료 버튼을 활성화합니다.

이상으로 정규식에 대한 개념을 다루어보았습니다.

아래에는 자주 사용되는 정규표현식을 정리한 표를 남기며 포스팅을 마무리하겠습니다.

긴 글 읽어주셔서 감사합니다.

 

자주 사용되는 정규표현식

정규 표현식 설명
^[0-9]*$ 숫자
^[a-zA-Z]*$ 영문자
^[가-힣]*$ 한글
\\w+@\\w+\\.\\w+(\\.\\w+)? E-Mail
^\d{2,3}-\d{3,4}-\d{4}$ 전화번호
^01(?:0|1|[6-9])-(?:\d{3}|\d{4})-\d{4}$ 휴대전화번호
\d{6} \- [1-4]\d{6} 주민등록번호
^\d{3}-\d{2}$ 우편번호

 

 

내용에 오류가 있거나, 질문이 있으신 분들은 댓글을 남겨주시면 감사하겠습니다! 😊

저작자표시 비영리 변경금지

'Android' 카테고리의 다른 글

[Android] Listview vs RecyclerView  (1) 2023.04.20
[Android] This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) 오류 해결  (2) 2022.12.23
[Android] ViewModel + Event Wrapper Pattern 단일 이벤트 처리  (0) 2022.12.12
[Android] Firebase Dynamic Link를 활용하여 사용자 초대링크 생성하기  (2) 2022.02.08
[Android][어따세워] 음성인식으로 주차장을 검색해보자! STT(Speech To Text) SpeechRecognizer  (2) 2021.12.11
    'Android' 카테고리의 다른 글
    • [Android] This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) 오류 해결
    • [Android] ViewModel + Event Wrapper Pattern 단일 이벤트 처리
    • [Android] Firebase Dynamic Link를 활용하여 사용자 초대링크 생성하기
    • [Android][어따세워] 음성인식으로 주차장을 검색해보자! STT(Speech To Text) SpeechRecognizer
    BuNa_
    BuNa_
    안드로이드 개발자를 향해 달리고 있는 공대생입니다! 🧑 Android, Kotlin, Java, Python 등 학습하고 있는 내용과 프로젝트를 주로 업로드하고 있습니다. 지적과 조언은 언제나 환영입니다!😊 github : https://github.com/tmdgh1592

    티스토리툴바