큰푸른물의 코딩일기 [2일차 20180208] C# 매번하는 유효성 검사의 코딩 노가다를 줄이는 방법


아 우여곡절 끝에 막바지였던 프로젝트의 프로그램을 완성 했다.

물론 돌리다가 발생하는 에러 같은건 수정 해야겠지만,

일단은 소프트웨어는 해결 됐고, 배선 부분만 마무리 하면 탈출(?) 할 수 있을 것 같다.

요즘 계속 천안으로 출장 중인데, 어느정도 마무리 짓고 내려오다 보니 이 시간이 되어 버렸다.

같이 출장갔던 직원은 가면 바로 뻗을 것 같다고 했지만,

100일 연속 도전 중에 기껏 어제 하루 써놓고 포기할 수 없어서 이렇게 글을 적으러 왔다.


어제 글에서도 언급을 했었는데, 나는 중복코딩을 정말 싫어한다.

정말 한줄만 반복적으로 나와도 함수를 만들어 호출하려고 궁리한다.

물론 상황은 급한데, 내마음 편하려고 복잡한 것 들도 구현하려고 붙잡고 있을 수는 없으니

그럴때는 일단 중복코딩이든 뭐든 해놓고 나중에 정리해야지 하고 넘어가는 경우도 많기 하지만.

뭔가 찜찜한 마음은 언제나 남아 있다.


오늘은 그 중복 코딩들 중에서도 모든 프로젝트에 다 나온다고 자신있게 말할 수 있는

입력 컨트롤의 유효성 검사에 대해서 이야기 해보자.


이름이라든가, 아이디, 비밀번호, 전화번호, 주소, 등등.

사용자의 입력을 받는 프로그램에서는 온갖 종류의 사용자 입력값을 제대로 입력을 했는지 확인을 거쳐서 사용하게 된다.

사용자의 입력을 안받는 프로그램이라 하더라도 기본적으로 환경설정 같은데서

접속할 서버의 주소라든가, 포트 같은것들을 설정하는 UI에서 설정을 저장하는 시점에서 체크 해야 하기도 하니 정말 입력 컨트롤에 대한 유효성 검사를 하지 않는 프로젝트는 없을 것이다.


이렇게 자주 사용되는 유효성 검사를 다들 어떻게 하고 있는가?

체크해야 하는 시점이 오면,

사용자 이름 텍스트박스에 한글말고 기호나 영문같은게 들어있지는 않은지 체크하고,

아니면 아예 입력자체를 안한것은 아닌지도 살펴보고,

사용자 이름 체크가 통과 되었으면 다음으로 전화번호로 넘어가서 이번에는 숫자말고 다른게 있지는 않은지도 살펴보고.. 이런식의 작업을 반복해야 한다.

그냥 체크만하고 넘기는 것이 아니라, 너님 이름 입력안했네, 비밀번호 틀렸네,  같은 메세지도 뿌려주고,

잘 못 입력한 컨트롤에 커서까지 갖다놓는 친절함 정도는 기본으로들 하고 있을 것이다.


이것을 그냥 매번 일반적으로 코딩을 한다면

각컨트롤들의 세부 포멧에 대한 부분은 차치 하고서라도 최소한 매번 입력을 안하거나 했을 때,

메세지를 뿌려주고, 커서를 갖다 놓는 작업을 컨트롤 마다 다 하고 있어야 한다.

이런건 당연히 내 스타일이 아니지,


그래서 이 방법 저 방법 써보다가

얼마전까지는 Control 타입을 인자로 받는 공용 유효성 검사 함수를 하나 만들어 놓고

유효성 검사를 할 일이 있을 때 마다 해당함수에 입력 컨트롤을 던져주는 식으로 했었다.

그리고 메세지를 보여줄 상황에서 자연스러운 안내 메세지를 위해서

디자인단에 입력컨트롤의 속성중에 엿장수 마음대로  개발자 마음대로 쓸 수 있는

Tag속성에 오류메세지의 이름을 미리 넣는 식으로 해서

유효성 함수 한 번 호출로 만약 잘못된 값이라면

"Control.Tag.ToString() 의 입력값이 잘못되었습니다."라고

나름 잘못된 부분까지 매끄럽게 안내해주게 해준다고 쓰고 있었는데,

사실 이것도 귀찮은 부분이 있는 것이,

보통 폼을 디자인 할 때, 컨트롤 하나를 샘플 삼아서 크기나 모양 같은것들을 맞춰놓고

그 컨트롤을 복사해서 쓰는 경우가 많은데,

이럴 때 Tag속성을 수정하는 것을 깜빡해서

유효성 검사할 때, 이름을 잘 못 입력했고, 실제로 커서도 이름칸에서 깜빡이고 있는데,

정작 메세지는 아이디를 잘못 입력했다고 뜨는 경우들이 종종 발생했다.

아이디 컨트롤을 복사해서 이름 컨트롤을 만들고 Tag를 수정안한 문제라서 Tag만 제대로 수정해 주면 되긴 하지만, 사람인지라 이런 실수는 얼마든지 반복 할 수 있기에 이건 좋은 방법이 아닌것 같았다.


오늘 완성한 프로그램에서는 근본적으로는 비슷하긴 한데,

확장메서드를 사용해서 구현해 보았다.

호출하는 부분을 먼저 살펴보면 다음과 같다.


if (false == txtDbId.CheckNullOrEmptyOk("DB사용자 아이디")) return;

if (false == txtDbPw.CheckNullOrEmptyOk("DB사용자 비밀번호")) return;


만약 사용자 아이디가 잘못 되었다면 "DB사용자 아이디를 입력해 주십시오."라고 메세지를 띄우고 나서 아이디 칸에 커서를 갖다 놓은 다음에 이후 단계는 빠져나가 버린다.

메서드 호출시 인자로 메세지에서 사용할 타이틀을 적어주는 것이라서

바로 눈에 보이므로 Tag속성을 사용할때의 실수 걱정은 줄어들 듯하다.


함수의 구현은 대략 다음과 같다.

public static bool CheckNullOrEmptyOk(this TextBox txtInput, string Title)

{

    if(string.IsNullOrEmpty(txtInput.Text.Trim()))

    {

        MessageBox.Show(string.Format("{0}이(가) 입력되지 않았습니다. {0}을(를) 입력해 주십시오.", Title), "입력오류", MessageBoxButtons.OK, MessageBoxIcon.Error);

        txtInput.Focus();

        return false;

    }

    else

    {

        return true;

    }

}


이렇게 함수 하나만 만들어 놓으면,

아무것도 안해도 프로젝트에 추가로 생성되는 모든 텍스트박스에 유효성검사가 필요할 때면

그냥 컨트롤 이름뒤에 쩜(.)하나만 찍어서 나오는 확장 함수를 호출해서 쓰면 된다.


오늘은 입력하지 않은 경우만 체크를 할 수 있는 함수를 만들었지만

오버로딩과 비트 플래그 열거형을 활용해서

if (false == txtDbId.IsValidateOk("DB사용자 아이디", ChkType.NullOrEmpty|chkType.Alphanumeric)) return;

위와같이 공백불가, 영문자나 숫자만 입력가능 등. 체크할 조건을 자유롭게 복합적으로 부여할 수 있도록 만드는 중이다.


그동안 앞서 말한 Tag속성을 사용하는 방법 말고도

함수 호출 한방으로 끝내 보려고

인자로 params Control[]을 받는 유효성검사 함수를 만들어서 검사할 컨트롤들을 죄다 나열해서 호출해 보기도 하고

몇가지 방법을 써봤었는데, 다들 썩 마음에 들지 않았었다.

아 내머리로는 이것까지가 한계인가.

혹시 이 글을 보게되는 누군가가 좋은 아이디어가 있다면 공유해 주면 좋겠다.

당분간은 이 방법을 개선해 봐야겠다.

Posted by 5CFM
,