React 사용사례

FBDG 2015

Created by Ironhee

Ediket

https://ediket.com

상황

구현로직

Backend < Frontend

스타트업

lean

잦은 기획의 변경

개발팀

3명

목표

글로벌 플랫폼

유연하고
효율적이면서
확장가능한
개발구조

기존 개발스택

backbone
marionette handlebars

Backbone + Marionette + Handlebars
mv*

DOM 직접 제어

View 복잡함

가독성 낮음

재사용성 낮음

협업 어려움

requirejs

Require.js
Module Loader

AMD 전용 코드

Dependencies Hell

복잡함

flask jinja2 python-babel

Flask + Jinja2 + Babel
server-side template

프론트 개발자: 백엔드 코드를 작성

백엔드 개발자: 프론트 코드를 작성

Context Switching Cost

프론트와 백엔드의 역할 분리 X

flask

Flask
Server-Side Routing

프론트 개발자: 백엔드의 구현에 의존

팀의 핵심역량 = 프론트

Client-Side Routing 필요

grunt

Grunt
Task Runner

더 좋은 대안

Gulp

NPM scripts

ES7 Generator

현재 개발 스택

react flux

React + Flux(Reflux)
mv*

View 단순함

가독성 높음

재사용성 높음

협업 쉬움

webpack

Webpack
module bundler

NPM 생태계

Chunk + Lazy Loading

Plugin + Loader (Babel, Sass, postCSS)

var _ = require('lodash');  // load node module
var path = require('path');  // load built-in module

function helloWorld() {
  console.log('hello world!');
}

module.exports = helloWorld;  // export like node module

/* webpack.config.js */
export default {
  // configs...
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: VERBOSE,
      },
    }),
  ],
  module: {
    loaders: [
      {
        test: /\.(js|es6)$/,
        include: path.join(__dirname, '../src'),
        loaders: [...DEBUG ? ['react-hot'] : [], 'babel'],
      },
      {
        test: /\.scss$/,
        include: path.join(__dirname, '../src'),
        loaders: ['style/useable', 'css', 'postcss', 'sass?sourceMap'],
      },
      {
        test: /\.css$/,
        loaders: ['style/useable', 'css', 'postcss'],
      },
    ],
  },
};

babel

Babel
JS compiler

ES6 / ES7

JSX

import _ from 'lodash';

const helloWorld = () => {
  console.log('hello world!');
}

const jsx = (
  

Hello world

); export default helloWorld;

'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var helloWorld = function helloWorld() {
  console.log('hello world!');
};

var jsx = React.createElement(
  'div',
  null,
  React.createElement(
    'h1',
    null,
    'Hello world'
  )
);

exports['default'] = helloWorld;
module.exports = exports['default'];

react react-intl nunjucks

React + React-Intl + Nunjucks
client-side template

프론트 개발자: 프론트 코드를 작성

백엔드 개발자: 백엔드 코드를 작성

단일 책임 원칙

nunjucks-code
nunjucks-render-code
react-intl-message
react-intl-code
react-router

React-Router
Client-Side Routing (SPA)

백엔드라우팅 의존성 제거

추가적 Refresh X

Chunk + Lazy Loading

react-router-code

ES7 Generator
Task runner

Just Javascript

유연함

단순함

react-starter-kit

개발 시나리오

'쿠폰 생성 페이지가 필요해요!'

Run Webpack Devserver

npm-run-serve

Dummy Component 작성

react-couponpage

Router 에 Component 추가

router-code

Header 에 CouponPage Link 추가

topbar-code

Browser 에서 구현 확인

couponpage-dummy-web

Component UI 구현

coupon-ui-code coupon-ui-web

Style 적용

coupon-style-scss coupon-style-web coupon-style

Store 및 Action 구현

store-code coupon-reducer-code coupon-action-code

Component 에서 Store & Action 이용하도록 변경

coupon-ui-code => coupon-page-use-redux-code

Browser 에서 구현 확인

coupon-ui-web => coupon-use-redux-web

다국어 (Intl) 적용

서버와 연동 (REST API)

Web

http://ironhee.github.io/ironhee-frontend-boilerplate

Source

https://github.com/ironhee/ironhee-frontend-boilerplate

얻게된 것

단순함

유연함

재사용성

개발속도

가장 중요한 것

소통

communication

신뢰

trust

Thanks to

End

Event

https://ediket.com/coupon/