1. React 이벤트 타입 기초
React는 브라우저의 네이티브 이벤트를 SyntheticEvent로 래핑하여 제공함
TypeScript에서는 각 이벤트별로 구체적인 타입을 제공함
주요 이벤트 타입들
import React from 'react';
// 1. MouseEvent - 마우스 관련 이벤트
function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
console.log('클릭됨:', e.button);
}
const handleClick: React.MouseEventHandler<HTMLButtonElement> = (e) => {
console.log('클릭됨:', e.button);
}
// <button onClick={handleClick}>
// 2. FormEvent - 폼 관련 이벤트
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
console.log('폼 제출됨');
}
// 3. ChangeEvent - 입력값 변경 이벤트
function handleChenge(e: React.ChangeEvent<HTMLInputElement>) {
console.log('입력값:', e.target.value);
}
// <input onChange={handleChange} />
// 4. keyboardEvent - 키보드 이벤트
function handleKeyDown(e: React.keyboardEvent<HTMLInputElement>) {
if (e.key === 'Enter') {
console.log('엔터키 눌림');
}
}
2. 이벤트 타입의 제네릭 활용
React의 이벤트 타입은 제네릭을 사용하여 이벤트가 발생한 Element의 타입을 지정할 수 있음
// 다양한 Element 타입 지정
function Component() {
// 버튼 클릭
const handleButtonClick = (e: React.MouseEvent<HTMLButtonElement>) => {
// e.currentTarget은 이벤트 핸들러가 등록된 요소(항상 HTMLButtonElement)
console.log(e.currentTarget.disabled);
};
// div 클릭
const handleDivClick = (e: React.MouseEvent<HTMLDivElement>) => {
// e.currentTarget은 HTMLDivElement 타입
console.log(e.currentTarget.className);
};
// input 변경
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
// e.target은 HTMLInputElement 타입
console.log(e.target.value);
};
return (
<div>
<button onClick={handleButtonClick}>클릭</button>
<div onClick={handleDivClick}>div 클릭</div>
<input onChange={handleInputChange} />
</div>
);
}
3. EventHandler 타입 정의하기
재사용 가능한 이벤트 핸들러 타입을 정의할 수 있음
// 기본적인 EventHandler 타입들
type ButtonClickHandler = React.MouseEventHandler<HTMLButtonElement>;
type InputChangeHandler = React.ChangeEventHandler<HTMLInputElement>;
type FormSubmitHandler = React.FormEventHandler<HTMLFormElement>;
type KeyDownHandler = React.KeyboardEventHandler<HTMLInputElement>;
// 커스텀 EventHandler 타입 만들기
type CustomClickHandler = (
event: React.MouseEvent<HTMLButtonElement>,
data?: any
) => void;
type CustomInputHandler = (
event: React.ChangeEvent<HTMLInputElement>,
fieldName: string
) => void;
// 사용 예시
function MyComponent() {
const handleClick: ButtonClickHandler = (e) => {
console.log('버튼 클릭됨');
};
const handleCustomClick: CustomClickHandler = (e, data) => {
console.log('커스텀 클릭:', data);
};
const handleInput: CustomInputHandler = (e, fieldName) => {
console.log(`${fieldName} 필드값:', e.target.value);
};
return (
<div>
<button onClick={handleClick}>기본 클릭</button>
<buttonn onClick={(e) => handleCustomClick(e, 'test')}>
커스텀 클릭
</button>
<input
onChange={(e) => handleInput(e, 'username')}
placeholder="사용자명"
/>
</div>
);
}
4. e.target vs e.currentTarget 이해하기
JavaScript vs TypeScript 사용 패턴의 변화
- JavaScript: e.target을 주로 사용(타입 검증 없이)
- TypeScript: e.currentTarget을 더 선호(타입 안정성 때문에)
차이점
- e.target: 실제로 이벤트가 발생한 element
- e.currentTarget: 이벤트 리스너가 등록된 element
function EventPropagationExample() {
const handleParentClick = (e: React.MouseEvent<HTMLDivElement>) => {
console.log('target:', e.target); // 실제 클릭된 Element
console.log('currentTarget:', e.currentTarget); // div Element
// currentTarget은 항상 HTMLDivElement 타입이 보장됨
console.log('부모 클래스:', e.currentTarget.className);
};
return (
<div onClick={handleParentClick} className="parent">
<button>버튼 1</button>
<span>텍스트</span>
<button>버튼 2</button>
</div>
);
}
타입 안정성 장점
function TypeSafetyExample() {
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
// ✅ currentTarget은 항상 HTMLButtonElement 타입
e.currentTarget.disabled = true;// 타입 안전
// 🤔 Native DOM에서는 target, currentTarget 모두 EventTarget | null 타입
// React의 SyntheticEvent는 제네릭 타입(<HTMLButtonElement>)을 통해
// currentTarget의 타입을 정확하게 추론해주므로 타입 가드 불필요
// 리액트가 아닌 바닐라 자바스크립트 상황이면 target 사용시 타입 가드로 추가 검증(타입좁히기) 필요
// if (e.target instanceof HTMLButtonElement) {
// e.target.disabled = true;
// }
// };
return <button onClick={handleClick}>클릭하세요</button>;
}
5. 실전 예제: 폼 관리
import React, { useState } from 'react';
interface FormData {
username: string;
email: string;
password: string;
}
// 이벤트 핸들러 타입 정의
type InputHandler = React.ChangeEventHandler<HTMLInputElement>;
type SubmitHandler = React.FormEventHandler<HTMLFormElement>;
type ButtonClickHandler = React.MouseEventHandler<HTMLButtonElement>;
function LoginForm() {
const [formData, setFormData] = useState<FormData>({
username: '',
email: '',
password: ''
});
// 입력 필드 변경 처리
const handleInputChange: InputHandler = (e) => {
const { name, value } = e.currentTarget; // currentTarget 사용으로 타입 안전
setFormData(prev => ({
...prev,
[name]: value
}));
};
// 폼 제출 처리
const handleSubmit: SubmitHandler = (e) => {
e.preventDefault();
console.log('제출된 데이터:', formData);
};
// 리셋 버튼 처리
const handleReset: ButtonClickHandler = (e) => {
e.currentTarget.blur(); // currentTarget으로 안전하게 접근
setFormData({ username: '', email: '', password: '' });
};
// 엔터키 처리
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter' && e.ctrlKey) {
console.log('Ctrl + Enter 눌림');
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
name="username"
value={formData.username}
onChange={handleInputChange}
onKeyDown={handleKeyDown}
placeholder="사용자명"
/>
<input
type="email"
name="email"
value={formData.email}
onChange={handleInputChange}
placeholder="이메일"
/>
<input
type="password"
name="password"
value={formData.password}
onChange={handleInputChange}
placeholder="비밀번호"
/>
<button type="submit">로그인</button>
<button type="button" onClick={handleReset}>
리셋
</button>
</form>
);
}'DEV > TypeScript' 카테고리의 다른 글
| React에 TypeScript 적용하기 - 4. Context 타입 적용하기 (1) | 2026.08.04 |
|---|---|
| React에 TypeScript 적용하기 - 3. 기본 Hook 타입 적용하기 (0) | 2026.08.04 |
| React에 TypeScript 적용하기 - 1. 컴포넌트 타입 적용하기 (0) | 2026.08.04 |
| TypeScript 심화 - 17. d.ts 파일과 패키지 타입 (0) | 2026.08.03 |
| TypeScript 심화 - 16. 유틸리티 타입 (0) | 2026.08.03 |