추석 연휴동안 스벨트로 삽질한 썰 풉니다.

dante Yoon·2021년 9월 26일
1

영차영차 삽질기

목록 보기
2/2
post-thumbnail

안녕하세요, 단테입니다.

삽질하기 적당한 만큼 선선한 날씨가 되었습니다. 추석 연휴 잘 보내셨나요?

요 근래 스벨트 앤 새퍼 인 액션 책을 읽으며 svelte와 sapper 공부에 푹 빠져있습니다.
스벨트는 리엑트, 뷰와 같은 싱글페이지 어플리케이션을 만드는데 편리함을 주는 프레임워크이며,
2019, 2020년을 거치며 점점 인기있는 프레임워크로서의 입지를 다지고 있습니다.
리엑트, 뷰와 다르게 가상돔을 사용하지 않아 번들 사이즈 측면에서 매우 경량화 된 용량과 간편한 코드 길이로 생산성 있는 웹을 만들 수 있다는 장점을 가지고 있습니다.

성능 부분에서 다른 프레임워크와 비교하는 것은 본 글의 주제가 아니므로 포스팅 하단에 다른 리소스를 첨부하는 것으로 생략하겠습니다.

올 연휴 기간이 책을 거의 다 읽어가는 시점과 맞물리기도 했고 평소 만들어보고 싶던 웹 어플리케이션도 있던 상황이라 빠르게 프로토타이핑을 해보기 시작했습니다.

만들고 싶은 것

저는 기독교인으로서 작년도 12월 31일에서 올해 1월 1일로 넘어오는 사이 연례 행사와 같은 느낌으로 성경 말씀 뽑기를 했었습니다. 코로나로 인해 온라인으로 대부분의 행사들이 진행됨에 따라 온라인 말씀뽑기 사이트를 이용했었고, 당시 이거 내년에 내가 만들어봐야겠다.라는 생각을 했습니다.

도구 정하기

말씀 뽑기 소개 페이지와 말씀 뽑기 결과 페이지, 두 페이지만 만들면 되었기에 평소 익숙한 리엑트를 이용한다면 보다 빠르게 작업을 완료할 수 있었습니다. 하지만 본 프로젝트가 처음 사용하는 스벨트를 실제 프로젝트에 적용하는데 안성맞춤이라는 생각이 들었고, 좋은 공부가 될 수 있을 것 같아 스벨트를 선택했습니다.

CSR, SSR, SSG

공부를 한다는 것은 굉장히 좋은 것이지만, 실제 주변 사람들과 함께 사용할 프로젝트임을 고려해보았을 때 SEO를 위해 CSR(Client Site Rendering)을 배제했습니다.

유저에 따라 동적으로 콘텐츠가 변경되어야 할 스펙이 아니었기에 SSR(Server Side Rendering)을 사용할 이유가 없었고, 빌드타임에 미리 번들시켜놓으면 어느 곳에서 접속하더라도 캐시 유무와 상관없이 빠르게 페이지 렌더링이 가능하므로 SSG(Static Site Generation)를 선택했습니다.

상태관리

스벨트와 새퍼에서는 리엑트의 콘텍스트와 같은 컴포넌트 prop drilling을 제어하기 위한 도구들이 미리 마련되어 있습니다. 리엑트 훅스 이후에 추가적인 상태관리 도구를 사용하지 않더라도 앱을 쉽게 만들 수 있는 것 처럼, 스벨트에서 미리 제공해주는 도구들로 충분했기에 다른 라이브러리를 사용하지 않았습니다.

프로젝트 관리 (CI/CD)

지인과 함께 둘이서 진행하는 프로젝트이므로 외롭지 않아서 좋았습니다.
슬랙을 이용해 프로젝트 아이디에이션이나 프로젝트 진행사항과 관련한 커뮤니케이션을 진행했고,

github action을 이용해 커밋, 푸시, 브랜치 생성, 풀 리퀘스트에 대한 내역을 자동으로 슬랙 채널에 올라가게 만들었습니다.

커밋, 머지에 대해서는 eslint 룰에 대해 action 봇을 하나 만들어 action 결과를 채널에 올리게 만들었습니다.
(항상 익살스러운 표정으로 날 반겨주는 surprise 아저씨)

CSR,SSR를 이용했다면 ec2를 이용해 배포했을 것 같습니다만,
SSG와 같은 CMS에 요즘 많이 사용한다는 vercel을 이용해 보기로 했습니다. vercel은 next.js로 유명한 팀의 이름이기도 합니다.

이번 프로젝트를 통해 새롭게 배운 배포 툴인 vercel은 정말 배포하는데 편리한 환경을 제공해주었습니다. 개발환경 용 배포 서버인 preview와 프로덕션 배포 서버인 production을 나누어 브랜치 환경에 따라 커밋이나 풀 리퀘스트가 올라올 경우 자동으로 push를 해주었고, 프로젝트 폴더에
vercel.sh 파일을 만들어 배포 관련 스크립트를 이용해 배포 정책을 커스터마이징 할 수 있었습니다.

배포도 굉장히 빨라 1분 이내에 새롭게 배포된 환경을 점검해 볼 수 있었습니다.
vercel은 그 외에도 serverless function을 제공해 nextjs의 api routes (server routes)와 같은 기능을 제공해주기도 합니다. 기회가 된다면 보다 깊이있게 학습해보고 싶습니다.

관련 포스팅 -> next.js api fetching

테스팅

jest와 storybook을 이용했습니다.
이번 프로젝트에서 애니메이션을 적용해야 할 컴포넌트가 몇개 있었기에, manual testing 하지 않고 storybook을 이용한 ui testing을 했습니다.

API / DB

데이터 베이스는 aws RDS의 mysql을 사용하였으며
API는 넥스트의 fetch api 처럼 새퍼에서 제공하는 server routes를 사용했습니다.
이 기능을 통해 새퍼는 넥스트와 동일하게 풀스택 프레임워크로서의 기능을 제공할 수 있습니다.

굳이 DB를 사용하지 않아도 요구사항을 충족할 수 있었는데, 추후 관리자 페이지를 통해 말씀에 대한 DB를 gui 환경을 통해 접근 및 조작할 가능성을 염두에 두고 DB를 사용했습니다.

SSG 환경이기에 첫 빌드 시에만 새퍼가 접근 가능한 server routes들을 통해 db와 통신하여 json 파일로 캐싱을 해두고, 사용자의 사이트 접근시 해당 캐시 파일을 사용하기에 커넥션에 대한 부담이 없었습니다.

디자인

개발하는 시간에 못지 않게 디자인 하는 시간에 공수가 많이 들었습니다.
말씀카드 디자인과, 전체적인 페이지 테마, 버튼 위치 및 폰트 스타일, 색상 배치등 신경쓸게 많았습니다.

너무 딱딱하지도 않게, 너무 가볍지도 않고 다정한 느낌이 드는 일러스트레이션과 색상들을 사용했습니다. 귀엽지만 중요한 파비콘도 놓치지 않았습니다.
디자인 툴로는 피그마를 사용했습니다.

이제 본격적인 개발로 들어왔습니다.

새퍼는 react의 next.js격인 프레임워크입니다. SSR, SSG를 사용하게 해줍니다.

스벨트의 특징은 리엑트와는 다르게 양방향 바인딩으로 props를 연결할 수 있으며,
쉐도우 돔을 사용한 웹 컴포넌트와 마찬가지로 특정 컴포넌트 내부에서 사용된 스타일은 외부 영역과 완전히 독립적인 영역으로 존재합니다.

각 svelte 파일은

한 개의 모듈 컨텍스트 스트립트 태그,
한 개의 스크립트 태그
한 개의 스타일 태그를 포함할 수 있습니다.

리엑트와는 다르게 동일 레벨의 컴포넌트들은 상위 부모 컴포넌트로 감싸지 않아도 되며, CSS-in-JS를 사용하지 않아도 되는 점이 빠른 생산성을 불러 일으켰습니다.

<script context="module">
</script>
<script>
	import Nested from './Nested.svelte';
</script>

<p>These styles...</p>
<Nested/>

<style>
	p {
		color: purple;
		font-family: 'Comic Sans MS', cursive;
		font-size: 2em;
	}
</style>

state를 변경할 때도 스크립트 태그 내에서 선언, 변경하면 자동으로 해당 변수를 사용하는 UI가 변경내용을 파악하여 갱신합니다.

<script>
import {onMount} from "svelte/app";
let writeText = "";
onMount(() => { // 리엑트의 useEffect
  writeText = "hello there";
})
</script>

<div>{writeText} </div>

이미 한 개 이상의 자바스크립트 프레임워크에 익숙한 사람이라면 누구든지 빠르게 배울 수 있을 것 같습니다. 콘텍스트, 스토어등의 내용은 어느 라이브러리에서도 통용되는 단어이기에 친숙하게 받아들일 수 있을 것입니다.

난관

스벨트를 이용한 앱 개발 과정은 훌륭한 개발 경험을 선사해주었습니다. 그런데 개발된 내용들을 새퍼의 라우팅 시스템과 붙여 배포를 하며 문제는 발생하기 시작했습니다.

정적 사이트는 앱 빌드 시간에 미리 페이지들을 사용자에게 전달해줍니다.
넥스트의 경우 getStaticPaths의 옵션을 통해 미리 빌드된 페이지 범위에 없는 라우트에 접근하는 경우 404 페이지를 보여줄지, 아니면 요청된 부분을 빌드해서 사용자에게 렌더링해 줄지에 대한 선택이 가능합니다.

새퍼는 현재 이 기능을 제공하지 않습니다. a 링크 태그로 접근이 불가능한 영역의 경우 빌드 명령어에 추가적으로 빌드할 페이지의 경로를 명시적으로 컴파일러에게 안내해주어야 합니다.

넥스트와 새퍼는 모두 동적 라우팅을 제공해줍니다.
/posting/[id].svelte라는 라우트를 가지고 있는 페이지들은 첫 빌드 대상인 엔트리 라우트인 /의 a 태그를 통해 연결되지 않는다면, 새퍼는 해당 페이지들로 접근할 때 404를 띄어주는 것입니다.

해당 문제에 대한 이슈는 새퍼 깃허브 레포에 많이 언급되었음을 확인했습니다.
이미 프로젝트를 개발한 제 입장에서는 해당 부분에 대한 이슈를 배포 전까지는 확인하지 못했기에 다른 라이브러리로 마이그레이션 하는 것에 대한 부담감이 있었고, 해결 방법을 찾아보기 시작했습니다.

새퍼는 sapper export 명령어를 통해 SSG 제공을 위한 파일을 빌드할 수 있습니다.

첫번째 해결방안은 SSG를 포기하고 SSR을 사용하는 것인데, sapper build를 통해 빌드한 파일들로는 프로덕션 배포가 불가능했습니다.

두번째 해결방안은 다른 라이브러리를 사용하는 것입니다. 새퍼는 지금 1.x 버전이 나와있지 않은 베타 버전입니다. 여러 글들을 확인해보니 sapper 개발을 잠정적으로 중단하는 대화들이 오고간 것을 확인했고 스벨트의 창시자인 리치해리스는 routify를 추천했으며 , 그리고 sveltkit 이라는 스벨트 팀에서 만든 자체 라이브러리를 이용해 SSR를 사용하는 사람들이 많이 보였습니다.

하지만 위에서 언급한 대로 마이그레이션 하는 것은 잘못되면 배 보다 배꼽이 더 커지는 상황이 올 수 있기에 후보에서 제외했습니다.

엎친데 덮친격으로 server routes 또한 다이나믹 라우팅을 지원하지 않아 params가 아니라 query를 사용해야 했습니다. 또한 에러에 대응하는 _error.svelte 파일 또한 정적 렌더링에서는 접근되지 않아 커스텀 404 페이지가 렌더링되지 않았습니다.

여러 해결방안을 시도하고 검색하는 삽질을 거치고 난 후

404 페이지는 다음과 같이 --entry 옵션으로 /404 라는 빌드타임에 컴파일러가 미리 강제로 렌더링하게 한후
postexport 명령어를 통해 정적 빌드된 파일 중 404/index.html을 디폴트 404 페이지인 404.html에 덮어씌어 주었습니다.

"export": "sapper export --entry \"/ /404\"",
"postexport": "mv __sapper__/export/404/index.html __sapper__/export/404.html",

server routes 는 dynamic route를 포기하고 다음과 같이 새퍼 공식 문서와 스택오버플로우, 깃헙 리서치를 통해
--entry 옵션을 통해 해당 서버라우트를 미리 방문하여 json 파일을 미리 캐싱하게 했으며,

동적 라우팅이 필요했던 다른 페이지들은 a 태그를 이용한 방법으로 해결했습니다.

마무리

본 프로젝트를 통해 베타 버전까지 배포된 라이브러리들은 사용하기 전 충분한 리서치를 해야한다는 경험을 얻었습니다.

스벨트, 새퍼라는 라이브러리가 비교적 최근에 나왔기 때문에 활발하게 이슈 레이징이 되는 것은 당연하다고 생각했으며, 이에 따른 수정본 또한 활발하게 이뤄질 것이라 단정하고 새퍼를 사용했던 것이 많은 시간을 잡아먹었던 것 같습니다. 스벨트를 이용해 웹 사이트를 만들어 보실 분들은 새퍼 대신 위에서 언급한 다른 라이브러리를 사용하시는 것을 권장드립니다.

스벨트는 간결한 문법과 더불어 빠른 러닝커브, 자체적인 상태관리 툴과 다른 SPA 프레임워크들과 비교해 작은 번들 사이즈로 여러 부분에서 성능적인 장점을 가져다 주는 매력적인 프레임워크입니다. 창시자인 리치 해리스는 번들러인 롤업의 창시자이기도 합니다.

스벨트의 스토어는 리엑티브 프로그래밍에서 사용하는 옵저버 패턴을 사용합니다. 이를 통해 기존 명령형 패러다임 식으로 프로그래밍 하던 비즈니스 로직에서 벗어나 함수형 프로그래밍을 자연스럽게 비즈니스 로직에 담아볼 수 있지 않을까 하는 생각을 해보았습니다.

연휴동안 새로운 기술스택을 공부하고 다시 적응하느라 부지런하고 보람찬 시간을 보낼 수 있었던 것 같습니다.

저희가 만든 앱은 필수 기능만 구현했으며 추후 추가되는 기능이 있을 예정입니다.
관련해서 관심있으신 분들은 한번씩 구경하셔도 좋을 것 같습니다.

감사합니다.

https://www.2022hispick.com/

profile
성장을 향한 작은 몸부림의 흔적들

0개의 댓글