TIL - 전화번호 입력칸 만들기 : 숫자 타입의 input의 최대 자릿수 제한하기

Jisu Park·2022년 12월 1일
2

오늘의개발일지-TIL

목록 보기
7/12

💣 문제상황


사용자가 전화번호를 입력할 때 지정된 전화번호 길이만큼만 입력할 수 있도록 제한하고 싶다!

🧪 세 가지의 시행착오들

첫 번째 시도 : maxLength

<input type="number" maxLength={13} />

처음엔 기존에 다른 input 창에서 사용하던 대로 maxLength를 사용하려고 했다. 하지만 maxLength를 지정해도 input에는 무한대로 입력이 가능했다. maxLength를 잘못 입력했나 싶어서 몇 번이나 다시 작성했지만 결과는 달라지지 않았다. 그래서 바로 검색해보니,

음, 안되는 게 맞았다. maxLength는 text 타입의 input에만 작동하는 것이었다. 한 가지의 배움을 가지고 해당 블로그에 제시된 방법 중에 간단해보이는 두 번째 방법을 시도했다.

두 번째 시도 : min, max 설정

<input type="number" max="13" />

하지만 두 번째 시도라고 이름 붙인 만큼, 해당 코드도 작동하지 않았다. 처음엔 max만 적어서 그런가 싶어서 min을 함께 작성해보기도 하고, max 속성의 타입이 숫자인지 문자열인지 모르겠어서 두 가지 방법도 모두 적용해보았으나 별 다른 진전이 없었다. 또 안되는 이유를 찾아야했다.

블로그를 처음부터 찬찬히 읽고 적용했다면 이런 일이 없었을 것을... min, max가 숫자 타입의 input을 위한 것은 맞지만 직접 입력에 대해서는 적용이 안된다. 두 속성은 값을 선택하는 방식으로 숫자 input을 사용할 때 값의 범위를 설정해주는 속성이었던 것이다. 그러므로 직접 입력하는 방식을 취할 때에는 사용할 수 없었다.

마지막 시도 : onChange event에서 제어하기

<input onChange={(e) =>{ if(e.target.value.length >= max_length) return; }
       type="number" />

좋은 코드인지는 모르겠으나 잘 돌아가는 해결방법은 바로 onChange에서 입력값의 길이를 항상 비교하여 최대 자릿수보다 길면 더이상 입력할 수 없게 막는 것이었다. 하지만 조금 더 의미있는 코드를 작성해보기 위해 이번엔 pattern을 사용하는 방식을 적용해보게 되는데,,

👣 한 단계 나아가기

onChange 이벤트에 조건문을 삽입하는 것으로 마무리지을 수도 있지만, 전화번호 입력칸을 좀 더 완벽하게 (디자인대로) 만들기 위해서는 자동 빈칸 입력도 적용해야 했다. 예를 들면 사용자가 전화번호를 01012345678 이라고 띄어쓰기 없이 입력하더라도 실시간으로 빈칸을 입력하여 결과적으로 010 1234 5678 이 되도록 하는 것이었다. 한국 사용자의 전화번호만 고려한다면 구글에 있는 블로그들을 참고하여 금방 끝낼 수 있었겠지만, 전세계의 전화번호 형식을 모두 고려해야 했기에 동적인 방법을 찾아야했다.

첫 번째 시도 : pattern 속성 활용하기


다양한 블로그에서 input의 validation은 pattern 속성을 활용하라는 글을 많이 봤다. 그래서 처음엔 pattern을 적용하는 방식을 이용하기 위해 모든 나라의 전화번호의 pattern을 가져오는 함수까지 만들었다. 하지만.. 위의 인용구에서 볼 수 있듯이 pattern 속성은 number type의 input에서는 사용할 수 없어서 적용이 어려웠다. 더불어 pattern의 경우 폼 제출시 validation을 하기 때문에 실시간 적용을 원하는 디자인에 알맞지 않았다. 다른 방법을 찾아야했다.

두 번째 시도 : 기존에 가지고 있던 sample과 비교하여 띄어쓰기 입력하기

전세계의 전화번호 포맷 등 다양한 정보를 불러올 수 있는 라이브러리 : libphonenumber-js

이 라이브러리를 사용하여 전세계의 전화번호 형식을 가져올 수 있었기 때문에 여기서 다시 출발하기로 했다. 내가 생각해낸 방법은 입력된 value의 length값을 index 값으로 활용하여 sample에서 해당 인덱스의 값이 띄어쓰기이면 띄어쓰기를 입력하는 형식이었다. 원하는 대로 잘 돌아가는 듯 했으나.. 알고보니 type이 text로 되어 있어서 잘 돌아가고 있던 것이었으므로 type을 number로 바꿨더니 띄어쓰기를 아예 받아주지 않았다. 괘씸한 놈 하지만 이 방식이 가장 괜찮다고 판단하였기 때문에 그냥 type은 text로 두고 onChange에서 들어오는 문자열값이 number인지 확인하는 형식을 도입하기로 마음 먹었다. 그로 인해 타이핑되는 value가 숫자인지 아닌지 판별하는 validation도 여기에 포함되게 되었다.

   onChange={(e) => {
     
	//Check the length of input value is longer than phone number example or not and block the exceeded input.
	if (e.target.value.length > phoneNumberExample.length) return;

	//Check input value is only formed with number or space.
	const isNumeric = (val: string) => {
		return val === "" || /^[0-9 ]+$/.test(val);
	};
	if (!isNumeric(e.target.value)) return;

	let phoneNumberInput = e.target.value;
	const lastWordIndex = phoneNumberInput.length;

	//For erasing action, when the last word is space, erase that space
	if (phoneNumberInput[lastWordIndex - 1] === " ") phoneNumberInput = phoneNumberInput.slice(0, lastWordIndex - 1);

	// Add space for right location based on phone number example
	if (phoneNumberExample[lastWordIndex] === " ") {
		phoneNumberInput = phoneNumberInput.slice(0, lastWordIndex) + " " + phoneNumberInput.slice(lastWordIndex);
	}
     
	setPhoneNumber(phoneNumberInput);
}}

결국 모든 validation 관련 코드가 onChange안으로 들어가게 되었다. 이게 좋은 방법일지는 모르겠지만 (추후에 코드리뷰를 받고, 고치게 되는 부분이 있다면 업데이트해야겠다) 지금으로선 디자인 가이드를 따라서 기술적으로 모든 케이스를 커버할 수 있는 방법이었다.

🎉 결과물!

그리하여.. 하루를 거의 다 잡아먹은 결과물되시겠다. 사실 처음엔 이렇게 자세하게 적을 생각이 없었고 시행착오 부분까지만 간단하게 설명하려고 했었다. 하지만 전화번호 입력칸을 만들다보니 생각해야 할 것들이 점점 다양해졌고, 오랜만에 머리를 굴려 작성한 코드라 이왕 이렇게 된 김에 기록해두면 좋겠다 싶어서 끝까지 작성하게 되었다. 아직 자잘한 버그가 남아있어 손을 봐야하지만 큰 흐름엔 변화가 없을 것 같다.

📚 Reference

input 태그 관련

[Html] Input 태그 Number 타입의 Maxlength 최대 자릿수 설정하기
html5 | input type number maxlength 설정 ( 모바일 ) / oninput, max, min
<input> 태그의 pattern 속성

전화번호 입력칸 디자인 구현 관련

핸드폰 번호 하이픈(-) 자동입력
html input pattern 정규표현식 모음
JavaScript에서 Sring이 숫자인지 확인
[javascript] 자주 사용하는 정규 표현식 (Regular Expression) 정리

profile
언젠간 데이터 분석을 하고 싶은 초짜 프론트엔드 개발자입니다🙃

0개의 댓글