Svelte 5에서는 on:click이 사라지고 onclick으로 바뀌었습니다 — HTML 표준에 더 가까워졌다는 뜻입니다.

개념 정의

Svelte에서 이벤트 핸들링은 DOM 요소에 이벤트 리스너를 연결하는 것입니다. Svelte 5에서는 기존의 on: 디렉티브 대신 표준 HTML 이벤트 속성 방식(onclick, oninput 등)을 사용합니다.

DOM 이벤트 기본

SVELTE
<script>
  let count = $state(0);

  function handleClick() {
    count++;
  }
</script>

<!-- 함수 참조 -->
<button onclick={handleClick}>클릭: {count}</button>

<!-- 인라인 함수 -->
<button onclick={() => count++}>클릭: {count}</button>

<!-- 이벤트 객체 사용 -->
<button onclick={(e) => {
  console.log('클릭 위치:', e.clientX, e.clientY);
  count++;
}}>
  클릭: {count}
</button>

자주 쓰는 이벤트

SVELTE
<script>
  let text = $state('');
  let isHovered = $state(false);
  let position = $state({ x: 0, y: 0 });
</script>

<!-- 입력 이벤트 -->
<input
  oninput={(e) => text = e.target.value}
  placeholder="입력하세요"
/>

<!-- 키보드 이벤트 -->
<input
  onkeydown={(e) => {
    if (e.key === 'Enter') {
      console.log('엔터 입력:', text);
    }
  }}
/>

<!-- 마우스 이벤트 -->
<div
  onmouseenter={() => isHovered = true}
  onmouseleave={() => isHovered = false}
  onmousemove={(e) => position = { x: e.clientX, y: e.clientY }}
  class:hovered={isHovered}
>
  {isHovered ? '마우스 올림!' : '마우스를 올려보세요'}
</div>

<!-- 폼 제출 -->
<form onsubmit={(e) => {
  e.preventDefault();
  console.log('제출:', text);
}}>
  <input bind:value={text} />
  <button type="submit">제출</button>
</form>

<style>
  .hovered { background: #f0f0f0; }
</style>

이벤트 수정자

Svelte 5에서는 on:click|preventDefault 같은 수정자 문법이 사라졌습니다. 대신 이벤트 핸들러 안에서 직접 처리합니다.

SVELTE
<script>
  function handleSubmit(e) {
    e.preventDefault();
    console.log('폼 제출 방지됨');
  }

  function handleInnerClick(e) {
    e.stopPropagation();
    console.log('내부 클릭 — 버블링 중단');
  }
</script>

<form onsubmit={handleSubmit}>
  <button type="submit">제출</button>
</form>

<div onclick={() => console.log('외부')}>
  <button onclick={handleInnerClick}>내부</button>
</div>

유틸 함수로 수정자 구현

SVELTE
<script>
  // 재사용 가능한 이벤트 수정자 유틸
  function preventDefault(fn) {
    return (e) => {
      e.preventDefault();
      fn(e);
    };
  }

  function handleSubmit(e) {
    console.log('제출!');
  }
</script>

<form onsubmit={preventDefault(handleSubmit)}>
  <button type="submit">제출</button>
</form>

컴포넌트 이벤트 — 콜백 Props

Svelte 5에서는 createEventDispatcher 대신 ** 콜백 props** 패턴을 사용합니다.

SVELTE
<!-- Button.svelte -->
<script>
  let { onclick, label } = $props();
</script>

<button {onclick}>{label}</button>
SVELTE
<!-- App.svelte -->
<script>
  import Button from './Button.svelte';

  function handleClick() {
    console.log('버튼 클릭됨!');
  }
</script>

<Button onclick={handleClick} label="클릭하세요" />

커스텀 데이터 전달

SVELTE
<!-- TodoItem.svelte -->
<script>
  let { todo, onDelete, onToggle } = $props();
</script>

<div class="todo">
  <input
    type="checkbox"
    checked={todo.done}
    onchange={() => onToggle(todo.id)}
  />
  <span class:done={todo.done}>{todo.text}</span>
  <button onclick={() => onDelete(todo.id)}>삭제</button>
</div>

<style>
  .done { text-decoration: line-through; }
</style>
SVELTE
<!-- TodoList.svelte -->
<script>
  import TodoItem from './TodoItem.svelte';

  let todos = $state([
    { id: 1, text: '공부하기', done: false },
    { id: 2, text: '운동하기', done: true },
  ]);

  function deleteTodo(id) {
    todos = todos.filter(t => t.id !== id);
  }

  function toggleTodo(id) {
    const todo = todos.find(t => t.id === id);
    if (todo) todo.done = !todo.done;
  }
</script>

{#each todos as todo (todo.id)}
  <TodoItem {todo} onDelete={deleteTodo} onToggle={toggleTodo} />
{/each}

이벤트 위임

SVELTE
<script>
  let items = $state(['사과', '바나나', '딸기', '포도', '수박']);

  function handleClick(e) {
    const index = e.target.dataset.index;
    if (index !== undefined) {
      console.log(`${items[index]} 클릭됨`);
    }
  }
</script>

<ul onclick={handleClick}>
  {#each items as item, i}
    <li data-index={i}>{item}</li>
  {/each}
</ul>

면접 포인트

  • "Svelte 5에서 이벤트 처리가 어떻게 바뀌었나요?": on: 디렉티브가 사라지고 표준 HTML 이벤트 속성(onclick 등)을 사용합니다. 컴포넌트 이벤트도 createEventDispatcher 대신 콜백 props 패턴으로 전환되었습니다.
  • "이벤트 수정자가 없어진 이유는?": HTML 표준에 가까운 API를 지향하면서 Svelte 전용 문법을 줄였습니다. e.preventDefault()를 직접 호출하는 것이 더 명시적이고 표준에 부합합니다.

정리

Svelte 5의 이벤트 핸들링은 "특별한 문법 없이, 표준 HTML/JavaScript와 동일하게"를 지향합니다. on:click 대신 onclick, dispatch 대신 콜백 props — JavaScript를 잘 알면 Svelte도 잘 쓸 수 있다는 설계 철학이 드러납니다.

댓글 로딩 중...