nestjs를 위한 typescript의 지식을 알아보자.
- class생성과 강한 결합
class 생성을 먼저 알아보고 강한결합을 알아보자.
class란 무엇이고 언제 어떻게 사용되지?
-class정의
class는 객체 지향 프로그래밍에서 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀이고, 객체를 정의하기 위한 상태(멤버 변수)와 메서드(함수)로 구성된다.
이는 설명서라고 생각하면 된다. 이 클래스로 인스턴스를 만들 수 있다.
-class는 언제 사용하는가?
실무에선 사용자나 물건 같이 동일한 종류의 객체를 여러 개 생성해야 하는 경우 사용한다.
API를 만들때 미들웨어 함수를 class로 만들고 그 내부의 함수를 다른 class에서 만든 인스턴스의 매소드로 활용할때 사용한다.
-예) class 이해를 위해 nestjs를 사용하지 않았다.
/느슨한 결합/의존성 주입import { CashService } from "./services/cash.services.js"; export class CouponController { cashService; constructor(cashService) { this.cashService = cashService; } buyCoupon = (req, res) => { //1.가진동 검증하는 코드(대략10줄=>2줄) const cashService = new CashService(); //설명서로 만들어 낸다. const hasMoney = this.cashService.checkValue(); //2.상품권 구매하는 코드() if (hasMoney) { res.send("상품권 구매 완료!!"); } }; }
CouponController라는 class를 만들었다. 이 class내에서 화살표 함수로 이뤄진 부분이 클래스의 매소드에 해당하고. constructor()함수는 생성자라고 하는데 이는 class내에 인자로 가져오고 싶은게 있을때 사용한다. 추후에 이를 이용해 의존성 주입을 한다.
그리고 constructor()윗줄에 있는 cashServic를 멤버 변수라고 한다. class에서는 변수를 선언할때 선언자(식별자)var,let,const를 사용하지 않는다.
예로 의존성 주입(약한 결합)을 들었지만 지금부터 강한결합을 알아보자.
강한 결합을 알아보고 약한결합을 알아보는게 더 이해 잘될지 모르지만 constructor()함수와 연결하여 설명하다 보니 순서가 좀 바뀌었다.
강한결합을 설명한후 역한결합을 더 알아보자.
예) 강한결합
import { CashService } from "./services/cash.services.js"; import { ProductService } from ".services/product.services.js"; export class ProductController { buyProduct = (req, res) => { //1.가진돈 검증하는 코드(대략 10줄 정도=>2줄) const cashService = new CashService(); const hasMoney = cashService.checkValue(); //2.판매여부 검증하는 코드(대략 10줄정도=>2줄) const productService = new ProductService(); const isSoldOut = ProductService.checkSoldOut(); //3.상품 구매하는 코드 if (hasMoney && isSolidOut) { res.send("상품 구매 완료!!"); } }; refundProduct = (req, res) => { //1.판매여부 검증하는 코드(대략 10줄정도=>2줄) // 위 코드를 가지고 왔다. 공통되는것이니 하나를 만들고 가져다 쓰는 방식으로 사용할 수 있다. 함수를 만들어서 import해서 사용하거나. 헷갈리기에 그룹핑해준다. const ProductService = new ProductService(); const isSoldOut = ProductService.checkSoldOut(); //2.상품환불하는 코드() // 이는 상품구매하는 코드를 전략패턴으로 변형시키면 되지 않나? if (isSoldOut) { res.send("상품 환불 완료!!"); } }; }
강한 결합을 이해해보자.
일단 결합니 뭘까? 뭘 결합한것이라 할까? 결합이 되지 않을경우 해당 class가 정의 되지 않는 경우를 결합이라고 한다. 위의 예를 보면ProductController 라는 class안에 아래와 같은 코드가 작성되어 있다.import { CashService } from "./services/cash.services.js"; ..... ..... .... buyProduct = (req, res) => { //1.가진돈 검증하는 코드(대략 10줄 정도=>2줄) const cashService = new CashService(); const hasMoney = cashService.checkValue(); //2.판매여부 검증하는 코드(대략 10줄정도=>2줄) const productService = new ProductService(); const isSoldOut = ProductService.checkSoldOut(); //3.상품 구매하는 코드 if (hasMoney && isSolidOut) { res.send("상품 구매 완료!!"); } };
보면 ProductController 의 매소드 buyProduct를 정의하는 요소중하나인 const hasMoney = cashService.checkValue();가 있는데 이 코드에서 cashService는
const cashService = new CashService();이과정을 거쳐 만들어진 인스턴스이고 CashService 클래스는 import { CashService } from "./services/cash.services.js";이과정을 거쳐 import된 클래스이다.
대략적으로 말하면 CashService 클래스에 의해 ProductController가 정의 되고 있다.
이것을 결합이라고 한다. 그중에서 위의 결합을 강한 결합이라고 하는데 이유는 의존성이 높기 때문이다.
강한 결합의 특징은 아래와 같다.
- 하나의 객체를 변경하게 되면 다른 객체들의 변경도 요구되어 변경점들을 확인하고 쉽게 놓칠 수 가 있어 유지보수및 관리가 어렵다.
- 결합이 강하게 되어있어 결합이 되어있지 않으면 사용을 할 수 없게 된다.
- new를 선언할 때마다 컴퓨터 메모리를 사용하게 되는데 비교적으로 강한 결합에서 new를 더 많이 사용해 메모리를 많이 잡아먹어 저장공간을 비효율적으로 쓰게된다.
이제 약한결합과 의존성주입을 알아보자.
- 약한 결합과 의존성주입
-약한 결합의 정의
의존성주입으로 인안 결합을 약한결합이라고 하며 강한결합에 비해 유지보수및 관리가 쉽고, new연산자 사용이 적어 상대적으로 저장공간 효율이 좋다고, 테스트 대역으로 치환하기가 쉬워 유닛 테스트가 용이하다.
아래의 예를 보면서 이해하자.
-예) 의존성 주입**index.js** import express from "express"; import { ProductController } from "./mvc/controllers/product.controller.js"; import { CouponController } from "./mvc/controllers/coupon.controller.js"; import { CashService } from "./mvc/controllers/services/cash.services.js"; import { PointService } from "./mvc/controllers/services/point.services.js"; import { ProductService } from "./mvc/controllers/services/product.services.js" const app = express(); const productService = new ProductService(); const cashService = new CashService(); const pointService = new PointService(); const productController = new ProductController(pointService, productService); app.post("/products/buy", productController.buyProduct); app.post("/products/refund", productController.refundProduct); const couponController = new CouponController(pointService); app.post("/coupons/buy", couponController.buyCoupon); app.listen(3000);
index.js에서 코드를 살펴보면
const productService = new ProductService(); const cashService = new CashService(); const pointService = new PointService(); const productController = new ProductController(pointService, productService);
class를 import해와서 새로운 인스턴스를 만들고 있다.
그리고 ProductController 클래스의 인스턴스를 만들때 인자로 넣어 주어 의존성 주입을 해준다.**coupon.controller.js** import { CashService } from "./services/cash.services.js"; export class CouponController { cashService; constructor(cashService) { this.cashService = cashService; } buyCoupon = (req, res) => { //1.가진동 검증하는 코드(대략10줄=>2줄) const cashService = new CashService(); //설명서로 만들어 낸다. const hasMoney = this.cashService.checkValue(); //2.상품권 구매하는 코드() if (hasMoney) { res.send("상품권 구매 완료!!"); } }; }
coupon.controller.js에서 constructor함수로 인자로 받아와주고 주입받은 인스턴스를 활용하고 있다. 이를 의존성주입이라 하고,
이렇게 되면 내가 정의한 클래스,변수 등등을 개발자스스로가 아닌 컴퓨터가 대신 제어해주게 된다. 내가 직접 import하지 않았음에도 다른 파일에서 사용되게 된다. 이를 제어의 역전이라고 한다.
의존성주입과 연관된 싱글톤패턴을 알아보자. 싱글톤 패턴은 한번의 인스턴스 생성으로 의존성주입을 한 클래스에서 여러번 쓰이는 것을 말한다. 이는 유지보수측면에서 효율적이다.
출처[코드캠프-부트캠프-수업자료]