컴포넌트

lee jae hwan·2022년 8월 28일

앵귤러

목록 보기
12/83

컴포넌트 소개

컴포넌트는 앵귤러의 핵심 구성요소로서 앵귤러 어플리케이션은 컴포넌트를 중심으로 구성된다. CBD: Component Base Development

컴포넌트의 역활은 화면을 구성하는 뷰(View)를 생성하고 뷰에 보여지는 데이터를 관리한다.

앵귤러는 컴포넌트들을 조립하여 하나의 어플리케이션이 된다.


웹컴포넌트

웹어플리케이션(웹페이지)의 뷰는 내용(Conents)과 구조(Structure)를 담당하는 HTML과 스타일을 담당하는 CSS의 조합으로 구성되며 DOM과 이벤트를 담당하는 자바스크립트가 필요하다.


기존의 객체지향개발방식은 로직을 클래스단위로 부품화하였지만 웹어플리케이션의 뷰를 부품화하는 것은 적합하지 않다.

왜냐하면 HTML은 어느정도 템플릿을 이용해 부품화가 가능하지만 CSS는 상속과 캐스케이딩이 적용되어 다른 CSS룰셋에 영향을 받기 때문이다. 이 설명으로 충분한것 같지 않다....ㅠㅠ


뷰를 부품화하기 어렵기때문에 뷰를 소유한 컴포넌트의 부품화에대해 알아보자.

컴포넌트는 동작가능한 하나의 부품이다.

컴포넌트의 부품화를 위해서는 다른 컴포넌트의 간섭을 받지 않도록 독립된 스코프를 가져야 한다.

다시말해 컴포넌트내에서만 유효한 상태정보와 로직, 스타일을 소유한 완결된 뷰를 생성하는 것이 바로 컴포넌트다.


컴포넌트는 독립적이고 완결된 뷰를 생성하기위해 HTML, CSS, Javascript를 하나의 단위로 묶는것이며 W3C표준인 웹컴포넌트를 기반으로 한다.

웹컴포넌트는 재사용이 가능하도록 캡슐화된 컴스텀요소노드를 생성하는 웹플렛폼API의 집합이다.

웹컴포넌트가 제공해야하는 기능

  1. 컴포넌트의 뷰를 생성할 수 있어야 하며 (HTML Template)

  2. 외부로부터의 간섭을 제어하기위해 스코프를 분리하며 DOM을 캡슐화할 수 있어야 하며(Shadow DOM)

  3. 외부에서 컴포넌트를 호출할 수 있어야 하며 (HTML import)

  4. 컴포넌트를 명시적으로 호출하기 위한 명칭(Alias)을 선언하며 마치 네이티브 HTML요소와 같이 사용할 수 있어야 한다.(Custom Element).


컴포넌트 트리

어떠한 복잡한 화면이라도 컴포넌트 하나로 생성하고 관리할 수 있다.

하지만 재사용이 용이한 구조로 분할하여 작성하며 분할된 컴포넌트를 조립하여 화면을 구성하는 것이 효율적이다.

헤더(header), 사이드바(aside), 푸터(footer) 영역은 모든 화면에서 공통으로 사용되고 본문(section)만 변경될 가능성이 높다.

이러한 경우 컴포넌트를 분할하고 컴포넌트를 조립하여 화면을 구성하는 것은 재사용과 유지보수의 관점에서 매우 바람직하다.


앵귤러 어플리케이션은 분할된 컴포넌트들로 구성되기 때문에 컴포넌트 트리로 표현되는 상위-하위관계가 형성된다.

컴포넌트의 상하관계는 데이터와 이벤트가 왕래하는 상태정보 흐름의 통로가 되기때문에 중요한 의미를 갖는다.

따라서 설계단계에서 화면과 컴포넌트의 상하관계를 고려한 분할을 검토하는 것이 중요하다.


프로젝트생성후 src/app/app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'hello';
}

컴포넌트는 import영역과 @Component 데코레이터영역 , 클래스영역으로 구분할 수 있다.


import영역

컴포넌트에 필요한 의존모듈을 임포트한다. 앵귤러가 제공하는 라이브러리모듈의 경우 @가 붙으며 경로를 명시하지 않는다. 또한 npm으로 설치한 의존모듈도 명시하지 않는다. 이외 임포트하는 모듈은 경로를 명시한다.

@Component 데코레이터 영역

데코레이터에는 메타데이터객체를 인자로 전달한다.
메타데이터 객체는 컴포넌트생성에 필요한 정보(셀렉터, 템플릿, 스타일등)를 갖는다.

클래스영역

컴포넌트 뷰를 관리하기위한 로직을 담은 클래스를 정의한다.
컴포넌트 클래스는 뷰의 관리에 집중하며 어플리케이션의 공통관심사는 서비스로 분리하여야 한다.


<h1>
    Welcome to {{ title }}!
  </h1>

템플릿은 컴포넌트 뷰를 정의하기위해 HTML과 앵귤러고유의 템플릿문법(Template Syntax)으로 작성할 수 있다.

{{ title }}은 앵귤러 템플릿문법중의 하나인 문자열 인터폴레이션(String Interpolation)으로 클래스의 데이터를 템플릿에 바인딩한다.

클래스에는 title프로퍼티가 있고 템플릿에는 {{title}} 앵귤러템플릿문법이 있어서 클래스 프로퍼티와 템플릿 인터폴레이션은 앵귤러의 프로퍼티바인딩에 해당된다.


컴포넌트 생성

컴포넌트는 화면전환(라우팅)의 단위가 되기때문에 폴더로 구분하는 것이 바람직하다.

네이밍컨밴션은 유지보수와 가독성을 위해 매우 중요하다. 혼란을 방지하고 원하는 파일을 쉽게 찾기위해 네이밍 컨밴션은 일관성을 유지해야 한다.

예를 들어 할일관리 애플리케이션의 할일 리스트를 위한 컴포넌트를 생성하는 경우, 아래와 같이 파일명을 작성한다. 구성요소 이름이 여러 단어로 구성되는 경우, 하이픈으로 구별된 케밥 표기법(kebab-case) 명칭을 사용하는 것이 좋다.
todo-list.component.ts



클래스

export class HelloComponent {}

선언한 클래스를 모듈화하여 외부에 공개하기위해 export키워드를 사용했다.

TypeScript는 ECMAScript6 Module을 지원하며 export 키워드가 선언된 파일을 모듈로 간주한다.

타입스크립트(ES6)의 모듈과 앵귤의 모듈을 구분해야 한다.

ES6모듈
자바스크립트의 일반적인 모듈은 파일단위로 분리되어있어 필요시 명시적으로 모듈을 로드할 수 있다. 모듈은 기능적으로 분리되어 작성되므로 개발효율성과 유지보수성을 향상시킨다.

앵귤러 모듈
앵귤러의 구성요소(컴포넌트, 디렉티브, 서비스등)들을 하나로 묶어 어플리케이션을 구성하는 하나의 단위로 묶는 역활을 한다.


데코레이터

데코레이터는 클래스를 확장하는 함수로서 앵귤러에서 데코레이터는 클래스를 컴포넌트, 디렉티브, 서비스, 프로퍼티, 메소드, 파라메터등 앵귤러를 구성하는 요소들로 특성화하는 역활을 한다.

Angular는 아래와 같이 4가지 유형의 데코레이터를 제공한다.

  1. 클래스데 코레이터
    @Component, @NgModule, @Directive, @Injectable, @Pipe

  2. 프로퍼티 데코레이터
    @Input, @Output, @ViewChild, @ViewChildren, @ContentChild, @ContentChildren, @HostBinding

  3. 메소드 데코레이터
    @HostListener

  4. 파라미터 데코레이터
    @Inject


@Component 데코레이터는 Angular core 패키지에 정의되어 있어 @Component를 사용하려면 import키워드를 사용하여 Angular core패키지를 임포트한다.

앵귤러라이브러리는 @기호가 붙으며 경로를 명시하지 않는다.

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

@Component()
export class HelloComponent {}

일반 클래스를 컴포넌트화하기위해서는 @Component데코레이터를 사용해야 하며 앵귤러에게 컴포넌트화를 위한 정보를 제공해야 한다.

데코레이터 인자로 앵귤러에서 정의한 메타데이터객체를 전달하면 된다.

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

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css']
})
export class HelloComponent {}

selector는 컴포넌트의 뷰를 HTML 템플릿에 마크업할때 사용된다. 앵귤러는 다른 요소노드와 충돌을 피하기위해 기본접두사 app-를 사용한다.

app-hello는 이 컴포넌트를 이름짓는 마크업 식별자로서 이 컴포넌트를 삽입할 템플릿에 < app-hello>< /app-hello>와 같이 사용하면 된다.

컴포넌트 스타일은 해당 컴포넌트만을 위한 것이다. 즉, 컴포넌트 스타일의 CSS 셀렉터는 해당 컴포넌트의 템플릿 내에서만 적용된다. 위의 예제에서 h2 셀렉터는 hello 컴포넌트의 템플릿 내부에 있는 h2 요소만을 선택하고 다른 컴포넌트에 속해 있는 h2 요소는 선택하지 않는다. 이와 같은 특성은 웹 컴포넌트의 Shadow DOM을 구현한 것으로 컴포넌트의 DOM을 캡슐화(Encapsulation)하여 외부로부터의 간섭을 제어한다. 이것은 마치 변수의 스코프와 유사하다. 기존 CSS는 전역 변수와 같이 동작하지만 컴포넌트의 CSS는 지역 변수와 같이 동작한다.


컴포넌트 클래스와 템플릿의 연동

export class HelloComponent {
  name: string;

  setName(name: string) {
    this.name = name;
  }
}

컴포넌트는 템플릿의 상태를 관리한다. 이 말은 컴포넌트는 뷰의 변화를 감시하고 있으며 그 변화에 적절한 대응을 한다는 것이다.

더우기 데이터바인딩을 통해 템플릿에 데이터를 제공한다.

컴포넌트의 호출

어플리케이션이 시작하면 루트모듈의 bootstrap프로퍼티의 AppComponent 컴포넌트가 호출되어 AppComponent컴포넌트의 뷰가 브라우저에 표시된다.

하지만 루트컴포넌트가 아닌 컴포넌트는 다른 컴포넌트의 호출에의해 브라우저에 랜더링된다.

컴포넌트를 호출하는 방법은 호출하고자하는 컴포넌트의 selector를 호출하는 컴포넌트의 템플릿에 포함하는 것이다.

호출된 컴포넌트는 호출한 컴포넌트의 하위컴포넌트가 되는 것이다.

2개의 컴포넌트가 상하위 관계를 가지게되면 정보흐름의 통로가 되며 이를 통해 상태공유가 가능하게 된다.

모듈에 컴포넌트 등록

모듈은 관련된 앵귤러 구성요소를 하나로 묶어 어플리케이션을 구성하는 하나의 단위로 묶는 역활을 한다.

컴포넌트, 디렉티브, 파이프, 서비스등의 앵귤러구성요소는 모듈에 등록되어야 사용할 수 있다.

이전 설명에 컴포넌트를 템플릿에 넣으면 브라우저에 보인다고 설명했지만 컴포넌트는 모듈에 등록되어야 한다.

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

import { AppComponent } from './app.component';
import { HelloComponent } from './hello/hello.component'; // 1

@NgModule({
  declarations: [
    AppComponent,
    HelloComponent // 2
  ],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

사용자가 생성한 컴포넌트 HelloComponent 클래스를 임포트한다.

NgModue데코레이터에 전달된 메타데이터객체의 declarations에 HelloComponent가 추가된다.


declarations : 모듈에 소속될 구성요소(컴포넌트, 디렉티브, 파이프)들을 지정한다.

imports : 의존관계에 있는 앵귤러라이브러리, 기능모듈, 라우팅모듈, 서드파티모듈등을 지정한다.

providers : 주입가능한 객체 즉 서비스객체들을 지정한다. 루트모듈에 선언된 서비스는 어플리케이션 전역에 사용가능하다.

bootstrap : 어플리케이션의 진입점인 루트 컴포넌트를 지정한다.

0개의 댓글