snippod-boilerplate (Deprecated) – Full Stack Architecture : React & Flux + Django REST Framework
본 포스팅은 2016년 07월 부로 새롭게 업데이트된 소스코드에 따라 ‘snippod-starter-demo-app – Full Stack : React, Flux (Redux), Django’로 다시 포스팅 되었습니다.
일명 Single Page Application (SPA), 웹 어플리케이션은 네이티브앱과는 별도로 빠르게 성장하고 있는 플랫폼입니다. 여전히 웹은 누구에게나 친숙하고 접근성이 좋은 플랫폼이며, SPA는 네이티브와 유사한 경험을 줄 수 있기 때문에 사용성이 중요한 웹서비스는 웹앱으로 만들어 지고 있습니다.
저 역시 준비하고 있는 첫 프로덕트를 웹앱으로 만들기로 정했기에, 이때부터는 어떤 stack으로 웹앱을 구현할지가 새로운 고민이었습니다. 그리고 Facebook이 공개한 React JavaScript 라이브러리와 Flux Architecture를 접하며 이를 이용하는 것이 현재 저로서는 가장 좋은 선택지라고 결론을 내렸고, 관련된 오픈소스들을 분석해보면서 사용법을 익히고 가장 standard한 적용방식을 고민했습니다.
대부분의 웹앱 샘플 프로그램의 오픈소스 서버사이드는 JavaScript End to End 구현에 따른 여러 잇점때문에 Node.js를 사용하고 있었습니다. 그래서 처음에는 저 역시 Node.js로 구현하려 했습니다. 하지만 향후 본 프로덕트를 보다 복잡한 데이터 모델을 사용하는 서비스로 발전시켜야 했기 때문에, 이전에 경험해본 Django ORM 모델을 활용하고 싶었고,1 그래서 Django로 서버를 구축하게 되었습니다.
그리고 수많은 오픈소스가 Github에서 공유되고 있지만 의외로 React + Flux 프론트사이드와 Django REST 서버사이드로 Full Stack을 구현한 오픈소스를 찾지 못했기에, 저와 유사한 고민을 하시는 분들에게 조금이나마 도움이 될까 싶어 데모 프로그램을 만들고 이를 오픈소스로 공유하였습니다. 참고로 본 데모 프로그램은 기존에 React로 만들어진 Evan의 데모 프로그램을 clone하였기 때문에 프로덕트 구조, 기획 및 디자인을 거의 그대로 가져와서 발전시켰습니다.2
- Git Repository (Deprecated) : https://github.com/shalomeir/snippod-boilerplate
그래서 본 포스팅에서는 공유한 Full Stack 데모 프로그램에서 사용하고 있는 기술 스택들과 세부적인 라이브러리들을 간단히 소개하고 본 기술 스택을 처음 사용하게 되면서 도움이 되었던 여러 자료들을 공유하고자 합니다.
참고로 저는 근래 몇개월 동안 JavaScript, Django 관련 서적 및 온라인 강의3와 Github 를 통해 셀프 스터디로 코딩을 배워나갔지만 아직 내공이 많이 부족합니다. 그래서 소스를 보시면 엉성한 부분이 많이 있습니다. 피드백 주시면 더욱 감사하겠습니다!
사용한 기술 스택
본 snippod demo 프로그램에서 사용한 주요 라이브러리 들과 간략한 소감은 다음과 같습니다.
Frontend side
- React: UI View 를 만들어 주기 위한 라이브러리. 만들고자 하는 부분들을 Component단위로 구현
- Reflux: Flux 의 구조에 영향을 받아 단방향 데이터 흐름을 사용하게 해주는 라이브러리
- Immutable js: JavaScript 에서 Immutable 한 List, Map 등 자료구조 지원
- React-router: SPA 에서 중요한 Routing (url path) 처리
- superagent: ajax call 을 쉽게 하기 위한 라이브러리
Server side
- Django: 장고 웹 프레임워크
- Django REST Framework: REST API 서버를 만들기 위한 프레임워크
- psycopg2: PostgreSQL 을 장고에서 쓰기 위한 어답터
React + Flux(Reflux)
모던 웹이 점차 Component로 구현하는 것이 중요해지고 있으며, Polymer는 아직 IE에서 문제가 많기에, React를 사용하기로 결정하게 되었습니다. 그리고 이에 따라 Flux 아키텍쳐를 쉽게 구현하기 위한 여러 라이브러리를 고려했었는데요, 이 중 많은 분들이 사용하고 있는 reflux를 적용하였습니다. reflux는 아직 ES6를 완벽하게 지원하지 않는다는 단점이 있지만, Flux의 기존 구조에서 Action과 같은 패턴으로 만들어지는 Dispatcher와 Action과 Store간의 연결을 위한 여러 메소드를 자동으로 생성해주어서 좀 더 코드가 줄고 깔끔하게 보이는 편 입니다. 현재 React + Flux 형태의 프론트를 만들때 많은 개발자분들이 reflux를 이용하고 있습니다.
reflux는 모든 Action, Store, Component 간에 event 기반으로 출판, 구독하는 방식으로 이루어져 있고 이에 대해서 ‘The Reflux data flow model’ 블로그 포스팅에서 그 특징을 잘 서술하고 있습니다. 결국 Pub/Sub 모델이고 Action 이벤트가 일어나면 이를 Store/Component 모두 구독가능합니다. Store에서 ‘trigger()’를 통해 publish한 event는 Component 뿐 아니라 다른 Store도 구독할수 있게 되어 있기 때문에 굉장히 다양한 direction 구조가 가능하게 됩니다. 그래서 사용자에 따라 다양한 방식으로 사용할 수 있고 그러다보니 현재까지 획일적인 방식이 보편화 되있지는 않았습니다. 예를 들면 Async 한 ajax call 등을 Store에서 처리하는 경우와 Action에서 처리하는 경우가 사용자에 따라 다르기도 하고요, Reflux 관련 자료들에서도 Store에서 external 서버 통신을 처리하는 방법을 많이들 이용합니다. 저의 경우 action 파트에서 ajax call을 처리하고 async 분기도 처리하도록 만들었습니다. 이렇게 함으로서 Action과 Store간의 역할을 확실하게 분리하고 data flow가 깔끔하게 드러납니다.
Immutable js
React에서는 Component 하위로 props를 전달하면서 UI를 렌더링하게 되는데, 이 때 자식콤포넌트들에게 JavaScript Object가 변경된 것을 빠르게 인식해서 변경된 데이터만 다시 렌더링함으로서 뛰어난 퍼포먼스를 보여줍니다. 하지만 전달되는 Object가 nested한 형태로 참조되는 값이 변경되면 React가 다시 렌러딩할 때 같은 props인줄 알고 다시 렌더링을 하지 않는 경우가 있습니다. 하지만 Immutable js를 사용하면 nested한 객체에서 바라보는 값이 변경되면 무조건 root값도 변경되어서 이러한 문제가 발생하지 않습니다. 그래서 어떤 형태의 props를 받게 되던 상관없이 변경된 데이터가 오게되면 새롭게 rendering을 하게 됩니다. 또한 React Component에서 편하게 PureRenderMixin을 적용하여 퍼포먼스를 향상 시킬 수 있습니다. 저는 Immutable js를 오직 Store에서만 적용했습니다. 그렇게 처리하면 View는 Immutable 객체를 신경안써도 되기 때문에 편하고 어차피 항상 새로운 데이터는 Store에서 받아오고 Immutable 객체를 통해 재생성된 값을 Store에서 던져주게 되므로 Immutable한 데이터를 처리하게 됩니다.
React-router
WebApp을 만들때 routing 처리는 까다롭지만 너무 중요한 요소 입니다. React-router가 그 역할을 잘 수행해줍니다. 실제 router를 구현하는 데 있어 처음에는 조금 막막한데, 샘플 소스가 좋은 가이드가 될 수 있을 것 같습니다.
superagent
ajax call 을 하기 위해 사용하였습니다. jQuery로 처리할 때보다 편한것 같아요.
Django
서버 프로그래밍에선 비동기 프로그래밍이 더욱 까다롭기에 JavaScript보다 python이 더 편하것 같습니다. 게다가 Django Model 에서 제공하는 ORM이 아주 훌륭하고 공식 문서도 너무 잘 되어 있어요.
Django REST Framework
RESTful 한 API 서버가 서버와 클라이언트간의 기준이라고 할 때, 이 기준을 잘 지킬 수 있게 해주는 고마운 프레임워크 입니다. REST API를 제대로 다 이해하고 직접 구현했어야 한다면 굉장히 많은 시간을 이 부분에 쓰거나, 또는 무시하고 나중에 고생하거나 하지 않을까 싶습니다.
psycopg2
RDBMS 를 선택하는데 있어 Django 와 함께 사용한다면 PostgreSQL과 MySQL이라는 두가지 선택지 중에 고민하게 되는 경우가 많을 것 같습니다. 저는 처음에는 MySQL로 배포를 하다 변경사항 발생시 Migration 과정에서 여러가지로 애를 먹고 PostgreSQL로 바꾸었습니다. PostgreSQL에서는 Migration 중에 문제가 사라져서 초보인 저는 맘 편하게 고민하지 않고 PostgreSQL를 사용하고 있습니다. 공유된 snippod-boilerplate 소스에서는 SQLite3로 개발환경 셋업이 되어 있어서 배포를 하지 않는 다면 DB는 따로 신경을 쓰지 않으셔도 됩니다.
AWS 배포하기
현재 블로그를 구축하면서 AWS의 EC2,RDS,S3를 한번 이용해 보았기 때문에 손쉽게 데모 프로그램도 배포가 가능하리라 생각했습니다. 그러나… ㅎ~
Elastic Beanstalk은 로드 밸런싱, 스케일링 작업도 손쉽게 가능하고 모니터링도 쉽게 가능하다는 여러 홍보물을 접해왔었기에 이를 이용해봐야 겠다고 생각하고 이번에 데모 프로그램을 배포하는데 사용했습니다. 공유된 ‘snippod-boilerplate DEMO'(Depreceated)을 살펴보시면 Elastic Beanstalk에서 제공하는 것을 그대로 사용하였음을 알 수 있는데요.
개발환경에서 올려보는 것과는 여러가지로 다르다는 것을 알게 되었고, 셋팅 수정에 한 스텝 진행 할때 마다 error를 만나면서 겨우 마쳤습니다. 최적화 하고 싶은 욕심이 끝이 없는건 배포환경도 마찬가지라는 생각도 들었네요 ㅎ
혹시 Elastic Beanstalk에 Django 배포 셋업을 참고하시고 싶으시다면 공유된 소스 중 ‘./ebextensions’과 Django Settings for Production file을 참고하세요~ 추가로 AWS console 에서 ‘Elastic Beanstalk>[application]>Configration>Software Configration>Environment Properties’화면에서 아래 Properties를 셋업해두어야 ‘eb deploy’과정에서 이를 읽어 사용합니다.
- ‘AWS_ACCESS_KEY_ID’ : 사용하는 AWS Access Key_ID
- ‘AWS_SECRET_ACCESS_KEY’ : 사용하는 AWS Secret Key
- ‘SECRET_KEY’ : Production 에 사용하는 random value Secret key
향후 추가를 고려할만한 기술들
CSS Framework & Animation
현재 데모는 기존의 evan’s react news 데모 프로그램의 기능들과 디자인을 그대로 clone 하기만 하였기에 디자인 적용에 신경을 쓰지 못한 상태 입니다. 현재 react에서 개별 component는 new line 처리가 되기 때문에 기존의 Bootstrap을 그래도 적용하기 까다롭고 className 을 처리하는 과정이 반복적인데 이를 좀 더 심플하게 해주기 위해 React-Bootstrap 라이브러리가 나왔습니다. 현재 충분히 프로덕션 레벨로 적용할만한지는 모르겠지만 Bootstrap을 쓴다면 고려해 볼만한 라이브러리 인듯 합니다.
또한 Google이 제안한 Material 디자인이 트렌드가 되면서 이를 React Component 로 구현한 라이브러리가 나오기 시작했습니다. 그중 material-ui.com 라이브러리가 굉장히 깔끔하게 Component들을 잘 제공하는 것 같습니다.
한편 CSS Animation 효과를 주기 위해 React에서 직접 Animation 관련 addon component를 제공하는데요, 가이드대로 적용해 본 후 잘 안되서 홀딩했는데 향후 디자인을 제대로 적용할 때 살펴 볼 예정입니다.
React Server-side Rendering
초기 React를 Node.js서버로 구현하고 싶었던 가장 큰 이유는 Server-side Rendering 구현이 훨씬 쉽다는 점 때문입니다. SEO를 위해서는 React Server-side Rendering이 반드시 적용되어야 하며, 첫 페이지 로딩 속도도 훨씬 빨라지기 때문에 Django 에서도 React Server-side Rendering을 할 수 있는 방안을 검토해 보았습니다.
첫번째 방안은 내부적으로 Node.js서버를 띄워서 React Component 를 렌더링 한후 이를 다시 Text형태로 Django서버에서 받아 클라이언트에 전달하는 방식입니다. 조금 무식한 느낌을 받았는데요, 관련 샘플 예제 소스을 보면서 그래도 Node.js에 익숙하다면 이 방안이 가장 확실하다는 느낌을 받았습니다.
두번째 방안으로 python 에서 JSX translation을 해주는 라이브러리를 이용해 react rendering을 하는 방법을 고려해 보았는데요, 아직 충분히 도입할 만한 수준인지 확신이 들지 않았습니다.
프로덕션 레벨로 가려면 결국 Node.js도 도입해야 하는것 아닌가 싶은 생각이 들었습니다.
i18n & l10n : internationalization (국제화) & localization (지역화)
Django에서 기본적으로 제공하는 i18n은 굉장히 잘 되어 있지만, Django의 Template을 쓰지 않고 React를 사용했기에, 다른 대안이 필요합니다. Yahoo에서 공개한 Format.js가 아주 훌륭한거 같고 React를 많이 고려해서 React Component를 위한 integration도 잘 지원합니다. 하지만 Translation 은 결국 server에서 접속자에 따라 다르게 제공해 주어야 할 텐데 이를 처리하려면 Django에서 static 파일을 분류해서 던져주어야 할 것 같습니다. django-statici18n이 그러한 기능을 제공해주고 있는데, 단순한 분기 처리 정도만 해주는 듯 해 보입니다.
소셜 인증
요즘 같은 시대에 Python-Social-Auth를 이용해서 소셜 인증 가입/로그인을 적용 안할 수는 없는 듯 합니다~
Cache Framework
캐쉬 프레임워크도 역시 이젠 기본인데.. 현재는 전혀 적용이 되어 있지 않습니다.
Reference
Instagram Stack
React에 처음 관심을 가지게 된 것은 역시 Instagram의 Pete Hunt가 발표했던 Instagram에서 React를 통해 SPA를 도입한 사례 소개 영상 때문이었고 이후 Instagram이 굉장히 효율적으로 서비스를 만들었다는 생각에 Instagram 관련 기술 정보 들을 많이 참고하였습니다. Instagram에서 적극적으로 정보를 공유해주어 참고할 수 있는 자료가 많았는데요, 개발팀이 스타트업 초기 고려했던 기술 스택에 대해 쓴 글인 ‘What Powers Instagram: Hundreds of Instances, Dozens of Technologies’은 한글로 번역된 포스팅도 존재합니다. 결국 본 데모 프로그램에 사용한 주요 기술들인 React+Django+PostgreSQL 은 Instagram 과 정확히 일치합니다.
GitHub Open Source
GitHub 에서 React, Flux, Django 및 그외 사용한 라이브러리들에 관련된 샘플 프로그램들은 되도록 많이 설치해 보려했고 굉장히 도움이 많이 되었습니다. 개별적인 소스 들 중에 본 데모 프로그램에 직접적으로 영향을 준 소스는 아래와 같습니다.
Front side
- yeogurt generator : front build tool 인 grunt 관련해서 굉장히 세부적으로 셋업이 잘 되어 있어서 잘 가져다 적용했습니다.
- Evan’s React News & blog post : 본 데모의 기능적인 부분, 디자인을 그대로 가져왔습니다. 일부 Component들 중 유사하게 변형하거나 배치를 다르게 하긴 했으나 기본적인 틀을 거의 같고 CSS는 그대로 가져왔습니다. 하지만 내부적인 Architecture는 본 데모에서는 완전히 새로 만들었기 때문에 구조적으로 많이 다릅니다. 일단 Evan의 소스는 Firebase기반으로 서버사이드가 존재하지 않으며, Store 에서 ajax처리를 합니다. Upvoting이 중복해서 입력되는 등 기본적으로 심플한 구조를 가지고 있습니다.
- gaeron’s Flux React Router Example : 한번 GET 해온 데이터들을 Page 나 Sorting 옵션이 바뀌어도 잘 보관하고 있도록 하는 것은 중복적인 서버와의 통신을 막고 훨씬 빠르게 페이지간 이동을 가능하게 해주는 데요, 이러한 방식의 Store를 구현하기 위해 gaeron이 공유한 소스가 굉장히 도움이 되었습니다.
Server side
- Thinkster.io Django and AngularJS Tutorial : Django가 Template이 아닌 AngularJS를 주로 사용하는 케이스로 Django REST Framework를 사용하고 있었기에 서버 측면에서 참고가 되었습니다.