ReactReact 기초강의 10개 중 3번째난이도 기초

이벤트 처리 — 클릭, 입력, 폼 다루기

발행 읽는 시간 약 1 분

  • React
  • 이벤트
  • onClick
  • onChange
  • 폼처리

강의 소개

React에서 이벤트를 처리하는 방법을 배웁니다. onClick, onChange, onSubmit 등 주요 이벤트 핸들러와 타입 안전한 이벤트 처리를 익힙니다.

React 이벤트 시스템#

React는 브라우저 이벤트를 SyntheticEvent로 감싸 크로스브라우저 일관성을 제공합니다.

TSX
// HTML
<button onclick="handleClick()">클릭</button>

// React (camelCase, 함수 참조)
<button onClick={handleClick}>클릭</button>

클릭 이벤트#

TSX
import { MouseEvent } from "react";

function ButtonExample() {
    // 이벤트 객체 없이
    function handleSimpleClick() {
        console.log("클릭됨");
    }

    // 이벤트 객체 사용
    function handleClick(e: MouseEvent<HTMLButtonElement>) {
        console.log("클릭 위치:", e.clientX, e.clientY);
        e.preventDefault();  // 기본 동작 방지
    }

    // 인라인 + 추가 데이터
    return (
        <div>
            <button onClick={handleSimpleClick}>단순 클릭</button>
            <button onClick={handleClick}>이벤트 사용</button>
            {[1, 2, 3].map(id => (
                <button key={id} onClick={() => console.log(id)}>
                    항목 {id}
                </button>
            ))}
        </div>
    );
}

입력 이벤트#

TSX
import { ChangeEvent, useState } from "react";

function InputExample() {
    const [value, setValue] = useState("");

    function handleChange(e: ChangeEvent<HTMLInputElement>) {
        setValue(e.target.value);
    }

    return (
        <div>
            <input
                type="text"
                value={value}          // 제어 컴포넌트
                onChange={handleChange}
                placeholder="입력하세요"
            />
            <p>입력값: {value}</p>
            <p>글자 수: {value.length}</p>
        </div>
    );
}

제어 vs 비제어 컴포넌트#

TSX
// 제어 컴포넌트: React가 상태 관리 (권장)
<input value={value} onChange={e => setValue(e.target.value)} />

// 비제어 컴포넌트: DOM이 상태 관리
const inputRef = useRef<HTMLInputElement>(null);
<input ref={inputRef} defaultValue="초기값" />
// 값 읽기: inputRef.current?.value

폼 처리#

TSX
import { FormEvent, useState } from "react";

interface LoginForm {
    email: string;
    password: string;
}

function LoginForm() {
    const [form, setForm] = useState<LoginForm>({ email: "", password: "" });
    const [error, setError] = useState<string | null>(null);
    const [isLoading, setIsLoading] = useState(false);

    function handleChange(e: ChangeEvent<HTMLInputElement>) {
        const { name, value } = e.target;
        setForm(prev => ({ ...prev, [name]: value }));
    }

    async function handleSubmit(e: FormEvent<HTMLFormElement>) {
        e.preventDefault();  // 페이지 새로고침 방지

        if (!form.email || !form.password) {
            setError("이메일과 비밀번호를 입력하세요.");
            return;
        }

        setIsLoading(true);
        setError(null);

        try {
            await login(form);
            alert("로그인 성공!");
        } catch (err) {
            setError("로그인에 실패했습니다.");
        } finally {
            setIsLoading(false);
        }
    }

    return (
        <form onSubmit={handleSubmit}>
            <input
                name="email"
                type="email"
                value={form.email}
                onChange={handleChange}
                placeholder="이메일"
            />
            <input
                name="password"
                type="password"
                value={form.password}
                onChange={handleChange}
                placeholder="비밀번호"
            />
            {error && <p className="error">{error}</p>}
            <button type="submit" disabled={isLoading}>
                {isLoading ? "로그인 중..." : "로그인"}
            </button>
        </form>
    );
}

키보드 이벤트#

TSX
import { KeyboardEvent } from "react";

function SearchInput() {
    const [query, setQuery] = useState("");

    function handleKeyDown(e: KeyboardEvent<HTMLInputElement>) {
        if (e.key === "Enter") {
            performSearch(query);
        }
        if (e.key === "Escape") {
            setQuery("");
        }
    }

    return (
        <input
            value={query}
            onChange={e => setQuery(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder="Enter로 검색"
        />
    );
}

주요 이벤트 타입#

이벤트타입요소
onClickMouseEvent<T>대부분
onChangeChangeEvent<T>input, select, textarea
onSubmitFormEvent<HTMLFormElement>form
onKeyDownKeyboardEvent<T>키보드 입력 가능 요소
onFocusFocusEvent<T>포커스 가능 요소
onBlurFocusEvent<T>포커스 가능 요소

정리#

  • React 이벤트는 camelCase: onClick, onChange, onSubmit
  • e.preventDefault()로 기본 동작 방지
  • e.stopPropagation()으로 이벤트 버블링 중단
  • TypeScript에서 이벤트 타입을 명시하면 자동완성 지원
  • 폼은 onSubmit + e.preventDefault() 패턴 사용

다음 편에서는 useEffect — 컴포넌트 생명주기와 부수 효과를 처리하는 방법을 배웁니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.