참고 문서
https://beepeach.tistory.com/194
https://daheenallwhite.github.io/swift/2019/05/01/check-input-using-CharacterSet/
유니코드 - Table 12. General_Category Values
https://www.unicode.org/reports/tr44/#General_Category_Values
애플 공식 문서 - CharacterSet
https://developer.apple.com/documentation/foundation/characterset
애플 공식 문서에서 CharacterSet의 설명을 보면 "검색 연산에서의 사용을 위한 유니코드 문자 값의 집합"이라고 되어 있다.
Topics의 설명을 봤을 때도 Unicode General Category에 대해 언급하기 때문에 먼저 이 부분에 대한 이해가 필요했다.
Unicode General Category 로 구글링하니 해당 문서가 검색되었다.
해당 문서의 5.7.1 General Category Values - Table 12. General_Category Values를 보면 어떤 약자와 함께 간략한 설명이 되어 있다.
대충 읽어보자면 "General_Category는 간단히 말하자면 첫 번째로 가장 일반적인 문자 분류"라고 설명하며 표를 제시하고 있다.
아래는 그 표를 이해 되는 부분만큼만 정리한 내용이다.
CharacterSet 는 말 그대로 문자 집합이라는 뜻이다.
CharacterSet을 통해 문자 검색(필터링), 유효성 검사(비밀번호, 이메일 등) 같은 것을 쉽게 할 수 있다. 문서를 보니 URL 인코딩도 가능한 듯.
공식 문서의 "Getting Standard Character Sets" 에 있는 문자 집합을 활용하거나, 직접 문자 집합을 만들어 요소를 추가/삭제할 수도 있다.
집합이기 때문에 집합 연산을 통해 문자 검사가 가능하다.
위의 유니코드 General Category Values 약자를 참고하면 쉽게 이해할 수 있다.
alphanumerics
: 유니코드 L*, M*, N*
을 포함한 문자 집합. 즉 문자+기호+숫자decimalDigits
: 십진법 숫자 문자 집합letters
: 유니코드 L*, M*
을 포함한 문자 집합. 즉 문자+기호이외에도 훨씬 많은 문자 집합이 준비되어 있다.
위의 만들어진 문자집합 또는 내가 만든 문자집합을 가지고 집합 연산을 하는 메서드들을 제공한다.
insert(charactersIn : String)
: 문자 집합에 특정 문자열 추가intersection(CharacterSet)
: 교집합을 구해 줌isSubset(of: CharacterSet)
: 부분집합인지 확인isSuperSet(of: CharacterSet)
: 상위집합인지 확인isDisjoint(with: CharacterSet)
: 서로소집합인지 확인union(CharacterSet)
: 합집합을 구해 줌역시 이외에도 훨씬 많은 집합 연산, 검사 메서드들이 있다.
아래는 내가 연습했던 비밀번호 검사 예제 코드이다.
func passwordValidator(password: String) -> Int {
let passwordCharSet = CharacterSet(charactersIn: password)
let passwordLength = password.count
// 숫자로만 구성되고 길이가 8글자 미만 : 아주 약한 암호(1 Level)
// 영문자로만 구성되고 길이가 8글자 미만 : 약한 암호 (2 Level)
// 영문자와 한 개 이상의 숫자로만 구성되어 있고 길이 8글자 이상 : 강한 암호 (4 Level)
// 영문자와 숫자, 특수문자(-, +, !, @, #, $, %)가 한 개 이상씩 구성되어 있고 길이가 8글자 이상 : 아주 강한 암호 (5 Level)
// 나머지 경우는 : 보통 암호 (3 Level)
let numberSet = CharacterSet.decimalDigits
let letterSet = CharacterSet.letters
let alphanumericSet = CharacterSet.alphanumerics
let specialLetterSet = CharacterSet(charactersIn: "-+!@#$%") // CharacterSet.symbols ?
if !numberSet.intersection(passwordCharSet).isEmpty && !letterSet.intersection(passwordCharSet).isEmpty && !specialLetterSet.intersection(passwordCharSet).isEmpty && passwordLength >= 8 {
return 5
}
if !numberSet.intersection(passwordCharSet).isEmpty && !letterSet.intersection(passwordCharSet).isEmpty && passwordLength >= 8 {
return 4
}
if passwordCharSet.isSubset(of: letterSet) && passwordLength < 8 {
return 2
}
if passwordCharSet.isSubset(of: numberSet) && passwordLength < 8 {
return 1
}
return 3
}