5. 논리 문법 / Props

2020. 9. 4. 13:29재주껏 하는 Front-End/Svelte (준비중)

반응형

이번 글에서는 Svelte의 논리 문법과 Props에 대해서 알아보도록 하겠다.

 

분기 처리

 

프로그래밍을 하다 보면 어느 언어든 반드시 분기 처리를 통하여 상황에 맞게 동작해야 하는 경우가 많다. Svelte에서는 템플릿에 분기 처리를 통하여 조건에 따라 출력을 제어할 수 있다. Svelte에서는 템플릿에 if / else를 지원하며 기본적인 사용 방법은 아래와 같다.

 

1. if문 사용 방법

{#if 조건식}
  조건이 참일 경우 실행할 코드
{/if}

2. if / else문 사용 방법

{#if 조건식}
  조건이 참일 경우 실행할 코드
{:else}
  조건이 거짓일 경우 실행할 코드
{/if}

3. if / else-if / else문 사용 방법

{#if 조건식1}
  조건 1이 참일 경우 실행할 코드
{:else if 조건식 2}
  조건 2가 참일 경우 실행할 코드
{:else}
  모든 조건이 거짓일 경우 실행할 코드
{/if}

 

아래는 if문을 사용한 예제 코드이다. 조건에 따라 로그인 버튼과 로그아웃 버튼을 출력하는 예제이다.

 

<script>
	let user = { loggedIn: false };

	function toggle() {
		user.loggedIn = !user.loggedIn;
	}
</script>


{#if user.loggedIn}
  <button on:click={toggle}>
      Log out
  </button>
{/if}

{#if !user.loggedIn}
  <button on:click={toggle}>
      Log in
  </button>
{/if}

 

실행 결과는 아래와 같다. 버튼을 클릭하면 분기에 따라 버튼이 변경된다.

 

 

위의 코드는 if / else 문으로도 끝낼 수 있다. 아래의 코드로 변경해보자.

 

<script>
	let user = { loggedIn: false };

	function toggle() {
		user.loggedIn = !user.loggedIn;
	}
</script>

{#if user.loggedIn}
	<button on:click={toggle}>
		Log out
	</button>
{:else}
	<button on:click={toggle}>
		Log in
	</button>
{/if}

 

실행 결과는 위와 같다. 다음은 if / else-if / else를 사용한 예제 코드를 살펴보자.

 

<script>
	let x = 7;
</script>

{#if x > 10}
	<p>{x} is greater than 10</p>
{:else if 5 > x}
	<p>{x} is less than 5</p>
{:else}
	<p>{x} is between 5 and 10</p>
{/if}

 

딱히 설명할 내용이 없다. 일반적으로 우리가 아는 if / else 문과 동일하기 때문이다. 실행 결과는 아래와 같다.

 

 

Svelte의 분기문은 우리가 잘 아는 if / else와 크게 다르지 않았다. 참고로 Svelte의 분기분을 사용하면 DOM 자체가 변경되기 때문에 자주 사용되는 컴포넌트라면 스타일의 hidden 속성을 활용하는 편이 나을 수도 있겠다.

 

if / else 사용 시 DOM 자체가 변경된다.

 

반복문

 

반복문은 프로그래밍에서 절대 빠질 수 없는 문법으로 알고리즘의 핵심이다. Svelte의 템플릿에서는 each문을 사용하여 요소의 반복 작업을 지원한다. 기본적인 사용 방법은 아래와 같다.

 

{#each 이터레이터 타입 객체 as 객체의 아이템, 이터레이터 인덱스 (유니크 키 값)}
  반복 작업을 수행할 자바스크립트 코드
{/each}

 

예제 코드를 살펴보자. cats라는 배열을 선언하고 ul 태그의 아이템을 반복적으로 추가하는 코드다.

 

<script>
	let cats = [
		{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
		{ id: 'z_AbfPXTKms', name: 'Maru' },
		{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
	];
</script>

<h1>The Famous Cats of YouTube</h1>

<ul>
	<!-- open each block -->
	{#each cats as cat}
		<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
			{cat.name}
		</a></li>
	{/each}
	<!-- close each block -->
</ul>

 

실행 결과는 아래와 같다.

 

 

아이템 앞에 인덱스 값을 붙여서 출력할 수도 있다.

 

<script>
	let cats = [
		{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
		{ id: 'z_AbfPXTKms', name: 'Maru' },
		{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
	];
</script>

<h1>The Famous Cats of YouTube</h1>

<ul>
	<!-- open each block -->
	{#each cats as cat, idx}
		<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
			{idx + 1} : {cat.name}
		</a></li>
	{/each}
	<!-- close each block -->
</ul>

 

실행 결과는 아래와 같다.

 

 

반복문에는 DOM을 업데이트할 대상을 정확하게 찾기 위한 목적으로 id를 제공한다. VueJS의 경우 v-for를 사용할 때 필수적으로 key Props를 요구하는데, 이 역시 업데이트할 대상을 가리기 위함이다.

 

업데이트 대상을 명확하게 구분해서 오는 장점은 Svelte가 업데이트된 요소만 수정할 경우 성능이 향상되기 때문이다. 그만큼 브라우저가 레이아웃 과정을 적게 수행한다. 만약 키가 없거나 같은 키 값을 가진다면, 모든 요소가 변경되었다고 판단하고 모든 요소를 업데이트한다. 즉, 브라우저는 여러 번 레이아웃 과정을 수행하게 된다.

 

아래는 Svelte 튜토리얼의 id 예제다. 화면에 출력할 Thing 컴포넌트를 id와 color별로 정의하여 출력하는 페이지 코드이다. "Remove first thing" 버튼을 클릭하면 맨 앞에 아이템부터 잘라버린다.

 

// App.svelte

<script>
	import Thing from './Thing.svelte';

	let things = [
		{ id: 1, color: '#0d0887' },
		{ id: 2, color: '#6a00a8' },
		{ id: 3, color: '#b12a90' },
		{ id: 4, color: '#e16462' },
		{ id: 5, color: '#fca636' }
	];

	function handleClick() {
		things = things.slice(1);
	}
</script>

<button on:click={handleClick}>
	Remove first thing
</button>

{#each things as thing}
	<Thing current={thing.color}/>
{/each}



// Thing.svelte



<script>
	// `current` is updated whenever the prop value changes...
	export let current;

	// ...but `initial` is fixed upon initialisation
	const initial = current;
</script>

<p>
	<span style="background-color: {initial}">initial</span>
	<span style="background-color: {current}">current</span>
</p>

<style>
	span {
		display: inline-block;
		padding: 0.2em 0.5em;
		margin: 0 0.2em 0.2em 0;
		width: 4em;
		text-align: center;
		border-radius: 0.2em;
		color: white;
	}
</style>

 

출력 결과는 아래와 같다. 버튼을 클릭하면 맨 위의 아이템이 제거된다. 그런데 맨 위의 요소를 삭제하였음에도 왼쪽 요소의 색상은 그대로 유지되고 있다. Thing 컴포넌트의 왼쪽 요소가 초기의 컬러 값을 가지고 있기 때문이다. 이것은 우리가 의도한 결과가 아니다.

 

 

이 문제를 해결하기 위해 반복문에 아래에 ID를 추가해보자.

 

{#each things as thing (thing.id)}
	<Thing current={thing.color}/>
{/each}

 

다시 실행하면 의도한 대로 동작하는 것을 확인할 수 있다. 사실 이런 용도로 사용하기보다는 Svelte 애플리케이션의 성능 향상을 위해 사용한다고 생각하는 것이 좋다. VueJS의 반복문에서 Key Props를 필수로 요구하는 것과 같이, Svelte도 가능하면 ID를 설정해주는 것이 여러모로 좋다고 생각한다.

 

 

Async / Await

 

ES7에 추가된 async / await는 ES6의 제너레이터와 프로미스를 이용하여 비동기 코드를 마치 동기식으로 동작하는 것처럼 생각하며 코드를 작성할 수 있도록 하는 아주 유용한 문법이다. 옛날에 쓴 글이지만 제너레이터와 프로미스의 개념이 필요하다면 아래의 링크를 참고하기 바란다. 글 아래쪽에 설명되어 있다.

 

kim1124.tistory.com/2?category=232835

 

[KoaJS] 1. KoaJS 시작하기

1. Express is dead? NodeJS 진영에서 가장 유명한 풀스택 웹 프레임워크로 알려져있는 Express가 작년부터 이상한 말들이 나오기 시작했다. 그림 1. Express is dead? 구글에서 "Express is dead" 를 검색하면 나..

kim1124.tistory.com

 

Svelte에서는 Promise 객체를 템플릿에서 바로 출력할 수 있도록 Async / Await 문법을 제공한다. 사용 방법은 아래와 같다.

 

{#await 프로미스 객체}
  프로미스 객체가 작업을 수행할 때 표시할 부분
{:then 요청 결과 값}
  Resolve 호출 시 실행되는 부분
{:catch 에러 값}
  Reject 호출 시 실행되는 부분
{/await}

 

자바스크립트의 Async / Await 문법의 개념만 알고 있다면 쉽게 이해할 수 있다. 아래의 예제 코드를 보고 어떻게 사용해야 되는지 확인해보자. 실행 결과는 따로 올리지 않겠다.

 

<script>
	let promise = getRandomNumber();

	async function getRandomNumber() {
		const res = await fetch(`tutorial/random-number`);
		const text = await res.text();

		if (res.ok) {
			return text;
		} else {
			throw new Error(text);
		}
	}

	function handleClick() {
		promise = getRandomNumber();
	}
</script>

<button on:click={handleClick}>
	generate random number
</button>

{#await promise}
	<p>...waiting</p>
{:then number}
	<p>The number is {number}</p>
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}

 

Props

 

Props는 상위 컴포넌트가 하위 컴포넌트에게 값을 넘길 때 사용한다. 기본적인 사용 방법은 아래와 같다.

 

1. 상위 컴포넌트에서 하위 컴포넌트로 값을 전달할 때

<하위 컴포넌트 Props 변수명 = {전달할 값} />

2. 하위 컴포넌트에서 Props 선언

<script>
  export let Props 변수명 = Props가 전달되지 않았을 경우 기본값
</script>

3. ES6 스프레드 문법을 사용하는 경우

<하위 컴포넌트 Props 변수명 = {... 전달할 객체} />

 

간단한 예제 하나만 살펴보자. Nested 컴포넌트에 answer라는 Props를 선언하고 상위 컴포넌트인 App.svelte가 42라는 값을 Nested 컴포넌트로 넘기는 예제다. 만약, Props가 전달되지 않는다면, "a mystery" 문자열을 출력한다.

 

// App.svelte

<script>
	import Nested from './Nested.svelte';
</script>

<Nested answer={42}/>
<Nested/>


// Nested.svelte


<script>
	export let answer = 'a mystery';
</script>

<p>The answer is {answer}</p>

 

실행 결과는 아래와 같다.

 

 

이것으로 논리 문법 및 Props에 대한 설명을 마치겠다. 다음에는 이벤트 관리에 대해 알아보도록 하겠다. 오늘은 여기까지~

반응형

'재주껏 하는 Front-End > Svelte (준비중)' 카테고리의 다른 글

7. 바인딩  (0) 2020.09.14
6. 이벤트 처리  (0) 2020.09.08
4. 반응형 문법  (0) 2020.09.02
3. 기본 문법  (0) 2020.09.01
2. Quick Start Guide + VS Code 개발 환경 구성  (0) 2020.08.27