흔한 2017년의 Front-end 기술 스택

흔한 2017년의 Front-end 기술 스택

프론트 엔드 개발자의 관점에서

DevOps 를 위한 기술 스택

쏘카에서의 마지막 프로젝트는 2017년 제로카 웹 프로모션을 대비하여 전체적인 스텍을 새로 설계 및 개발하는 것이다. 기존의 제로카 프로모션 페이지는 빠르게 개발하기 위해 기술 부채를 상당히 껴안고 시작한 프로젝트였고, 올해 제로카가 주요 사업 목표 안에 들어있기 때문에 전체적으로 개선할 필요가 있었다.

Requirement

요구사항 혹은 기능명세서가 없는 개발은 제대로 된 개발이라고 할 수 없다는데, 동의하지 않는다. 어차피 변경될 요구사항을 지키자고 문서질을 하느니, 대략적인 큰 방향 몇가지 두고 유연성을 확보하기 위한 방식으로 설계했다.

  • 확장성 및 개발 편의성

    현재 웹 프로모션 페이지는 테마 사이트에서 구매한 php 템플릿을 기반으로 작업했기 때문에 확장성이 떨어졌다. 약관의 경우 엑셀이 자동으로 만든 코드를 그대로 사용했기 때문에 한줄을 수정하려고 해도 td, tr, span 덩어리의 html 코드를 뒤져야 하는 어려움이 있었다. 때문에 코드 재사용성도 매우 떨여저서 확장하는 것이 거의 불가능한데다가, 이후 개발을 편하게 하려고 추가한 react 코드가 오히려 더욱 상황을 복잡하게 만드는 비극(?)을 해결해야했다.

  • 검색 엔진 최적화와 첫페이지 로딩

    쏘카는 제품이었다면, 제로카는 상품이라고 말할 수 있다. 서비스라기 보다는 기간 한정으로 판매하는 물건(?)에 가깝기 때문에 검색 엔진 최적화는 무시할 수 없었다. 특히 프로모션이나 마케팅을 통해서 많은 사람들이 일시적으로 몰리는 상태를 의도하고 있기 때문에 단순한 SPA 은 리텐션에 영향을 줄 수 있다고 생각했다.

  • 개발 속도, 유연성 그리고 사내 시스템

    프로젝트가 예상외로 갑작스럽게 시작되었고, 일정 또한 넉넉치 않았다. 따라서 개발 속도를 무시할 수 없었고, 러닝 커브는 최소한으로 제한해야 했다. 게다가 서비스 스펙이 완전히 확정되어 있지 않은 상태이기 때문에 유연하게 수정할 수 있는 스텍을 갖추어야 했다. 사내에서 광범위하게 쓰고 있는 툴은 그대로 사용해야 한다는 점도 있었다.

Front-end libraries

프론트엔드 개발자가 어려운 역할이라는건 시장에 정말 많은 기술이 나와있는데 대부분 각각의 장단점을 지니고 있기 때문이다. React 가 조금 과장해서 사실상의 de-facto standard 라고 할만하지만, 그렇다 해도 모든 케이스에 딱 맞아들어가는 선택은 아니다.

View / Router

외쳐 갓액트

말은 그렇게 했지만, 사실 View 나 Router 라이브러리는 다른 옵션을 크게 고려하지 않았다. 최근 잘나가는 Vue.jsAurelia 같은 녀석들을 써보고 싶은 것도 사실이지만, 프론트엔드 웹 개발자가 많지 않은 회사의 엔지니어로서 러닝 커브가 들어가야 하는 새로운 라이브러리를 소화하기는 어려웠다.

2016년 10월 쏘카에 입사한 후 기존의 php, jQuery, css 기반에서 웹 프론트엔드 스택에 React 와 Sass 로 전환하는 작업을 시작했는데, 이 때 역시 도입 및 전파까지 적지 않은 시간을 들인 것도 사실이다. 지금은 쏘카 앱의 네이티브로도 개발되고 있어서 상대적으로 웹 어플리케이션 엔지니어링에 큰 시간을 들이지는 않지만, 지금까지 그리고 앞으로도 쏘카 기술 스택에서 큰 부분을 차지할 것이 확실하다.

  1. react
  2. react-router

상술한 것과 같이 큰 고민없이 바로 적용하였다. 퇴사를 앞둔 상황에 많은 개발자에게 익숙치 않은 개발 스텍을 도입하는 것은 모험에 가까웠다.

  1. react-helmet

meta, link, script 같은 헤더에 들어가는 항목들을 손쉽게 관리할 수 있는 패키지다. 이전부터 들어만 보고 있다가, SSR 이 필요했기 때문에 도입했다.

Swiper.js 괜찮은 녀석이다

  1. Swiper

쓸만한 Carousel 라이브러리가 없던 차에 동료 개발자가 이 라이브러리를 추천하여 사용하였다. 옵션이 다양해서, 커스터마이징 할 수 있는 여지가 많았다. 기존에 사용하던 Slick 라이브러리는 사용하기에는 편리했지만 제약이 많아서 불편함을 느끼고 있었다.

Data Handling

짹째기도 한다 redux

우선 리덕스를 식탁에 올려놓고 나머지 반찬을 고민했다.

  1. redux

이 쪽 역시 익숙한 것을 가장 중요하게 생각했고, 이미 쏘카의 중요한 개발 스택인 redux 를 중심에 두고 다른 옵션들을 고려했다.

  1. redux-form

예전에 누군가 추천해줬는데 쓸 기회가 없어서 안쓰다가 이번 기회에 테스트 해보았다. 폼 핸들링이 간편했고, 커스터마이징 방식도 직관적이었다. 제로카의 신청 및 계약 프로세스의 필수적으로 들어가야 하는 위자드 형식도 지원하고 있어 적극적으로 사용하고 있다. 키보드의 onChange 이벤트를 보고 폼의 value 에 직접 데이터를 넣는 방식이고, 벨리데이션 지원도 충실하다. 다만 개발 문서 가독성이 다소 떨어진다.

  1. redux-persist
  2. redux-persist-cookie-storage

제로카의 신청 및 계약 플로우는 여러가지 복잡한 과정을 거쳐야 한다. 우선 쏘카 준회원 가입이 필수적인데다가, 신청에 이르는 절차도 복잡하고 입력해야하는 항목도 다양하다. 때문에 입력 중 네트워크나 기타 문제가 생겼을때 되살리는 기능이 꼭 필요했고, 이 때문에 redux-persist 를 적용했다. 원래는 localStorage 에 저장하다가 서버에서 현재 로그인 상태를 알 수 없어 서버사이드 라우팅이 어려워 cookie 로 변경하였다.

다만, redux-form 은 쿠키에 넣지 않고 localStorage 에 리덕스 미들웨어를 따로 만들어서 보관하는 방식으로 개발했다. 이유는 헤더에 포함하기에 무거운 데이터가 많아서 부담스럽다는 것도 있었지만, form store 에 불필요한 정보까지 저장되기도 하고 redux-form 은 기본적으로 하나만 관리하기 때문에 새로운 폼을 사용할때 매번 기존 폼을 날려버린다는 점도 있었다. (옵션으로 제어는 가능하다) redux-persist 를 사용할때는 불필요한 store 까지 저장하지 않는지 블랙리스트나 화이트리스트로 꼭 관리하는 것이 좋다. 특히 쿠키를 쓰게 될때는.

Server Side Renderning

검색 엔진 최적화와 첫 페이지 로딩 속도 이슈 떄문에 SSR 은 반드시 염두에 두고 개발해야 했다. 직접 설정하기는 시간도 없고, 어렵기도 해서 Universal Redux Template 이라는 프로젝트를 클론하여 필요한 것들을 추가하거나 뺴는 방식으로 설정했다. 위의 스택 중 많은 부분이 이 템플릿에 자체적으로 포함되어 있는 것이 많았다. 굳이 잘 돌아가는 바퀴를 새로 발명할 이유는 없다.

고민될땐 Express

  1. express

koa 를 고려했던 것도 사실이지만 많이 써보지 않아서 아직 사용에 서툴었고, 기간 또한 짧았기 때문에 부담이 되었다. 구관이 명관이라고 express 를 그대로 쓰기로 했다.

  1. http-proxy-middleware

CORS 를 피하고 싶었기 때문에, 애초에 프로덕션 스택에서는 HAproxy 로 로드밸런서를 두고 reverse-proxy 로 api 서버를 연결했는데 개발 환경에서는 테스트가 힘들었다. 그래서 미들웨어로 프록시 설정을 추가했다.

Style

인간적으로... 사실적으로... 볼때 프론트 엔드에서 제일 어려운게 스타일이다. Postcss 나 stylejs 같은 애들을 고려 했지만, 템플릿 고치는게 귀찮아서 그냥 쓰기로 했다. Sass mixin 이나 가져다 쓸 수 있는게 많기도 했고.

  1. Spectre.css

하.. 그냥 milligram 쓰는건데..

밑바탕에 깔 프레임웤이 필요했다. 아시아 폰트를 지원한다고 해서 선택했는데... 잘못 결정한 것 같다. milligram 이나 skeleton 을 깔고 개발하는 것이 훨씬 수월했을 것 같다. 이미 개발한 것이 많아서 지금에 와서 교체할 여유는 없었다. 쓰지마세요.

  1. sass
  2. gulp-sass

굳이 이제와서 less 로 갈 이유도 없었고, 일정이 좀 촉박해서 webpack 으로 빌드하기 보다는 그냥 템플릿에 있던 gulp 셋업을 고수했다.

  1. sass-lint

그냥 기본 설정을 쓰고 있다. 설정이 너무 귀찮았다. (반성중)

어지간하면 잘되있는 셋팅을 수정하고 싶지 않아서 그냥 썼는데, HMR 이 잘 되지 않아서 이 부분은 확실히 개선할 필요가 있는 것 같다. 다음 개발자의 몫으로 남겨둔다

CI/CD

개발자가 프로젝트를 셋업할때 하는 일 중에 제일 재미없는게 CI/CD 라고 생각한다. 서버 보안 설정, 파이프 라인, 빌드, 롤백까지 절차를 꾸준히 따라야 해서 손이 많이 가는데 시행착오 또한 많이 겪게 된다. 기본적으로 하나의 프록시 서버를 로드밸런서로 두고 AWS 의 Elastic load balancer 에 붙여둔 프론트엔드와 백엔드 EC2 인스턴스에 각각 연결해주었다.

Front-end JS

요즘은 grunt 나 gulp 를 아예 안쓰는 추세이긴 하지만 좀 귀찮아서...

  1. webpack
  2. webpack-dev-server

리액트 스택에서 필수적인 것이라 별도로 언급하지 않겠다.

  1. gulp

Sass 와 기타 에셋 캐시 인벨리데이션 용으로 사용하고 있다. 다만 sass 컴파일 이후 바로바로 스타일 적용이 안되서 좋은 방법을 찾고 있다. 역시 템플릿 설정에 캐싱이나 최적화를 위한 설정을 추가하였다. universal-redux-template 쓰세요 두번 쓰세요

  1. babel

react 와 es6 를 추가하고 object spread 같은 문법을 위해서 stage-2 를 추가했다.

Deployment

배포에 AWS CodeDeploy 같은 녀석들은 쓰지 않았고, Buddyworks 에서 docker 로 필드하여 docker hub 에 올린 뒤 ssh 로 서버에 접근하여 docker-compose 를 사용하고 있다.

아이콘이 귀염귀염 하다

  • Buddy

    기존 쏘카에서 쓰고 있던 springloops 를 대체한 것으로, hashnode 에서도 최근 옮겼다고 한다. 한달에 $100 를 내는 유료 정책을 사용하고 있고, CI 툴보다는 배포 툴에 적합하다. 설치형도 있다고 하는데 아직 시도는 못해봤다.

docker 는 이미 서비스 스택

  • docker

    쏘카에서는 최근에 만들어지는 신규 프로젝트는 전부 docker 를 통해 배포하고 있다. 배포 환경 설정하기도 편하고, 무작위 해킹에도 큰 영향을 받지 않아 유용하다. 리모트 저장소로는 docker hub 를 역시 유료로 사용하고 있다. $50 달러 정도 매달 납부하고 있는 것으로 기억한다. 실제로 배포에는 docker-compose 로 편하게 만들고 있다. 구동이나 재시작은 스크립트로 만들어서 간혹 가는 문제 상황을 대처하고 있다.

  • HAProxy

    nginx 와 HAProxy 중 뭘 쓸까 고민하다가 스태틱 에셋 캐싱은 cloudfront 로 관리하는 편이 편리해서 그냥 로드밸런서와 리버스 프록시 용도만 사용하기로 했다. nginx 도 다양한 방식의 load balancing 을 지원하지만, 헬스쳌이 어렵고 통계 기능도 없기 때문에 기본적으로 stats 을 가지고 있는 haproxy 를 사용했다.

  • S3, Cloudfront

    그냥 쓰던 거고 잘 되는거라서 자세한 설명은 생략한다.

etc

yarn 쓰세요 그냥 쓰세요

  • yarn

    npm 이 빌드 속도에 영향을 많이 주어서 얼마전부터 yarn 으로 갈아탔다. 이외에도 npm run build 대신 yarn build 라고 쓸 수 있는 깨알같은 장점도 있다.

  • eslint

    airbnb/base 에 과도한 설정을 블랙리스트로 걸러서 쓰고 있다.

  • lodash, bluebird, moment

    이거 없으면 나 개발 안해

  • Google Analytics

    개발자만 보는 것이 아니기 때문이 큰 고민 없이 결정했다. 회사 전반적으로 많이 쓰고 있는 툴이라 딱히 다른걸 고려하지는 않았다.

프론트엔드 개발자는 솔직히 월급 두배로 줘야된다

이렇게 길게 썼는데도 백엔드 관련된 건 한줄도 들어가 있지 않다. 일주일 정도 시간을 써서 설정한 것 같고, AWS t2.small 기준으로 첫페이지 로딩 타임 1.2~1.4 초 정도로 쾌적하게 로드 되고 있다. (라이브 사양임) 실제 오픈 전에는 서버를 몇개 더 만들어서 로드밸런서에 올린 후에 ci 에 추가해주면 높은 사양의 서버를 사용하지 않아도 큰 문제없이 운영 가능할것이라고 생각한다.

동영상이나 무압축 이미지가 있어서 느려보이지만 실제로 로딩 시간은 빠르다

재밌는(?) 건 이 마-------------------------안----------ㅎ---------은 일을 하고 나서야 프론트 엔드 개발자의 일이 비로소 시작된다는 것이다. 그나마도 저 템플릿이 상당부분 부담을 줄여주지 않았으면 더 오랜 시간이 걸렸을 것이다. 참고로 백엔드 API 서버는 node.js 를 쓰고 있는데, 내 기준에 가볍고 빠른 개발에 가장 편한 것 같다.

한번 프로젝트 셋업할때 이 정도까지 하는데 월급 두배 줘야된다 진짜로.