TIL Code_Camp 12일차 의존성 주입

박선우·2023년 1월 27일
0

code_camp

목록 보기
26/31
post-thumbnail

🌼 학습내용

1️⃣ 의존성 주입

  • 의존성 주입이란 강한 결합을 느슨한 결합으로 만드는 DI(의존성 주입)이다.

⛔️ 강한결합

  • 강한 결합에서는 비교적 new를 더 많이 사용해 메모리를 많이 잡아먹게 된다.
export class ProductController {
  buyProduct = (req, res) => {
    const cashService = new CashService();
    const hasMoney = cashService.checkValue();
    
    const productService = new ProductService();
    const isSoldout = productService.checkSoldout(); 
  };

  refundProduct = (req, res) => {
    const productService = new ProductService();
    const isSoldout = productService.checkSoldout(); 
  };
}
  • ProductController가 CashService와 ProductService에 의존하고 있는 상태
  • 하위클래스(CashService와ProductService)가 정의 되지 않으면
  • 상위클래스(ProductController)를 정의할 수 없다.
  • 하위클래스를 수정하게 되면 상위 클래스도 대부분에서 변경이 일어나게 된다.

⛔️ 느슨한 결합(의존성 주입)

  • 클래스/클래스를 느슨하게 결합되어 새로운 기능을 개발하거나 기존 기능을 수정하고 확장하는게 쉽습니다.
  • 유지 보수가 비교적 쉽다.
// index.js

// 생성자 -> 싱글톤 패턴
const cashService = new CashService();

// ProductController(cashService) 추가
const productController = new ProductController(cashService);
app.post("/products/buy", productController.buyProduct);
app.post("/products/refund", productController.refundProduct);

const couponController = new CouponController();
app.post("/coupons/buy", couponController.buyCoupon);
  • cashService 생성자를 ProductController() 안에 넣어주게 된다.
export class ProductController {
   constructor(cashService) {
    this.cashService = cashService;
  }
  buyProduct = (req, res) => {
    // const cashService = new CashService(); 이부분을 제외 가능하게 된다.
    const hasMoney = this.cashService.checkValue(); //this.을 붙여줘야한다.
    
    const productService = new ProductService();
    const isSoldout = productService.checkSoldout(); 
  };

  refundProduct = (req, res) => {
    const productService = new ProductService();
    const isSoldout = productService.checkSoldout(); 
}
  • constructor 사용해 cashService를 받는다.

⛔️ 싱글톤 패턴

  • index.js에서 new 한 번으로 모든 곳에서 사용 가능하게 된다.
  • 의존성 주입이면 싱글톤 패턴이다!? 그건 아니다.
const cashService1 = new CashService();
const cashService2 = new CashService();
  • cashService1 와 cashService2 로 만들고 똑같은 CashService를 서로 다른 곳에서 사용 => 의존성 주입 O 싱글톤 패턴 X

2️⃣ Typescript

Typescript 전반적인 이해

// 타입 추론
let aaa = '안녕하세요';
aaa = 3; // number 형식은 string 형식이 될 수 없다.

// 타입 명시
let bbb: string = '반갑습니다.';
bbb = 10;

// 타입 명시가 필요한 상황
let ccc: number | string = 1000;
ccc = '1000원'; 

// 숫자타입
let ddd: number = 10;
ddd = '철수'; // string 형식은 number 형식이 될 수 없다.

// boolean타입
let eee: boolean = true;
eee = false;
eee = 'false'; // boolean 형식은 string 형식이 될 수 없다.

// 배열타입
let fff: number[] = [1, 2, 3, 4, 5, 'hi']; // string 형식은 number 형식이 될 수 없다.
let ggg: string[] = ['철수', '영희', '훈이', 10];  // number형식은 string 형식이 될 수 없다.
let hhh: (number | string)[] = [1, 2, 3, 4, 'Hi'];

// 객체타입
interface IProfile {
    name: string;
    age: number | string;
    school: string;
    hobby?: string;
}
const profile: IProfile = {
    name: '짱구',
    age: 4,
    school: '떡잎유치원',
};

profile.name = '유리'; // 타입 추론으로는 이것만 가능
profile.age = '8살'; // 인터페이스 생성으로 인해 가능 타입을 지정해줘서 가능
profile.hobby = '수영'; // 인터페이스 (?)때문에 가능

// 함수타입 => 어디서 몇번이든 호출 가능하므로, 타입추론 할 수 없음(반드시, 타입명시 필요!!)
function add(num1: number, num2: number, unit: string): string {
    return num1 + num2 + unit;
}

const result = add(1000, 2000, '원'); // 결과의 retrun 타입도 예측 가능!!!

const add2 = (num1: number, num2: number, unit: string): string => {
    return num1 + num2 + unit;
};

const result2 = add2(1000, 2000, '원'); // 결과의 retrun 타입도 예측 가능!!!

// any타입
let qqq: any = '철수'; // 자바스크립트와 동일!!
qqq = 123;
qqq = true;

3️⃣ Decorator(@)

  • Decorator는 함수로써 호출한다.
  • aaa => [class CatsController]를 암시한다.
function Controller(aaa: any) {
    console.log('=========');
    console.log(aaa);
    console.log('=========');
}

@Controller
class CatsController {}

// 실행 결과
// =========
// [class CatsController]
// =========

4️⃣ public, private, protected, readonly

  • public, private, protected, readonly 중 1개라도 있으면 생략가능

① public

// public, private, protected, readonly

class Monster {
    // power 생략가능

    constructor(public power) {
        // this.power = power; 생략가능
    }

    attack1 = () => {
        this.power = 30; // 안에서 수정 가능
        console.log(`${this.power} 만큼 공격한다`); // 안에서 접근 가능
    };
}

class 공중몬스터2 extends Monster {
    attack2 = () => {
        this.power = 30; // 자식이 수정 가능
        console.log(`${this.power} 만큼 공격한다`); // 자식이 접근 가능
    };
}

const mymonster = new 공중몬스터(20);
mymonster.attack1();
mymonster.attack2();
console.log(mymonster22.power); // 밖에서 접근 가능
mymonster.power = 10; // 밖에서 수정 가능

② private

class Monster {
    // power 생략가능

    constructor(private power) {
        // this.power = power; 생략가능
    }

    attack1 = () => {
        this.power = 30; // 안에서 수정 가능
        console.log(`${this.power} 만큼 공격한다`); // 안에서 접근 가능
    };
}

class 공중몬스터 extends Monster {
    attack2 = () => {
        this.power = 30; // 자식이 수정 불가
        console.log(`${this.power} 만큼 공격한다`); // 자식이 접근 불가
    };
}

const mymonster = new 공중몬스터(20);
mymonster.attack1();
mymonster.attack2();
console.log(mymonster.power); // 밖에서 접근 불가
mymonster.power = 10; // 밖에서 수정 불가

③ protected

// public, private, protected, readonly

class Monster {
    // power => public, private, protected, readonly 중 1개라도 있으면 생략가능

    constructor(protected power) {
        // this.power = power; => public, private, protected, readonly 중 1개라도 있으면 생략가능
    }

    attack1 = () => {
        this.power = 30; // 안에서 수정 가능
        console.log(`${this.power} 만큼 공격한다`); // 안에서 접근 가능
    };
}

class 공중몬스터 extends Monster {
    attack2 = () => {
        this.power = 30; // 자식이 수정 가능
        console.log(`${this.power} 만큼 공격한다`); // 자식이 접근 가능
    };
}

const mymonster = new 공중몬스터(20);
mymonster.attack1();
mymonster.attack2();
console.log(mymonster.power); // 밖에서 접근 불가
mymonster.power = 10; // 밖에서 수정 불가

④ readonly

// public, private, protected, readonly

class Monster {
    // power => public, private, protected, readonly 중 1개라도 있으면 생략가능

    constructor(readonly power) {
        // this.power = power; => public, private, protected, readonly 중 1개라도 있으면 생략가능
    }

    attack1 = () => {
        this.power = 30; // 안에서 수정 불가
        console.log(`${this.power} 만큼 공격한다`); // 안에서 접근 가능
    };
}

class 공중몬스터 extends Monster {
    attack2 = () => {
        this.power = 30; // 자식이 수정 불가
        console.log(`${this.power} 만큼 공격한다`); // 자식이 접근 가능
    };
}

const mymonster = new 공중몬스터(20);
mymonster.attack1();
mymonster.attack2();
console.log(mymonster.power); // 밖에서 접근 가능
mymonster.power = 10; // 밖에서 수정 불가

⓹ private-readonly

// public, private, protected, readonly

class Monster {
    // power => public, private, protected, readonly 중 1개라도 있으면 생략가능

    constructor(private readonly power) {
        // this.power = power; => public, private, protected, readonly 중 1개라도 있으면 생략가능
    }

    attack1 = () => {
        this.power = 30; // 안에서 수정 불가
        console.log(`${this.power} 만큼 공격한다`); // 안에서 접근 가능
    };
}

class 공중몬스터 extends Monster {
    attack2 = () => {
        this.power = 30; // 자식이 수정 불가
        console.log(`${this.power} 만큼 공격한다`); // 자식이 접근 불가
    };
}

const mymonster = new 공중몬스터(20);
mymonster.attack1();
mymonster.attack2();
console.log(mymonster.power); // 밖에서 접근 불가
mymonster.power = 10; // 밖에서 수정 불가
profile
코린이 열심히 배우자!

0개의 댓글