Blog for QTI developers

2017/01/16

ECMAScript, React.js 그리고 IE 8 (feat. Node.js & npm)

최근 C/S POS를 Web 기반으로 전환하는 프로젝트를 준비하고 있다.
 
이번 프로젝트의 최대 문제점이라고 할 수 있는 부분은, 최종 사용자가 `컴퓨터 운용에 익숙하지 않고, 다소 연령대가 높은 불특정 일반인`이라는 점이다. 아무래도 최종 사용자들에 대한 타겟이 이렇다보니, Web을 운용하는 브라우저가 사용자별로 천차만별일 것이며 그 호환성 해결 방법에 대한 부분을 불안요소로 지적했다.
 
그 결과 사용 환경은 최소한 `Microsoft Windows XP SP3` 운영체제와 `Internet Explorer 8.0` 브라우저로 결정이 되었다.
하지만, 집고 넘어갈 부분은 `MS Windows XP`와 `IE 8`은 MS社의 `수명 주기 지원 정책`에 따라 이미 지원이 중단된 제품들이라는 점이다. (맙소사...)
 
 
다음의 그래프는 2015년부터 2016년까지 데스크탑용 Web 브라우저에 대한 통계를 전세계 기준으로 정리한 자료와 한국 기준으로 정리된 자료이다.

 
2015-2016 데스크탑 브라우저별 사용 추세(세계)
 
2015-2016 데스크탑 브라우저별 사용 비율(세계)
 
2015-2016 데스크탑 브라우저 및 버전별 사용 추세(세계)
 
 
2015-2016 데스크탑 브라우저별 사용 추세(한국)
 
2015-2016 데스크탑 브라우저별 사용 비율(한국)
 
2015-2016 데스크탑 브라우저 및 버전별 사용 비율(한국)
 

이미 몇년 전부터 세계적으로 `Chrome`과 `Firefox`등 `IE`가 아닌 브라우저들이 차지하는 비율이 압도적이였지만, 최근 우리나라에서도 IE가 아닌 브라우저가 차지하는 비율이 상당히 높아졌다.
 
어쨌든 앞으로 개발될 어플리케이션은 시궁창 같은 `IE 8`에 호환성을 맞춰야되므로, 이를 위해서 상당한 시간과 노력이 필요하다는 것이다.
 
위 화면은 테스트를 위해 `ECMAScript` + `React.js` + `react-bootstrap 모듈`로 작성한 어플리케이션을 `Microsoft Windows XP SP3` 운영체제의 `Internet Explorer 8.0` 브라우저에서 실행 가능하도록 구현한 화면이다.
 
 

ECMAScript에 대하여

이 글은 ECMAScript가 무엇[1]이며, 어떠한 내용[2]을 담고 있는 지를 알리기 위한 글이 아니므로 해당 부분은 각주를 참고하기 바라며, 특별히 ECMAScript에 주목하게 된 계기는 다음과 같다.
 
이외에도 `Arrow 함수`라던지 `import`와 `export` 구문 등 매력적인 부분이 충분히 많지만, 위 목록에 명시해둔 항목들은 지난 10년동안 Curl로써 개발을 해온 개발자 입장에서는 무척이나 반가운 부분이다.
 
일반적인 자바스크립트 프로그램의 실행 환경은 브라우저이지만 이것이 유일한 실행 환경은 아니다. 그래서 실행 환경은 자신만의 호스트 객체를 제공할 경우가 있는데, 이 호스트 객체는 표준에 정의되지 않았으며 예상치 못한 방식으로 동작할 수도 있다. 하지만 코어 자바스크립트는 그런 실행 환경과는 무관하다.
`class 구문`은 자바스크립트 프로그램에 있어서 오히려 거추장스러울 수도 있지만, 객체지향 언어 프로그램에 익숙한 개발자들을 위한 설탕 혹은 계륵이라고 해야될 것 같다.
자바스크립는 예약어인 `var`를 사용해서 변수를 선언한다. `var`에 의해 선언된 변수는 전역 혹은 함수 유효 범위를 가지고 있어서 이는 호이스팅(hoisting)이라는 동작 방식과 맞물려 예기치 않은 오류를 발생시키는 경우가 있다. 하지만 `let` 예약어는 변수가 사용되는 블록, 구문 또는 표현식 유효 범위를 갖는 변수를 선언하므로 그런 위험은 없다. `let`은 Curl에서 변수를 선언할때 사용하는 예약어와 동일하다.
`Rest 매개 변수`와 `Default 매개 변수`는 Curl에서 당연스럽게 사용하던 기능이였는데, 드디어 다시 사용할 수 있게된 것이다! (만세~)
 
 

React.js에 대하여

`React`는 Facebook의 오픈소스 프로젝트로서, UI 개발에 최적화된 기술이며 브라우저별 또는 브라우저의 버전별 차이로 인해 발생할 수 있는 문제점들을 완화 시켜준다. 더군다나 React의 `JSX`는 놀랍게도 Curl과 흡사한 코딩 방법을 제공한다.
물론 JSX를 사용하지 않는다고 해서 React를 활용할 수 없는 것은 아니지만, 개발과 유지보수를 생각한다면 수고를 줄일 수 있는 방법을 굳이 마다할 이유는 없다.
현재 React의 최신 버전은 15.4.2(2017/01/06 발표)이며, IE 8을 지원하는 마지막 버전은 0.14.8(2016/03/29 발표)이다.
 
다음은 위 테스트용 어플리케이션에서 JSX로 작성된 React.js의 코드들이다.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//App.jsx
import React, { Component } from 'react';
import { render } from 'react-dom';
 
import PilotHeader from './components/PilotHeader.jsx';
import PilotNav from './components/PilotNav.jsx';
import PilotMenuItem from './components/PilotMenuItem.jsx';
 
export default class App extends Component {
    constructor(props) {
        super(props);
    }
 
    render() {
        return (
            <div>
                <PilotHeader />
                <PilotNav />
 
                <div className="jumbotron">
                    <div className="container">
                        <div className="row">
                            <PilotMenuItem />
                            <PilotMenuItem />
                            <PilotMenuItem />
                            <PilotMenuItem />
                        </div>
                        <div className="row">
                            <PilotMenuItem />
                            <PilotMenuItem />
                            <PilotMenuItem />
                            <PilotMenuItem />
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}
 
render(<App />document.getElementById('root'));
 
cs
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//PilotHeader.jsx
import React, { Component } from 'react';
import { PageHeader } from 'react-bootstrap';
 
class PilotHeader extends Component {
    render() {
        return (
            <PageHeader>
                ECMAScript, React.js 그리고 IE 8
            </PageHeader>
        );
    }
//End-of Class
 
export default PilotHeader;
 
cs
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//PilotNav.jsx
import React, { Component } from 'react';
import { Tabs, Tab, TabContainer, TabContent, TabPane } from 'react-bootstrap';
 
class PilotNav extends Component {
    render() {
        return (
            <Tabs defaultActiveKey={2} id="uncontrolled-tab-example">
                <Tab eventKey={1} title="Tab 1">Tab 1 content</Tab>
                <Tab eventKey={2} title="Tab 2">Tab 2 content</Tab>
                <Tab eventKey={3} title="Tab 3" disabled>Tab 3 content</Tab>
            </Tabs>
        );
    }
//End-of Class
 
export default PilotNav;
 
cs
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//PilotMenuItem.jsx
import React, { Component } from 'react';
import { ButtonToolbar, Button } from 'react-bootstrap';
 
class PilotMenuItem extends Component {
    render() {
        return (
            <div className="col-xs-6 col-md-3">
                <ButtonToolbar>
                    <Button>Default</Button>
                    <Button bsStyle="primary">Primary</Button>
                    <Button bsStyle="success">Success</Button>
                    <Button bsStyle="info">Info</Button>
                    <Button bsStyle="warning">Warning</Button>
                    <Button bsStyle="danger">Danger</Button>
                    <Button bsStyle="link">Link</Button>
                    <Button bsStyle="primary" bsSize="large" active>Primary button</Button>
                    <Button bsSize="large" active>Button</Button>
                </ButtonToolbar>
 
                <h3 className="thumbnail">item_1</h3>
            </div>
        );
    }
//End-of Class
 
export default PilotMenuItem;
 
cs
 
위의 JSX 코드에서 조금 특별한 점은, `react-bootstrap 모듈`을 이용함으로서 `Bootstrap`의 장점을 고스란히 누릴 수 있다는 것이다.
 
이렇게 작성된 코드들은 IE 8에서 날 것(?)으로 사용할 수 없다.
그러므로 우선 Babel을 이용해 범용 JavaScript 코드로 변환하고, IE 8에서 인식 가능하게 만들기 위해서 `es3ify-loader`로 다시 한번 더 변환한다.
최종적으로, 변환된 JavaScript 코드들은 `webpack`을 이용해서 번들 파일로 만든다.
 
 

IE 8에 대하여

위에서 생성된 번들 파일을 HTML에 절적히 포함시켜 브라우저에서 볼 수 있게 구성한다.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>ECMAScript, React.js 그리고 IE 8</title>
 
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="bootstrap-3.3.7/css/bootstrap.min.css" />
        <!-- Optional theme -->
        <link rel="stylesheet" href="bootstrap-3.3.7/css/bootstrap-theme.min.css" />
 
        <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
        <link rel="stylesheet" href="css/ie10-viewport-bug-workaround.css" />
 
        <!-- IE8 에서 HTML5 요소와 미디어 쿼리를 위한 HTML5 shim 와 Respond.js -->
        <!--[if lt IE 9]>
            <script src="js/ie/html5shiv.min.js"></script>
            <script src="js/ie/respond.src.js"></script>
            <script src="js/ie/es5-shim.min.js"></script>
            <script src="js/ie/es5-sham.min.js"></script>
        <![endif]-->
    </head>
 
    <body>
        <!--[if lt IE 8]>
        <div class="jumbotron">
            <div class="container">
                <h1>알림!</h1>
                <p>현재 사용하는 브라우저를 지원하지 않습니다.</p>
            </div>
        </div>
        <![endif]-->
 
        <!--[if (IE 8)|(IE 9)]>
        <div class="alert alert-danger alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
            <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
            <span class="sr-only"><strong><알림!></strong></span>
             최신의 `Internet Explorer` 브라우저 또는 `<a class="alert-link" href="https://www.google.co.kr/chrome/browser/desktop/" target="_blank">Chrome 브라우저</a>`를 사용하면 더욱 원활한 환경에서 사용이 가능합니다.
        </div>
        <![endif]-->
        <!--[if gte IE 8]><!-->
        <!-- React JavaScript -->
        <div id='root'></div>
        <script src="bundle.js" defer></script>
 
        <!-- Bootstrap core JavaScript -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script>window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')</script>
        <script src="bootstrap-3.3.7/js/bootstrap.min.js"></script>
        <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
        <script src="js/ie10-viewport-bug-workaround.js"></script>
        <!--<![endif]-->
    </body>
</html>
 
cs
 
위 HTML 코드에서 8, 27, 36, 44번째 줄에 최종 사용자들의 브라우저 환경에 따라 대응하기 위해서 `조건부 주석`이 사용되었다.
 
        <!--[if lt IE 8]>
        <div class="jumbotron">
            <div class="container">
                <h1>알림!</h1>
                <p>현재 사용하는 브라우저를 지원하지 않습니다.</p>
            </div>
        </div>
        <![endif]-->
 
cs
 
특히 27번째 줄부터 34번째 줄까지의 코드로 IE 8 버전 미만의 브라우저는 단호하게 거부하도록 처리하고,
 
        <!--[if (IE 8)|(IE 9)]>
        <div class="alert alert-danger alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
            <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
            <span class="sr-only"><strong><알림!></strong></span>
             최신의 `Internet Explorer` 브라우저 또는 `<a class="alert-link" href="https://www.google.co.kr/chrome/browser/desktop/" target="_blank">Chrome 브라우저</a>`를 사용하면 더욱 원활한 환경에서 사용이 가능합니다.
        </div>
        <![endif]-->
 
cs
 
36번째 줄부터 43번째 줄까지의 코드로 IE 8 또는 IE 9 버전의 브라우저일때, 최신의 브라우저를 사용하도록 알림을 띄워 최종 사용자들이 자발적으로 업데이트를 하게 유도한다.
 
        <!-- React JavaScript -->
        <div id='root'></div>
        <script src="bundle.js" defer></script>
 
cs
 
46번째 줄과 47번째 줄이 번들된 파일을 HTML 영역에 실제로 구현하는 부분이다.
 
 
미래를 예측해서 잘 짜여진 프로그램의 수명이 얼마나 지속될지는 아무도 예측할 수 없다.
그렇지만 현재 적용 가능한 기술로만 단순히 프로그램을 구현한다면, 그 프로그램의 수명은 얼마가지 않을 것이다.
IE 8과 같은 오래된 브라우저에 지원하지도 않는 최신의 기술들을 억지로 들이붓는 것이 과연 잘하는 일인지 고민을 많이 했다.
하지만 2011년에 Curl로 개발한 POS 프로그램이 S그룹의 식자재 기업의 핵심 운영 프로그램으로 아직도 사용하고 있다.
나는 내가 만든 프로그램의 수명이 오랫동안 지속되기를 바란다.  
 

 
Share:

0 개의 댓글:

댓글 쓰기