클래스와 객체가 서로
의존(Dependency)
하고 있는 것!
//product.controller.js
import { CashService } from './services/cash.service.js'
import { ProductService } from './services/product.service.js'
export class ProductController{
buyProduct = (req, res) => {
// 1. 가진돈 검증하는 코드 (대략 10줄 => class로 인해 2줄)
const cashService = new CashService() //강한 결합
const hasMoney = cashService.checkValue()
// 2. 판매여부 검증하는 코드 (대략 10줄 => class로 인해 2줄)
const productService = new ProductService() // 강한 결합
const isSoldout = productService.checkSoldOut()
// 3. 상품 구매하는 코드
if(hasMoney && !isSoldout ){
res.send("상품 구매 완료!!")
}
}
refundProduct = (req,res) => {
// 1. 판매여부 검증하는 코드 (대략 10줄 => class로 인해 2줄)
const productService = new ProductService() //강한 결합
const isSoldout = productService.checkSoldOut()
// 2. 상품 환불하는 코드
if(isSoldout){
res.send("상품 환불 완료!!")
}
}
}
ProductController
클래스에 선언한 메서드에서 CashService
,ProductService
의 객체를 직접 생성해 메서드를 호출하는 형태 코드이다.
ProductController
클래스가 CashService
, ProductService
클래스를 직접 사용해 생성한 객체에 의존하고 있는 강한 결합 상태이다.
⇒new 를 세번 사용해 메모리를 더 잡아먹는 단점이 생긴다.
⇒ ex) 여기서 CashService
가 CouponService
로 바뀌게 되면 다른 객체들의 변경이 요구되며 하나하나 바꿔줘야하는 단점이 생긴다.
ProductController
가 CashService
와 ProductService
에 **의존성이 존재한다고 하는 것**
이며,
다른 말로는 **강하게 결합되어 있다(Tight Coupling)**
라고도 부른다.
// index.js
// const express = require('express') // 옛날방식 => commonjs
import express from "express"; // 요즘방식 => module
import { ProductController } from "./mvc/controllers/product.controller.js";
import { CouponController } from "./mvc/controllers/coupon.controller.js";
import { ProductService } from "./mvc/controllers/services/product.service.js";
const app = express();
// 추가되는 부분
const cashService = new CashService();
// 상품 API
const productController = new ProductController(cashService);
app.post("/products/buy", productController.buyProduct);
app.post("/products/refund", productController.refundProduct);
// 쿠폰(상품권) API
const couponController = new CouponController();
app.post("/coupons/buy", couponController.buyCoupon);
app.listen(3000, () => {
console.log("백엔드 API 서버가 켜졌어요!!!");
});
controller.js 에 있는 new Cashservice()
을 index.js 밖에서 실행시켜 준다.
ProductController
인자를 cashService 을 넣어줌으로써 cashService 를 생성자
로 넣어주게 된다.
그리고 product.controller.js
파일에서 constructor(){}
함수를 추가해준다.
// product.controller.js
import { ProductService } from './services/product.service.js'
// import { CashService } from "./services/point.service.js";
export class ProductController {
//추가 코드 🐥
constructor(cashService) {
this.cashService = cashService;
}
buyProduct = (req, res) => {
// 1. 가진돈 검증하는 코드(10줄 => 2줄 => 1줄)
// const cashService = new CashService();
const hasMoney = this.cashService.checkValue();
// 판매여부 검증하는 코드(10줄 => 2줄)
const productService = new ProductService()
const isSoldout = productService.checkSoldout();
// 3. 상품 구매하는 코드
if (hasMoney && !isSoldout) {
res.send("상품을 구매합니다.");
}
};
refundProduct = (req, res) => {
// 1. 판매여부 검증하는 코드(10줄 => 2줄 => 1줄)
const productService = new ProductService()
const isSoldout = productService.checkSoldout();
// 2. 상품 환불하는 코드
if (isSoldout) {
res.send("상품을 환불합니다.");
}
};
}
그리곤 hasMoney
선언해준 코드에서 cashService
앞에 this.
를 반드시 붙여줘야한다.
this.
을 사용하게 되면 ProductController class 안의 함수들 선택이 가능해지게 됩니다!
이와 같은 결과로 보면,
ProductController
클래스는 CashService
클래스를 사용해 객체를 생성하지 않는다.
ProductController
외부에서 객체를 생성하여 constructor
를 통해 안으로 전달하는 형태이다.
Constructor Injection(생성자 주입)
을 사용하는 의존성 주입(Dependency Injection)
으로 두 클래스를 느슨한 결합 상태로 만든 것이다.
✋ 주의점 .
의존성주입
으로싱글톤 패턴
을 구현가능하게 하지만의존성주입
이싱글톤 패턴
이 아니다.
객체의
인스턴스
가 오직 1개만 생성되는 패턴이다.
인스턴스
??비슷한 성질(?)을 가진 여러개의 객체를 만들기 위해서 생성자 함수,
Constructor
를 만들어 찍어내듯이 사용하는데 이렇게 생성된 객체를 인스턴스라 부를 수 있습니다. 객체지향언어에서 흔히 사용되는 클래스(Class)가 자바스크립트에서는 프로토타입(prototype)이며 생성자 함수가 사용됩니다. 다시 말하면 클래스나 프로토타입을 사용하여 만들어 낸 것이인스턴스
라고 볼 수 있습니다.