자바스크립트 개발환경에서 Ajax로 백엔드와 통신을 테스트 할때 걸리적 거리는 것 중 하나가 바로 CORS이다. 

CORS는 웹 브라우저의 기본 보안 모델로,
자바스크립트로 원격 리소스에 접근하고자 할 때, 자바스크립트를 내려 준 원천(Origin)이 아니면 Cross-Origin HTTP 요청으로 판단하여 요청을 허가하지 않게끔 한다.

그래서 웹 서버 설정이나 프로그래밍 방식으로 CORS 설정(HTTP 헤더 설정)을 통해 상호 통신이 가능케 한다.

이는 프로덕션 환경에서는 당연하겠지만, 개발 환경에서는 여간 불편한게 아니다.

개발 환경에서 서버 측을 직접 제어 할 수 있으면 별로 문제 될 것이 없으나, 그렇지 않을 경우 서버 측 담당자에게 CORS 설정을 요청해야 한다. 

만일 서버 측 환경이 다수의 서비스와 통신을 해야 하는 상황이라면 더욱 귀찮아 진다.

그래서 프론트엔드 단에서 Cross-Origin HTTP 요청이 가능하게끔 하는 방법이 자주 사용된다.

흔히 사용되는 방법으로는 Node.js의 http-proxy 관련 모듈을 사용해서 중간에 프록시 계층을 하나 두는 것인데, 이는 프록시 만을 위한 Node 응용프로그램을 별도로 띄워야 하는 점이 마음에 들지 않는다.


따라서 이 글에서는 프론트엔드 테스트 도구와 프록시 설정을 한방에 해결 할 수 있는 편리한 환경에 대해 소개하고자 한다.

몇 가지 선택지가 있으나 여기서는 Browser-Sync를 이용해 보자

1. 설치
 > npm install -g browser-sync

2. 프록시 설정 없이 테스트 돌려 보기
 > browser-sync start --server --files “*.*”

기본포트인 3000번 포트로 프론트엔드 파일들을 마치 웹 서버에서 실행하듯 테스트 해 볼 수 있다.
물론 Browser-Sync가 제공하는 각종 브라우저 동기화, 라이브로딩 등의 장점을 만끽하면서 말이다.
그런데 이렇게만 하면, CORS 통신을 하지 못하게 된다.

따라서 아래와 같이 실행.

3. 프록시 모드로 돌려보기

  > browser-sync start --proxy "localhost:8080" --serverStatic "public" --files "public"

정적리소스는 "public" 폴더에 있다고 가정하고 나머지 요청은 8080포트로 서비스 중인 서버 측으로 요청을 프록시하도록 한다.

이렇게 함으로써 정적파일은 정적파일대로 테스트 할 수 있고, 다른 도메인(포트)로 서비스 되고 있는 원격 API도 CORS상에서 호출이 가능해 진다.

음.. 아주 편하군...

끝!!!

그런데 이런 환경을 만들어 주는 게 비단, Browser-Sync만 있는 것이 아니다. 다음은 이와 같은 개발 환경을 가능케 해 주는 다른 모듈을 안내한다.

1) lite-server
- AngularJS 계의 거장(?)인 존파파께서 만들어준 로컬 서버 환경. Broswer-Sync를 기반으로 하고 있기 때문에 동일하게 동작한다. 물론 Angular 환경이 아니더라도 얼마던지 사용가능하다.

2) webpack-dev-server
- Angular2가 처음 출시될 때는 System.js에 lite-server를 사용했는데, 이후 버전 업이 되면서 최근 Angular-CLI는 webpack을 빌드도구를 채용하고 로컬 서버를 webpack-dev-server로 교체하였다.

역시나 Angular 환경이 아니더라도 webpack-dev-server를 사용할 수 있으며, 이 환경에서 CROS 설정이 가능하다.

다음 URL에서 아주 잘 설명하고 있다.

> https://webpack.github.io/docs/webpack-dev-server.html#proxy 


3) Angular환경 
- 만일 최신 Angular 프레임워크로 작업하고 있다면 ng serve 실행 시 프록시 설정을 추가 할 수 있다. 역시 다음 URL에서 아주 잘 설명하고 있다.

https://www.npmjs.com/package/angular-cli#proxy-to-backend



'모바일 > Javascript' 카테고리의 다른 글

Proxy to Back-end(프론트엔드단 CORS 통신설정)  (1) 2017.07.28
Javascript Compiler, Babel  (0) 2017.03.16
[Angular] Angular Modules(NgModule)  (0) 2017.01.25
Isomorphic Javascript  (0) 2017.01.23
[Node] npm(node package manager)  (0) 2017.01.20
[Angular] Lazy Loading  (0) 2017.01.18

submit

Javascript Compiler, Babel

Posted in 모바일/Javascript // Posted at 2017. 3. 16. 10:49

* ECMAScript 6 브라우저 지원 현황

https://kangax.github.io/compat-table/es6/ 


'모바일 > Javascript' 카테고리의 다른 글

Proxy to Back-end(프론트엔드단 CORS 통신설정)  (1) 2017.07.28
Javascript Compiler, Babel  (0) 2017.03.16
[Angular] Angular Modules(NgModule)  (0) 2017.01.25
Isomorphic Javascript  (0) 2017.01.23
[Node] npm(node package manager)  (0) 2017.01.20
[Angular] Lazy Loading  (0) 2017.01.18
Tags Babel, babel.js

submit

[Angular] Angular Modules(NgModule)

Posted in 모바일/Javascript // Posted at 2017. 1. 25. 19:30

본 아티클에서는 Angular 2.4.4 버전에서 테스트 되었습니다.

Angular 응용프로그램은 컴포넌트와 디렉티브, 파이프, 서비스 등의 조합으로 이루어진다.

응용프로그램의 규모가 커질 수록, 이러한 구성요소들을 특정 기준에 따라 그룹화시켜 관리하는 것이 좋은데 이를 위해 Angular에서는 @NgModule이라는 decorator를 통해 모듈화 구성을 지원한다.

Angular의 모듈 구성을 사용하면, 컴포넌트들을 논리적으로 그룹핑하여 관리할 수 있으며
라우팅과 연계하면 모듈 단위 Lazy Loading을 구현할 수도 있다.

(참고: 논리적 그룹이라는 측면에서 보면 닷넷의 namespace, 자바의 package와 유사할 것이다.)

Angular의 모듈화 구성에 대해 살펴보자

@NgModule Decorator
Angular 모듈구성을 위한 메타데이터 객체정보를 전달받는 데코레이터 함수이다.
전달된 메타데이터 정보에 기반해서 현재 모듈로 구성해야할 컴포넌트와 디렉티브, 파이브 등의 정보를 식별하고 외부로 노출할 컴포넌트를 결정한다.

전달되는 메타데이터 속성은 다음과 같다.

1) declarations
- 현재 모듈에 포함시킬 뷰 클래스들을 지정.(뷰 클래스 종류: 컴포넌트/디렉티브/파이프)

2) exports
- declarations에서 정의한 현재 모듈의 구성요소를 다른 모듈의 템플릿에서 사용할 수 있도록 노출시킬 뷰 클래스들을 지정.(여기서 지정하지 않은 뷰 클래스들은 다른 모듈에서 사용 불가)

3) imports
- 다른 모듈에서 노출(exports)한 뷰 클래스들를 사용하기 위해 해당 모듈 임포트.

4) providers
- 공통 서비스의 등록. 등록된 서비스는 앱의 모든 부분에서 사용 가능.

5) bootstrap
- 메인 뷰로 사용될 루트 컴포넌트 지정. 루트모듈에서만 지정가능.

(https://angular.io/docs/ts/latest/guide/architecture.html#!#modules 참고)


이제 @NgModule을 사용해서 모듈화 구성의 초간단 샘플을 작성해보자.
두 가지 형태로 테스트를 해볼텐데, 첫번째는 규모가 작은 응용프로그램이라는 가정 하에 단일 모듈(루트모듈) 구성을 두번째는 서브모듈을 하나 더 만들어 볼 것이다.

1. 루트 모듈만 사용
Angular는 최소한 하나 이상의 모듈로 구성해야 하는데, 가장 기본이 되는 모듈이 바로, 
루트모듈(Root Module)이다. 
angular-cli로 프로젝트를 생성하면 루트모듈이 자동으로 생성된다.

기본 생성된 구조에서, 컴포넌트와 서비스를 추가해보자.
추가된 컴포넌트는 sub.component와 sub.service이다. 폴더구조와 소스는 다음과 같다.

* 폴더구조


* 소스(sub.service.ts)


* 소스(sub.component.ts)


새로 추가한 SubComponent는 서비스를 주입 받아서 id/name 데이터를 획득해서 자신의 멤버변수에 할당하는 간단한 코드이다.

이렇게 추가한 SubComponent를 루트 컴포넌트에 해당하는 AppComponent에서 사용하기 위해 AppComponent의 HTML에 SubComponent 태그를 추가시킨다.

* 소스(app.component.html)

 그런데 이렇게 사용하려면 루트 모듈에 SubComponent와 SubService에 대한 참조가 정의되어 있어야 한다.

* 소스(app.module.ts)

이로써 결과를 확인할 수 있게 되었다.

* 결과화면


2. 모듈 분리하기.
앞서 루트모듈만 사용했을 경우 문제는, 프로그램 규모가 복잡하고 커질 경우 상당량이 컴포넌트/서비스/파이프/디렉티브가 생기게 되는데 이것들을 모두 하나의 모듈로 관리해야 하기 때문에 구조가 비직관적으로 복잡해지고 모듈단위 관리(라우팅 및 비동기모듈로딩 등)가 용이하지 않다는 점이다.

이에 데모를 조금 변경하여 모듈을 분리해 보자.

SubComponent와 SubService를 묶어서, 별도의 다른 모듈로 그룹화 시키기 위해 SubModule을 생성한다.

* 소스(sub.module.ts)

여기서 주의 할 점은 이 모듈의 컴포넌트를 외부 모듈에서도 사용하게끔 하려면 exports로 명시를 해줘야 한다는 것이다.

이렇게 함으로써 Sub집합(여기서는 하나의 컴포넌트와 하나의 서비스)을 별도의 Angular 모듈로 만들었으며 이 모듈을 루트모듈에서 사용하려면 다음과 루트모듈을 수정하면 된다.

* 소스(app.module.ts)


앞서 루트모듈만 사용했을 때에는, 컴포넌트와 서비스를 모두 참조해야 했지만 모듈을 분리하고 나서는 해당 모듈(여기서는 SubModule)만 참조하면 된다.

그리고 결과화면은 (볼 것도 없이) 앞의 예와 동일한다.

다음 아티클에서는 모듈과 연관되는 라우팅(Routing)에 대해 정리할 예정.


* 참고자료
- Angular 공식 가이드
- Angular Architecture Overview
- Angular Tutorial


'모바일 > Javascript' 카테고리의 다른 글

Proxy to Back-end(프론트엔드단 CORS 통신설정)  (1) 2017.07.28
Javascript Compiler, Babel  (0) 2017.03.16
[Angular] Angular Modules(NgModule)  (0) 2017.01.25
Isomorphic Javascript  (0) 2017.01.23
[Node] npm(node package manager)  (0) 2017.01.20
[Angular] Lazy Loading  (0) 2017.01.18

submit

Isomorphic Javascript

Posted in 모바일/Javascript // Posted at 2017. 1. 23. 14:45

서버와 클라이언트 사이드에서 모두 동작하는 자바스크립트 어플리케이션을 Isomorphic JavaScript(동형 자바스크립트)라고 한다.

굳이... 새로운 용어에 피로감이 들긴 하지만.

그간, 클라이언트.. 그것도 웹 브라우저에서만 주로 동작하던 자바스크립트가 명실상부! 그 영역을 점차 확대하고 있는 획기적인 시대에 이러한 패러다임을 공유하기 위한 개념적 용어는 필요해 보인다.

Isomorphic JavaScript 또는 Universal JavaScript라고들 하는데... 용어가 중요한 것이 아니라 서로 공감하고 이해되는 개념이 중요한 것이다.

Isomorphic JavaScript의 개념을 조금 더 확장시켜서, 서버-클라이언트의 동형은 물론이고 데스크톱, 가상현실/증강현실 분야에서의 자바스크립트와 하나의 어플리케이션 개발 생태계에 일조하는 개발 지원환경등을 모아서 다음과 같이 정리해 보았다

자바스크립트는 더 이상 웹만을 위하지 않는다. 그는 데스크톱 영역을 침범하기 시작했으며 가상현실 영역으로부터도 러브콜(?)을 받고 있다. 그의 생태계는 점점 넓어지고 깊어지고 있는 것이다.

순전히 개인적으로 좋아서, 틈틈히 해 오던 자바스크립트 공부에 활력소가 되고 있다. 음.. 좋아~~~




'모바일 > Javascript' 카테고리의 다른 글

Javascript Compiler, Babel  (0) 2017.03.16
[Angular] Angular Modules(NgModule)  (0) 2017.01.25
Isomorphic Javascript  (0) 2017.01.23
[Node] npm(node package manager)  (0) 2017.01.20
[Angular] Lazy Loading  (0) 2017.01.18
SPA 단점에 대한 단상  (1) 2017.01.17

submit

[Node] npm(node package manager)

Posted in 모바일/Javascript // Posted at 2017. 1. 20. 10:55

간혹 헷갈리는 npm 옵션들.

각 명령어들의 상세한 옵션 등을 확인하려면 npm 문서 참조

https://docs.npmjs.com/cli/{명령어}


차차 추가하기로 함...

'모바일 > Javascript' 카테고리의 다른 글

[Angular] Angular Modules(NgModule)  (0) 2017.01.25
Isomorphic Javascript  (0) 2017.01.23
[Node] npm(node package manager)  (0) 2017.01.20
[Angular] Lazy Loading  (0) 2017.01.18
SPA 단점에 대한 단상  (1) 2017.01.17
[Webpack] 비동기 번들 로딩  (0) 2017.01.14
Tags Node, NPM

submit

[Angular] Lazy Loading

Posted in 모바일/Javascript // Posted at 2017. 1. 18. 14:29

앞서 'SPA의 단점에 대한 단상'이라는 글에서 초기 구동속도 문제에 대해 다루었었다.

SPA의 초기 구동속도 문제를 완화하기 위해, 모듈을 청크단위로 분리해서 해당 모듈이 필요한 시점이 되었을 때 관련 리소스들이 다운로드 될 수 있도록 하는 Lazy Loading 기법을 사용할 수 있다.

Angular2에서는 모듈 단위로 컴포넌트와 서비스, 파이프 등 각종 구성요소들을 논리적으로 그룹화 시키고 해당 모듈단위로 Lazy Loading을 적용할 수 있는데, 이의 구현에 대해 알아본다.

1. 시나리오는 대략 이렇다

1) 총 3개의 모듈(일반적인 웹 페이지 개념으로는 3개의 웹 페이지라고 생각하자)

2) 첫 구동 페이지(메인페이지에 해당)에서는 메인 구성을 위한 리소스만 다운로드

3) 나머지 두 개의 페이지도 그 페이지에 요청이 있을 경우에만 관련 리소스 다운로드

4) 이후에는 모든 페이지를 재 방문해도, 새로고침 없이 다운로드 된 리소스 사용

2. Angular 개발 환경은 다음과 같다.

참고로 부트스트랩 3.3.7도 사용.


3. 데모 프로젝트 디렉터리 구조는 다음과 같다.
앞서 시나리오와 같이 총 3개의 페이지를 위한 3개의 Angular 모듈 구성(one/two/three)


4. 각 모듈의 라우팅 구성은 다음과 같다.
1) 루트 라우팅 구성

2) 하위 모듈 라우팅 구성


5. 각 모듈 구성은 다음과 같다.
1) 루트 모듈


2) 하위 모듈 구성


컴포넌트 구성은 중요한 것이 아니라서, 생략하고 프로젝트를 빌드 한다


6. 청크(Chunk)단위 모듈 로딩 확인하기
1) 메인 페이지 요청

Angular 구동을 위한 번들 파일과 메인페이지의 리소스들을 다운로드 받는다.


2) 두번째 페이지 요청
두번째 페이지에서 사용하는 모듈이 번들링된 청크파일과 리소스만 로딩



3) 세번째 페이지 요청
세번째 페이지에서 사용하는 모듈이 번들링된 청크파일과 리소스만 로딩


이제 모든 리소스가 다운로드 되었고, 이후부터는 해당 페이지들을 다시 방문해도 (비동기 통신 데이터를 제외하고는) 이미 다운로드 된 리소스들을 사용해서 반응성이 빨라지게 된다.

추가로 이 데모에서는 초기 페이지의 컴포넌트 재생성을 방지하기 위해 사용자 정의 RouteReuseStrategy를 적용해서 매번 컴포넌트 생성을 하지 않게끔(싱글톤) 하였다.

아래 이미지를 확인해 보면, 세 개의 페이지를 왔다갔다 할 때 첫번째 페이지의 컴포넌트의 경우 더 이상 객체를 생성하지 않는 것을 알 수 있다.(해당 로그는 객체의 생성자에서 기록하도록 했음)





'모바일 > Javascript' 카테고리의 다른 글

Isomorphic Javascript  (0) 2017.01.23
[Node] npm(node package manager)  (0) 2017.01.20
[Angular] Lazy Loading  (0) 2017.01.18
SPA 단점에 대한 단상  (1) 2017.01.17
[Webpack] 비동기 번들 로딩  (0) 2017.01.14
[Webpack] 자바스크립 모듈 번들러, 웹팩(Webpack)  (0) 2017.01.12

submit

SPA 단점에 대한 단상

Posted in 모바일/Javascript // Posted at 2017. 1. 17. 16:33

모바일 시대로 접어들면서 웹 환경에도 많은 변화가 동반되었다.

그 중 SPA(Single Page Application)도 단단히 한몫을 차지하고 있는데, 항간에 들리는 SPA의 단점들을 나열해 보면 크게 세 가지로 압축되는 듯 하다.

1. 초기 구동 속도

2. 검색엔진 최적화(SEO)

3. 보안

4. IE 8 이하 지원 (추가)

사실 이것들은 SPA의 단점이라기 보다는, SPA 구조이기에 당연히 생길수 밖에 없는 상황으로 이해되어야 한다.

모든 소프트웨어 아키텍처 전략에는 트레이드 오프(Trade-off)가 존재한다. 흔히 '은탄환'은 없다는 말처럼, SPA가 모든 웹 애플리케이션에 가장 적합한 구조는 아니다.

SPA 직역하면 '단일 페이지 어플리케이션'으로, 기존의 전통적인 새로고침 방식의 웹과는 달리 필요한 정적파일을 한번에(나눠서도 가능하다) 모두 다운로드 받고, 이후 사용자와의 상호작용 가운데 필요한 데이터만 서버로부터 (비동기로) 동적으로 받게하여 트래픽의 총량을 줄이고, 네이티브 앱과 유사한 사용자 경험을 제공할 수 있는 어플리케이션 형태이다.

결국 SPA가 추구하는 핵심적인 가치는 웹의 (사용자 경험을 향상시키는, UX) 사용성이라 할 수 있으며 부가적으로 속도의 향상도 얻게 된다.(물론 속도에 큰 틀에서 보면 사용성에 포함시킬 수 있다.)

특히 모바일 환경에서는 트래픽 최소화와 속도 및 반응성, 사용성 등이 보다 중요한 이슈이므로 SPA 구조는 모바일 퍼스트(Mobile First) 전략에서는 거의 모범사례에 가까운 모델이라 할 수 있다.

최근 App-likeNaively Web을 지향하는 구글의 PWA(Progressive Web App) 역시 모바일 환경에서의 웹의 사용성을 향상시키는 일환으로 대두되고 있다. PWA가 SPA를 직접적으로 포함하는 개념은 아니지만 비동기 통신과 SPA 구조는 PWA와 궁합이 잘 맞는 선택이다. 개인적으로 SPA도 PWA와 같은 선상에서 이해되기를 바라는 마음이다.

위에서 언급한 SPA 단점(?)이란 것들도, 가만히 들여다 보면 SPA가 추구하는 사상에서 파생되는 당연한 특징들에 가까우며, 저런 단점들 때문에 SPA 적용에 대해 큰 의문이 든다면, 그것은 SPA 자체의 문제가 아니라 현재 어플리케이션이 SPA모델과는 어울리지 않을 가능성이 더 높다.

다시 말하지만, SPA가 모든 상황에 있어 최고의 아키텍처 전략이 아니라, SPA가 어울리는 곳에 사용했을 때만이 최적의 효과와 효율을 발휘할 수 있을 것이다.

위에서 언급한 SPA의 문제(문제라고 해 두자)들을 하나씩 살펴보자.

1. 초기 구동속도 문제
평소 우리는 많은 모바일 '네이티브 앱'을 사용한다. 당신의 스마트폰에 깔려 있는 많은 앱들을 생각해보라. 이 앱들을 사용하는 우리의 자세(?)를 돌이켜보자.

먼저 앱스토어에서 수메가(mb)에 달하는
 앱을, 몇 초에 걸쳐 다운로드 받는다. 그리고 또다시 몇 초의 시간을 설치하는데 할애한다. 아직 끝이 아니다. 설치한 앱을 처음 띄울때 초기 구동을 위한 각종 설정과 초기화 작업을 기다리며 앱 초기배너 혹은 광고배너를 무심히 바라본다.

드디어 앱이 실행되면 그때부터는 큰 기다림 없이 앱을 사용한다. 물론 이제부터는 빠른 응답과 높은 반응성을 만끽(?)하면서 말이다.

(또한 설치된 앱을 종료하고 다시 실행할 때도 약간의 시간을 감수해야 한다.)

이제 SPA로 돌아와보자. SPA 역시 모바일 네이티브 앱과 같은 효과를 웹에서 제공해 주고자 한다.
즉 앱의 사용성을 추구하고자 SPA에서도 초기에 필요한 대부분의 리소스를 다운로드 받는다. 물론 이것은 초기 구동속도를 조금 손해보고 더 많은 가치(전체적인 앱의 속도/반응성/사용성 등)를 추구하기 위함이다.

우리는 모바일 앱(극단적인 예로 모바일 게임을 떠올려 보자)을 사용하면서 초기 구동속도가 치명적인 단점이라고 생각하지 않는다. 오히려 다운로드와 설치과정 및 앱 초기 구동을 위한 약간의 시간들을 오히려 자연스럽게 받아들인다.

SPA 사상도 이와 유사하기에 초기 구동속도가 치명적인 단점이라고 언급되는 것은 곤란하다고 강조하고 싶다.

SPA의 사상은, 더 이상 웹이 단순한 웹 문서(웹 페이지)가 아닌 하나의 응용프로그램으로 바라보기에 개념의 전환이 필요한 것이다.

물론 그럼에도 불구하고 SPA도 (여전히) 웹 이기에 기존 웹의 경험을 무시할 수 없는 측면도 있을 것이다.

이런 조건 말이다. "SPA가 좋은건 알겠는데... 메인 페이지는 무조건 빨리 떠야 합니다."

SPA에서도 이런 상황에 대한 기술적 대안을 마련할 수 있다.
초기 페이지에서 모든 리소스를 다운받지 않고, 리소스를 청크(Chunk) 단위로 묶어서 해당 리소스에 대한 요청이 있을 때만 다운로드 받도록 하는 방법을 적용하면 초기 구동속도 문제를 많이 완화시킬 수 있다.

많은 자바스크립트 모듈 번들러에서 Lazy Loading 혹은 비동기 모듈로딩이라는 이름으로 이런 시나리오를 지원하며, 우리의 훌륭한 Angular에서도 모듈단위로 구성요소를 묶고 청크단위로 다운로드 받게 할 수 있다.

심지어 SPA에 PWA를 조합하면 보다 뛰어난 사용성을 부가적으로 제공할 수도 있다. 초기 구동에 필요한 필수적 파일을 웹쉘로 구성하고 백그라운드에서 서비스워커를 통해 비동기 리소스 탐방(?)을 실현할 수 있다.

다시 강조하지만, SPA에서 초기 구동속도는 더 이상 결정적인 단점으로 논해져서는 안된다.
오히려 현재 적용하려는 웹 사이트가 SPA 사상과 맞지 않는 것이 아닌가 살펴보기 바란다.


2. 검색엔진 최적화(SEO) 문제
SEO는 서버랜더링 방식이 아닌 자바스크립트 기반 비동기 연동 모델(클라이언트 랜더링 방식)에서는 항상 이슈가 되어 왔던 주제이다. SPA로 가면서 극단적(?) 자바스크립트 기반 웹이 되다 보니 그 문제가 더욱 부각되는 것이다. 구글 크롬 브라우저는 최신 웹 트랜드를 반영해서 자사의 검색엔진에서 클라이언트 래더링 방식도 검색 봇(Bot)이 컨텐츠를 가져갈 수 있도록 개선하고 있지만 기타 다른 브라우저에서는 그 방향성이 불투명하다.

그러나 이 문제 역시 비슷한 맥락에서 말할 수 있다.

다시 말하지만, SPA로 구현된 웹은 더 이상 단순한 정보제공을 위한 웹 문서(페이지)가 아니다.
SPA 결과물을 하나의 응용프로그램으로 본다면 기존 웹 페이지의 정보제공이란 측면의 SEO가 맞지 않을 수도 있다는 것이다.

생각해 보자. 모바일 네이티브 앱을 만들면서 SEO를 걱정하는 이는 드물 것이다.
(다시 극단적인 예로, 모바일 게임을 만들면서 SEO가 안된다고 걱정하는 것을 상상해보라)

SPA를 적용하면서도 개념은 여전히 웹 페이지에 머물러 있다면 둘 중 하나일 것이다.

SPA 사상을 이해하지 못했거나 해당 프로젝트가 SPA와 어울리지 않거나!

(다시한번) 그럼에도 불구하고 SPA도 웹이기에 SEO가 되어야 한다면 역시 대안 기술이 존재한다.

prerender.io 같은 상용 솔루션도 존재하고, Angular나 React같은 SPA 프레임워크에서도 서버 랜더링이라는 이름으로 SEO에 대응하고 있다.  

Angular의 경우 Angular Universal 이라는 SEO 대응 기술이 이미 존재한다.
아직까지 Node.js나 ASP.NET 서버 환경에서만 서버 랜더링을 지원하지만 향후 다른 서버플랫폼도 지원을 계속 추가해 나갈 것이며, 중요한 것은 SPA로 구현된 모든 페이지가 SEO가 되어야 하는 것은 아닐 것이다.

따라서 SEO에 노출되어야 하는 전략적인 페이지들을 선별해서 서버랜더링 기술을 적용하면 될 것이다.


3. 보안문제
SPA의 보안문제로 자주 언급되는 것이 사용자 정보가, 기존 서버기반 세션이 아닌 클라이언트 기반 쿠키라는 것이다. 

그런데 세션은 쿠키 아닌가? 세선도 클라이언트에는 쿠키형태로 저장되고 모든 요청의 헤더에 그 값이 전달된다. 단지 쿠키와 다른점은 서버측에도 클라이언트 쿠키와 매핑되는 세션정보가 저장되어 있다는 것만 다를 뿐 이다.

보안관점에서 보면 쿠키의 가장 큰 문제는 '도용'이다. 쿠키 정보의 기밀성이나 변조는 쉽게 방어할 수 있지만 누군가의 쿠키를 그대로 복사해서 재사용하는 것은 조금더 높은 방어기술을 요구한다.

그런데 이런 쿠키도용은 서버세션이라는 시나리오에서도 동일하게 적용된다. 물론 서버측에 세션만료시간내에 도용해야 한다는 제약이 존재하지만, 요즘 쿠키는 대부분 브라우저 쿠키로 영구적으로 저장하지 않으니 별반 차이가 없다고 보는 것이 맞다.

따라서 사용자 정보저장이라는 측면에서는 SPA의 쿠키나, 기존 서버랜더링 방식의 세션이나 별반 다를 것이 없다. 그리고 요즘 왠만한데는 쿠키 잘 쓰지도 않는다.

SPA의 보안이라는 측면에서 더욱 심각한 것은 핵심로직이 자바스크립트로 구현된다는 점이다.

기존에는 대부분의 비즈니스 로직이 서버에서 수행되어 최종 결과만을 (HTML 덩어리로) 전달받았을 뿐인데, SPA에서는 필요한 데이터만 전달받고 많은 비즈니스 기능을 클라이언트에서 수행하기 때문에 핵심 로직이 노출될 수 있다는 점이 문제라면 문제일 것이다.

따라서 SPA 보안문제를 언급하려면 이 관점에서 풀어나가야 한다.

이것은 별다른 방법이 없다.
핵심로직은 서버에서 수행하도록 하고 중요한 유효성 검사는 양측 모두에서 수행하도록 해야 한다.

유효성 검사의 양측 모두 구현은, 굳이 SPA가 아니더라도 기존방식에서도 그렇게 해 왔었고 해야 되는 것이었다. SPA라서 더욱 신경써야 할 포인트는 바로 클라이언트에서 수행되는 핵심로직을 최소화시키는 것이다.

자바스크립트 난독화만으로 해결될 문제가 아니기에 설계시 고민해야 하는 부분이다.
실제로 게임 어플리케이션을 만들 때 이런 고민을 한다.


4. IE 8 이하 지원
SPA가 비단 Angular, ReactJS로만 만들 수 있는 것은 아니지만, 진정한 SPA 다운 결과물을 만들기 위해서는 이런 프레임워크의 도움이 절실하다. 
그리고 이런 최신의 자바스크립트 프레임워크들은 IE8을 지원대상에서 제외하고 있는 추세이다.
따라서 SPA를 진정 원한다면 IE8 이하를 과감히 버리는 것을 고려해야 한다.

그렇게 하지 못한다면, IE8용 대안을 별도로 마련해야 하는데 대국민 서비스에 규모가 큰 조직이라면 해 볼만 하다. 그러나 서비스 특징과 비용 효율 측면을 따져보고 결정할 일이다.

-----------------------------------------------------------------

하나를 얻으면 하나를 잃게 되는 것이 세상사가 아닌가 한다.

SPA로 얻는 가치가 있다면 SPA로 잃는 가치도 있을 것이다. 그런데 SPA에서 언급되는 저러한 단점들이 과연 단점이라 할 수 있는지 의문이 든다. 

심지어 SPA의 특징으로 인해 부각되는 몇 가지 문제상황들은 대안 기술로 해결될 수 있는 부분이 많다.

결론을 내리자.
SPA 자체를 보지 말고, 현재 수행하는 프로젝트의 특성을 먼저 살펴보기 바란다.
지금 개발하려는 애플리케이션이 SPA의 사상과 일치하는지 말이다.

당신의 프로젝트에 SPA를 적용하지 않는다고 해서 SPA가 서운해 하거나 하지는 않을 것이다.



Tags Spa
  1. Myeongwon Choi

    제가 궁금했던 부분을 딱 짚어서 설명해주셨네요. 좋은 글 감사합니다.

submit

[Webpack] 비동기 번들 로딩

Posted in 모바일/Javascript // Posted at 2017. 1. 14. 12:09

Webpack을 사용한 비동기 번들 로딩.

관심사의 분리/분할과 정복 등의 기본 원리를 바탕으로 잘 나눠진 모듈로 분리된 자바스크립트 파일을 만들고..

배포할때는 웹팩으로 단 하나의 번들 파일로 배포해서 사용하는 좋은 시나리오에서...

어떤 경우에는 이런 방식이 부담되기도 하는데, 예를 들어 (필요는 하지만) 굳이 미리 다운로드 받지 않아도 되는 즉 필요할 때만 다운로드 받게 하고 싶은 경우가 있다.

이때 사용할 수 있는 것이 비동기 번들 로딩

내부적으로 번들파일이 나눠지고 해당 스크립트를 사용하게 되면 그때 관련된 번들파일이 다운로드 되게해서 초기 로딩 속도를 향상시키고 사용자의 행동에 따라 추가 스크립트를 제공해 주는 Lazy Loading 기법이라 할 수 있다.

* 비동기 번들 로딩 구현

1) 먼저 필요한 것들 설치
- webpack 환경(npm, webpack, babel-load, babel-core 등등 필요한 것)


2) webpack 설정파일(옵션)

module.exports = {

  entry: './src/index.js',

  output: {

    path: './public',

    filename: 'bundle.js'

  },

  module: {

    loaders: [

      {

        test: /\.jsx?$/,

        exclude: /(node_modules|bower_components)/,

        loader: 'babel-loader',

        query: {

          presets: ['es2015']

        }

      }

    ]

  }

};

3) 스크리트 작성 및 html 작성

//index.js
document.querySelector('button')  

  .addEventListener('click', () => {

    require.ensure([], function (ev) {

      var asyncModule = require('./asyncModule'); //비동기 로딩 스크립트가 다운로드 되는 시점

      asyncModule.showModal();

    });

}, false);


//asyncModule.js (비동기 로딩 대상 스크립트)

module.exports = {  

  showModal: () => {

    alert('load asyncModule.js');

  }

}

//index.html

<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8">

</head>

<body>

    <h1> AsyncModle Loding Demo </h1>

    <button>async load</button>

    <script src="/public/bundle.js"></script>

</body>

</html>

4) 빌드
웹펙으로 빌드하면 다음과 같이 두 개의 번들 파일이 생성됨


브라우저에서 실행을 해 보면, 처음에는 index.html과 bundle.js 파일만 다운로드 받고, 버튼을 클릭하면 그때 1.bundle.js 파일을 다운받게 된다

처음 로딩 시


버튼 클릭 후

이제 중요한 것은 모듈을 어떻게 나누고, 비동기 로딩의 대상과 시점을 어떻게 하느냐.. 하는 전략.

샘플 수행의 거의 모든 소스는 다음 사이트를 참조함
(내 환경에서 버그가 나서 아주 미미한 수정을 가했으며 문구도 내 입맛에 맞게 맘대로 바꿈 ^^;)
=> http://jilles.me/webpack-async-bundle-loading/


Tags webpack

submit

Webpack 제공 기능 정리.

자바스크립트 개발과 관리...

대규모 복잡한 자바스크립트 개발 환경에서는 무지 편해지고 추가 이득이 수루룩... 

But, 소규모 단순한 자바스크립트 개발에서는 괜한 복잡성 증가...

삽으로 파야할 땅인지 포크레인으로 파야할 땅인지 부터 보고 결정.

요즘 대부분 포크레인이 요구되기는 함.




Tags webpack

submit

[Angular2] Angular2 선택을 위한 명분

Posted in 모바일/Javascript // Posted at 2016. 12. 19. 11:17

조만간 Front-end 개발 프레임워크를 선정해야 될 지도 모르겠다.

몇 년 전부터 AngularJS가 핫 트랜드로 떠오르면서, 진보적 프로젝트에서 많이 도입되어 왔다.

지금의 선택지는 AngularJS 버전 2의 릴리즈로 하나 더 늘어난 셈이다.

우리의 프로젝트에 AngularJS 버전 2를 도입을 고려한다면 다음과 같은 품질속성 관점의 접근이 일종의 명분이 될 수 있을 것이다.




성능

Angular2에서 성능 관점의 어프로치는 크게 두 가지로 속도와 용량부분이다.

AoT 컴파일(ahead of time compilation)
요즘 AoT 컴파일이 성능향상의 주요 컨셉으로 도입되는 추세다. 얼마전 안드로이드에서도 이와 유사한 컨셉이 도입되어 앱의 실행 성능을 향상시켜 왔는데, Angular2에서도 도입되었다.
AoT는 사전에 미리 컴파일 해 둔다는 개념으로, 기존 AngualrJS의 ng-** 따위의 해석을 위한 런타임의 컴파일 과정을 미리 해 둬서 실행 속도를 향상시키는 기법이다.

또한 이러한 AoT컴파일 덕분에 런타임시 필요했던 JIT(just-in-time compiler)를 더 이상 적재하지 않아도 되기 때문에 용량부분에서도 이점을 가져다 준다.(JIT 컴파일러는 기존 AngularJS 라이브러리 용량의 50%가까이 차지하던 녀석이다)

Lazy Loading
지연(Lazy) 바인딩, 지연 로딩 등의 개념도 다른 많은 언어들에서 차용하고 있는 최적화 기법이다.
지연(Lazy)이라는 개념은 최대한 필요한 시점까지 지연시킨다는 개념으로 불필요한 리소스 낭비를 막자는 컨셉이다. Angular2의 지연 로딩은 어플리케이션 실행 시점에 모든 모듈을 로딩하지 않고 현재 페이지에 실제로 필요한 모듈만 로딩함으로써 최적화를 시키는 기법이다. 역시 모든 내용을 처음부터 로딩하지 않게 함으로써 속도와 불필요한 리소스 낭비를 막을 수 있게 된다.

Digest Loop로 인한 성능저하 제거
이전 버전의 AngularJS에서 대표적으로 성능 문제로 지적되었던 Digest Loop로 인한 성능저하가 AngularJS에서는 더 이상 발생하지 않는다. 

코드 최적화
Angular2 자체의 코드 최적화도 수행되어 50KB 정도의 용량 축소가 되었다고 한다.


생산성

컴포넌트 중심 개발

기존 AngularJS는 컨트롤러 중심으로 개발이 진해되었던 것에 반해 Angular2에서는 컴포넌트 중심으로 개발이 진행된다. 오래된 SW 공학 예기지만, CBD(Component Based Developement)의 생산성 향상을 꾀할 수 있을 것이다. 물론 컴포넌트 설계가 잘 되었다는 가정하에..

TypeScript
AngularJS2에서는 MS(Microsoft)에서 개발한 자바스크립트를 위한 타입 명시적 스크립트 언어인 TypeScript를 주력 언어로 채택했다. TypeScript는 자바스크립트의 슈퍼 셋(Super Set)으로 자바스크립트의 문법을 그대로 이용 가능하며 명시적 타입 지정이 가능하도록 하여 타입 안정성을 향상시키고 ECMA Script 버전 7까지의 표준 스크립트 문법을 지원한다.

개인적으로 MS가 모바일 시대에 미미하게나마(?) 선전한 걸작으로 평가하고 싶다.
TypeScript로 개발하면 타입 안정적인 상황에서 객체 지향적 프로그래밍이 가능하고 원하는 버전의 자바스크립트 버전으로 변환이 가능해 생산성 향상을 꾀할 수 있다.

Learning Curve
생산성 향상은 마치 양날의 검과 같다. 컴포넌트 중심 개발, TypeScript라는 새로은 언어 등이 무조건 생산성 향상을 가져다 주지는 않는다. 컴포넌트는 해당 프로젝트와 도메인에 맞도록 컴포넌트 단위가 잘 분리되고 조립되어야 하며 TypeScript 역시 자바스크립트 기반이라고는 하지만 적절한 러닝커브가 존재한다. 즉 초기에 약간의 투자를 한다면 점차 그 혜택은 커질 것이다.


Mobile First
Angular2는 모바일 환경을 목표로 만들어진 고성능 프레임워크를 표방한다.
앞서 살펴본, 속도와 용량 최적화는 모바일 환경에서 보다 중요한 특성으로 어필될 것이며 생산성은 대규모 프로젝트에 많은 이점을 가져다 줄 것이다.


Tags Angular2

submit