인프런 커뮤니티 질문&답변

Truestar님의 프로필 이미지

작성한 질문수

호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)

게시글 작성 API 연결

(솔루션 수정)'tsyringe' Error: TypeInfo not known for "클래스명"

24.09.08 03:27 작성

·

393

·

수정됨

0

진작에 질문을 남겼어야 했는데, 애러 해결이 어려워 너무 지체되네요. 첫 질문 남기게 되었습니다.

 

문제의 요지
: 추측 하기로container.resolve 가 vue 와 라이프사이클 에 순서때문인지, 다른 이유가 있는지 DI 가 안됩니다. 

 

Menu.vue 디버깅

강의내용에도 있듯 tsyringe 는@singleton 이 달려있는 클래스를 컨테이너에 등록 후, 클래스 자체를 DI 키로 사용할 수 있다고 알고있습니다. 디버깅 상황에서 보다시피container 내부 _registryMap 안에 AuthorityApi 클래스가 정상등록 된 것을 확인할 수 있었습니다.

image

 

하지만 Break-point 된 container.resolve 처리가 안되어 아래처럼 애러가 발생합니다. 아래는 다음줄로 가지않고, 이벨류에이터로 실행한 모습이구요, AuthorityApi를 찾아올 수 없다 합니다.

image.png

Error: TypeInfo not known for "AuthorityApi"
    at http://localhost:4000/node_modules/.vite/deps/tsyringe.js?v=a355aabe:746:17
    at InternalDependencyContainer2.construct (http://localhost:4000/node_modules/.vite/deps/tsyringe.js?v=a355aabe:751:6)
    at InternalDependencyContainer2.resolveRegistration (http://localhost:4000/node_modules/.vite/deps/tsyringe.js?v=a355aabe:573:90)
    at InternalDependencyContainer2.resolve (http://localhost:4000/node_modules/.vite/deps/tsyringe.js?v=a355aabe:500:25)
    at eval (eval at setup (http://localhost:4000/src/widgets/Menu.vue:28:26), <anonymous>:1:11)
    at setup (http://localhost:4000/src/widgets/Menu.vue:28:26)
    at callWithErrorHandling (http://localhost:4000/node_modules/.vite/deps/chunk-VJROVW5H.js?v=a355aabe:1884:19)
    at setupStatefulComponent (http://localhost:4000/node_modules/.vite/deps/chunk-VJROVW5H.js?v=a355aabe:8253:25)
    at setupComponent (http://localhost:4000/node_modules/.vite/deps/chunk-VJROVW5H.js?v=a355aabe:8214:36)
    at mountComponent (http://localhost:4000/node_modules/.vite/deps/chunk-VJROVW5H.js?v=a355aabe:5604:7)

 

해결방법을 tsyringe 공식 깃헙이슈, 구글링, 스택오버플로 몽창 뒤져봐도 힌트얻기가 참으로 힘드네요. AI 센세는 그저 스택오버플로 내용만 읊어줍니다.

이것에 원인을 알 수 있을까요? 실마리만 얻어도 해결하기 수월할텐데, 몇일 째 어째야 되나 고민입니다. 도움을 얻을 수 있을까요?

 

: Source-Code

src-front 소스코드

주의: 개인 npm lib 가 포함되어 node_modules 을 포함한 체 그대로 압축된 파일입니다. npm i 인스톨 없이 앱을 실행해야될거라 예상합니다.

 

도움을 구합니다. 감사드려요.

답변 2

0

Truestar님의 프로필 이미지
Truestar
질문자

2024. 09. 15. 22:53

솔루션 수정본

기존 댓글에 정리된 내용이 적절치 않아 삭제 후, 실제 동작하는 방법에 대해 다시 정리합니다.

다음은 알려진 OOP 인터페이스 분리 패턴(ISP)을 TS기반 tsyringe 에서 추상클래스를 InjectionToken 으로 사용하는 방법입니다.

 

updates: 

  • 24-09-19: InjectionToken 형 변환 시, as InjectionToken 에서 `as InjectionToken 또는 as unknown as InjectionToken 으로 변경

 

1. extends AbstractClass

: 추상클래스를 상속,확장합니다.

abstract class Super {}

class Impl extends Super {}

 

2. 구현체 클래스에 @registry([..]) 추가

@singleton()
// ✅ @registry 에 직접 연관된 부모클래스(추상체)를 지정해야 @inject 를 통해 주입이 가능해집니다.
@registry([
  {
    // 💡 tsyringe 는 추상클래스 등록을 지원하지 않아 타입미스매치 애러 발생.
    //    해결은 unknown as InjectionToken 으로 강제 케스팅 후 등록이 가능함.
    // 1안
    token: Super as InjectionToken, 
    // 또는 2안
    token: Super as unknown as InjectionToken,
    useClass: Impl,
  },
])
class Impl extends Super {}

 

3. 사용

export class ConstructorInjectionWithTsyringe {
  constructor(
    @inject(Impl)
    readonly sup: Super,
  ) {}
}

 

동작확인

아래는 질문의 소스코드 디버깅 상황에서 캡쳐된 이미지입니다. 추상클래스 HttpClient 타입 맴버변수에, 구현체 AxiosHttpClient 인스턴스가 정상 주입된 것을 확인할 수 있었습니다.

image.png

 

Truestar님의 프로필 이미지
Truestar
질문자

2024. 09. 19. 02:45

:: 추가이슈 해결 ::


문제
: 추상클래스를 container.resolve 인수로 대입 시, 반환된 인스턴스가 any 타입으로 추론됩니다.

: AppLogger 가 추상클래스 일때, InjectionToken 으로 형변환 시, 변수 logany 타입으로 추론됩니다. 이로인해 IDE 의 메서드 추론기능을 사용할 수 없습니다.

// 🚫 log: any 
const log = container.resolve(AppLogger as InjectionToken)

 

해결:

InjectionToken 타입의 구성은 다음과 같습니다.

declare type InjectionToken<T = any> = constructor<T> | string | symbol | DelayedConstructor<T>;

이 중에 constructor<T> 를 사용해서 강제케스팅 합니다.

 

적용코드:
import { container } from 'tsyringe'
import type { constructor } from 'tsyringe/dist/typings/types'

// log: AppLogger ✅
const log = container.resolve(AppLogger as constructor<AppLogger>)  

 

0

호돌맨님의 프로필 이미지
호돌맨
지식공유자

2024. 09. 09. 09:46

import {AxiosHttpClient, HttpClient, type ResponseHandlerOptions} from '@/features'

@singleton()
export class AuthorityApi {
  constructor(@inject(HttpClient) readonly httpClient: AxiosHttpClient) {}

    // 생략
}

AuthorityApi의 생성자 주입이 안되는 상태입니다.

때문에 외부에서 container.resolve(AuthorityApi)가 안먹히는 상황입니다.

위 코드와 같이 AxiosHttpClient를 직접 지정해서 해결할 수 있습니다.

혹은 tsyringe 예제 문서와 같이 interface를 이용해서 주입할수도 있긴합니다.

관련링크: https://github.com/microsoft/tsyringe?tab=readme-ov-file#example-with-interfaces

Truestar님의 프로필 이미지
Truestar
질문자

2024. 09. 10. 00:45

앗... 한참 정리중에 답글을 달아주셨군요... 해결상태로 종결하겠습니다!

Truestar님의 프로필 이미지
Truestar
질문자

2024. 09. 15. 23:01

일반적인 OOP 방식처럼, inject 데코레이터에 구현체클래스, 필드변수타입에 추상체클래스 선언이 가능한 방법이 있었습니다. 너무 해맨것 치고 너무 해결방법이 간단해 허탈했고, 알려주신 방법이 다른 경우에서 잘 안되는거 같아, 용법을 새-댓글에 다시 정리하게 되었어요.

참고: microsoft/tsyringe: @registry

Truestar님의 프로필 이미지

작성한 질문수

질문하기