웹페이지를 만들다보면 자주 사용하는 레이아웃 부분은 별도로 모듈화 하여 재사용하고 싶어진다. svelte
에도 독립적인 기능을 하는 컴포넌트를 쉽게 만들 수 있으며, 그 컴포넌트를 사용하여 앱의 구조를 조직화하고 코드를 재사용할 수 있게 된다. svelte document 에서 Nested Components 라는 주제로 설명되어 있으니 참고하자.
이전 포스팅에서 만든 결과를 컴포넌트로 분리해서 다시 구성해보기로 한다. 아래 소스는 변경전 소스이다.
<!-- 변경전 -->
<script>
let contents = {};
const cdGender = [ { id : null, name : '-'},
{ id : 'M', name : '남' },
{ id : 'F', name : '여'}];
</script>
<div class="row">
<div class="col">
<div class="mb-2">
<label for="name" class="form-label">이름</label>
<input type="text" class="form-control"
bind:value={contents.name}>
</div>
<div class="mb-2">
<label for="gender" class="form-label">성별</label>
<select class="form-select" bind:value={contents.gender}>
{#each cdGender as code, i}
<option value="{code.id}">{code.name}</option>
{/each}
</select>
</div>
</div>
</div>
1. 중첩된 컴포넌트 만들기
중첩된 컴포넌트를 먼저 만들건데, 이 컴포넌트는 부모 컴포넌트에서 사용될 자식 컴포넌트이다. 자식 컴포넌트는 독립적으로 재사용 가능한 기능이나 뷰를 정의한다. HTML 입력폼이 길어지면 길어질수록 input 과 select 태그를 많이 쓰게 될텐데, 그 부분을 각각 컴포넌트로 분리해보기로 한다.
input
입력부를 별도의 svelte 파일로 정의한다.
<!-- InputText.svelte -->
<script>
export let title = "제목";
export let id;
export let val;
</script>
<label for="{id}" class="form-label">{title}</label>
<input type="text" class="form-control"
id="{id}" name="{id}" bind:value={val}
placeholder="" aria-label="">
select
입력란도 별도 svelte 파일로 정의한다.
<!-- Select.svelte -->
<script>
export let title = "제목";
export let id;
export let val;
export let cdSet;
</script>
<label for="{id}" class="form-label">{title}</label>
<select class="form-select" bind:value={val}
id="{id}" name="{id}" aria-label="">
{#each cdSet as code, i}
<option value="{code.id}">{code.name}</option>
{/each}
</select>
2. Nested Component 를 import 하기
이제 만들어놓은 컴포넌트를 가져와 import 만 해서 기존 소스를 대체하기만 하면된다. 컴포넌트간 값전달시에는 공백으로 구분하여 하나씩 입력하면 된다. bind:
기능을 사용하면 바로바로 객체에 입력된 값을 바인딩할 수 있게 된다. 여기만 넣으면 안되고 Nested 컴포넌트
내에도 bind:
로 끝까지 연결해줘야 한다. 소스가 원래도 길지 않았어서 별차이가 없다고 생각할지 모르지만, 코드가 길어질수록 유용할 듯 하다.
<!-- 변경후 -->
<script>
import InputText from './InputText.svelte'
import Select from './Select.svelte'
let contents = {};
const cdGender = [ { id : null, name : '-'},
{ id : 'M', name : '남' },
{ id : 'F', name : '여'}];
</script>
<div class="row">
<div class="col">
<div class="mb-2">
<InputText id = "name" title="이름"
bind:val={contents.name} />
</div>
<div class="mb-2">
<Select id="gender" cdSet={cdGender}
bind:val={contents.gender} />
</div>
</div>
</div>