Skip to content

SNURFER/wedding-invi

Repository files navigation

모바일 청첩장 개발

기술스택

  • Sveltekit
    • Svelte를 사용하여 웹 애플리케이션을 구축하기 위한 프레임워크
    • SvelteKit을 사용하면 서버 측 렌더링, 라우팅 및 API 호출을 쉽게 처리가능
    • Node.js, Deno 및 Lambda와 같은 다양한 백엔드와 함께 사용할 수 있음
  • Vercel
    • AWS와 같은 클라우드 컴퓨팅 서비스를 제공하는 회사
    • Next.js 개발팀에서 만든 프론트엔드 호스팅 사이트를 제공
    • 모든 설정을 수동으로 할 필요 없이 사용하고 싶은 소스를 정하고 Deploy만 하면 나머지 빌드 과정이나 운영(스케일링 등)은 버셀이 모두 처리
    • 개발자는 개발을 한 후 deploy후 결과를 받는 프로세스를 반복하며 개발을 진행
  • MongoDB
    • MongoDB는 유연하고 확장 가능한 방식으로 데이터를 저장하고 검색하는 데 사용되는 인기 있는 오픈 소스 No SQL 데이터베이스
    • MongoDB atlas는 MongoDB의 완전 관리형 클라우드 데이터베이스 서비스
    • Vercel과의 연계성이 좋음

프로젝트 아키텍처

스크린샷 2023-10-07 오전 10 09 53

개발 이유?

결혼 준비 과정에서 직접 할 수 있는 부분은 없을 지 고민해보았다. 직접하게되면 완성도 면에서는 조금 떨어질 지 몰라도, 특별한 output이 나온다는 데에 의의가 있다고 생각한다. 프로포즈 영상, 웨딩 촬영, 모바일 청첩 등을 직접 제작을 하였다. 모바일 청첩의 경우 최대한 다른 청첩장들을 참고하되, 하트를 누르면 애니메이션이 변경되는 효과를 적용하여 차별화하였다. 모바일 청첩장의 구성은 다음으로 이루어진다.

  1. 제목
  2. 메인이미지
  • 하트 내려오는 애니메이션 구현
  1. 메인글귀
  • 메인 글귀
  • 글귀에 맞는 이미지 배치
  1. 달력
  • 정적인 날짜를 표기하는 달력 컴포넌트 구현
  1. 갤러리
  • 라이브러리(swiper.js)를 사용하여 개발
  1. 위치안내
  • 카카오, 네이버, 티맵 API 연동
  • 네이버 지도 연동
  1. 방명록
  • mongo db atlas 구성
  • 이름, 비밀번호, 문구를 저장하는 컬렉션 생성
  • get/set API 구현
  1. 계좌
  • 카카오페이 연동
  • 계좌 복사하기 기능 구현
  1. 꼬리말
  • 깃헙 연동

스벨트는 각각을 컴포넌트화하여 개발할 수 있는게 직관적이고 코드가 짧다고 느꼈다. 그리고 기본 HTML 베이스에 템플릿코드를 짜는 것과 비슷하였다. 위의 항목들에서 몇가지 기억에 남는 것들을 정리해보았다.

하트 이미지 애니메니션

가끔 특정 웹사이트를 들어가면 CSS를 통해 웹사이트에 변화를 주던게 생각이 났다. 네이버 메인페이지에 들어갔을 때 날씨에 따라 눈,비가 내리는 애니메이션 효과가 그러한 예시인데, 구글링을 통하여 비슷한 기능을 찾아볼 수 있었고, 이를 svelte 쪽 TS로 변경하여 적용하였다. 하트를 누를 때마다 떨어지는 애니메이션을 달리주면 재밌을 것 같아 해당 기능을 적용했다. 코드 내부적으로는 이모지를 많이 썼는데 특정 브라우저에 따라 이모지가 깨져보이는 경험도 하여(최신 아이폰 사파리, 윈도우 엣지) 이모지를 변경한 기억이 인상깊다. 플랫폼 디펜던시가 없겠거니 하고 내폰인 아이폰미니12와 여자친구의 갤럭시S20 그리고 맥 크롬만 확인하고 넘어갔었다. 그 후엔 다양한 케이스에 대해 테스트를 해보면서 진행을 하게 되었다.

메인글귀

메인글귀를 직접 만든만큼 그에 맞는 이미지도 직접 생성하고 싶었다. 아이디어상으로는 넝쿨이 문구를 감싸는 이미지를 이미 구상하고 있었고, 저작권이 없는 이미지가 필요했다. 처음으로 생각했던건 AI를 통해 이미지를 생성하는거 였으나 무료 사이트의 경우 생각보다 내가 원하는 이미지가 나오지 않았다. DALL-E를 사용해보고 싶었으나, 무료체험 크레딧이 없어 하지는 못했다. 결국은 여자친구가 미리캔버스로 직접 개체들을 한땀한땀 붙여가며 만들었다. 이번 프로젝트에서 매우 만족스러운 결과물 중 하나이다. 여자친구도 같이참여했다는거에 큰 의미가 있다. 이외에도 여자친구는 최초의 1인 고객이었기 때문에 다양한 요구사항이나 불편사항들을 리포팅해주었다. 고칠 것들은 고쳐가면서 점점 괜찮아지는 결과물을 보니 매우 뿌듯했다.

달력

달력의 경우에도 라이브러리를 이용해서 해보았으나, 레이아웃이 생각보다 마음에 들지 않았고 요일 배치가 마음에 들지 않았다. 따로 사용자 이벤트를 처리하거나 구글 캘린더에 저장등 복잡한 기능을 요하지 않았기 때문에 특정날짜를 visualize만 할 수 있고 남은 일수만 계산해주는 컴포넌트를 구성했다.

갤러리

갤러리의 경우 가장 난관이 컸었는데, 처음에는 직접 구현을 했었다. 다른 청첩장들을 참고하여 사진한장을 메인으로 배치하고, 하단에 이미지 리스트를 스와이핑할 수 있도록 구성했었다. 그런데 스와이프 중인 상태를 보여주기엔 좀 더 난이도가 필요했었고... 조악하게 직접 만든 티를 벗어날 순 없었다. 결국 swiper.js를 이용하여 몇줄로 더욱 많은 기능들이 들어간 깔끔한 갤러리를 구성할 수 있었다. 라이브러리 도큐먼트를 읽어가며 원하는 갤러리로 만들어갔다. 그러나 그 뒤에도 문제가 좀 있었는데, 카톡 인앱브라우저에서만 스와이핑이 매우 불편했다.(그것도 아이폰에서만) 좌우 스와이핑 중에 상하 스크롤이 먹는 이슈가 있었는데, 사용자가 좌우 스와이핑을 정확히 수평으로 하지 않기 때문에 한손으로 하게되면 스크롤이 같이 먹혀 불편했다. 처음엔 특정 브라우저에서 발생하는 문제인지도 인지를 못했고, 사용하다보니 아이폰 사파리에서는 가능한데 카톡 채팅방 링크를 통해 들어간 인앱브라우저에서만 그런 말썽이 생겼다. 결국은 라이브러리를 더 정독하여 swipe 시작 시 받을 수 있는 콜백과, 스와이프중인 상태를 확인할 수 있는 값을 통해 스와이프 중일 때는 스크롤이 불가하도록 예외처리를 했다. 사진 비율이 다를 때에 레이아웃 대한 문제점 있었는데 이것도 도큐먼트를 통해서 이리저리 해보아도 원하는 결과가 나오지 않았다. 결국은 차선책으로 슬라이더의 height를 강제하고, 들어가는 사진의 사이즈가 다르더라도 중앙 정렬할 수 있도록 CSS로 처리했다.
덕분에 라이브러리도큐먼트도 정독하고 많은 시간을 투자하여 그래도 어느정도 이슈를 해결한 뿌듯함이 있었다.

위치안내

위치 안내의 경우 메인지도를 네이버지도를 API key를 받아서 띄우고, 내비게이션을 위한 버튼들을 구성했다. 각각 API key를 받아서 사용하면 되고 참고할 자료도 많아서 외부연동은 큰 문제는 없이 진행할 수 있었다. 다만 svelte 및 프론트엔드 자체에 대한 이해도가 부족했기 때문에 간헐적으로 지도가 안뜨는 이슈가 있었다. (정확히는 최초 웹사이트 진입 시 지도가 비워져있음) 클라이언트 block이 될 것을 우려해서 defer async 예약어를 넣은 것인데 이 때문에 API를 이용해 가져온 JS 코드가 load 되기전에 청첩장 페이지를 띄우게 되어 빈화면이 표출되었었다. async로 JS code를 가져온 후, 다시 한 번 layout을 해줄 줄 알았으나 그런 동작을 처리하지 않아 발생했었고, 새로고침하면 브라우저 캐싱된 데이터 때문에 지도가 잘 보였던 것이었다. 비동기 동작을 없애서 간단히 해결을 하였다.

방명록

방명록도 시간을 많이 쓴 기능중 하나이다. 방명록만 없다면 정적페이지만 디자인하면 되기 때문에 훨씬 간편했다. 그렇지만 여자친구의 필수 요구사항 중 하나였기 때문에 시간을 많이 썼다. 방명록 기능을 위해 때문에 백엔드 API 및 클라우드 DB를 구성해야했다. 다행이 나와같은 간단한 요구사항을 위해서 구축할 수 있는 플랫폼이 많이 있었다. MongoDB atlas를 통해 방명록 데이터를 저장할 수 있는 간단한 컬렉션을 클라우드로 구성했다. 그리고 해당 컬렉션으로 접근가능한 API는 sveltekit에서 제공해주는 예약어들을 통해 간단히 구현할 수 있었다. server.ts를 구성하고 서비스를 구현하면 API를 클라이언트에서 사용할 수 있다. 해당 코드는 별도로 백엔드 서버처럼 구동되기 때문에 클라이언트 사이드에서는(브라우저) 코드를 확인할 수 없다. 따라서 개발자도구를 통해서도 확인할 수 없다. sveltekit가 구조적으로 어떻게 동작하는지는 추후에 꼭 더 확인해보고 싶다.(정해진 납기 때문에 사실 숲을 보지 못하고 나무만 보고 진행했다.) 서버리스 프로젝트이기 때문에 좀 더 보안적인 코드들은 해당 부분에서 구현이 필요하다. 요구사항 중 방명록 등록 및 삭제가 되어야했기 때문에 등록 시 비밀번호 입력도 필요하게 구성하였고, 기본 동작들은 view적인 요소들로 처리 했다. 다이얼로그의 모든 textfield가 작성되었어야지만 API 콜을 날릴 수 있는 버튼이 활성화 될 수 있도록 처리했다. 비밀번호의 경우에도 재밌는 이슈가 하나 있었는데, 방명록 기능을 개발 후 지인 개발자들에게 이상없는지 확인해달라고 링크를 공유한적이 있었다. 그런데 친구 중 한명이 MongoDB injection을 이용해서 삭제 api 처리 시, 비밀번호를 항상 true로 set되도록 시도한 것이다. 쿼리에 파라미터로 값이 들어가서 DB 내부적으로 string으로 인식하지 않고 파라미터인 nested한 값으로 인식하여 password가 항상 true가 되었다.

payload = {'_id': "test", 'password': {"$ne": "bar"}}
requests.delete(url, json=payload)

위와 같이 요청을 보내면 비번이 bar만 아니면 항상 true로 delete가 동작하게 된다. 보안 지식이 많이 없었기 때문에 매우 당황했었고, 서버단에서 받은 nested 한 값을 string으로 한번 더 변환하여, 비밀번호 값으로만 인식하도로 처리했다.

계좌

계좌의 경우 복사하기 기능이 약간의 문제가 있었다. 기존 web api를 통해서 복사하도록 해보았을 때, 특정기기에서만 복사가 안되는 문제가 있었다. 클립보드는 티맥스에서도 오피스 제품을 할 때 담당하던 주요 기능이었는데, 구글링 해보니 직접 처리를 할 수는 있어보였지만... 시간관계상 그런걸 처리해주는 라이브러리를 사용하여 바로 해결하였다.
카카오페이 연동도 추가하였는데, 구글링을 하니 설명이 꽤 잘 되어있었다.

공유하기

공유하기의 경우에는 카카오 공유하기와 공유링크 복사하기가 있었고, 공유링크 복사하기는 계좌 복사하기와 다를 것이 없기 때문에 큰 문제는 없었다. 문제는 카카오 공유하기 였다. 대부분의 사람들은 카카오톡을 통해 모바일 청첩장을 공유하고 보기 때문에 가장 중요한 기능이었다. 이런 기능이 있는지도 몰랐고, kakao developer 를 통해 제공하는 api key를 이용하여 쉽게 등록은 할 수 있었다. 그러나 간헐적으로 공유하기가 안되는 문제가 있었고, 공유시 나오는 썸네일 이미지가 변경되지 않아 골치를 많이 겪었다. 간헐적으로 공유하기가 안되는 문제는 svelte에 대한 이해도가 부족해서 발생한 문제였다. view적인 요소가 아니기 때문에 비동기적으로 수행하도록 처리하고 수행 완료 후 콜백으로 처리되도록 onMount에서 필요한 일들을 수행하도록 수정하여 해결했다. 공유 시 나오는 썸네일 이미지가 변경되지 않는 문제의 경우, 내 문제가 아니었는데 그 부분을 몰라서 시간을 많이 허비했다. 카카오 서버 캐싱정책에 따라 변경되지 않는 것이었고, 캐싱을 의도적으로 flush할 수 없었기 때문에 컨텐츠명을 변경하여 해결하였다.

폰트

폰트도 나름 의미를 부여하고 싶었기 때문에 단순한 폰트를 사용하고 싶지 않았다. 친형이 진행했던 프로젝트가 있었는데 무료로 109종의 폰트를 제공하였다. 여기서 원하는 폰트를 다른 청첩장의 경우 보통 사용하는 폰트를 cdn에서 다운로드 받아 로드하도록 되어있었으나, 그런식으로 아름답게? 처리하지는 못했다. 폰트를 직접 받아서 프로젝트 코드안에 직접 적재를 하였다. 덕분에 웹페이지를 로드할 때마다 폰트 크기만큼 트래픽량이 더 증가할 수 밖에 없었다.(보통 5MB 정도였다.) vercel도 무료 bandwidth(매달 100GB 이내)가 정해져있기 때문에 신경이 쓰이기 시작했고, 결국은 압축률이 좋다는 woff2로 변환(2MB)하여 적재해서 조금이라도 트래픽량을 줄였다. 지금 생각해보면 좀 더 스마트하게 한다면, 이미 네이버 손글씨 웹페이지에서 다운로드 할 수 있기 때문에 개발자도구를 통해 다운로드 링크를 따올 수 있을 것 같다. 그리고 해당 링크를 이용하여 다운로드하도록 처리하도록 한다면 woff2 용량 마저도 줄일 수 있었을 것 같다.

종합

사실 종이청첩장을 주문한 곳에서 무료로 모바일 청첩장을 제공하긴하지만... 배수진을 치기위해 신청하지 않고 개발했다. 만약 따로 모바일 청첩도 백업플랜으로 만들어놨더라면 이 프로젝트는 내 성격상 제대로 못끝났을 수도 있다. 이번에 진행하면서 다양한 생태계?를 경험 했고, 좋아져가는 제품을 보면서 몰입하게되는 좋은 경험을 할 수 있었다.
github 프로젝트와 vercel의 연동, vercel-mongodb 연동 등을 하면서 클라우드가 참 편리하다는 생각을 하게 되었다. 따지고보면 내가 짠 코드도 github에 올라가 있고, 이를 바라보고 웹서버를 구성해주는 vercel도 클라우드 서비스로서 제공을 하고, mongoDB atlas로 클라우드 db 서비스이기 때문이다. 물론 무료 제공량은 모두 정해져있기 때문에 모니터링을 계속해야하고, 보안도 신경써야한다. 각 사에서 제공하는 API를 이용하기 위해 개인 API key를 발급받았기 때문에 이게 외부에 노출이 된다면 억울하게 과금당할 수도 있다. 이런 클라우드 생태계를 위해 sveltekit에서는 env를 통해 처리할 수 있도록 되어있었다. 따라서 github에 코드가 퍼블릭하게 노출되어 있어도 아직까지는 큰 문제가 없었다.(물론 다른 문제가 더 없는지 확인해봐야한다)
앞으로는 이 경험을 확장하여 누구나 사용할 수 있는 청첩장 템플릿 레포지토리를 개발해보고 싶다. 더 나아가서는 간단한 청첩장 에디터와 웹페이지 호스팅 서비스까지 연동해줄 수 있는 플랫폼을 개발해보고 싶다.

TODO

  • 별도의 청첩장 템플릿 레포지토리 개발
    • 현 레포지토리는 본인의 모바일 청첩 개발용 하드코딩된 레포지토리
    • 리소스(문구, 앨범 등) 변경을 스크립트를 통해 자동화 할 수 있도록 추가 예정
  • 간단한 청첩장 에디터 구현
    • GUI 상에서 청첩장 에디팅이 가능한 프로젝트 개발
    • 배포기능도 제공

Vercel hosting URL

Developing

로컬 서버를 띄워보는 방법

npm install
npm run dev

# or start the server and open the app in a new browser tab
npm run dev -- --open

Building

To create a production version of your app:

npm run build

You can preview the production build with npm run preview.

To deploy your app, you may need to install an adapter for your target environment.