본문 바로가기
Angular.js

[Angular] 의존성 주입(Dependency Injection)과 서비스 객체(class)

by 찬찬2 2023. 1. 6.

의존성 등록하는 3가지 방법

1. @Injectable() "{ providedIn: 컴포넌트명 or 'root' }" [Singleton Services]

- 의존성 주입 시 반드시 필요한 데코레이터. 인자에 provideIn필드를 가진 객체를 넣을 경우 한 개의 컴포넌트에만 의존성을 주입한다. 아무것도 넣지 않을 경우 모든 컴포넌트에서 사용할 수 있다.

- provideIn의 값을 "root"로 지정할 경우 의존성 객체의 인스턴스를 한번만 생성하고, 의존성 객체를 요청하는 곳마다 모두 같은 인스턴스를 주입한다.

"의존성 객체를 이렇게 등록하면 이 객체가 실제로 사용되지 않았을 때 최적화하는 작업을 수행하는데, 이 작업을 트리 셰이킹(tree-shaking)이라고 합니다."

 

2. @component() "{ providers: [서비스] }"

- 컴포넌트 계층에 등록한다. 해당 컴포넌트 템플릿에 존재하는 모든 컴포넌트와 디렉티브에서 의존성 객체의 인스턴스에 접근할 수 있다.

- 컴포넌트 인스턴스마다 의존성 객체의 인스턴스를 생성한다. (독립적인)

 

3. @NgModule() "{ providers: [서비스] }" [Singleton Services]

- 모듈 계층에 등록한다. NgModule 안에 있는 모든 컴포넌트, 디렉티브, 파이프에서 서비스 인스턴스에 접근할 수 있다.

- NgModule 안에 있는 모든 컴포넌트는 같은 의존성 객체의 인스턴스를 사용한다.

 


 

의존성 객체 주입하는 방법

- 컴포넌트의 constructor함수의 매개변수에 추가

 

@Component({ … })
class HeroListComponent {
  constructor(private service: HeroService) {}
}

 

앵귤러는 생성자 함수에 있는 매개변수를 보고 해당 컴포넌트에 의존성 주입이 필요하다는 것을 할게 되고, 서비스의 인스턴스를 찾는 과정을 진행한다. (공식문서)

 


 

아래 그림과 의존성 객채를 찾는 과정은 "component level"에서 시작한다. component level에서 찾지 못했을 경우 root 모듈(NgModule)에서 자식 모듈로 이동하며 의존성 객체를 찾는다. (component level → module level)

 

 

컴포넌트가 의존성 객체를 찾는 과정 (injector tree)

 

 

참고링크들...

모듈 안에서 의존성 객체 제공하기

실전 의존성 주입

 


 

Angular에서 서비스란?

"컴포넌트는 데이터를 직접 가져오거나 직접 저장하도록 요청하지 않는 것이 좋습니다. 그리고 사용하는 데이터가 실제 데이터인지 가짜 데이터인지 알 필요도 없습니다. 컴포넌트는 데이터를 표시하는 것에만 집중하는 것이 좋으며, 데이터를 처리하는 로직은 서비스에게 맡겨두는 것이 좋습니다."

 

즉, MVC 패턴과 같이 Model, View, Controller로 파일을 분리하고 각각의 역할만 수행하도록 하는 편이 유지보수에 용이할 것이다. 또한 유닛테스트를 수행할때도 내가 작업해야 할 파일만 열어서 작업하면 되기 때문에 혹시 있을 수 있는 실수들을 방지할 수 있을 것이다.

 

ngOnInit( )에서 서비스 호출

constructor( )에서 비동기 호출을 수행하는 것은 좋지 않다고 한다. ngOnInit 라이프싸이클 후킹 함수에서 실행하는 것이 좋다고 한다. (공식문서)

ngOnInit 함수는 컴포넌트 인스턴스를 생성한 직후에 실행되는 함수이다. 리액트의 "componentDidMount"와 같은 역할인 것 같다.

 


 

싱글톤 서비스 Singleton services

- 앱 전역에 하나의 서비스만 존재하는 것.

 

■ 싱글턴 서비스 생성하기

1. @Injectable() provideIn 프로퍼티에 "root"를 지정

2. @NgModule의 provider 배열에 추가. 위치는 AppModule, root계층이어야 한다.

3. forRoot 패턴 사용

 

"이 경우에도 서비스가 추가되는 모듈은 AppModule이기 때문에 UserService는 앱 전역에서 인스턴스 하나만 존재합니다. 동작은 동일하지만, Angular 6.0부터는 트리 셰이킹이 가능한 서비스를 명확하게 지정하기 위해 서비스 클래스의 @Injectable() 데코레이터에 providedIn 메타데이터를 지정하는 방법을 더 권장합니다."

댓글