차세대 웹 개발 FAQ

웹 표준 개발 관련 질문과 답변을 확인 하실 수 있습니다.

전체 43건 (1페이지/5페이지)

  • Q

    [고급] Node.js의 스트림은 어떻게 구현하나요?

  • A

    Node.js에는 네 가지 기초 스트림 타입이 있습니다.


    모든 스트림은 EventEmitter의 인스턴스 입니다. 데이터를 읽거나 쓸 때 사용할 이벤트를 방출(emit) 합니다.



    용어 설명
    용어 설명
    읽기 가능한(readable) 스트림 소비할수 있는 데이터를 추상화한 것입니다.
    ex) fs.createReadStream 메소드
    쓰기 가능한 (writable) 스트림 데이터를 기록할수 있는 종착점을 추상화한 것입니다.
    ex) fs.createWriteStream 메소드
    듀플렉스(duplex) 스트림 읽기/쓰기 모두 가능한 스트림입니다.
    ex) TCP 소켓
    트랜스폼(transform) 스트림 기본적으로 듀플렉스 스트림이며 데이터를 읽거나 기록할 때 수정이나 변환될 수 있는 데이터입니다.
    ex) zlib.createGzip 스트림

    스트림 구현체들은 대게 stream 모듈을 require 합니다.




    ∎ 쓰기 스트림 만들기


    쓰기 가능한 스트림을 만들기 위해서는 스트림 모듈의 Writable 생성자로 객체를 생성합니다.


    필수 옵션은 앞으로 기록될 데이터 청크(chunk)를 보내기 위한 write 함수 입니다.



    첨부이미지



    write 함수는 세 개의 인자가 필요합니다.



    1. 스트림을 다르게 설정하지 않는다면 chunk는 보통 버퍼입니다.


    2. 위에서는 encoding 인자를 썼지만 보통은 무시할 수 있습니다.


    3. callback은 데이터 청크를 처리한 뒤에 호출되는 함수 이며 쓰기 성공 여부를 알리는 신호입니다. 실패를 알리려면 에러 객체와 함께 콜백을 호출하면 됩니다.



    이 스트림을 소비하려면 읽기 스트림인 process.stdin을 outStream으로 연결하면 됩니다.


    위 코드를 실행하면 process.stdin으로 입력한 것은 outStream과 console.log를 이용해 에코되어 나올 것입니다.




    ∎ 읽기 스트림 만들기


    읽기 가능한 스트림을 만들기 위해서는 Readable 인터페이스가 필요하고 이것으로 객체를 만들어야 합니다.



    첨부이미지



    위 코드를 실행하면 inStream 으로부터 데이터를 읽을 수 있고 표준 출력으로 이것을 에코할 것입니다.



    하지만 읽기스트림은 기본적으로 process.stdout 하기 전에 스트림에 있는 모든 데이터를 푸시해 버립니다. 따라서 효율성을 위해 소비자의 요청이 있을 때만 (on demand) 데이터를 푸시하는 방법이 있습니다.


    아래와 같이 읽기 스트림 설정에서 read() 메소드를 구현하면 됩니다.



    첨부이미지



    읽기 스트림을 읽는 동안 read 메소드는 계속 실행되고 더 많은 문자를 푸시할 것입니다.


    위 예제 사이클은 if 문의 currentCharCode가 90("Z")보다 클 때 null을 푸시하면서 종료됩니다.






    위 예제는 (https://jeonghwan-kim.github.io/node/2017/08/12/node-stream-you-need-to-know-3.html)에서 확인할 수 있습니다.

  • Q

    [중급] Node.js의 event는 어떻게 사용하나요?

  • A

    node.js 는 이벤트 기반 비동기 방식의 서버프레임워크 입니다.


    대부분의 이벤트를 비동기 방식으로 처리하며 비동기 방식으로 이벤트를 전달합니다.


    이벤트는 한쪽에서 다른 쪽으로 알림 메시지를 보내는 것과 비슷합니다.



    ∎ 기본객체


    용어 설명
    용어 설명
    EventEmitter 이벤트를 사용하기 위해서는 이 객체를 재정의해서 on()과 emit() 메소드를 사용할 수 있습니다.
    on( ) 이벤트가 전달될 객체에 이벤트 리스너를 설정하는 역할을 하는데 이 리스너 함수는 객체로 전달된 이벤트를 받아 처리할 수 있습니다.
    emit( ) 이벤트를 발생시키는 함수입니다.
    once( ) 지정한 이벤트의 리스너를 추가하지만 한 번 실행한 후에는 자동으로 리스너를 제거합니다.
    removeListener( ) 지정한 이벤트에 대한 리스너를 제거합니다.


    ∎ 이벤트를 가진 객체 만들기


    node.js 에서 이벤트는 events라는 내장모듈에 정의 되어 있습니다.


    아래 예제에서는 events 모듈을 재정의 해서 새로운 객체를 생성한 후 사용해 보겠습니다.


    먼저 custom_event.js 파일을 생성하고 아래와 같이 입력합니다.



    •custom_event.js



    node custom_event 를 실행하면 아래와 같이 출력되는 것을 확인할 수 있습니다.


    첨부이미지

    첨부이미지

    // 1. 이벤트가 정의되 있는 events 모듈 생성. 이전 버전의 process.EventEmitter()는 deprecated! var EventEmitter = require('events'); //2. 생성된 이벤트 모듈을 사용하기 위해 custom_object로 초기화 var custom_object = new EventEmitter(); //3. events 모듈에 선언되어 있는 on() 함수를 재정의 하여 'call' 이벤트를 처리 custom_object.on('call', () => { }); console.log('called events!'); // 4. call 이벤트를 강제로 발생 custom_object.emit ('call');

    위의 예제에서는 단순하게 events 모듈을 그대로 사용해보았지만 객체지향에서처럼 EventEmitter 객체를 상속한 후 재정의 할 수도 있습니다.



    ∎ request 객체로 보는 이벤트처리


    아래는 http request 객체 로그의 일부 입니다.


    로그의 중간 부분에 보면 아래와 같이 _events 로 각각의 이벤트명이 정의되어 있습니다.


    request 객체는 이렇게 events 모듈을 재정의해서 구현되어 있기 때문에 우리가 단순하게 on('end') 형태로 이벤트를 호출만 해도 사용할 수 있는 것입니다.


    첨부이미지

    --- request 객체 로그 일부 --- ... _events : { end: [Object], finish: [Function: onSocketFinish], _socketEnd: [Function: onSocketEnd], drain: [Object], timeout: {function], close: [Object], data: [Function: socketOnData], resume: [Function onSocketResume], pause: [Function onSocketPause] }, ...




    이렇게 node.js 에서 event 처리는 events 모듈을 재정의 해서 만들어지게 되는데, 어떤 요청에 대해 event를 사용해서 비동기 처리를 하게되면, 단일요청에 대한 thread 대기시간이 없어지기 때문에 동기처리에 비해 프로세스를 좀 더 효율적으로 사용할 수 있습니다.


    단점으로 지적되는 비동기로 인한 callback 이벤트의 개수가 많아지면 로직상의 가독성이 떨어지는 면이 있지만, 그걸 감안하더라도 성능 면에서는 기존 multi-thread 동기 방식에 비해 진보된 형태의 서버 아키텍처라고 말할 수 있습니다.



  • Q

    [초급] Node.js의 특징 및 장•단점은 무엇인가요?

  • A

    ∎ Node.js 란?


    노드는 2009년에 등장한 js기반의 플랫폼으로 노드의 공식 사이트(http://www.nodejs.org/)에 따르면 노드는 "크롬의 자바스크립트 실행 환경에 기반을 둔 빠르고 확장성 있는 네트워크 애플리케이션을 만들기 위한 플랫폼"을 의미합니다.


    자바스크립트는 노드를 바탕으로 서버를 만들거나 웹크롤링을 가능할 수 있게 되면서 최근에는 노드를 기반으로한 자바스크립트의 웹개발이 증가되는 추세입니다.


    그렇다고해서 Node.js자체가 웹서버를 의미하는 것은 아닙니다. 웹서버를 만들 수 있는 하나의 수단이라고 생각하면 좋습니다.



    ∎ Node.js의 특징


    - 비동기 I/O 처리(Non-blocking)


    Node.js 라이브러리의 모든 API는 비동기식(async)입니다. 즉 한 메소드가 끝날 때까지 대기하는 것이 아니라 모든 메소드가 멈추지 않고 실행되게 됩니다.


    Node.js 기반 서버는 API가 실행되었을 때, 데이터를 반환할 때까지 기다리지 않고 다음 API 를 실행합니다.


    그리고 이전에 실행했던 API가 결과값을 반환할 때, Node.js의 이벤트 메커니즘을 통해 결과값을 받습니다.



    - 싱글 쓰레드 기반의 구조


    Node.js의 웹 서버는 내부적으로 이벤트 루프(Event Loop)라 불리는 컴포넌트를 가집니다.


    이벤트 루프는 싱글 스레드를 사용합니다. 이 이벤트 루프는 Node.js의 핵심적인 기능입니다.


    대략적으로 이벤트 루프는 이벤트 큐에 배치된 클라이언트의 요청을 확인합니다. 요청이 없다면 요청이 들어올 때까지 계속 대기하게 되고, 요청이 있다면 이벤트 큐에 배치된 클라이언트의 요청을 가져온 후 클라이언트의 요청을 처리하는 구조를 가지고 있습니다.


    이런 Node.js의 구조는 동시에 발생하는 클라이언트의 요청이 증가할 때 많은 쓰레드를 이용하지 않아 메모리 자원소모가 적습니다.



    ∎ Node.js의 장점


    1. 자바스크립트를 동일하게 사용해서 서버단 로직을 처리할 수 있다는 게 가장 큰 장점입니다. 새로운 언어를 습득하지 않고도 자바스크립트를 활용해 서버기술을 빨리 향상시킬 수 있습니다.


    2. 이벤트 기반 비동기방식이라 서버에 무리가 적습니다.


    3. npm(node package manager)을 통한 다양한 모듈(패키지)을 제공합니다. npm을 이용해 자신이 필요한 라이브러리와 패키지를 검색해서 설치하고 사용할 수 있기 때문에 효율성이 좋습니다.


    4. 구글이 만드는 JavaScript 엔진을 사용합니다. (구글은 V8 엔진 성능 업그레이드를 계속 하고 있습니다.)


    5. C++로 개발된 V8 JavaScript 엔진이기 때문에 확장성이 좋습니다.



    ∎ Node.js의 단점


    1. 이벤트 기반 비동기방식이라 서버 단 로직이 복잡한 경우 콜백함수의 늪에 빠질 수 있습니다. 예를 들어, 한 번의 요청에 대해 DB에서 조회한 결과값에 따라 다른 로직을 처리해야 하며, 이런 로직이 여러 개인 경우 콜백함수의 늪 (Callback Hell) 에 빠집니다.


    2. 단일 쓰레드(Single Thread)이기 때문에 하나의 작업 자체가 많이 걸리는 웹서비스에는 어울리지 않습니다. (게시판형태와 같이 가벼운 I/O가 많은 웹서비스에 어울립니다.)


    3. 코드가 수행되어야 코드에 에러가 있는지 알 수 있으며, 에러가 날 경우 프로세스가 내려가기 때문에 테스트가 매우 중요합니다. 반드시 모든 케이스에 대해 소스코드를 검증해야 합니다.


  • Q

    [고급] Angular의 Directive에는 어떤 것들이 있나요?

  • A

    ∎ Directive란?


    쉽게 말해 "AnglilarJS의 HTML Compiler에 의해 해석된 특정한 행위의 기능을 가진 DOM 엘리먼트"입니다.


    Directive를 이해하고 생성하기 앞서 사전지식으로 HTML Compiler에 대해 알아두어야할 필요가 있습니다.


    built-in된, 또는 사용자가 새롭게 생성한 사용자정의 Directive를 HTML에서 사용할 수 있는 이유는 AngularJS의 HTML Compiler가 HTML의 DOM을 돌면서 Directive 이름과 같은 DOM 엘리먼트를 찾아내기 때문입니다.


    • compile 단계 : HTML의 DOM 엘리먼트들을 돌면서 Directive를 찾는다. (attribute name, tag name, comments, classname을 이용하여 Directive를 매칭시킨다.) 결과로 linkfunction을 리턴한다.


    • link 단계 : Directive와 HTML이 상호작용(동적인 view) 할 수 있도록 Directive에 event listener를 등록하며 scope와 DOM 엘리먼트간에 2-way data binding을 위한 Swatch를 설정한다.


    위의 HTML Compiler의 두 단계를 거쳐 HTML에서 Directive를 사용할 수 있게 됩니다.


    Angular에는 다수의 내장 Directive가 존재하며 ‘ng’ 접두사를 사용합니다.



    용어 설명
    용어 설명
    Components Directives (컴포넌트 지시자) 컴포넌트의 selector 속성을 이용하여 컴포넌트 지시자로 사용합니다.
    Structural Directives (구조 지시자) 컴포넌트나 DOM을 추가/삭제하여 어떻게 화면에 나타내는지를 표현합니다.
    Attribute Directives (속성 지시자) DOM의 외형이나 동작을 변경합니다.
    Custom Directives (커스텀 지시자) 지시자를 추가할 때 지시자의 이름을 원하는 대로 지정할 수 있습니다.

    이중 가장 많이 사용하는 Structural Directives (구조 지시자)의 간단한 예제를 보겠습니다.


    다음 표에는 Structural Directives의 중요한 Directive가 나열되어 있습니다.



    Directive and Description

    Directive and Description ng-app : Auto bootstrap AngularJS application. ng-init : Initializes AngularJS variables ng-model : Binds HTML contol's value to a property on the $scope object. ng-controller : Attaches the controller of MVC to the view. ng-bind : Replaces the value of HTML control with the value of specified AngularJS expression. ng-repeat Repeats HTML template once per each item in the specified collection. ng-show : Display HTML element based on the value of the specified expression. ng-readonly Makes HTML elemnt read-only based on the value of the specified expression. ng-disbled : Set the disable attribute on the HTML elemnt if specified expression evaluates th true. ng-if : Removes or recreates HTML element based on ans expression. ng-click : Specifies custom behavior when an elemnt is clicked.

    • ng-app


    NgDirective

    위 예제에서 ‘ng-app’ 은 AngularJS 애플리케이션을 초기화합니다.


    즉, body 요소가 AngularJS 애플리케이션의 "소유자"임을 AngularJS에 알려줍니다.


    ‘ng-controller’ Directive를 사용하면 해당 요소의 $scope를 컨트롤러에 할당합니다.



    • ng-repeat


    NgDirective
    NgDirective

    위 예제에서는 ‘ng-repeat’ Directive를 사용하였습니다.


    ‘ng-repeat’는 컬렉션의 아이템마다 새로운 템플릿을 생성합니다. 예제에서는 4개의 아이템이 있으므로 ‘ng-repeat‘가 이 코드 부분을 4번 생성합니다.


    ‘ng-repeat’에서 각 복사본은 자신만의 $scope를 가집니다. 따라서 템플릿에서는 컨트롤러가 $scope의 역할을 하지 않고 이 예제에서는 ‘person’이 스코프가 됩니다.


    또한 ‘|’로 필터를 사용할 수 있는데, 이는 유닉스 환경에서 파이프를 사용하는 것과 비슷합니다.


    필터의 파라미터는 search객체에 바인딩 되어있고 입력의 이름을 찾아서 이름으로 필터링합니다.



    • ng-click


    NgDirective

    위 예제에서는 ‘ng-click‘ Directive를 사용하여 $scope에 함수를 바인딩 합니다.


    또한 해당 요소를 클릭할 수 있게 만들어서 클릭할 때마다 할당한 함수를 실행하는데 예제에서는 greet()를 실행합니다.


  • Q

    [중급] Angular의 모듈

  • A

    ∎ NgModule 메타데이터



    NgModule은 @NgModule()로 수식되어진 클래스로 정의됩니다.


    @NgModules 데코레이터는 프로퍼티가 모듈을 설명하는 하나의 메타데이터 객체를 입력받는 함수입니다.


    이 메타데이터 객체의 중요한 프로퍼티는 다음과 같은 것들이 있습니다.





    import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; @NgModule({ imports:[BrowserModule], providers:[Logger], declarations:[AppComponent], exports:[AppComponent], //최상위 NgModule은 굳이 exports를 할 필요 없습니다. //(다른 NgModule에서 참조 할 일이 없기 때문) //여기서는 exports의 사용법을 보여주기 위하여 추가했습니다. bootstrap:[AppComponent], }) export class AppModule { }


    최상위 NgModule의 예시입니다.


    imports : 현 NgModule에 정의된 컴포넌트 템플릿이 참조하는 클래스를 export하는 다른모듈들


    providers: 현 NgModule이 영향을 미치는 서비스들의 생성자(프로바이더)


    declarations: 현 NgModule에 속하는 컴포넌트, 디렉티브, pipe


    exports : 다른 NgModule의 템플릿에서 보여질 수 있으며 사용가능한 정의들의 부분집합


    bootstrap: 다른 모든 애플리케이션 뷰를 호출하는 최상위(root) 컴포넌트를 지정합니다.


    그렇기에 bootstrap 프로퍼티는 최상위 NgModule만이 가질 수 있습니다.




    ∎ NgModule과 컴포넌트



    NgModules은 컴포넌트들에게 컴파일 컨텍스트를 제공합니다.


    최상위 NgModule은 항상 부트스트랩시 생성되는 하나의 컴포넌트만을 가지지만, 다른 NgModule은 라우터를 통해 로드되거나 템플릿을 통해 생성되는 다수의 컴포넌트를 가질 수 있습니다.


    특정 NgModule에 속하는 컴포넌트들은 동일한 컴파일 컨텍스트를 가집니다.



    NgModule

    NgModule A 는 Root CompA 에서 A1, A2, A3 와 같은 동일한 컴파일 컨텍스틀 가집니다. NgModule B 는 Root CompA 에서 B1, B2, B3 와 같은 동일한 컴파일 컨텍스틀 가집니다.


    컴포넌트와 이 컴포넌트의 템플릿은 함께 뷰를 정의합니다.


    컴포넌트는 또한 뷰 계층을 구성할 수 있는데, 이 뷰 계층은 유닛으로써 생성, 수정, 삭제될 수 있는 복잡한 스크린의 일부를 정의합니다.


    뷰 계층은 각자 다른 NgModules에 속하는 컴포넌트에 정의된 뷰들을 혼합할 수 있습니다.



    NgModule

    트리 구조 형태의 1차 계층인 Host View CompA 에는 Embeded view A1, Embeded view A2, Embeded view B3 의 2차 계층이 포함되며 2차 계층의 Embeded view A1에는 Embeded view B1, Embeded view B2, Embeded view A3 3차 계층을 포함한 형태로 컴포넌트들이 연결 됩니다.


    컴포넌트를 생성하면 "호스트 뷰(host view)"라는 단일 뷰에 연결됩니다.


    호스트 뷰는 뷰 계층의 최상위 뷰라고 할 수 있는데, 이 호스트 뷰는 다른 하위 컴포넌트들의 호스튜 뷰가 될 수 있는 "종속 뷰(embedded view)"를 포함 할 수도 있습니다.


    이 컴포넌트들은 동일 NgModule내에 존재해도 되며, 다른 NgModules로부터 참조되어도 됩니다.


    트리 내의 뷰는 어떠한 깊이(depth)로도 중첩될 수 있습니다.




    ∎ 자주 사용하는 NgModule



    Angular 애플리케이션에는 최상위 모듈이 반드시 존재하기 때문에, 모든 Angular 애플리케이션은 모듈을 하나 이상 갖고 있다고 할 수 있습니다.


    그리고 개발을 진행하면서 Angular 프레임워크가 제공하는 기능은 Angular 모듈을 불러와서 사용할 수 있으며, 이 때 다음과 같은 모듈을 자주 사용하게 될 것입니다.



    NgModule

    NgModuel 의 모듈 위치와 용도순으로 설명 합니다. BrowserModule 은 @angular/platform-browser 에 위치하며 브라우저에서 애플리케이션을 실행하는 합니다. CommonModule 은 @angular/common 에 위치하며 NgIf, NgFor 를 사용합니다. FormsModule 은 @angular/forms 에 위치하며 템플릿 기반 폼을 사용합니다.(NgModel 포함) ReactiveFormsModule 은 @angular/forms 에 위치하며 반응형 폼을 사용합니다. RouterModule 은 @angular/router 에 위치하며 RouterLink, .forRoot(), .forChild() 를 사용합니다. HttpClientModule 은 @angular/common/http 에 위치하며 서버와 HTTP 통신을 해야 할 때 사용합니다.



    ∎ Angular 라이브러리



    앵귤러는 여러 JavaScript 모듈의 묶음 형식으로 로드되며, 라이브러리 모듈의 묶음과 같다고 생각할 수 있습니다.


    각 앵귤러 라이브러리는 @angular 접두사로 명명됩니다.


    npm(node package manager)을 통해 설치할 수 있으며 JavaScript import 구문을 통해 이 앵귤러 프레임워크의 일부를 사용할 수 있습니다.


    예를 들어, @angular/core 라이브러리 내의 Component 데코레이터는 다음과 같이 참조하여 사용할 수 있습니다.


    NgModule

    import { Component } from '@angular/core';


    JavaScript import 구문을 사용하여 앵귤러 라이브러리로부터 NgModules을 참조할 수도 있습니다.


    예를 들어, 아래의 코드는 앵귤러 platform-browser 내의 BrowserModule NgModule을 참조하도록 해줍니다.


    NgModule

    import { BrowserModule } from '@angular/platform-browser';


    상단의 최상위 모듈 예시에서 애플리케이션 모듈은 BrowserModule 내의 객체들을 필요로 합니다.


    이 객체들에 접근하기 위해서 @NgModule 메타데이터 내의 imports 구문에 BrowserMoulde을 추가해줘야 합니다.


    NgModule

    imports: [ BrowserModule ],



  • Q

    [초급] Angular의 특징 및 장•단점은 무엇인가요?

  • A

    ∎ Angular 이란?


    Angular는 SPA(Single Page Application) 개발을 위한 구글의 오픈소스 자바스크립트 프레임워크입니다.


    웹 애플리케이션은 물론 모바일 웹, 네이티브 모바일과 데스크탑 애플리케이션까지 프론트엔드 개발에 필요한 대부분의 기능을 갖추고 있습니다.


    정적 타입을 제공하는 TypeScript를 주력 언어로 채택하여 대규모 애플리케이션 개발에 보다 적합한 환경을 제공합니다.



    ∎ Angular 특징


    1. 완전한 프레임 워크로, 프로젝트의 생성, 테스트, 빌드, 배포를 위한 모든 기능을 제공합니다.


    2. TypeScript를 사용합니다.


    3. Angular CLI를 제공하여 개발환경을 지원합니다. 파일 생성, 빌드, 패키징, 라이트 서버 기능 등 개발에 필요한 거의 모든 기능을 자체적으로 제공합니다.


    4. 모듈과 컴포넌트 기반으로 동작합니다.


    5. 대다수 기능의 라이브러리는 모두 포함시켜서 자체적으로 제공합니다.라우팅, HTTP, Form 등등)


    6. 단일 페이지 애플리케이션 (SPA, Single Page Application) 개발을 위한 프레임워크입니다. 다만, Server Side Rendering을 위한 기능을 구비하고 있습니다



    ∎ Angular 장점


    1. 컴포넌트 기반


    Angular를 이용한 프론트엔드 웹 개발은 Spring을 이용한 백엔드 개발과 유사합니다.


    DI(Dependency Injection)의 강력한 지원을 통해, 기능에 따라 코드를 분리하고, 재사용하는 것이 굉장히 쉬워집니다. 서버에 Ajax 요청을 하는 부분 및 기타 부분 담당하는 Service클래스와 HTML 컴포넌트를 담당하는 Component 클래스가 명확히 구분되고, 이로 인해 Service 클래스는 여러 Component 클래스에서 재사용이 가능합니다. 또한, 각각의 Component 클래스는 자신만의 HTML 컴포넌트에 집중할 수 있기 때문에 웹 화면을 구성하는 컴포넌트간 독립이 명확해 집니다.


    2. 웹페이지 속도


    Angular로 만든 SPA(Single Page Application)은 다른 페이지로의 전환 속도가 굉장히 빠릅니다. 일반적인 웹페이지는 링크를 클릭할 때마다 서버에 새로운 페이지를 요청하지만, Angular는 클라이언트 측에서 화면을 생성하고 필요한 데이터만 Ajax 요청을 통해 서버에서 내려받기 때문에 네트워크에 의한 딜레이가 적습니다.


    3. 프레임워크


    Angular는 프론트엔드 웹 개발을 위한 종합 프레임워크이므로 전체를 아우르는 구조를 제공합니다. 뷰에서 부터 테스트까지 많은 모듈을 가지고 있으며, 기본 제공되는 모듈이기 때문에 각 모듈의 정합성을 보장할 수 있고 자연스러운 데이터 연결이 보장됩니다.



    ∎ Angular 단점


    1. 학습분량


    Angular는 여러가지 언어를 제공하지만, 주력언어는 TypeScript입니다. 그러므로 대부분의 Angular 앱은 TypeScript로 쓰여있으며, 이를 활용하기 위해서는 Angular 개발자는 필히 TypeScript를 익힐 필요가 있습니다. 또한, TypeScript만 배우면 끝이 아니라, Angular가 지니고 있는 여러가지 개념들을 익혀야하고, 그 개념들이 어떻게 TypeScript로 표현되는지도 익혀야합니다.


    2. 초기 로딩속도


    Angular로 만든 SPA의 초기 로딩속도는 다소 느린편 입니다. 성능이 좋은 데스크탑이나 모바일에서는 큰 문제가 아니라고 생각할 수 있으나, 성능이 좋지 않은 모바일에서는 로딩시간이 1초 이상 걸리기도 하므로 생각보다 큰 문제입니다. 물론 초기화면이 로딩된 다음에 웹페이지 내에서의 이동은 위에서 말했듯이 매우 빠릅니다.


    3. 검색엔진 인덱싱


    Angular로 만든 SPA를 제대로 인덱싱하지 못하는 크롤러가 생각보다 많아서, 모든 검색엔진에 검색되게 하기 위해서는 다른 방법을 사용해야 합니다. SPA를 포기하고 서버측에서 렌더링 할 수 있게 해주는 Angular Universial을 사용하는 것도 방법 중 하나입니다. 하지만 이러한 방법을 사용하게 되면, Angular를 사용해서 얻는 이점이 적어질 수 있습니다.


  • Q

    [고급] Virtual DOM 이란 무엇인가요?

  • A

    ∎ DOM 이란?


    DOM은 Document Object Model의 약어입니다.


    즉, 객체로 문서 구조를 표현하는 방법으로 XML이나 HTML로 작성합니다.


    웹 브라우저는 DOM을 활용하여 객체에 자바스크립트와 CSS를 적용합니다.


    DOM은 트리 형태라 노드를 찾거나 수정하거나 제거하거나 원하는 곳에 삽입할 수 있습니다.



    ∎ Virtual DOM이란?


    Virtual DOM을 사용하면 실제 DOM에 접근하여 조작하는 대신, 이를 추상화한 자바스크립트 객체를 구성하여 사용합니다.


    마치 실제 DOM의 가벼운 사본과 비슷합니다. 리액트에서 데이터가 변하여 웹 브라우저에 실제 DOM을 업데이트할 때는 3가지 절차를 진행합니다.


    1. 데이터를 업데이트하면 전체 UI를 Virtual DOM 에 리렌더링합니다.


    2. 이전 Virtual DOM에 있던 내용과 현재 내용을 비교합니다.


    3. 바뀐 부분만 실제 DOM에 적용합니다.


    Virtual DOM

    이전 DOM 트리와 새로운 DOM 트리를 비교합니다.


    ∎ 참고사항


    Virtual DOM을 사용한다고 해서 사용하지 않을 때와 비교하여 무조건 빠른 것은 아닙니다.


    결국에는 적절한 곳에 사용해야 리액트가 지닌 진가를 비로소 발휘할 수 있습니다.


    리액트를 사용하지 않아도 코드 최적화를 열심히 하면 DOM 작업이 느려지는 문제를 개선할 수 있고, 또 작업이 매우 간단할 때는 오히려 리액트를 사용하지 않는 편이 더 나은 성능을 보이기도 합니다


    리액트와 Virtual DOM이 언제나 제공할 수 있는 것은 바로 업데이트 처리 간결성입니다. UI를 업데이트하는 과정에서 생기는 복잡함을 모두 해소하고, 더욱 쉽게 업데이트에 접근할 수 있습니다.


  • Q

    [중급] React JSX문법의 규칙에는 어떤 것들이 있나요?

  • A

    ∎ JSX의 정의


    JSX는 함수 호출과 객체 생성을 위한 문법적 편의를 제공하는 자바스크립트의 확장으로, 특히 React.createElement() 호출을 반복해야 하는 불편을 해소합니다. 템플릿 엔진이나 HTML처럼 보일 수도 있지만 그렇지 않습니다. JSX는 React 엘리먼트를 생성하면서 자바스크립트의 모든 기능을 쓸 수 있도록 도와줍니다.



    ∎ JSX문법의 규칙 7가지


    1. JSX에 표현식 포함하기


    2. 두 개 이상의 태그는 하나의 태그로 감싸야 합니다.


      - self closing tag


      - Fragment 사용방법


    3. Style 설정 방법


    4. Class 설정 방법


    5. JSX 주석처리


    6. return(<div></div>);은 가독성을 위해서 사용합니다.


    7. 컴포넌트 네이밍은 항상 대문자로 시작합니다.



    ① JSX에 표현식 포함하기


    Recat JSX

    import React from 'react'; function Test() { const name = "Hello React World'; return(<div>{name}</div>); }

    JSX 중괄호 안에는 유효한 Javascript 표현식을 넣을 수 있습니다


    Recat JSX

    import React from 'react'; const user = { firstName: 'bam', lastName: 'ahn' }; function formatName(user) { return user.firstName+''+user.lastName; } function Test() { return( <div>{formatName(user)}</div> ); }

    함수 호출 결과인 formatName(user)를 JSX 표현식에 넣을 수도 있습니다.


    -JSX를 if, for loop 안에 사용하고 반환할 수도 있습니다.



    ② 두 개 이상의 태그는 하나의 태그로 감싸야 합니다.


    Recat JSX

    import React, { Fragment } from 'react'; function Test() { return ( <Fragment> <p>Hello</p> <p>Bye</p> <br /> {/* self closing tag */} <input /> </Fragment> ); }

    [self closing tag] 태그는 꼭 닫혀져 있어야 합니다.


    - 두개 이상의 태그를 사용할 경우 하나의 태그로 감싸 져있지 않으면 오류가 발생되는데,


    이럴 때 Fragment를 사용하여 불필요한 div 코드를 방지할 수 있습니다.


    Recat JSX

    import React, { Fragment } from 'react'; function Test() { return ( <> <p>Hello</p> <p>Bye</p> <&br /> {/* self closing tag */} <input /> </> ); }

    [Fragment 사용방법] Fragment 를 더 짧게 쓰는 새로운 문법입니다.


    <></> 빈 태그



    ③ style 설정 방법


    - 객체를 생성한 후, 네이밍은 모두 CamelCase로 작성합니다.


    Recat JSX

    import React, { Fragment } from 'react'; const fontStyle = { backgroundColor: '#eee', fontSize: 20, } function Test() { return( <> <p style={fontStyle}>Hello</p> </> ); }



    ④ class 설정 방법


    Recat JSX

    import React, { Fragment } from 'react'; import './Test.css'; function Test() { return( <> <p className="font-style">Hello</p> </> ); } export default Test;



    ⑤ JSX 주석처리


    - 중괄호안에 기존 JS주석처리를 넣으면 됩니다.


    Recat JSX

    import React, { Fragment } from 'react'; import './Test.css'; function Test() { return( <> { /* JSX 주석 표기 방법 : 중괄호 사용 */ } <p className="font-style">Hello</p> </> ); } export default Test;



    ⑥ return(<div></div>); 은 가독성을 위해서 사용합니다.



    ⑦ 컴포넌트 네이밍은 항상 대문자로 시작합니다.


    - React는 소문자로 시작하는 컴포넌트를 DOM태그로 처리합니다


    예를 들어 <div />는 HTML div태그를 나타내지만,


    <Welcome />은 컴포넌트를 나타내며 범위 안에 Welcome이 있어야 합니다.


  • Q

    [초급] React를 사용하는 이유와 특징 및 장점은 무엇인가요?

  • A

    ∎ 리액트는 페이스 북에서 제공하는 프론트 엔드 라이브러리 입니다.


    페이스 북이 리 액트를 만들기 전에 이미 AngularJS, Backbone.js, Knockout.js, Ember.js 등의 수많은 프레임 워크가 존재했습니다.


    위 프레임 워크는 MVC 패턴 또는 MVVM (View Model) 등의 패턴으로 애플리케이션을 구조화하고 있습니다






    View에서 DataBinding and Commands를 통해 View Model 전달하고 이는 다시 View로 Send notifications을 전달하며, 그리고 View Model에서 ViewModel updates the model을 통해 Model 로 전달하고 이는 다시 View Model로 Send notifications을 전달하는 구조를 설명한 그립

    즉, 이벤트가 발생했을 때 모델 (Model)에서 데이터를 처리하여 그 정보를 바탕으로 화면을 담당하는 뷰 (View)를 변화시켜줍니다.


    이 과정은 간단해 보이지만, 애플리케이션 규모가 크면 상당히 복잡하고 성능도 떨어집니다. 여기서 페이스북 개발팀이 생각한 아이디어는, 데이터가 변할 때마다 어떤 변화를 줄지 고민하는 것이 아니라 “기존 뷰 (View)를 날려 버리고 Virtual DOM을 사용하여 처음부터 새로” 하는 방식으로 좀 더 빠른 속도로 뷰 (View)를 변경 해주게 됩니다.




    ∎ React의 장점


    • Component를 사용해서 효율적으로 재사용이 가능하고 유지보수가 용이


    - Component는 UI를 구성하는 개별적인 뷰 단위로 전체 앱은 각 Component들이 결합해서 만들어 지게 되는데 무엇보다 각 Component들은 앱의 다른 부분, 또는 다른 앱에서 쉽게 재사용이 가능합니다. Redux의 창시자이며, 현재는 Facebook React Core팀의 일원인 Dan Abramov는 React의 목표가 성능보다는 유지가능한 앱을 만드는 것에 있다고 설명합니다.



    • 생태계가 넓고, 다양한 라이브러리 사용 가능


    - 개발을 하다보면 막히는 부분, 오류가 있는 부분이 많은데 Vue에 비해 사용자가 많고, 역시 Facebook에서 만들었다보니 확실히 커뮤니티나 자료가 굉장히 방대합니다.



    • 리액트는 라이브러리이기 때문에 다른 프레임워크나 라이브러리와 혼용 가능


    - React는 다른 프레임워크나 라이브러리와 쉽게 함께 사용할 수 있고 이미 개발된 서비스에서도 일정 부분에서만 선택적으로 적용이 가능하여 단계적으로 React로의 변경이 가능합니다.



    • virtual DOM을 활용하여 빠른 렌더링이 가능


    - DOM은 브라우저가 화면을 그리기위한 정보를 담고있는 문서 객체입니다. JQuery처럼 실제 DOM을 변경할 경우, 변경할 부분이 일부분이더라도 DOM 전체를 다시 렌더링해야하고, 이는 성능 저하로 직결된다는 단점이 있습니다.



    • 단방향 데이터 바인딩을 통한 디버깅 용이, 다른 라이브러리에 비해 안정성이 높음


    - React 내에서의 데이터의 흐름은 부모(Parent)에서 자식(Child)으로 단방향적입니다. 그렇기 때문에 디버깅이 용이하며, 다른 라이브러리에 비해 안전성이 높습니다.



    • 리액트 네이티브를 활용하여 앱개발 가능


    - 리액트 네이티브는 네이트브 모바일 앱을 만들기 위한 프레임워크로서 리액트를 기반으로 개발되었습니다. 리액트 라이브러리가 웹 개발자나 하이브리드 앱 개발자에게 유용하고 관심을 끌게 하는 기술이라면, 리액트 네이티브는 모바일 개발자들이 몹시 주목할 기술입니다.




    ※ 리액트 네이티브 : 대다수의 모바일 앱은 하이브리드가 아닌 네이티브 앱 형식으로 개발이 되는데 여기서 일반적으로 안드로이드와 iOS에서 동시 작동하는 소스코드를 작성하기 위해서는 '웹뷰'를 이용해야만 했다. 그러나 웹뷰를 이용한 하이브리드 앱 기술은 기존의 네이티브 앱에서 지원하는 속성을 이해하지 못했는데 리액트 네이티브 활용으로 네이티브 속성을 그대로 이용하는 것이 가능해졌다.




    ∎ React의 특징


    • 자바스크립트 기반


    - 리액트는 자바스크립트 기반으로 별도의 프레임워크를 배울 필요가 없으며 자바스크립트를 그대로 활용하면 됩니다. 앵귤러(Angular)또는 뷰(Vue)처럼 다른 언어를 배울 필요가 없기 때문에 자바스크립트와 HTML을 조금 아는 정도로도 개발이 가능합니다.



    • 선언형


    - 사용자 인터페이스를 만들때 쉽고 간결하게 해줍니다. 애플리케이션 안에서 각각 상태에 따른 디자인 뷰와 연결된 데이터가 변경되면, 이에 맞는 컴포넌트들을 올바르게 랜더링해 화면 구성을 합니다. 이 처럼 선언형의 화면뷰는 예측 가능한 코드 및 쉬운 디버깅을 하게 합니다.



    • 가상 DOM (Virtual DOM)


    - DOM Tree와 같은 구조체를 Virtual DOM으로 가진다. 'diffing'알고리즘을 통해 문서의 변화를 확인, 'Recomfillation' 진행으로 부분 조작이 가능합니다. 무엇보다 DOM을 직접 조작하는 것이 아니라 In-memory의 가상 DOM을 조작하기 때문에 효율적이라고 빠릅니다.



    • 컴포넌트 (Components)


    - 요소라고 하는 컴포넌트 별로 나누어 개발이 가능하다. 또 이렇게 개발한 것을 다른 곳에 활용할 수도 있습니다. 또 자바스크립트와 JSX를 조금 사용할 줄 안다면 간단하게 구현이 가능한데 이 때문에 개발을 쉽게 하고 유지보수를 하는데도 큰 장점입니다. (*JSX란? 리액트로 HTML을 개발하는 방법, 매우 간단하며 쉽다.) 상태를 관리하는 컴포넌트들을 캡슐화해 빌드한 후 그 컴포넌트들을 복잡한 UI로 조합하여 구성이 가능한데, 컴포넌트 로직은 자바스크립트로 구성이 되어있어 애플리케이션을 통한 대량 데이터를 전송가능하게 하고 DOM의 외부상태를 쉽게 유지할 수 있습니다.



    • 단방향 데이터플로우


    - 데이터가 UI로 흐르는 구조이며, 데이터가 변했을때 UI가 업데이트 됩니다. 하지만 단방향이므로, UI쪽에서 데이터를 변화시키는 것은 불가능합니다. 즉 데이터가 변하게 되면 UI는 변화된 새로운 데이터와 함께 업데이트 됩니다. 앵귤러(Angular)와 비교하면 앵귤러의 경우는 양방향 데이터플로우이며, 이와는 반대로 데이터를 관리하는 컴포넌트가 있고 데이터를 UI컴포넌트에 전달하는 단순한 데이터 흐름으로 이해해 쉽고 편리하게 구현 가능합니다.



  • Q

    [고급] Vue.js의 동적 & 비동기 컴포넌트

  • A

    ∎ 동적 컴포넌트


    들어가기 앞서 아래 예제는 (https://jsfiddle.net/chrisvfritz/Lp20op9o/)에서 확인할 수 있습니다.


    소스코드

      <component v-bind:is="currentTabComponent"></component>

    위의 코드와 같이 is를 사용하여 동적으로 컴포넌트를 랜더링 할 수 있습니다.


    ①. Post 탭에서 Hipster lpusm 클릭

    /br>
    Vue 실습1

    Post 탭에서 Hipster lpusm 클릭 하는 실습1 화면 입니다.


    ②. Archive 탭으로 변경

    /br>
    Vue 실습2

    Archive 탭으로 변경 하는 실습2 화면 입니다.


    ③ Post 탭으로 이동 시 Hipster Ipsum 미노출

    /br>
    Vue 실습3

    Post 탭으로 이동 시 Hipster Ipsum 미노출된는 실습3 화면 입니다.


    is를 사용한 동적 컴포넌트 랜더링을 사용하여 위의 그림와 같이 탭 뷰를 만들 수 있습니다. 하지만 탭을 이동 할 때마다, 새로운 컴포넌트가 그려지기 때문에, 이전의 tab의 상태를 기억하지 못합니다. 위의 예제에서는 Posts 탭에서 Hipster Ipsum을 클릭 했지만, Archive 탭으로 변경하고 다시 Posts 탭으로 돌아오면 이전에 클릭했던 Hipster Ipsum이 보이는 상태가 아니게 됩니다. 탭을 변경 할 때, 이전 탭의 상태를 유지하는 것이 성능 상 좋을 수 있습니다.


    소스코드

      <!-- Inactive components will be cached! -->


      <keep-alive><component v-bind:is="currentTabComponent"></component>


    위의 코드와 같이 <keep-alive>를 사용하면 인스턴스를 캐시로 저장 할 수 있습니다. <keep-alive>를 사용하면 생성된 탭의 인스턴스를 캐시에 저장 하고 있기 때문에, 탭을 변경 후 돌아 왔을 때 탭을 새로 그리지 않고 이전 탭을 보이게 됩니다.



    ①. Post 탭에서 Hipster lpusm 클릭

    /br>
    Vue 실습4

    Post 탭에서 Hipster lpusm 클릭하는 실습4 화면 입니다.


    ②. Archive 탭으로 변경

    /br>
    Vue 실습5

    Archive 탭으로 변경하는 실습5 화면 입니다.


    ③ Post 탭으로 이동 시 Hipster Ipsum 미노출

    /br>
    Vue 실습6

    Post 탭으로 이동 시 Hipster Ipsum 미노출되는 실습6 화면 입니다.


    위의 그림과 같이 Posts 탭에서 Hipster Ipsum을 클릭한 후 Archive 탭을 클릭하고 Posts 탭으로 돌아온 경우 Posts 탭을 캐시에 저장하고 있기 때문에 다시 돌아왔을 때, 이전에 클릭한 Hipster Ipsum이 보이게 됩니다.



    ∎비동기 컴포넌트


    어플리케이션이 커지면, 작은 부분으로 나누고 필요할 때에 가져와 사용하는 구조를 구현해야 할 때가 있습니다. 비동기 컴포넌트를 사용하여 필요할 때 비동기적으로 컴포넌트를 불러와 사용할 수 있습니다.


    소스코드

    Vue.component('async-example', function (resolve, reject) {


    setTimeout(function () {


    // Pass the component definition to the resolve callback


    resolve({


    template: '<div>I am async!</div>'


    })


    }, 1000)


    })



    위의 코드와 같이 팩토리 함수를 사용하여 비동기 컴포넌트를 구현 할 수 있습니다. 컴포넌트를 가져오는 것이 성공하면 resolve 콜백을 실행 해야 하고, 실패할 경우 reject 콜백을 실행해야 합니다. resolve와 reject의 인자는 컴포넌트를 생성 할 때의 옵션 값과 동일 합니다.



    소스코드

    Vue.component('async-webpack-example', function (resolve)


    { // This special require syntax will instruct Webpack to


    // automatically split your built code into bundles which


    // are loaded over Ajax requests.


    require(['./my-async-component'], resolve)


    })

    위의 코드와 같이 Webpack을 사용하여 다른 파일로 구분된 컴포넌트를 비동기 컴포넌트로 만들 수 있습니다.



    소스코드

    Vue.component(


    'async-webpack-example',


    // The `import` function returns a Promise.


    () => import('./my-async-component')


    )


    위의 코드와 같이 Webpack 2와 ES2015 문법을 사용하여 비동기 컴포넌트를 만들 수도 있습니다.



    소스코드

    new Vue({


    // ... components: {


    'my-component': () => import('./my-async-component')


    }


    })


    지역적으로 컴포넌트를 등록할때는 위의 코드와 같이 사용해야 합니다.



    ∎Handling Loading State


    2.3.0 이상의 Vue 버전에서 사용할 수 있는 기능입니다. 비동기 컴포넌트를 좀 더 간결하고, 직관적으로 사용할 수 있게 되었습니다.


    소스코드

    const AsyncComponent = () => ({


    // The component to load (should be a Promise)


    component: import('./MyComponent.vue'),


    // A component to use while the async component is loading


    loading: LoadingComponent,


    // A component to use if the load fails


    error: ErrorComponent,


    // Delay before showing the loading component. Default: 200ms.


    delay: 200,


    // The error component will be displayed if a timeout is


    // provided and exceeded. Default: Infinity.


    timeout: 3000


    })


    2.3.0 이상 부터 지원하는 간결한 비동기 컴포넌트 구현 방법