Angular - HiroSung/Study GitHub Wiki

Angular SPA (Single Page Application)

개요

  1. front-end
    • Angular, React, Vue.js 3파전.
  2. front-end의 history
    • 웹표준. 브라우저. Chrome. MVC pattern. 등
    • 완전히 거듭나고 있음. 개발자 영역으로 넘어옴.
    • 웹표준 : HTML5: W3C Recommendation (https://html.spec.whatwg.org/multipage/)
  3. Angular...
    • angular.io. 구글이 만듬
    • 2010년도 후반에 jquery의 모델과는 다른 mvc의 시작은 backbone.js 이다. (backbonejs.org). jQuery의 시작을 바꾼것.
    • 그 다음 embarjs
    • 그 다음으로 angularjs 나옴. Angular2와는 다름. 성능의 문제 발생.
    • React : F/B은 사용자를 50억명 기반으로 만들겠다는 범위로 설계함. 그래서 만든것은 react임. O2O는 react로 가고 있음. why? 개발자가 많음.
    • Vue.js : 중국人 만든언어. 개발자 관점에서 쉬움.
    • Angular는 TypeScript 이다.
    • 배울 내용 Web Application (Framework) HTML / CSS / Javascript EcmaScript6 / TypeScript / Node.js Angular CLI / NPM Angular 5.x (6.x)... 현재는 8.x : Components, Router, Service (Dependency Injection / Reactive Programming), Forms (Angular Form / Reactive Form)

시작하기.

사전지식

  • 웹의 발전. 2010년도 웹표준이 만들어진 시점.
  • 웹표준. W3C. HTML5/CSS3/EcmaScript5
  • Web Components : https://d2.naver.com/helloworld/188655, https://www.webcomponents.org/. 미래의 웹 환경을 바꿀것이라 예상. devide and concom. 화면을 분리하여 적용한다. (예. div 단위로 개발)
  • Angular에는 web components 개념이 적용되어 있음.
  • 웹 컴포넌트 : 웹 페이지를 특정 뷰 단위로 분리 가능하게 해 줌. Custom Elements, HTML Imports, Template, Shadow DOM
  • ECMA 스크립트에 대하여. (European Computer Manufacturers Association) 97년도에 중재를 시작함. ES5 완성. ES6 기능추가.
  • ECMAscript 2015, 2016 소개 : Modules, Classes, Arrow Functions(=>) 람다식 문법 지원, Let and Const 새로운 변수 선언 키워드, Default/Rest/Spread 함수파라미터 세 가지 새로운 기능.
  • Angular ES6를 그대로 사용하지 않음. but React는 그대로 사용해서 복잡.

개발환경

  • vscode, nodejs 설치

Javascript / ES6 / TypeScript

Javascript

  • javascript는 변수의 type을 알면 됨. (숫자, 문자, 배열, 함수, object)
  • 데이터는 object 단위로 전달됨.
// 변수의 3가지 Type
// 1. 숫자
var my_number = 3;
var my_number2 = 3.14;
console.log( typeof my_number);
console.log( typeof my_number2);

// 2. 스트링 타입
var my_string = 'Hello World';

console.log( my_string);
console.log( my_string.replace('World', 'EXO'));

// 3. Object 타입
// 3.1 Object 타입 세 가지
// 3.1.1 배열 array - 데이터를 다루기 위함.
var my_arry = [1, 2, 3, 4, 5];

// 3.1.2 함수
var my_function = function ( a, b) { // 함수 표현식 - 선언전 사용 불가. 명확하여 선호함.
    return a + b;
};

// function 없애고 =>  적고 body 작성 : ES6 에서 나온것. 람다식 문법
var my_function3 = (a, b) => {
    return a + b;
};

function my_function2 (a, b) { // 함수 선언식 - 선언전에 사용가능. hoisting 가능.
    return a + b;
}

console.log( my_function( 1, 2));

// 3.1.3 Object 객체
var my_object = { // {} 중괄호 사용
    title: '오늘은 교육중',
    author: 'DO',
    likes: 100,
    tags: ['javascript', 'angular', 'education'],
    replys: [
        { author: 'Lee', content: '너는 왜'},
        { author: 'Gowang', content: '너나 잘 하세요'}
    ] 
}; 

EM6

  • let, const 추가됨.
    • const 처음 정의된 값을 변경할 수 없음
    • 재할당이 필요한 변수는 let으로 정의.

TypeScript

  • Type을 가지고 있는 스크립트임.
    • number, string, boolean, array, function, object
  • 변수명: 타입명 = value
  • const 함수명 = function(변수:타입): 리턴타입 { ... };
// 데이터타입
// number, string, boolean, array, function, object
// - 변수명: 타입명

const my_number_ts: number = 3;

const my_string_ts: string = 'hello world';

const my_array_ts: Array<number> = [1, 2, 3, 4];
const my_array2_ts: Array<number> = [1, 2, 3, 'kim'];  // -> error

const my_object_ts: Object = {
    title: 'hello',
    author: 'kim'
}

const my_object2_ts: any = {
    title: 'hello',
    author: 'kim'
} 

const my_func = function(a: number, b: number): number {
    return a + b;
};
  • 코딩의 차이
    • 변수명을 이해할 수 있는 명칭으로 정의함. my_func_list... etc
    • stackoverfllow 많이 참조하였으면 함.
  • 배포환경과 개발환경이 상이해지고 있음.
  • 스캐폴딩 툴 : webpack 과 같은 툴로 통합되고 있음.

angular CLI 설치 : 설치되는 CLI 버젼을 체크해야 함.

  • 설치

npm install -g @angular/cli

  • cli project 생성 (현재 디렉토리)

ng new hello-angular routing - NO CSS - SCSS // 관련된 파일들이 생성됨.

 vscode에서 오픈폴더 - 만든 폴더 선택
    - node_modules : library
    - root : 설정파일
    - e2e : test 관련 파일
    - src : 개발과 관련된 파일

개발환경 (웹 서버가 필요한)

  • 개발환경 구성하기 위한 웹서버 구성.

ng serve --open

D:\hello-angular>ng serve
10% building 3/3 modules 0 activei 「wds」: Project is running at http://localhost:4200/webpack-dev-server/
i 「wds」: webpack output is served from /
i 「wds」: 404s will fallback to //index.html

chunk {main} main.js, main.js.map (main) 47.8 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 264 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.15 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 10 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 3.81 MB [initial] [rendered]
Date: 2020-01-20T05:56:17.394Z - Hash: 3a64ed6363a44f91c693 - Time: 5445ms
** Angular Live Development Server is listening on **localhost:4200**, open your browser on http://localhost:4200/ **
i 「wdm」: Compiled successfully.
  • chrome에서 http://localhost:4200 호출하면 페이지 조회됨.
  • 소스를 수정하면 바로바로 반영됨.
  • 배포는 별도로 있음.

컴포넌트

  • 세부적으로 구성하는 것이 좋음.
  • sample은 app 하나의 component 를 구성한것임. 컴포넌트 하나가 하나의 디렉토리이다 -- 그러면 중복되는 폴더가 많아지는데요?
  • 컴포넌트(화면)는 계층적이다. - 그래서 상단/메뉴/컨텐츠/바틈 으로 구성하더라도 root 의 컴포넌트가 필요하다. - root/ top/left/content/footer. 그래서 5개의 컴포넌트가 최소 필요. 로긴은 top에 속한 컴포넌트. - 구성하기 나름.
  • app/app.components. (아래의 3개의 파일이 하나의 set이 됨)
    • .html
    • .scss
    • .ts
  • app/app.module.ts : 하나의 application과 관련된 모듈. 여러개의 모듈로 만들면 raise loading 을 구성할 수 있음.
  • 대부분 소문자로 만듬.
  • 컴포넌트명.components. 로 생성됨.*

ng generate

  • 컴포넌트 추가 생성하기

ng generate component 이름

D:\hello-angular>ng g c header
CREATE src/app/header/header.component.html (21 bytes)
CREATE src/app/header/header.component.spec.ts (628 bytes)
CREATE src/app/header/header.component.ts (270 bytes)
CREATE src/app/header/header.component.scss (0 bytes)
UPDATE src/app/app.module.ts (396 bytes)
  • header.component.ts 파일이 중요함. 데이터가 위치하게 되는 파일. 클래스로 만들어지고 컴포넌트 이름을 카멜형태로 만들어짐.
import { Component, OnInit } from '@angular/core';

@Component({
  selector: **'app-header'**,  ==> **태그의 이름임**
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})
export class **HeaderComponent **implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}
  • app.component.html 안에
   추가
  • 이런 식으로 ... 진행합니다. 쉽다!
  • *.html 파일만 보더라도 어떠한 내용으로 구성되어 있는지 가독성이 있음.

demo

  • Front-end 개발은 종합적인 예술임.
  • 만들어진 화면을 angular로 바꾸는 작업을 하고자 함.
  • bootstrap : 디자인 적인 관점의 컴포넌트

Node.js & npm

Node.js

  • 2008년 chrome v8 발표. v8의 js 엔진이 200배 빨라짐에 따라 라이언달이 Node.js 발표.
  • node.js 는 javascript을 OS로 포팅한 것임.
  • node.js는 비동기식으로 동작하여 논블로킹I/O 처리.
  • javascript library를 모아둔 centeral repository.
  • 주로 이슈가 되는 javascript lib 찾아 볼 수 있음. 예) lodash. rxjs. ...
  • node.js 용 vs 브라우저용 js 또는 모두 지원하는 universal 라이브러리로 구분. rxjs는 모두 사용.
  • npm으로 설치되면 project root에 package.json 파일이 있음.
    • package.json 은 javascript 프로젝트의 메인설정파일임.
  • 설정파일...
    • .json 스타일로.
    • yaml : 최근에는 phthon의 문법을 사용하여 정의함. spring boot.

ECMAScript 6

script

  • 백틱이 생성됨('')
    • 스트링 이터폴레이션이 가능함. '내 나이는 ${this.age} 입니다'
  • 객체를 사용하는 경우 : 아래 예제 1번과 2번은 동일한 결과
  test(first: string, second:string): any {
    // 1번
    // const result = {
    //   first: first,
    //   second: second
    // }
    // return result;
    // 2번
    return {first, second};
  }
- 함수를 value로 가능 : age, age2는 같은 것임.
  post = {
    title: '아이유',
    author: 'IU',
    likes: 30, 
    age: function (a, b) {
      return a + b;
    }, 
    age2 (a, b) {
      return a+b;
    }

  }

객체 디스트럭처링

  test2(first: string, second:string):any {
    // 배열을 해체해서 담는 경우.
    const a = [1,2,3];
    const b = a[0];
    const c = a[1];
    const d = a[3];

    // 위의 코드를 아래와 같이 변경 가능
    const [e,f,g] = a;
  }

클래스 (3.9)

  • 데이터와 메소드로 이루어짐

프로미스

  • 자바스크립트는 비동기 처리를 위해 콜백 함수를 사용함.
  • 콜백 패턴은 가독성이 나쁘고 비동기 처리 중 발생한 에러의 예외처리가 곤란

모듈 (3.14)

Babel과 Webpack

Babel (babeljs.io)

  • 트랜스파일러

Webpack (webpack.js.org)

  • 모듈 번들러

TypeScript

  • TypeScript > ES6 > ES5
  • 데코레이터 형태(또는 어노테이션)으로 설정할 수 있음.

Angular의 파일구조와 처리 흐름

  • 폴더구조
  • main.ts
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) { // 개발/상용 구분 여부
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule) 
  .catch(err => console.error(err));
  • polyfills.ts
    • 크로스 브라우징을 위한 웹표준을 제공 임포트 역할.
  • app.module.ts
    • App에서 사용하는 콤포넌트 로딩 및 정의

컴포넌트

컴포넌트는 화면이다.

  • typescript는 데이터를 가지고 있으며, view페이지에서 {{ }} 형태는 데이터가 바인딩 되어 있는 것임.
  • 컴포넌트가 데이터를 주고 받는 방법.
  • 데이터바인딩을 템플릿팅이라 함.

바인딩

  • {{expression}}
  • [property]="expression"
  • (event)="handler"
  • [(ngModel)]="property"

1. 인터폴레이션

2. 프로퍼티 바인딩

<img [src]="imgSrc">
export class AppComponent {
  imgSrc = '/assets/IU.jpg'
}  

3. 이벤트 바인딩

<a (click)='btnSiginClicked()'>Sign In</a>
export class AppComponent {
  title = '환영합니다.'
  name = '어밴저스'
  age = 30
  myString = `Hello! ${this.name}.`

  btnSiginClicked() {
    this.myString = '아이유';
  }
}

4. 양방향 바인딩 (p.231)

  • 데이터가 바뀌어도 화면이 바뀌고 화면이 바뀌어도 데이터가 바뀌는 것.
  • FormsModule를 module.ts 파일에 추가해야 함.
import { FormsModule } from '@angular/forms';
@NgModule({
  imports: [
    FormsModule 
  ],
})
<input type='text' [(ngModel)]='initInputString'>
<span>{{initInputString}}</span>
export class AppComponent {
  initInputString = '이름을 입력하세요.'
}
  • input text에 값을 입력하면 span 안의 {{initInputString}} 값도 함께 변경됨.
  • 반복해서 보여지는 데이터
    • ngFor
    • ngIf

컴포넌트간 상태공유

  • 부모가 자식에게만 공유할 수 있음.
  • 할아버지가 자식에게 주려면, 할아버지 - 아버지 - 자식 에게 전달해야 함.
  • 자식은 부모에게만 전달할 수 있음.
  • Service 처리함

부모가 자식에게

  • 부모가 자식을 호출하는 html에 [자식이 받을 변수명]='부모 컴포넌트에 정의된 넘길 값'
<app-content [colors]='objFavoriteColors'></app-content>
  • 자식의 components.ts 파일에 정의함
export class ContentComponent implements OnInit {
  @Input()
  colors:any = {}
}

자식 데이터를 부모에게 (p.267)

Stateful 컴포넌트와 Stateless 컴포넌트

Stateful 컴포넌트

  • 데이터를 가지고 있는 컴포넌트
  • 그때 그때 다르다

Stateless 컴포넌트

  • 데이터를 가지고 있지 않는 컴포넌트

디렉티브 (지시자)

  • 재사용 컴포넌트. 애트리뷰트를 custom하게 만들어서 재사용 가능함.

디렉티브 종류

  • 어트립뷰트 디렉티브
  • 구조 디렉티브 : ngFor, ngIf 를 통해서 DOM 레이아웃 변경
  • 컴포넌트 디렉티브
D:\js-demo\MyStore>ng g directive textBlue
CREATE src/app/text-blue.directive.spec.ts (233 bytes)
CREATE src/app/text-blue.directive.ts (145 bytes)
UPDATE src/app/app.module.ts (897 bytes)
  • 아래와 같은 text-blue.directive.ts 파일 생성되고, app.module.ts 에 자동 추가됨.
import { Directive, ElementRef } from '@angular/core';

@Directive({
  selector: '[textBlue]'
})
export class TextBlueDirective {

  // 글자색을 파랑으로 변경
  constructor(el: ElementRef) { 
    el.nativeElement.style.color = 'blue';
  }
}
  • 템플릿에 아래와 같이 추가하면 조회시 파랑글이 조회됨
<p textBlue>textBlue directive</p>

파이프

데이터 자체를 변경하는 것은 부수 효과가 있으므로 화면에 표시하는 형식만 변경하고 싶을 때 사용하는 것이 파이프 이다.

빌트인 파이프

체이닝 파이프

  • 여러 개의 파이프를 조합하여 결과를 출력하는 것을 '체이닝 파이프' 라함.

커스텀 파이프

생명주기와 훅 메소드

생명주기

  • 컴포넌트와 디렉티브는 생명주기를 가지며, 생명주기 이름 앞에 ng가 붙은 생명주기 훅 메소드를 제공한다.
  • 라이프싸이클 함수 실행 순서
  • 자바스크립트는 On* : 이벤트와 관련된 콜백 함수인 경우가 대부분임

훅 메소드

  • 인터페이스의 형태로 제공됨.
  • cf) mutable & immutable (설명)

서비스

  • 컴포넌트는 화면을 구성하는 뷰를 생성하고 관리하는 것이 주된 역할.
  • 컴포넌트의 주요 관심사 이외의 부가적인 기능은 코드 중복되고 재사용성이 낮아지고 복잡도는 올라감.
  • 애플리케이션 전역의 관심사를 분리 하는 것이 필요. ==> 기능을 서비스로 분리 구성

의존성 주입

  • DI : 의존관계가 소스코드 내부가 아닌 외부의 설정에서 정의되게 하는 디자인 패턴 중의 하나.
  • 찾아볼까? google : dependency injection
  • 서비스 생성
    • article.service.ts 파일이 생성.
import { Injectable } from '@angular/core';

**@Injectable**({
  providedIn: 'root'
})
export class ArticleService{
  getArticles():Array<any> {
    return  [
        {title: 'Angular', content: 'Angular Study', author: 'lee', likes: 30},
        {title: 'Google', content: 'Google Cloud', author: 'gee', likes: 40},
        {title: 'Vue.js', content: 'Vue.js Study', author: 'yu', likes: 50},
        {title: 'Mom', content: 'Mom Study', author: 'lee', likes: 60},
        {title: 'Java8', content: 'java ramda Study', author: 'jee', likes: 70}
      ]  
  }
}
export class AppComponent implements OnInit {
  // 생성자 역할은 서비스 초기화
  constructor( private articleService: ArticleService) {
  }
}
<h1>책 목록</h1>

<ul>
  <li *ngFor='let article of objArticles'>
    {{article.title}} by {{article.author}}
  </li>

</ul>
  • 서브시 파일에 providedIn: 'root' 라는 정의는 angular6부터 생성됨.
    • 이전에는 app.module.ts 파일의 NgModule.providers 라는 부분에 정의해서 사용함.
    • 누락이 발생하여 서비스에 정의함.
    • root? 컴포넌트의 root. 화면의 root를 의미함.
    • 특정 컴포넌트로 제약할 수 있음.

인젝터 트리

프로바이더

서비스 중재자 패턴

  • 서비스를 컴포넌트 간 데이터 중재자로 사용하면 일정한 형식의 자료를 사용하여 컴포넌트 간의 상태 공유 가능.

리액티브 프로그래밍과 RxJS (p.400)

  • Reactive 프로그래밍 ... 예를 들어 설명하면...
    • 이터레이터 패턴 : 데이터 준비와 사용의 과정을 분리함. 데이터를 사용하는 과정에서 pull 하는 방법으로 사용.
    • 옵저버 패턴 : 데이터를 사용할때 push 하여 사용.
    • 옵저버 패턴을 계승한것임.
    • 데이터 전송시 끝났다라는 메시지도 함께 전송함.
    • 데이터를 전송하는 파트가 중심이 되어서 처리해야 함.
    • Rx (Reactive Extention) : ReactiveX
      • reactive 프로그램의 표준.
    • reactive-streams.org
      • java 9, spring 5
    • 데이터를 마블다이어그램 으로 시간의 흐름으로 처리한다. (마블 다이어그램을 통해 이 연산자들에 대해 설명)
  • reactive 방식으로 개발해야 함.
    • 생산자와 소비자로 분리
    • 데이터는 push 방식 (emit 방출한다)
    • 데이터 생산자 data emit 는 것을 provider or observer
    • 데이터 소비자 consumer
  • RxJS
    • observable / observer
  • subscriber

Cold Observer / Hot Observer

  • 대부분이 Cold Observer

오퍼레이터 (p.413)

  • 옵저버블을 생성, 변환, 필터링, 에러처리의 기능을 하는 함수.
  • 받을때 가공하면서 데이터를 받을 수 있음.
  • subscribe 메소드에 도달하기 전까지 체이닝을 통해 데이터를 전달할 수 있음.

HTTP통신

  • HttpClient
    • 웹표준은 fetch이지만 angular는 HttpClient 이다.
  • Angular4.3 이후에 추가됨.
  • 서비스형태. 주입받아 사용함.

HttpClientModule

  • 서비스 페이지에 아래 내용 추가
export class ArticleService{

  constructor( private http: HttpClient) {}

  fetchDataTest() {
    const html = this.http.get('http://www.google.com');
  }
...  
  • http 사용 방식
    • 동기식 : const html = this.http.get('http://www.google.com');
    • 비동기식 : 요청하고 응답하고 코드가 오는 동안 기다리지 않음. subscribe(콜백함수) .
  fetchDataTest() {
    this.http.get('https://api.github.com/')
      .subscribe(function(response) { // 응답이 오면 콜백되는 함수
        console.log(response);
      });
  }
// 사용할때
this.articleService.fetchDataTest();
    - 주소 : endpoint
    - 데이터 응답 스펙
  • Back-end는 endpoint와 data spec 을 정의하면됨.
    • endpoint는 API 주소
    • API 설명서가 필요하며 Front End는 Mock 서버를 통해서 테스트 할 수 있음.
    • 이런식의 Arch.를 SOA 라고도 함.
export class ArticleService{

  constructor( private http: HttpClient) {}

  fetchDataTest():Observable<any> {
    return this.http.get('https://api.github.com/users/HiroSung');
    
  }
...
// 사용할때
this.articleService.fetchDataTest()
    .subscribe(function(response) { // 응답이 오면 콜백되는 함수
      console.log(response);
    });
  • 또 다른 사용법
   this.articleService.fetchDataTest()
      .subscribe( res =>  { // 응답이 오면 콜백되는 함수
        console.log(res);
        this.gitInfo = res;
      });
  • Restful API 서비스
    • 서비스의 Format을 어떻게 가져갈 것인지 필요
    • API 요청 매뉴얼
      • 네이버 Developer
        • 네이버키 : clientID - 7Nfau_qhtlKWt9Duksod, Client Secret - S77xhQWZUl
        • -H: header에 설정할 정보
    • NewsAPI. API Key : 98180e15767742d79e166b95166dd7b6
curl "https://openapi.naver.com/v1/search/news.xml?query=%EC%A3%BC%EC%8B%9D&display=10&start=1&sort=sim" \
    -H "X-Naver-Client-Id: {애플리케이션 등록 시 발급받은 client id 값}" \
    -H "X-Naver-Client-Secret: {애플리케이션 등록 시 발급받은 client secret 값}" -v
    - 공공데이터포털 : https://www.data.go.kr/
    - 마블 : https://developer.marvel.com/docs#!/

HttpParams

  • URI : 파라미터가지 포함된 정보
  getNews():Observable<any> {
    const params = new HttpParams()
      .set('country', 'kr')
      .set('apiKey', '98180e15767742d79e166b95166dd7b6')
    return this.http.get('https://newsapi.org/v2/top-headlines', {params});

  }

HttpHeaders

  • DOM을 직접 handling 하도록 하였음.

템플릿 기반 폼

  • 폼에 직접 컨트롤

리액티브 기반 폰

  • FormBuilder를 생성자에 주입함.

라우팅과 네비게이션

  • angular가 제일 잘되어 있음
  • URL의 주소를 변경해 주는것.
  • SPA 에서 라우팅을 사용함.
  • 초기 로딩 속도가 중요함.
  • SEO 문제 : index는 데이터가 없기 때문에 검색엔진에서 검색이 안됨.

라우팅

  • Angular2 - 4(출발) - 5 - 6(쓸만함) - 8(안정화)
  • '#' 이후의 URI 는 Client side script 이다

라우트 가드

  • 보안에 적용 가능

참고

  1. [웹 프론트엔드 기술스택 선택] (https://ingeec.tistory.com/107)
  2. [Angular 저자 - 이웅모. 포이에마웹] (https://poiemaweb.com)
  3. Angular F/B 동호회 - 리쿠루팅.
  4. 사내포탈에서 사용할 수 있을지는 고민해야 함. Angular는 SPA 모듈이다.
  5. StackBlitz
  6. TypeScript. - "vue.js typescript", "angular typescript"
  7. Angular.kr 의 따라하기를 모두 해보기를 권장.

HuCloud 김순곤 강사. 1/20~22. 한국정보기술원.

⚠️ **GitHub.com Fallback** ⚠️