useClass와 useExisting의 비교 - different between useClass and useExisting

2 분 소요

이번 시간은 module에서 providers를 설정 시 useClass와 useExisting 의 차이를 알아보겠습니다.

useClass

Injectable class의 이름을 변경하여 사용할 수 있습니다.
이 때, 이름은 반드시 존재하는 다른 Injectable class의 명이여야 합니다.

사용법은 다음과 같습니다.

providers: [
  { provide: ProductService, useClass: fakeProductService }
]


useExisting

기존 토큰을 참조하되 별칭을 지정합니다.
반드시 두 injectable class가 존재해야 합니다.

providers: [
   NewProductService,
   { provide: ProductService, useExisting: NewProductService },
];


different between useClass and useExisting

얼핏 보면 useClass와 useExisting은 유사해 보이는데 왜 다른 옵션을 제공하고 있을까요?
이 두 차이를 예제를 통해 자세히 알아봅시다.

Setting Default Services for Testing

예를 들어 두 가지 service가 존재한다고 합시다. 두 service는 형태는 유사하지만 값이 다른 모양으로 쉽게 구분할 수 있게 구성하였습니다.

@Injectable()
export class TestService {
  index = 0;

  add(): number {
    return ++this.index;
  }
}


@Injectable()
export class NewTestService {
  index = 0;

  add(): number {
    this.index += 10;
    return this.index;
  }
}

component에서 두 service를 매 초 호출한다고 가정합시다.

export class AppComponent {
   constructor(
      private testService: TestService,
      private newTestService: NewTestService
} {
   setInterval(() => {
      console.log('test', this.testService.add());
      console.log('newTest', this.newTestService.add());
   }, 1000)
}

그리고 각각의 모듈의 다른 설정의 예제를 통해 왜 이런 기능을 구분하게 되었는지 알아보겠습니다.

기본 provider 설정

일반적인 방법으로 providers에 service를 직접 설정해보고 결과를 확인해봅시다.

// app.module
...
providers: [
   TestService,
   NewTestService
]

결과는 예상과 같이 두 service가 각각 다르게 동작함을 확인할 수 있습니다.

// result
test: 1
newTest: 10
test: 2
newTest: 20
test: 3
newTest: 30
test: 4
newTest: 40


useClass 활용

useClass를 활용하여 TestService를 NewTestClassService로 명명해봅시다.

// app.module
providers: [
   TestService,
   {provide: NewTestService, useClass: TestService },
]

결과는 NewTestService가 TestService로 전환되었으며, 기존 TestService와는 다른 Service인 것처럼 각각 다르게 동작함을 확인할 수 있습니다.

// result
test: 1
newTest: 1
test: 2
newTest: 2
test: 3
newTest: 3
test: 4
newTest: 4


useExisting 활용

위의 useClass와 동일한 조건에서 useClass만 useExisting으로 변경해보고 결과를 확인해봅시다.

// module
providers: [
   TestService,
   {provide: NewTestService, useExisting: TestService },
]

결과는 NewTestService가 TestService로 전환되었으며, 기존 TestService와 마치 하나의 Service인 것처럼 데이터를 공유하고 있음을 확인할 수 있습니다.

// result
test: 1
newTest: 2
test: 3
newTest: 4
test: 5
newTest: 6
test: 7
newTest: 8

Angular Standalone에서 useClass와 useExisting 활용

standalone에서는 module을 사용하지 않으므로 위의 예제를 활용하려면 service에서 직접 선언해야 합니다.
Injectable의 파라미터에서 useClass와 useExisting을 제공하므로 이를 활용할 수 있습니다.
위의 예제를 수정해봅시다.

useClass

@Injectable({
   providedIn: 'root',
   useClass: TestService
})
export class NewTestService {
  index = 0;

  add(): number {
    this.index += 10;
    return this.index;
  }
}

useExisting

@Injectable({
   providedIn: 'root',
   useExisting: TestService
})
export class NewTestService {
  index = 0;

  add(): number {
    this.index += 10;
    return this.index;
  }
}

댓글남기기