스벨트킷 설치와 데모앱 등을 아직 만들지 못했다면 앞의 컨텐츠를 먼저 참고하길 바란다.
MongoDB 그리고 Atlas
버튼의 상태를 DB에 저장하고 싶었다. 또한 해당 DB를 쉽고 빠르게, 양심없게도 무료로 사용하고 싶었다. 더더욱 양심리스하게 클라우드로 제공되는 DB를 이용하려고 했다. 그러다보니 MongoDB Atlas가 딱이다. 스벨트와 몽고DB는 핏이 맞고 Atlas라는 서비스를 통해 클라우드로 DB를 제공해줄 수 있었다. 아래와 같이 SvelteKit 루트에서 MongoDB를 설치하자.
npm install mongodb
이제 회원가입을 하고 클러스터를 추가해보자. 클러스터 및 DB 추가하는 방법은 여기서 다루지 않는 대신 링크를 남겨 놓겠다. 따라하기만 하면 무료 DB를 구축할 수 있다. 이제 컬렉션을 추가해보자. 데이터를 추가하는 작업이라고 생각하면 된다. 몽고DB는 ObjectId라는 객체로 ID를 구분한다. 뒤에서 어떻게 ID를 바라보는지 다시 다루도록 하겠다. 아래처럼 컬렉션을 만들어보자.
위는 아래의 정보를 바탕으로 만들어진 화면이다.
- Project : MyFirstDB
- DB : mydb
- Collection(테이블에 준함) : tutorials
- Document(Data에 준함) : ID, Title, State(버튼 상태)로 구성
SvelteKit + MongoDB Atlas
몽고DB의 프로젝트 화면 내부에 Overview탭으로 가면 CONNECT 버튼이 보인다. 여기서 "Connect your application" 버튼을 클릭해보면 연결하는 방법에 대해 가이드를 주고 있다. Driver를 Node.js로 세팅하고 "Include full driver code example" 옵션을 해제하면 아래와 비슷한 코드를 볼 수 있다.
MONGO_URL=mongodb+srv://admin:<password>@myfirstdb.*****.mongodb.net/?retryWrites=true&w=majority
이제 루트 위치에서 .env 파일을 생성하고, 위 코드를 여기에 입력한다. 그런 다음에 src 폴더 아래에 db 폴더를 생성하고 mongo.ts 파일을 생성, 아래 코드를 집어넣는다.
// mongo.ts
import { MongoClient } from 'mongodb';
import { MONGO_URL } from '$env/static/private';
console.log('url >>> ' + MONGO_URL);
const client = new MongoClient(MONGO_URL);
export function start_mongo(): Promise<MongoClient> {
console.log('Starting mongo...');
return client.connect();
}
export default client.db('mydb');
log를 통해 env 내부의 MONGO_URL을 확인할 수 있다. 또한 가장 하단에 db함수로 mydb에 접근할 수 있게 되었다. 이제는 컬렉션에 접근할 차례다. mongo.ts와 같은 위치에 tutorials.ts를 생성한다. 그리고 아래 코드를 입력해보자.
// tutorials.ts
import db from '$db/mongo';
export const tutorials = db.collection('tutorials');
그런데 $db/mongo쪽에 "'$db/mongo' 모듈 또는 해당 형식 선언을 찾을 수 없습니다."라는 에러 메시지가 나타난다. db alias 등록이 안되어 있어서 그런건데 svelte.config.js에서 지정할 수 있다. 아래처럼 지정하면 tutorials.ts의 에러가 사라진 것을 볼 수 있다.
// svelte.config.js
import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
adapter: adapter(),
alias: {
$db: './src/db',
}
}
};
export default config;
Data를 불러오기
DB 연결은 완료했으니 이제 실제 Data를 불러보자. 먼저 "+page.ts"라고 되어 있는 파일을 "+page.server.ts"로 이름을 변경한다. 로드(Load) 기능은 브라우저와 서버, 모두 사용이 가능하지만 오로지 서버에서만 사용하고자 할 때는 PageServerLoad를 이용하면 된다. 이때 반드시 이름을 "+page.server.ts"로 변경해야 한다. 자세한 사항은 개발문서를 참고하자. 아래 코드를 저장하면 터미널에 title 정보가 출력되는 것을 볼 수 있다.
// +page.server.ts
import { tutorials } from '$db/tutorials';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async function () {
console.log('>>>> start');
const data = await tutorials
.find(
{}
,{
projection: {
_id: String,
title: String,
state: Number
}
}
)
.toArray();
data.forEach((item) => {
console.log('>>>> title : ' + item.title);
if (item.title.length > 14) {
item.length = item.title.length * 0.7
} else {
item.length = item.title.length * 0.8
}
})
const loadData = JSON.parse(JSON.stringify(data))
return {
tutorials: loadData
};
};
item.length를 data에 담았는데 이 내용은 뒤에서 다루도록 하겠다. 여기까지 내용은 아래 깃헙에서 확인할 수 있다.
데이터를 화면에 가져오기
다시 +page.svetle로 이동하자. 아래처럼 작성하면 +page.server.ts의 tutorials와 +page.svelte의 data가 항상 일치하게 된다.
// +page.svelte
<script lang="ts">
import { onMount } from 'svelte';
import type { PageData } from './$types';
export let data: PageData;
$: ({ tutorials } = data);
data.tutorials.forEach((item:any) => {
console.log('>>>> ' + item.title)
});
// 이하 생략
page.svelte는 화면단이기에 브라우저의 개발자도구에서 제공하는 콘솔창으로 로그를 볼 수 있다. 이렇게 데이터를 가지고 왔으니 이제는 데이터 갯수만큼 버튼이 늘어나도록 해보자. 이 상태에서 버튼이 여러개 늘어나면 못생겨 보이니깐 CSS도 조금 수정했다.
<!-- styles.css -->
body {
display: flex;
justify-content: center;
align-content: center;
flex-wrap: wrap;
background-color: rgb(0, 48, 49);
}
.wrapper {
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
}
.button {
font-size: 1.2em;
text-align: left;
padding: 0.8em 1.4em;
margin: 0.4em 0.4em;
border-radius: 2em;
cursor: pointer;
font-family: 'Montserrat', sans-serif;
font-weight: 600;
border: 0;
color: WHITE;
line-height: 1.6em;
transition: background-color 300ms ease-in-out;
}
<!-- 일부 생략 -->
버튼에 title을 넣어보자. 또한 그대로 노출되었을 때 버튼 여백이 너무 많다. 그래서 이전에 세팅된 length를 여기에 적용한다. 태그에 바로 값을 입력하라 수 있는 것도 스벨트의 장점이다. input 태그가 나온 이유는 뒤에서 설명하겠다.
<!-- +page.svelte -->
<section>
<div class="wrapper">
{#each tutorials as tutorial}
<input hidden name="id" type="text" value={tutorial._id} />
<input hidden name="title" type="text" value={tutorial.title} />
<input hidden name="state" type="number" value={tutorial.state} />
<button
class="button +
{tutorial.state == 0 ? 'button--default' : ''} +
{tutorial.state == 1 ? 'button--process' : ''} +
{tutorial.state == 2 ? 'button--success' : ''} "
>
<div class="button__icon-wrapper">
<div class="button__icon" />
</div>
<div class="button__text-wrapper" style="width: {tutorial.length}em">
<div class="button__text button__text--default">{tutorial.title}</div>
<div class="button__text button__text--process">{tutorial.title}</div>
<div class="button__text button__text--success">{tutorial.title}</div>
</div>
</button>
{/each}
</div>
</section>
이렇게 구현하면 아래처럼 여러가지 버튼이 나타나는 것을 볼 수 있다. state에 따라서 버튼 모양도 달라보인다.
- state가 0일 때 : Default (> 모양)
- state가 1일 때 : Process (애니메이션 효과)
- state가 2일 때 : Success (v 모양)
여기까지 코드는 아래 깃헙에 남겨놓았다.
.
'Frontend' 카테고리의 다른 글
무작정 따라하는 Sveltekit + MongoDB + Vercel. [3] 구현 및 배포 (2) | 2022.10.25 |
---|---|
무작정 따라하는 Sveltekit + MongoDB + Vercel. [1] 설치 및 데모앱 (1) | 2022.10.25 |
자바스크립트는 모르지만 화려한 토글 버튼을 구현하고 싶어 (1) | 2022.10.04 |
Comment