개요

현재 회사(ODKMedia)로 입사 한 이후 진행했던 프로젝트인 OndemandChina(https://www.ondemandchina.com)를 얼마전 오픈했다.

미국을 대상으로 하는 서비스이며, 중국 컨텐츠를 미국 대상으로 스트리밍하는 서비스이다.

워드프레스 기반으로 만들어져있던 기존 서비스가 있었는데, 워드프레스로는 확장에 한계가 있어 바닥부터 새로 다시 만드는 프로젝트였으며 Back-end쪽에 새로 모델링된 API가 있어서 덕분에 Front-end 코드 작업에 집중할 수 있었다.

대략 4, 5월경 정도에 프로토타이핑을 시작하여 본격적으로 6월부터 달리기 시작했으며, 최종적으로 10월 1일에 오픈한 프로젝트다.

-----------2019-10-04------8.56.32

-----------2019-10-04------8.56.37

스쿼시 머지를 하고 있었기에 망정이지 그냥 리베이스 머지했었다면 커밋 수 폭발했을 듯.

주요 기술 스택

SPA

회사에 아무래도 Pythondjango에 익숙하신 분들이 많다보니 프로젝트 초기에는 django 기반으로 만드는 게 어떻겠냐는 이야기가 있었다.

경험상 API만 준비되어 있다면 SPA 방식으로 개발하는 것이 훨씬 더 개발 퍼포먼스로 잘 나오고 serverless 형태의 SPA로 가게 될 경우의 잇점들이 명확해서 요 방식으로 가기로 했다.

물론 단점도 명확하다. 단점에 대해 명확하게 알고 있어야 나중에 문제가 생겼을 때 대처가 가능하다.

특히 이 방식으로 만들게 되면 Front-end쪽의 배포를 매우 가볍고 빠르게 할 수 있다는 장점이 있다.

serverless

create-react-app 기반의 프로젝트이며, build를 통해 생성된 html, js, css를 s3에 업로드하고 cloudfront를 통해 서비스 되는 구조이다.

즉 별도의 server가 없다.

aws lambda edge

serverless 형식으로 만들다보니 meta og tag가 문제가 되는데, 이는 https://blog.roto.codes/create-react-app-using-firebase-functions/ 에서 했던 방식을 이용해 aws lambda edge에서 처리했다. 즉, meta og가 필요한 특정 url인 경우 response를 가로채서 head html만 재생성해서 내려주는 방식이다.

firebase functions로는 여러번 해본 경험이 있기도 하고 aws lambda edge도 다를바 없겠지 싶어서 요 방식을 선택했는데, 초반에 삽질을 대단히 많이 했다. 이것도 추후 별도의 포스트로.

django rest framework

back end API가 이것으로 되어있다.

요쪽 코드 기여는 한 것이 1도 없으므로 생략.

SPA를 구성하면서 굵직굵직하게 사용한 라이브러리들은 아래와 같다.

TypeScript

초기에 작업을 진행하면서 서버의 응답 데이터를 모두 Interface로 선언해두고 변경사항이 있을 때마다 변경해가며 작업을 했는데, 덕분에 시간을 무척 아낀 것 같다.

만약 TypeScript를 넣지 않았었다면 자잘한 에러 잡느라 스트레스 많이 받았을 것 같다.

여기서 미리 Interface를 만들어둔 덕분에 추후 어드민을 만들면서 거의 그대로 가져다 쓸 수 있어서 편리했다.

react.js

현재 제일 익숙한 웹 라이브러리이기도 하고, 같이 협업한 두 명의 프론트엔드 엔지니어 역시 react.js를 많이 사용했기 때문에 선택했다.

이 프로젝트를 시작할 즈음 16 버전이 출시되면서 hook을 적극적으로 도입했는데, 의외로 예상치 못한 곳에서 삽질을 많이 했다. (자세한 이야기는 별도의 포스트에서)

redux는 초기에 붙였으나 useReduceruseContext로 대체하면서 제거했는데 다시 붙일 예정이다.

reacr-router

이건 뭐..설명이 필요한지...

sass

컴포넌트와 동일한 위치에 같은 이름을 가진 scss 파일을 만드는 것으로 스타일링을 처리했으며, BEM 표기법을 차용했지만 엄격하게 사용하지는 않았다.

초기에 styled-component 사용 이야기도 나왔으나 같이 작업한 디자이너분이 마크업을 만질 수 있다는 장점을 살리기 위해 scss를 선택했다.

이는 실제로 프로젝트 막바지에 자잘한 스탛일링 작업은 디자이너분이 직접 해주게 되어서 시간을 매우 아낄 수 있게 되었다.

react-i18next

국제화 처리가 필요하여 붙였다. 현재 영어, 중국어 간체, 중국어 번체를 지원한다.

아래와 같은 흐름으로 사용하고 있다.

  1. 구글 시트에 번역을 양식에 맞게 작업해놓는다.
  2. 별도로 만들어둔 i18n 빌드 + 배포 스크립트를 실행한다.
  3. 구글 시트에 있는 내용들을 각 언어별 json으로 만들어서 s3에 업로드한다
  4. 프로젝트 내에선 저 json을 i18next-xhr-backend를 통해 사이트 접속 시 불러온다.

이 방식을 택한 이유가 i18n의 변경 때문에 애플리케이션을 재배포하지 않기 위함도 있고, 같은 i18n json 파일을 App에서도 사용하기 위함이다.

이전 직장에서는 i18n 파일이 프로젝트 내에 파일로 있었고, 이때문에 내용이 변경이 될 때마다 매번 Front-end 빌드 배포를 다시했었어야 했는데 위의 구조로 가니 언어 파일이 변경되어도 Front-end 배포 없이 갈 수 있어서 무척 편리해졌다.

axios, humps

API 연동은 axios를 이용해서 처리했다.

python - django 컨벤션 상 파라메터가 snake case(param_name)이었는데 JS에선 camel case를 쓰는 것이 표준이므로, humpscamelizeKeys 함수를 이용해 camel case로 만들어서 썼다.

storybook

프로젝트 초기에는 모든 컴포넌트를 storybook에 올리고, 이것을 이용해 커뮤니케이션을 하겠다는 크나큰 야심이 있었지만 프로젝트 막바지에 관리가 잘 안 되어서 한번 갈아엎어야 한다.

그래도 만들어두니 어떤 컴포넌트이 있는지 리스트화 할 수 있어서 좋았고 어떻게 렌더링되는지도 잘 볼 수 있어서 편리했다.

prettier

자동 포맷팅 도구. Visual Studio Code에 플러그인이 있어서 해당 플러그인을 썼다.

코드를 대충 휘갈겨도 알아서 포맷팅 해주니 무척 편했지만, 가끔 먹통이 될 때가 있고 이것 때문에 한줄만 수정해도 diff가 왕창 생기는 경우가 종종 있었어서 pre-commit으로 사용하는 것을 고려중이다.

jest

컴포넌트에 묶여있지 않은 유틸성 코드들은 jest를 이용해 Unit Test를 작성했다.

맺으며

각 기술 스택을 어떻게 적용했는지, 적용하면서 어떠한 일이 있었고 어떠한 고충을 겪었고 어떠한 점이 좋아졌는지에 대해서는 따로 포스팅 하도록 하겠다.

이어지는 글

ODC를 구축한 기술 - Serverless, SPA, AWS Lambda Edge