앵귤러 기본 - 아키텍쳐

앵귤러 아키텍쳐

모듈

NgModule 메타 데이터

  • declarations: 해당 NgModule에 포함될 컴포넌트나 디렉티브, 파이프를 선언한다.
  • exports: 모듈의 구성 요소를 다른 NgModule이나 컴포넌트 템플릿으로 재사용할 수 있도록 외부로 공개한다.
  • Imports: 다른 모듈에서 공개한 클래스를 지금 정의하는 NgModule에 가져올 때 사용한다.
  • Providers: NgModule 컨텍스트 안에서 사용하는 서비스 프로바이더를 지정한다. NgModule 안에서 사용하는 서비스는 이렇게 지정된 서비스 프로바이더를 사용해서 생성되며, 필요한 경우에는 하위 계층에 사용할 서비스 프로바이더를 따로 지정할 수도 있다.
  • Bootstrap: 애플리케이션의 최상위 뷰로 표시될 최상위 컴포넌트를 지정한다. Bootstrap 프로퍼티는 최상위 NgModule에만 지정할 수 있다.

컴포넌트

  • 뷰에서 사용할 로직은 컴포넌트에 정의한다.(뷰 로직은 컴포넌트에, 비지니스 로직은 서비스 또는 effect에)

  • @Component 데코레이터를 붙이기 전까지는 컴포넌트로 등록되지 않는다.

  • 데코레이터의 providers 메타데이터는 컴포넌트 생성시, 의존성으로 주입되는 서비스의 프로바이더를 지정한다.

    @Component({
      selector:    'app-hero-list',
      templateUrl: './hero-list.component.html',
      providers:  [ HeroService ]
    })
    export class HeroListComponent implements OnInit {
    /* . . . */
    }

파이프

  • 파이프는 원래값을 입력받고 새로운 형식의 값을 반환하는 함수에 @Pipe 데코레이터를 사용해서 Angular에 등록한다.

  • 사용법

    <!-- 기본 형식: 'Jun 15, 2015'-->
     <p>Today is {{today | date}}</p>
    
    <!-- fullDate 형식: 'Monday, June 15, 2015'-->
    <p>The date is {{today | date:'fullDate'}}</p>

디렉티브

  • 템플릿이 렌더링 될 때 디렉티브가 있으면 DOM의 모양을 디렉티브의 로직에 따라 변형시키며, 디렉티브는 클래스의 @Directive() 데코레이터를 사용해서 정의한다.

    @Copmonent() 도 문법적으로는 디렉티브의 한 종류이다. 커스텀 한 것.

  • 구조 디렉티브와 어브리뷰트 디렉티브로 나누어 진다.

    • 구조 디렉티브: DOM 엘리먼트를 추가하거나 제거, 치환하는 용도로 사용한다.

      <li *ngFor="let hero of heroes"></li>
      <app-hero-detail *ngIf="selectedHero"></app-hero-detail>
    • 어트리뷰트 디렉티브: 이미 존재하는 엘리먼트의 모양이나 동작을 변형한다.(HTML 어트리뷰트처럼 보인다.)

      <input [(ngModel)]="hero.name">

      ngModel 디렉티브는 양방향 바인딩에 사용되며, 어트리뷰트 디렉티브의 한 종류이다.

    서비스와 DI

    • 앱에서 공통으로 사용하는 상수나 함수, 기능을 모아놓은 단위이다.
    • 컴포넌트와 서비스를 확실하게 구분해서 모듈화와 재사용 효율성을 높이는 것을 권장한다. 컴포넌트에서 뷰와 관련된 로직을 다른 로직과 분리하면 컴포넌트 클래스를 간결하게 구성할 수 있으며, 결과적으로 컴포넌트 클래스를 유연하고 효율적으로 유지할 수 있다.
    • 컴포넌트에는 해당 뷰에서 일어나는 사용자의 행동에 관련된 로직만 둔다.

      • 화면에 사용되는 프로퍼티나 데이터 바인딩에 사용하는 메소드만 정의하는 것이 좋다.
      • 템플릿이 렌더링된 뷰와 모델을 정의하는 애플리케이션 로직을 중개하는 역할만 한다.
    • 서비스에는 AJAX요청 로직, 사용자 입력 검증 로직, 로그를 출력하는 것 등등 공통으로 사용할 수 있는 것들을 정의한다. 환경에 따라 서비스 프로바이더를 다르게 지정하면 애플리케이션을 다양한 환경에서 동작하도록 좀 더 유연하게 만들 수 있다.

    의존성 주입 (DI)

    • 서비스와 같은 객체를 Angular 프레임워크와 묶는 개념. 컴포넌트가 생성될 때 자유롭게 주입할 수 있다. 서비스를 컴포넌트에 의존성으로 주입하면 컴포넌트는 서비스 클래스에 접근할 수 있다.

    • Angular는 애플리케이션을 부트스트랩할 때 애플리케이션 전역 범위에 동작하는 인젝터를 생성한다.

    • 인젝터는 의존성 객체의 인스턴스를 생성하고, 이 인스턴스를 나중에 재사용할 수 있도록 컨테이너에서 관리한다.

    • 프로바이더는 의존성으로 주입되는 객체를 어떻게 만드는지 정의한 것이다.

    • 애플리케이션에 필요한 의존성 객체가 있다면, 이 의존성 객체의 프로바이더를 인젝터에 등록해야 한다. 그러면 인젝터가 이 프로바이더를 사용해서 의존성 객체의 인스턴스를 생성한다. 서비스의 경우에는 보통 서비스 클래스가 그 자체로 서비스 프로바이더의 역할을 한다.

      의존성 객체가 서비스만 가능한 것은 아니다. 함수나 기본 자료형도 의존성 객체가 될 수 있다.

    • Angular가 컴포넌트 클래스의 인스턴스를 새로 만들 때, 컴포넌트 생성자에 지정된 타입을 보고 이 컴포넌트에 서비스와 같은 의존성이 있는지 확인한다.

      // HeroService가 의존성으로 주입되어야 한다.
      constructor(private service: HeroService) { }

      컴포넌트에 서비스가 주입되어야 한다는 것을 Angular가 확인하면, 이 서비스의 인스턴스가 인젝터에 이미 있는지 먼저 확인한다. 이 때 인스턴스가 아직 생성되지 않았으면 프로바이더에 등록된 방법으로 객체의 인스턴스를 생성하고, 인젝터에 이 인스턴스를 추가한 후에 Angular로 전달한다.

      그리고 컴포넌트에 필요한 서비스가 모두 준비되고 나면 Angular가 컴포넌트 생성자를 실행하면서 이 서비스들을 인자로 전달한다.

      서비스 프로바이더 등록하기

      서비스를 사용하려면 프로바이더를 어디엔가 등록해야 하는데, 두가지 방법이 있다.

      1. 서비스 메타데이터(@Injectable()데코레이터)에 자신의 프로바이더를 직접 등록하는 방법

      2. @NgModule() 이나 @Component() 메타데이터에 프로바이더를 등록하고 하위 계층에서 이 프로바이더를 이용하는 방법

      3. Angular CLI로 ng generate service 명령을 실행하면 서비스 클래스를 생성하면서 @Injectable() 데코레이터를 사용해서 이 서비스를 최상위 인젝터에 등록한다.

        @Injectable({
        	providedIn: 'root'
        })

        서비스 프로바이더를 최상위 인젝터에 등록하면, 해당 Service의 인스턴스는 애플리케이션 전역에 딱 하나만 생성되며, 이 의존성을 주입하는 컴포넌트가 모두 같은 인스턴스를 공유한다.

        그리고 @Injectable() 메타데이터를 사용해서 프로바이더를 등록하면, 애플리케이션 배포 단계에서 코드를 최적화하면서 이 서비스가 실제로 사용되는지 확인하고 사용되지 않으면 최종 결과물에서 제외시킬 수도 있다.

      4. 서비스 프로바이더를 특정 NgModule에 등록하면, 이 NgModule 범위에 있는 컴포넌트만 같은 서비스 인스턴스를 공유한다. 이렇게 등록하려면 @NgModule() 데코레이터의 providers 프로퍼티를 다음과 같이 지정해야한다.

        @NgModule({
        	providers: [
        		BackendService,
        		Logger
        	],
        	...
        })
      5. 컴포넌트 계층에 프로바이더를 지정하면 해당 컴포넌트의 인스턴스가 생성될 때마다 의존성 객체에 대해 새로운 인스턴스를 생성한다. 컴포넌트 계층에 서비스 프로바이더를 등록하려면 @Component() 메타데이터의 providers 프로퍼티를 다음과 같이 지정한다.

        @Component({
        	selector: 'app-hero-list',
        	templateUrl: './hero-list.component.html',
        	providers: [ HeroService ]
        })

      개인적인 생각. service 관련 규칙이 참 뭐가 많다… 특히 프로바이더 등록하는 부분.. 방식이 여러개라 헷갈리기도 하고, 제대로 공부해서 사용하지 않으면 잘못된 코드를 생산할 가능성이 높을 것 같다. 왜 앵귤러에서 이렇게 만들었는지는 모르겠지만, 우리는 앵귤러를 사용하기에 빡시게 공부하고 정확한 사용법을 통해 어플리케이션을 만들어야 한다.💪🏽

      다음단계

      반응형 프로그래밍

      • 라이프사이클 후킹
      • 옵저버블, 이벤트 처리

      내가 정말정말 * 100 공부하고 싶은 부분이다. 다른 프레임워크와 달리 앵귤러의 장점 중 하나를 뽑자면, 애플리케이션 전체적으로 리액티브하게 만들 수 있다는 것이다..! 공부해서 정말 리액티브한 애플리케이션을 만들고 싶다.🙏

      클라이언트-서버통신

      • 서버 사이드 렌더링 - 앵귤러 기본을 다 공부하고 나면 꼭 공부하고 프로젝트에 적용하면서 배워야하는 내용. 애플리케이션을 더 고도화 하기 위한..!
      • 서비스워커 - 워너비… 이것까지 프로젝트에 적용할 때 쯤이면 우리 팀은 높은 수준의 프론트엔드 기술력을 갖게 되지 않을까 ㅎㅎ

      개발 지원

      • 컴파일 - JIT과 AOT
      • 테스트 플랫폼 - 이것도 올해 안에는 꼭 프로젝트에 적용하면서 개발하고 싶다!
      • internationalization - 갓 구글님 제발 런타임 번역 지원 해주세요.. 흑흑
      • 보안 가이드라인 - 오호… 보안까지 공부한다면 우리는 정말 좋은 프론트엔지니어가 될 수 있을거다.

      개발, 빌드, 배포 환경설정

      • CLI - 상민님.. 언제 커스텀 해주시나엽 ㅋㅋㅋㅋㅋ 바쁘시면 제가 공부해서 한번 해보도록 할까엽…?
      • 개발 환경과 파일 구성 - 오호 안그래도 항상 어떻게 구조를 더 좋게 해야 하나 고민했는데, 우선 순위를 높여 공부 해야겠다.

      출처: https://angular.kr/guide/architecture


[Abel ko]
Written by@[Abel ko]
이 세상을 먼지처럼 살다 갈 👨🏽‍💻입니다. 소프트웨어를 통해 사회적기업을 만드는 것이 꿈입니다.⭐️

GitHubFacebook