brunch

You can make anything
by writing

C.S.Lewis

by swimjiy Jul 11. 2020

반응형 웹 서비스 "카트 세이버" 개발기

2달 동안 프론트엔드 개발을 하며 얻은 경험

이전 포스팅에서도 해당 프로젝트를 언급했지만, 이번에는 좀 더 기술적인 차원에서 기록하고 싶어 이번 후기를 기획했습니다. 이번 포스팅에서는 제가 작업한 프론트엔드 개발 파트에 대해 집중적으로 다룰 예정이며 전반적인 개발 과정 및 스택에 대해서는 깃허브 위키에 자세하게 기록되어 있습니다.


카트 세이버 반응형 이미지





프로젝트 소개

이번에 완성한 프로젝트는 농수축산물 시세 찾기 웹 서비스 "카트 세이버" 입니다.

장보기 초년생을 대상으로, 오프라인으로 장을 볼 때 내가 구매하려는 물품이 싼 건지 아닌지를 판단하기 위해 만들게 된 서비스입니다.

올해 4월 중순부터 5월 중순까지 한 달간 작업을 진행했으며, 1~2주 차는 기획 및 디자인, 3~4주 차는 본격적인 개발에 들어갔습니다.

주요 기능은 아래와 같습니다.

1. 농수축산물 검색 기능
2. 당일, 저번 주, 저번 달, 작년 평균 가격 제공
3. 해당 품목을 판매하는 온라인 몰 가격 정보 제공


그리고 6월에 필요하다고 생각하는 기능들을 2.0 버전으로 추가 릴리스했습니다.

추가한 기능은 다음과 같습니다.

1. 잘 사는 법, 구매 시 팁 등 한 줄 위키 제공
2. 단위 계산기






담당 파트

저는 웹 디자인 및 프론트엔드 개발을 담당했습니다. 저번에 디자인 파트에 관해 포스팅을 작성했으므로 이번에는 프론트엔드 개발 과정에서 겪은 경험들을 공유하고자 합니다.


깃허브 wiki 중 프로젝트 참여자 페이지. 이름 오른쪽에 있는 영어는 42SEOUL 아이디입니다.



Jinja

verison: 2.11.2

python의 프레임워크인 Flask 기반으로 만들어졌기 때문에, 마크업은 Flask 내장 템플릿 엔진인 Jinja2를 사용했습니다.

템플릿 엔진은 React의 JSX, Node.js의 Pug (구. Jade)를 사용한 경험이 있기에 Jinja도 어렵지 않게 적응할 수 있었습니다. 다만 기초 문법이 위의 2가지 엔진보다는 Vue의 템플릿 문법과 더 유사하다는 느낌을 받았습니다.


// jinja
<span>메시지: {{ msg }}</span>

// Vue의 mustach 구문
<span>메시지: {{ msg }}</span>

// JSX
<span>메시지: { msg }</span>

// Pug
<span>메시지: #{ msg }</span>



meta 태그를 이용한 검색엔진 최적화(SEO)

메타태그는 문서의 정보를 담고 있는 HTML 태그입니다.

평소에는 아래와 같이 인코딩 방식을 정할 때나, viewport를 이용하여 반응형 웹을 만들기 위해 사용했는데, 이번 프로젝트에서 검색엔진 최적화를 위해 방법을 배워 적용했습니다.

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">


meta 태그에 title, image 등 저희 사이트에 대한 정보를 추가하여, 이를 검색엔진에게 제공함으로써 구글 등 검색 사이트에 더 잘 노출하게끔 작업했습니다. 이 기능 때문인지는 몰라도 지금 구글에 cart savior를 치면 최상단에 저희 사이트가 나와서 만족하고 있습니다.

또한 카카오톡에 링크를 공유할 때, 사진과 페이지 소개가 미리보기로 잘 정리되어 뜨는 것 또한 이 meta태그가 하는 일입니다.


예쁜 썸네일은 같이 개발한 소현님의 작품입니다.



Responsive Web

개발은 웹으로 했지만, 주로 사람들이 모바일 환경에서 서비스를 사용할 것을 고려하여 반응형 레이아웃으로 작업했습니다.

반응형이지만 Tablet은 Mobile디자인을 따르게 했기 때문에 768px을 기준으로 Mobile/PC 두 타입으로 나누어 CSS를 작업했습니다.

개인적으로 토이 프로젝트에서는 Flexbox 모듈을 많이 사용하기 때문에, 이번에도 Flexbox를 이용하여 반응형 레이아웃을 잡았습니다. breakpoints.css에서도 flex를 이용하여 컬럼별 스타일링을 진행했습니다.

 

breakpoints.css 일부. Bootstrap처럼 간편하게 컬럼화할 수 있도록 추가했습니다.



Animation

모션은 CSS의 animation 프로퍼티를 사용했으며 로딩 화면 및 블록 요소 등장에 사용했습니다.

사실 처음 디자인에서는 로딩 화면을 간단하게 만들었는데, 페이지 간 이동할 때 로딩 시간이 꽤 길어지자 체감 속도를 늦추기 위한 방안으로 로딩 화면을 더 재미있게 수정했습니다.

현재 서비스의 로딩 화면에 등장하는 머쓱한 일러스트는 이런 이슈로 생겨나게 되었습니다.


저희끼리는 "머쓱이"라고 부릅니다.



D3.js

version: v5

상세 페이지에 들어갈 그래프를 어떤 프레임워크로 구현할지 고민이 많았는데, 그중 D3.js를 이용하여 구현했습니다. 유력한 후보로 상대적으로 가벼운 Chart.js 가 있었으나, 평소 D3.js를 다뤄보고 싶었기에 이번에 공부도 할 겸 선택하게 되었습니다.

그래프 종류는 막대그래프를 선정했습니다. 각 항목들(당일, 지난주, 지난달, 작년)이 일정한 시간 간격을 두고 있지 않기 때문에 초기에 기획한 꺾은선 그래프로 작업할 경우 사용자에게 혼란을 줄 수 있다는 우려가 있어서 개발 도중 변경한 부분입니다.

전반적인 코드는 Bl.ocks 레퍼런스를 참고했으며, 수정이 필요한 부분 (y축 도메인 설정, 데이터가 없을 경우 등)은 D3.js 공식 문서 및 우리들의 친구 Stack Overflow를 참고하여 작업했습니다.


단순한 그래프 하나에도 엄청난 양의 전처리가  들어간다는 것을 깨달았습니다.



계산기

계산기는 프로젝트 종료 후, 6월에 2.0 버전으로 추가한 기능 중 하나입니다. 온라인 몰에서 올라오는 물품의 단위가 다양하기 때문에 사용자가 단위를 직접 입력하여 계산할 수 있으면 좋겠다는 의견을 적극 반영한 결과입니다.

input 디자인은 샐러리를 참고하여 작업했고, 입력값만큼 width값이 알맞게 늘어나는 기능을 추가했습니다.


디자인할 땐 간단하게 생각했으나, 막상 개발해보니 쉽지 않았습니다.


실시간으로 input의 width값이 바뀌는 이벤트는 처음 작업해보는 기능이라 시행착오가 많았는데, 최종으로 input에 들어온 onkeyup 이벤트를 감지하여, 들어온 value의 길이와 비례하게 width를 변경하도록 로직을 구현했습니다.



또한 flask로부터 받는 단위 값이 100g, 1마리처럼 숫자와 문자가 혼합된 형태였기 때문에 정규식을 이용하여 Number타입과 String타입으로 데이터를 분리해야 했던 이슈가 있었습니다.





결과

우선은 주최 이벤트였던 program42에서 1등을 수상하게 되었고, 최대 DAU (Daily Active Users ) 357명이라는 사용자 경험도 얻게 되었습니다.

또한 관심 있게 보시던 관련 업계 종사자 분들께서 먼저 컨택을 해주셔서 현업에서는 이 프로젝트를 어떤 시점으로 바라보시는지도 알아볼 수 있었습니다.

마지막으로 기술적으로는 D3.js에 대한 새로운 지식이 생겼고 meta태그를 활용하는 방법, 그리고 파이썬 환경에서 프론트엔드를 작업하는 방법 또한 경험할 수 있었습니다.



후기

개인적으로는 세 명의 비전공자가 기간 내 완성했다는 것만으로도 크게 의미를 두고 있는 프로젝트입니다. 예상치 못하게 좋은 결과가 나온 이유는 저희가 잘해서라기보단 저희의 프로젝트에 공감하시고 관심 있게 봐주신 분들이 계셨기 때문이지 않을까 싶습니다.

이번 프로젝트를 진행하며 고민하고, 의견을 나누고, 해결한 순간들이 앞으로 개발자로서의 저를 더 단단하게 만들어줄 수 있기를 바라며 이번 포스팅을 마치겠습니다.



브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari