유효성 검사를 하는 Regex, 정규 표현식에 대해 조금 찾아본 내용을 정리해본다.
Regular Expression, 줄여서 Regex라 불리는 정규 표현식은 주어진 String 값의 패턴을 분석하는 툴이다. 흔히 특정 단어 추출 또는 필터링 역할을 하는데, 특정 패턴을 탐색, 발견할 수 있다보니 반대로 원하는 구조인지 검사할 때도 사용할 수 있다.
따라서 기술 블로그에서 보면 regex를 비밀번호, 전화번호, 아이디 등의 검증 절차로 활용하는 형태가 많다. 번외로 이전에 매니저님께서는 regex가 만능처럼 보이겠지만 실질적으로 만능은 아니라는 의견을 주셨었다.
하지만 해당 의견을 들었다보니 어떤 이유로 만능이 아닌지, 어떨 때 regex를 사용하는게 좋은지 등을 조금 고민해보았는데, 구성해본 함수를 활용해서 나는 왜 regex를 사용하지 않았는지를 조금 적어보았다.
func validatePassword(_ password: String) -> Bool {
let passwordCheck = "^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{8}$"
let predicate = NSPredicate(format:"SELF MATCHES %@", passwordCheck)
return predicate.evaluate(with: password)
}
1. 복잡한 패턴을 가진 비밀번호가 필요없다
비밀번호 패턴을 검수하는 함수에서 regex를 사용하지 않았다.
위 코드로 대문자 1개, 숫자 또는 특수문자의 조합과 최소 8자리의 값을 넣도록 검사 할 수 있다고 하지만 너무 복잡해보였다. 너무 간단한 비밀번호임에도 불구하고 너무 복잡한 기술을 사용하는게 좋은걸까?.
비밀번호 또는 아이디의 조합이 특정 길이 이상, 몇가지 단어만 특정돼서 사용되면 문제는 없으니 아래와 같이 활용해보는 방식을 생각했다.
func validatePwWithoutRegex(_ password: String) -> Bool {
guard !password.isEmpty else { return false }
let firstLetter = password.prefix(1)
guard firstLetter == firstLetter.uppercased() else { return false }
let numbers = poassword.suffix(1)
guard numbers.rangeOfCharacter(from: .decimalDigits) != nil else { return false }
return true
이렇 방식으로 값이 비었는지, 첫단어는 대문자인지, 마지막 사용 표현은 숫자인지 확인할 수 있지 않을까?
물론 rangeOfCharacter 함수 자체를 처음 사용해보긴 했다!
2. regex는 '패턴 탐색'이다
가장 인상 깊었던 점은 regex가 올바른 값을 가지고 있는지 확인을 한다는 점이었다. 하지만 해당 값들을 사용해되, 어떤 구조로 짜여졌는지까지는 위에 소개한 regex는 판단하지를 못한다.
한 예로, 아이디를 jack@gmail.com으로 짜거나 aaa@com.com으로 생성하더라도 필터링되지 않는다는 점이었다. 물론 더 섬세한 regex를 사용한다면 충분히 걸러낼 수 있겠지만, 간단한 방식으로는 유효성 검사가 '유효성 검사' 기준에 부합하는지 의문이 갈 수 밖에 없는 구조라 생각됐다.
3. Front와 Back 모두 필터링을 해야한다
regex 관련해서 팀원 및 매니저님이 공유해준 내용은 프런트 엔드에서도 데이터를 확인해야하겠지만 백엔드 쪽에서도 검수를 해야한다는 점이었다.
간단하게 찾아보니 백엔드에서 데이터 검수가 필요한 이유를 조금은 이해하게 됐다.
3-1. 데이터 일관성 유지
프런트에서 데이터가 올바른 형식을 맞췄는지 1차 검수를 진행한 이후,
이메일 주소 형식이 맞는지, '@'이 어디에 위치해있는지 등 세세한 디테일을 잡야한다고 한다. 예상치 못한 오류를 방지하기 위함인데, 실제 테스트를 해볼 때 .co인지 .com인지 구분을 하지 못했었다. frontend 측에서 user@google.co을 이메일로 저장하게 될 경우 backend 측에서는 별도 안전 장치가 없다면 어쩔수 없이 틀린 이메일 주소를 계속 저장하는 과정을 거치는데 - 데이터 형식이 바뀌는 것만큼 골치 아픈 일은 없을 것 같다.
3-2. 보안 강화
Front에서 한번 확인한 값, 데이터가 유효하다고 판단하고 넘길 경우
과연 해당 데이터가 안전하다!고 생각할지 약간의 의심이 생겼다.
바로 데이터에게 합격 목걸이를 걸어주기 힘들어보였는데, 이유는 단순히 비밀번호, 이메일, 아이디를 넘어 더 넓은 개념의 '데이터'가 존재하기 때문이다.
이메일 주소를 아이디로 넣도록 유도했는데 url 링크를 넣으면 어떻게 되는걸까?
단 한번만에 검증 절차를 거쳐 간다면 해당 링크는 이메일로 인식을 할까 - 오류를 뱉어낼까 등 데이터 자체가 안전한지에 대한 생각을 해보게 됐다.
일상적인 상황을 예시로 든다면 체육대회에서 윗몸 일으키기 50개를 서로 적도록 친구와 합을 맞췄다면 과연 올바른 데이터라고 볼 수 있을까..? 싶다.
이외에 온라인 상에서 발생하는 바이러스, 피싱 링크 등 고려해야하는 요소들이 워낙 많다보니 2번의 나름 보안을 강화하는 편이 어플에서도 고려되어야 한다는 점을 깨닫게 됐다.
단! 지금 현시점에서는 백엔드 개발자 및 더 디테일한 regex를 짜거나 이해할 수 있는 수준은 아니라고 생각들어 regex가 아닌 다른 방식으로 풀어나가보고자 한다.
생각보다 regex가 만능이 아니라는 표현이 신기했는데,
막상 실제로 사용하다보면 애매해지는 경우가 많을 것 같았다.
애플 WWDC에서 또한 Regex를 사용하는 하나의 예시를 데이터가 많거나 반복되는 multi-line String에서 특정 패턴을 참고하여 데이터 추출하는 방식에 활용한 만큼, 간단한 데이터 유효성 검사 등은 일반 함수로 생성을 해보는 시도가 좋을 것 같다.
WWDC 2022 링크