1. HTML의 input은 무조건 "문자열(string)"을 다룬다
브라우저에서 우리가 쓰는 <input /> 태그는,
사용자가 어떤 걸 입력해도 결과는 무조건 string으로 나온다
<input type="text" />
<input type="number" />
<input type="password" />
<input type="email" />
위의 어떤 type을 쓰든 간에,
event.target.value로 받아오는 값은 무조건 string
예시
<input
type="number"
onChange={(e) => {
console.log(typeof e.target.value); // 👉 항상 "string"
console.log(e.target.value); // 👉 예: "123"
}}
/>
사용자가 123이라고 쳐도, "123"이라는 문자열로 들어옴
숫자로 보이지만 실제론 글자
그래서 우리가 하는 일
- 사용자가 입력한 value는 string으로 받고
- 그게 숫자처럼 생겼으면 → parseInt()나 Number()로 우리가 직접 숫자로 바꿔주는 거야
요약표
사용자가 입력한 값 브라우저가 주는 값 실제 타입 우리가 해야 할 일
123 | "123" | string | 숫자가 필요하면 변환해야 함 |
20001004 | "20001004" | string | parseInt("20001004") 필요 |
"HTML 인풋은 무조건 string인데, 타입스크립트에서 타입을 지정하는 건 왜? 무슨 의미야?"
TypeScript에서 아래처럼 value: string으로 타입을 명시하는 이유는 크게 두 가지야:
1. 개발자가 실수하는 걸 막기 위해서
<Input value={123} /> // ❌ 에러 발생
- 여기서 123은 number 타입이야. TypeScript는 이걸 보고 에러를 내줘.
- 왜냐하면 Input 컴포넌트가 value: string만 받는다고 약속했기 때문이야.
- 이런 식으로 숫자, 객체, 배열 같은 예상치 못한 타입이 들어오는 걸 미리 방지할 수 있어.
2. onChange 함수의 일관성을 유지하기 위해
onChange: (value: string) => void
- 인풋의 값은 문자열인데, 만약 value가 숫자일 수도 있다고 하면 onChange도 (value: number | string) => void처럼 복잡해져.
- 하지만 value가 무조건 string이라는 보장이 있으면, onChange도 심플하게 string만 다루면 되니까 코드가 더 안전하고 깔끔해져.
그런데 실제로는?
브라우저가 인풋 값을 "123"처럼 문자열로 처리해주긴 하지만, 우리가 실수로 number를 value로 넘기면 렌더링은 되지만 경고나 예기치 못한 결과가 발생할 수 있어.
그래서 아예 타입 차원에서 차단해주는 게 더 안전한 거야.
정리하면
"브라우저가 알아서 숫자도 string으로 바꿔주긴 해.
하지만 TypeScript에선 명확히 value: string으로 제한해서
실수를 줄이고, onChange 같은 로직도 안정적으로 만들 수 있어!"
🧸 요약
브라우저:
"나는 string밖에 못 줘"
타입스크립트:
"그래! 그럼 너 이게 string이란 거 확실히 알고 써. 실수하면 내가 막아줄게!"
이제 string인데 숫자나 특수기호가 왜 들어갈 수 있지? 하는 궁금증이 생긴 거지?
아주 쉽게, 완전 기초부터 풀어줄게.
이걸 이해하면 문자열(string)이 어떤 건지 더 확실히 감 잡을 수 있어!
먼저, 문자열(string)이란?
문자열은 글자 하나하나의 나열이야.
그 안에 들어갈 수 있는 건 숫자든, 알파벳이든, 특수기호든 상관없어!
"123"
"hello"
"!@#"
"abc123@naver.com"
위에 있는 건 전부 다 string 타입이야.
"숫자"가 들어왔다고 해서 그 값이 숫자(Number)인 건 아니야
예를 들어:
const value = "123";
console.log(typeof value); // 👉 string
비록 123이라는 숫자처럼 생겼어도,
따옴표로 묶여 있으면 그냥 문자야.
즉, '1', '2', '3'이 나란히 있는 "글자 덩어리"일 뿐이야.
특수기호도 마찬가지야
const email = "abc@naver.com"; // @는 문자 중 하나
console.log(typeof email); // 👉 string
@, !, #, $ 같은 것도 그냥 글자로 취급되는 거야.
그냥 우리가 보기엔 "기호"처럼 생겼지만, 컴퓨터는 이것도 "문자 1개"라고 생각해.
input은 모두 문자열(string)로 입력값을 받아
즉, input에 아래처럼 쳐도:
<input type="text" />
사용자가 "abc123@naver.com"이라고 쓰면,
value는 "abc123@naver.com" — 문자열이 되는 거야.
그럼 숫자가 필요할 땐?
그때는 우리가 string → number로 변환해줘야 해:
const str = "123";
const num = parseInt(str); // 👉 123 (숫자)
정리: string 안에는 뭐든 들어올 수 있어
"123" | string | 숫자처럼 생긴 문자열 |
"@#$%^" | string | 특수문자로 된 문자열 |
"abc123@naver.com" | string | 이메일 형식이지만 여전히 문자열 |
"true" | string | 불리언처럼 보이지만 그냥 글자 |
→ 이건 전부 문자열(string)로 처리됨!
✨ 마무리 요약
- input 값은 무조건 string
- 숫자, 특수기호, 영어 다 포함할 수 있어
- 진짜 숫자 계산하려면 → parseInt, Number()로 변환 필요
- 타입스크립트에서는 value: string으로 지정하는 게 맞아!
"그럼 유효성 검사는 어떻게 해? 문자열인데 숫자로 바꿔서 해?"
→ 이건 값의 형태에 따라 달라, 그래서 예시와 함께 하나씩 쉽게 설명할게!
유효성 검사의 핵심
입력값이 어떤 "형식"이나 "규칙"을 만족하는지 확인하는 과정
(숫자로 바꾸는 건 필요할 때만!)
숫자만 입력해야 하는 경우
예: 인증번호, 생년월일 등
const isValidCode = /^\d{6}$/.test(validCode);
// 숫자 6자리만 허용 (예: 123456)
여기서 숫자로 변환하지 않아도 돼!
왜냐하면 이건 문자열이 숫자로만 구성돼 있는지만 검사하는 거니까.
이메일 검증
const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
이건 @가 포함돼 있고 형식이 맞는지 체크
숫자 변환과는 전혀 관계 없어!
비밀번호 복잡도 (영문+숫자+특수문자)
const isValidPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,15}$/.test(password);
이건 문자열 안에
- 영문 소문자 하나 이상
- 영문 대문자 하나 이상
- 숫자 하나 이상
- 특수기호 하나 이상
- 총 8~15자
이 조건들을 확인하는 거고,
당연히 string 그대로 검사야.
정말 숫자 연산이 필요한 경우만 변환!
const ageString = "20";
const age = parseInt(ageString);
if (!isNaN(age) && age >= 18) {
// 성인
}
이런 경우는 "숫자로서의 의미"가 중요하니까 변환하는 거야.
정리표
검사 대상 | 예시 | 숫자로 변환 필요? |
이메일 | example@gmail.com | ❌ No |
비밀번호 조건 | 영문+숫자+기호 | ❌ No |
인증번호 6자리 | "123456" | ❌ No |
나이 계산, 생년월일 연산 | "20001004" → 계산할 때 | ✅ Yes |
마무리 요약
- 유효성 검사는 대부분 string 상태에서 검사
- 정규식 (/.test()) 많이 사용
- 진짜 숫자로 연산이 필요할 때만 parseInt, Number() 사용
결론
그니까, 인풋 자체는 string 타입이 들어오는데..(어떤 데이터가 들어와도 string이라고 처리 되는데)
굳이 타입을 string이라고 한번 더 지정 해주는 이유는.. 혹시 모를 실수 방지와, onchange 함수의 일관성 때문!
'Studying > React' 카테고리의 다른 글
리액트 공부하기 - 모달 만들기 (0) | 2025.06.28 |
---|---|
리액트 공부하기 - hook form (0) | 2025.06.24 |
리액트 타입스크립트 공부하기 - 유효성 검사 react-hook-form 으로 라이브러리 사용해서 검사하기 (0) | 2025.06.23 |
리액트 타입스크립트 공부하기 - input 박스 관련 속성 (0) | 2025.06.23 |
리액트 타입스크립트 공부하기 - props로 테일윈드 className 속성 내려주기 (0) | 2025.06.23 |