Show GN: prewire - 런타임 컨테이너 없이 빌드 타임에 연결하는 TypeScript 프론트엔드 DI

3 days ago 15

안녕하세요. TypeScript 프론트엔드용 빌드 타임 DI 라이브러리 prewire를 만들었습니다. 이 라이브러리를 만들게 된 계기는 제가 관리하는 프론트엔드 모노레포의 구조였습니다. 여러 사업의 프론트엔드가 하나의 core/kit 코드를 공유하고 있는데, 현재 앱들은 Next.js를 사용하고 있습니다. 앞으로 일부 사업에서는 TanStack Router를 사용해 보고 싶었지만, 그렇다고 공유 코어가 next/navigation이나 @tanstack/react-router에 직접 의존하게 만들고 싶지는 않았습니다. 사업마다 다른 구현을 선택하면서도 공유 코어는 수정하지 않는 구조가 필요했습니다. prewire에서는 공유 코드가 먼저 port와 token을 선언합니다. export interface RouterPort { href(to: string): string push(to: string): void } export const ROUTER = new InjectionToken<RouterPort>('router') 각 앱은 자신이 사용하는 프레임워크로 이 port를 구현합니다. export const tanstackRouter = injectable( { logger: LOGGER }, ({ logger }): RouterPort => ({ href: (to) => to, push: (to) => { logger.info(`navigate → ${to}`) throw redirect({ to }) }, }), { provides: ROUTER }, ) 공유 코드를 포함한 소비자 쪽에서는 구현이 어디서 왔는지 알 필요 없이 같은 경로만 import합니다. import { router } from '#prewire' prewire codegen이 앱과 공유 패키지의 injectable() 선언을 정적으로 분석해 의존성 순서대로 평범한 TypeScript composition root를 생성합니다. export const logger = consoleLoggerBinding.factory({}) export const router = tanstackRouterBinding.factory({ logger }) 런타임 컨테이너나 reflect-metadata, decorator는 사용하지 않습니다. 누락된 binding, 순환 의존성, 중복 binding 같은 문제는 실행 중이 아니라 코...

Read Entire Article