개발새발/Svelte

[Svelte v5] 재사용 가능한 컴포넌트 작성 (With Typing)

0xff 2025. 1. 5. 16:01

얼마 전에 Svelte v5가 릴리즈 되었다.

수정된 부분은 꽤나 많지만, 제일 눈여겨본 것은 export let의 deprecated와 props 변경이었다.

 

전체 변경사항은 아래에서 확인할 수 있다.

https://svelte.dev/docs/svelte/v5-migration-guide

 

보이는 바와 같이  $props() 를 통하여 속성들을 내려줄수 있게 되었다.

 

별거 아닌거같아 보이지만, 이는 재사용 가능한 컴포넌트 작성에 아주 큰 이점을 안겨준다.

 

만약 button, a 등의 element를 재사용 가능하게 컴포넌트화 할 시에 기존에는 $$restProps 를 통하여 내려줄 수 밖에 없었다.

근데 위와 같은 방식을 사용하게 되면 Type 안정성이 떨어진다.

 

restProps를 사용하게 되면 해당 엘리먼트가 어떤 타입을 지원하는지 자동완성이 되지 않기 때문이다.

오류 검출도 불가능할 뿐 더러, 유지보수가 어려워질 수 밖에 없는 구조다.

 

하지만 v5 버전으로 올라오면서, props 자체에 타입 부여가 가능해졌다.

 

 

스벨트에는 elements라는 alias가 존재한다.

https://github.com/sveltejs/svelte/blob/main/packages/svelte/elements.d.ts

 

svelte/packages/svelte/elements.d.ts at main · sveltejs/svelte

web development for the rest of us. Contribute to sveltejs/svelte development by creating an account on GitHub.

github.com

 

HTMLButtonAttributes 등의 속성 어트리뷰트를 props 타입에 상속해준다면 완벽한 타입 지원이 가능하다.

Button 컴포넌트의 소스코드는 아래와 같이 작성되었다.

src/components/button/Button.svelte

<script lang="ts">
	import type { HTMLButtonAttributes } from 'svelte/elements';
	import type { VariantProps } from 'class-variance-authority';

	import { buttonVariants } from './button.variants';
	import { cn } from '$lib/util';

	type ButtonProps = HTMLButtonAttributes & VariantProps<typeof buttonVariants>;

	let { variant, size, children, ...rest }: ButtonProps = $props();
</script>

<button {...rest} class={cn(buttonVariants({ variant, size }), rest.class)}>
	{@render children?.()}
</button>

class-variance-authority 라이브러리를 사용하여 variant props와 button attribute를 합쳐두었다.

 

 전체 소스코드

https://github.com/syail/svelte-v5-components-example

 

GitHub - syail/svelte-v5-components-example

Contribute to syail/svelte-v5-components-example development by creating an account on GitHub.

github.com