2. TSyringe

  • External Store์— ๋Œ€ํ•œ ๊ฐ•์ ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•œ ๊ฐ•์˜์ธ๋ฐ, ํ•œ ๋ฒˆ๋งŒ ๋ด์„œ๋Š” ์ดํ•ด๊ฐ€ ์ž˜ ์•ˆ๋๋‹ค. ์•Œ๊ณ ์žˆ์ง€๋งŒ ๋‚ฏ์„  ๊ฐœ๋…์ธ ์‹ฑ๊ธ€ํ†ค ๊ฐ™์€ ๊ฒƒ ๋•Œ๋ฌธ์ธ๋ฐ ๊ฐœ๋…์ ์œผ๋กœ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์—์„  ์˜ค์ง ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋งŒ ์ƒ์„ฑํ•œ๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•Œ๊ณ  ์žˆ์—ˆ์ง€๋งŒ, ์ฝ”๋“œ์— ํŒจํ„ด์„ ์ง์ ‘ ์ ์šฉํ•˜๋‹ˆ '์—ฅ ๋ญ์ง€?' ๋ผ๋Š” ์ƒ๊ฐ์ด ๊ณ„์† ๋“ค์–ด ์ด๋ฒˆ ํŒŒํŠธ๋Š” ์ฝ”๋“œ์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ํก์ˆ˜ํ•ด์•ผ๊ฒ ๋‹ค.

  • ์ค‘๊ฐ„์— Count ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‘ ๋ฒˆ ํ˜ธ์ถœํ•˜๋ฉด์„œ ๋‚˜์ค‘์— ํ˜ธ์ถœํ•œ ์ปดํฌ๋„ŒํŠธ์˜ count๋งŒ ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๋ฎ์–ด์“ด๋‹ค๊ณ  ํ‘œํ˜„์„ ํ•˜๋Š”๋ฐ ๋ฌด์Šจ ๋ง์ด์ง€? publish๋ฅผ ๊ฐ€๋กœ์ฑ„์„œ ๋งˆ์ง€๋ง‰ ์ปดํฌ๋„ŒํŠธ์˜ forceUpdate๋งŒ ๋“ฑ๋ก๋œ๊ฑด๊ฐ€?

  • new ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋…๋ฆฝ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— Store๋ฅผ ์ „์—ญ์œผ๋กœ ํ™œ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ˆ Singleton ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋‹จ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ „์—ญ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋งํ•˜๊ณ  ์‹ถ์—ˆ๋˜๊ฑด๊ฐ€? ์˜์ƒ์˜ ํ‘œํ˜„์ด ํ—ท๊ฐˆ๋ฆฐ๋‹ค.

Keyword

  • TSyringe

  • ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)

  • reflect-metadata

  • sington (์‹ฑ๊ธ€ํ†ค)


1. TSyringe

  • Typescript์šฉ ์˜์กด์„ฑ ์ฃผ์ž… ์ปจํ…Œ์ดํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • ํด๋ž˜์Šค, ํ•จ์ˆ˜ ๋“ฑ์˜ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•  ๋•Œ ํŽธ๋ฆฌํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•จ.

  • ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ, ์œ ์ง€๋ณด์ˆ˜์„ฑ, ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.

// stores/store.ts
import { singleton } from 'tsyringe';

@singleton
export default class Store {
  // ...
}

// components/Counter.tsx
import { container } from 'tsyringe';
import Store from '../stores/Store';

export default function Counter() {
  const store = container.resolve(Store);
  // ...
}

Counter ์ปดํฌ๋„ŒํŠธ์—์„œ container.resolve()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด Store ํด๋ž˜์Šค์— ๋ฆฌํ”Œ๋ ‰์…˜์œผ๋กœ ์ƒ์„ฑ์ž์™€ ๋ฉค๋ฒ„ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋ฆฌํ”Œ๋ ‰์…˜ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด reflect-metadata ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•œ ๊ฒƒ


2. ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)

  • ์˜์กด์„ฑ ์ฃผ์ž…์€ ์ปดํฌ๋„ŒํŠธ(React ์ปดํฌ๋„ŒํŠธ ์•„๋‹˜, ํ”„๋กœ๊ทธ๋žจ์˜ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์˜๋ฏธ) ๊ฐ„์˜ ๊ฒฐํ•ฉ์„ ์ตœ์†Œํ™”ํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ๋ชจ๋“ˆํ™”ํ•˜์—ฌ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ, ์œ ์ง€๋ณด์ˆ˜์„ฑ, ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.

  • ํด๋ž˜์Šค, ํ•จ์ˆ˜ ๋“ฑ์˜ ์˜์กด์„ฑ ๊ด€๋ฆฌ ๋กœ์ง์„ ์™ธ๋ถ€๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐ ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์‹ ์˜ ์—ญํ• ์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜์กด์„ฑ ์ฃผ์ž…์ด๋ผ๊ณ  ํ•˜๋ฉด ๋ˆ„๊ฐ€ ์˜์กดํ•˜๊ฒŒ ๋˜๋Š”๊ฑด์ง€ ํ—ท๊ฐˆ๋ฆฌ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‚˜๋Š” ๊ทน๋‹จ์ ์ธ ์˜ˆ์‹œ๋กœ ์ดํ•ดํ–ˆ๋Š”๋ฐ, ๋งˆ์•ฝ์„ ์ฃผ์‚ฌ๊ธฐ๋กœ ๋‚˜์—๊ฒŒ ์ฃผ์ž…ํ•˜๋ฉด ์ค‘๋…์„ฑ์œผ๋กœ ์ธํ•ด ๋‚˜๋Š” ๋งˆ์•ฝ์— ์˜์กดํ•œ๋‹ค.


3. reflect-metadata

  • metadata๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ ํด๋ž˜์Šค, ํ”„๋กœํผํ‹ฐ, ๋ฉ”์„œ๋“œ ๋“ฑ์˜ ์š”์†Œ์— ์ถ”๊ฐ€์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.

  • reflect-metadata๋Š” Typescript์—์„œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•  ๋•Œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.

  • Typescript๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ํƒ€์ž… ์ •๋ณด๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋Ÿฐํƒ€์ž„์—๋Š” ์ •๋ณด๋ฅผ ์–ป๊ธฐ ์–ด๋ ค์›Œ reflect-metadata๋ฅผ ์‚ฌ์šฉํ•ด ํƒ€์ž… ์ •๋ณด๋ฅผ ๋Ÿฐํƒ€์ž„์— ํ™œ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์ฃผ๋กœ ํด๋ž˜์Šค๋‚˜ ํ”„๋กœํผํ‹ฐ์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ฝ์–ด์˜ค๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.

container ์‚ฌ์šฉ์‹œ ํ•ญ์ƒ reflect-metadata ๋ชจ๋“ˆ์„ import ํ•˜๋Š”๋ฐ ์ด๊ฒƒ์ด reflection์„ ์ง€์›ํ•œ๋‹ค.

์‚ฌ์šฉ ์˜ˆ์ œ

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ(@)์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

ํด๋ž˜์Šค์— ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

import "reflect-metadata";

const MY_METADATA_KEY = "myMetadataKey";

function MyDecorator(data: any) {
  return Reflect.metadata(MY_METADATA_KEY, data);
}

@MyDecorator("Hello, metadata!")
class MyClass {
  // ...
}

const metadata = Reflect.getMetadata(MY_METADATA_KEY, MyClass);
console.log(metadata); // "Hello, metadata!"

๋ฉ”์„œ๋“œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

import "reflect-metadata";

const MY_METADATA_KEY = "myMetadataKey";

function MyDecorator(data: any) {
  return Reflect.metadata(MY_METADATA_KEY, data);
}

class MyClass {
  @MyDecorator("Hello, method metadata!")
  myMethod() {
    // ...
  }
}

const metadata = Reflect.getMetadata(MY_METADATA_KEY, MyClass.prototype, "myMethod");
console.log(metadata); // "Hello, method metadata!"

4. sington (์‹ฑ๊ธ€ํ†ค)

  • ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋Š” ์˜ค์ง ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋งŒ ์ƒ์„ฑํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด

  • ์ธ์Šคํ„ด์Šค๊ฐ€ ์˜ค์ง ํ•˜๋‚˜๋งŒ ์กด์žฌํ•˜๋ฉฐ, ์–ด๋””์„œ๋“  ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ณ  ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ „์—ญ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์„ค์ •, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ, ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ๋“ฑ์˜ ๊ณต์œ  ๋ฆฌ์†Œ์Šค๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ I/O ๋ฐ”์šด๋“œ ์ž‘์—…์€ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ํฐ ์ž‘์—…์ด๋ผ ์‹ฑํดํ†ค ํŒจํ„ด์„ ํ™œ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•˜์—ฌ ์ปค๋„ฅ์…˜ ํ’€์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๊ณ ์žˆ๋‹ค.

์‚ฌ์šฉ ์˜ˆ์‹œ

singleton ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ํด๋ž˜์Šค๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

import { singleton } from 'tsyringe';

@singleton
export default class Store {
  // ...
}

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ(@)

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ํด๋ž˜์Šค, ๋ฉ”์„œ๋“œ, ํ”„๋กœํผํ‹ฐ ๋“ฑ์˜ ์„ ์–ธ๋ถ€์— ์‚ฌ์šฉํ•ด ๋™์ž‘์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ๊ธฐ๋Šฅ ์ถ”๊ฐ€๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฌธ๋ฒ•์ด๋‹ค. ์œ„์˜ ์‚ฌ์šฉ์˜ˆ์‹œ ์ฝ”๋“œ์—์„œ Store ํด๋ž˜์Šค ์— ์‹ฑ๊ธ€ํ†ค ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‹จ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ๋œ๋‹ค.

Last updated