2023.03.28 TIL

μ •μŠΉμ›Β·2023λ…„ 4μ›” 6일
0
post-thumbnail
post-custom-banner

πŸ“’ λͺ©μ°¨

  • πŸ“Œ Tight-coupling & Dependency
  • πŸ“Œ Loose-coupling & Dependency
  • πŸ“Œ 싱글톀 νŒ¨ν„΄
  • πŸ“Œ DI(Dependency Injection/ μ˜μ‘΄μ„±μ£Όμž…)
  • πŸ“Œ IoC(Inversion of Control / μ œμ–΄μ˜ μ—­μ „)
  • πŸ“Œ TypeScript μ‚¬μš© 이유 및 μ‚¬μš©λ°©λ²•
  • πŸ“Œ Decorator 원리
  • πŸ“Œ TypeScript μ‚¬μš© 이유 및 μ‚¬μš©λ°©λ²•
  • 🌈 였늘 ν•˜λ£¨

πŸ“Œ Tight-coupling & Dependency

κ°•ν•œ κ²°ν•©(Tight Coupling)은 ν΄λž˜μŠ€μ™€ 객체가 μ„œλ‘œ 의쑴(Dependency)ν•˜κ³  μžˆλ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€.

βœ… κ°•ν•œ κ²°ν•©(Tight Coupling)의 νŠΉμ§•

  • ν•˜λ‚˜μ˜ 객체λ₯Ό λ³€κ²½ν•˜κ²Œ 되면 λ‹€λ₯Έ κ°μ²΄λ“€μ˜ 변경을 μš”κ΅¬λ˜κΈ° λ•Œλ¬Έμ— 변경점듀을 μ‰½κ²Œ 놓칠 수 μžˆλ‹€.

  • 결합이 κ°•ν•˜κ²Œ λ˜μ–΄μžˆμ–΄ 결합이 λ˜μ–΄μžˆμ§€ μ•ŠμœΌλ©΄ μ‚¬μš© ν•  수 μ—†λ‹€.

  • newλ₯Ό μ„ μ–Έν•  λ•Œλ§ˆλ‹€ 컴퓨터 λ©”λͺ¨λ¦¬λ₯Ό μ‚¬μš©ν•˜κ²Œ λœλ‹€. λ”°λΌμ„œ 비ꡐ적 κ°•ν•œ κ²°ν•©μ—μ„œ newλ₯Ό 더 많이 μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— λ©”λͺ¨λ¦¬λ₯Ό 많이 μž‘μ•„λ¨Ήκ²Œ λœλ‹€.

// 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쀄 => 2쀄)
    const cashService = new CashService();
    const hasMoney = cashService.checkValue(); // true λ˜λŠ” false 리턴

    // 2. νŒλ§€μ—¬λΆ€ κ²€μ¦ν•˜λŠ” μ½”λ“œ (λŒ€λž΅ 10쀄 => 2쀄)
    const productService = new ProductService();
    const isSoldout = productService.checkSoldout(); // true λ˜λŠ” false 리턴

    // 3. μƒν’ˆ κ΅¬λ§€ν•˜λŠ” μ½”λ“œ
    if (hasMoney && !isSoldout) {
      res.send("μƒν’ˆ ꡬ맀 μ™„λ£Œ!!");
    }
  };

  refundProduct = (req, res) => {
    // 1. νŒλ§€μ—¬λΆ€ κ²€μ¦ν•˜λŠ” μ½”λ“œ (λŒ€λž΅ 10쀄 정도)
    const productService = new ProductService();
    const isSoldout = productService.checkSoldout(); // true λ˜λŠ” false 리턴

    // 2. μƒν’ˆ ν™˜λΆˆν•˜λŠ” μ½”λ“œ
    if (isSoldout) {
      res.send("μƒν’ˆ ν™˜λΆˆ μ™„λ£Œ!!");
    }
  };
}

μœ„μ˜ μ†ŒμŠ€μ½”λ“œμ—μ„œ ProductControllerκ°€ CashService와 ProductService에 μ˜μ‘΄ν•˜κ³  μžˆλŠ” μƒνƒœμ΄λ‹€.

λ‹€λ₯Έ λ§λ‘œλŠ” κ°•ν•˜κ²Œ κ²°ν•©λ˜μ–΄ μžˆλ‹€κ³  λΆ€λ₯΄κΈ°λ„ ν•œλ‹€.

πŸ“Œ Loose-coupling & Dependency

λŠμŠ¨ν•œ 결합은 κ°•ν•œ κ²°ν•©μ˜ λ°˜λŒ€ κ°œλ…μ΄λ©°, λ‹€λ₯Έ 클래슀λ₯Ό μ§μ ‘μ μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 클래슀의 μ˜μ‘΄μ„±μ„ μ€„μ΄λŠ” 것이닀.

βœ… λŠμŠ¨ν•œ κ²°ν•©(Loose 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 μ„œλ²„κ°€ μΌœμ‘Œμ–΄μš”!!!");
});

product.controller.js νŒŒμΌμ— μžˆλŠ” new CashService()λ₯Ό λ°–μ—μ„œ μ‹€ν–‰μ‹œμΌœμ€„ 것인데, index.js νŒŒμΌμ—μ„œ μ‹€ν–‰μ‹œμΌœ 쀄 것이닀.

μΆ”κ°€ μž‘μ„±ν•œ cashServiceλ₯Ό ProductController() μ•ˆμ— λ„£μ–΄μ€ŒμœΌλ‘œμ¨ λ°–μ—μ„œ λ§Œλ“€μ–΄μ„œ μ•ˆμœΌλ‘œ λ„£μ–΄μ£Όκ²Œ λ˜λŠ” 것이닀.

즉, cashServiceλ₯Ό μƒμ„±μžλ‘œ λ„£μ–΄μ€€ 것이닀. μ΄λ ‡κ²Œ ν•¨μœΌλ‘œμ¨ κ°•ν•œκ²°ν•©μ„ μ•½ν•œκ²°ν•©μœΌλ‘œ λ°”κΏ€ 수 μžˆλ‹€.

λ˜ν•œ, μ΄λŸ¬ν•œ 방법은 싱글톀 νŒ¨ν„΄μ΄λ‹€.

πŸ“Œ 싱글톀 νŒ¨ν„΄

λΉ„μ¦ˆλ‹ˆμŠ€ 둜직인 CashService λ₯Ό λ¨Όμ € μ„ μ–Έν•˜μ˜€λ‹€.

μ΄λ ‡κ²Œ ν•˜λ©΄ new ν•œ 번으둜 λͺ¨λ“  κ³³μ—μ„œ μ‚¬μš© κ°€λŠ₯ν•˜κ²Œ λœλ‹€.

이런 λ””μžμΈ νŒ¨ν„΄μ„ Singleton Pattern(싱글톀 νŒ¨ν„΄)이라고 ν•œλ‹€.

μ§€κΈˆκΉŒμ§€ μ‚΄νŽ΄λ³Έ 바와 같이 μ˜μ‘΄μ„±μ£Όμž…μœΌλ‘œ 얻을 수 μžˆλŠ” μ‹±κΈ€ν†€νŒ¨ν„΄μ˜ μž₯μ μœΌλ‘œλŠ” 2가지가 μ‘΄μž¬ν•œλ‹€.

  • new ν•œ 번으둜 λͺ¨λ“  κ³³μ—μ„œ μ‚¬μš© κ°€λŠ₯ν•˜λ‹€.

  • κ°•ν•˜κ²Œ κ²°ν•©λ˜μ–΄ μžˆλŠ” μƒνƒœμ—μ„œ λŠμŠ¨ν•œ κ²°ν•©μœΌλ‘œ ν’€λ¦¬κ²Œ λœλ‹€.

πŸ“Œ DI(Dependency Injection/ μ˜μ‘΄μ„±μ£Όμž…)

DI(Dependency Injection) μ˜μ‘΄μ„±μ£Όμž…μ€ Tight Coupling(κ°•ν•œ κ²°ν•©)을 Loose Coupling(λŠμŠ¨ν•œ κ²°ν•©)으둜 μ „ν™˜ μ‹œν‚€λŠ” 방법이며, μ œμ–΄μ˜ μ—­μ „(Inversion of Control)의 기술 쀑 ν•˜λ‚˜μ΄λ‹€.

  • μ œμ–΄μ˜ μ—­μ „ :Β "λ‚΄κ°€ λŒ€μ‹  μ œμ–΄ν•΄ μ€„κ²Œ"

  • μ˜μ‘΄μ„±μ£Όμž… :Β "λ‹ˆκ°€ μ •μ˜ν•œ μ½”λ“œ(클래슀, λ³€μˆ˜ λ“±λ“±)λ₯Ό"

βœ… μ˜μ‘΄μ„± μ£Όμž…μ΄λ©΄ 싱글톀 νŒ¨ν„΄μΌκΉŒ?

μ˜μ‘΄μ„±μ£Όμž…μ΄λ©΄ μ‹±κΈ€ν†€νŒ¨ν„΄μ΄ μ•„λ‹ˆλ‹€.

new λ₯Ό λ°–μœΌλ‘œ 빼주게 λ˜λ©΄μ„œ μ‹±κΈ€ν†€νŒ¨ν„΄μ΄ 된 것은 λ§žμ§€λ§Œ μ˜μ‘΄μ„±μ£Όμž…μ΄λΌλŠ” 것은 λ°–μ—μ„œ μ•ˆμœΌλ‘œ λ„£μ–΄μ£ΌλŠ” 것이기에 κ°™λ‹€κ³ λŠ” ν•  수 μ—†λ‹€.

πŸ“Œ IoC(Inversion of Control / μ œμ–΄μ˜ μ—­μ „)

μ˜μ‘΄μ„±μ£Όμž…μœΌλ‘œ 얻을 수 μžˆλŠ” μž₯점 2κ°€μ§€μ˜ 과정이 NestJS μ—μ„œλŠ” μžλ™μœΌλ‘œ μ΄λ£¨μ–΄μ§€κ²Œ λœλ‹€!

λ”°λΌμ„œ, new λ₯Ό μ‚¬μš©ν•˜μ—¬ μš°λ¦¬κ°€ λ§Œλ“€μ–΄μ€˜μ•Όν–ˆλ˜ 것듀, μ˜μ‘΄μ„±μ£Όμž… 등을 NestJSκ°€ ν•΄μ£Όκ²Œ λ˜λ©΄μ„œ NestJS μͺ½μœΌλ‘œ μ œμ–΄κ°€ μ—­μ „(IoC)λ˜μ—ˆλ‹€.

μ œμ–΄μ˜ μ—­μ „(Inversion of Control)은 μΌλ°˜μ μΈΒ λ””μžμΈ νŒ¨ν„΄Β μ€‘ ν•˜λ‚˜λ‹€.

일반적으둜 κ°œλ°œμžκ°€ ν”„λ‘œκ·Έλž¨μ˜ 흐름을 μ œμ–΄ν•˜λŠ” μ£Όμ²΄μ˜€λ‹€λ©΄, IoC의 κ°œλ…μ΄ λ‚˜μ˜€κ²Œ λ˜λ©΄μ„œ ν”„λ ˆμž„μ›Œν¬κ°€ dependencyλ₯Ό containerν™” μ‹œμΌœ 생λͺ…μ£ΌκΈ°λ₯Ό κ΄€λ¦¬ν•˜κ²Œ λ˜μ—ˆλ‹€.

즉, dependency의 μ œμ–΄κΆŒμ΄ κ°œλ°œμžμ—μ„œ ν”„λ ˆμž„μ›Œν¬λ‘œ λ„˜μ–΄κ°€κ²Œ λ˜μ—ˆμœΌλ©° 이λ₯Ό μ œμ–΄κΆŒμ˜ 흐름이 λ³€κ²½λ˜μ—ˆλ‹€κ³  ν•˜μ—¬ IoC(Inversion of Control)라고 ν•œλ‹€.

πŸ“Œ TypeScript μ‚¬μš© 이유 및 μ‚¬μš©λ°©λ²•

νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ— νƒ€μž…μ„ λΆ€μ—¬ν•œ 언어이닀.

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν™•μž₯된 언어라고 λ³Ό 수 μžˆλ‹€.

νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ™€ 달리 λΈŒλΌμš°μ €μ—μ„œ μ‹€ν–‰ν•˜λ €λ©΄ νŒŒμΌμ„ ν•œλ²ˆ λ³€ν™˜ν•΄ μ£Όμ–΄μ•Ό ν•œλ‹€.

이 λ³€ν™˜ κ³Όμ •μ„Β μ»΄νŒŒμΌ(complile) 이라고 λΆ€λ₯Έλ‹€.

βœ… Why TypeScript?

μžλ°”μŠ€ν¬λ¦½νŠΈλ„ μΆ©λΆ„νžˆ λ³΅μž‘ν•˜κ³  μ–΄λ €μš΄λ° μ™œ 또 λ‹€λ₯Έ μ–Έμ–΄λ₯Ό λ°°μ›Œμ•Ό ν• κΉŒ? 단지 μ΅œμ‹  κΈ°μˆ μ΄λΌμ„œ? ν˜Ήμ€ λ‹€λ₯Έ νšŒμ‚¬λ„ 많이 μ‚¬μš©ν•˜λ‹ˆκΉŒ μš°λ¦¬λ„ 써야 ν•˜λŠ” 걸까? λΌλŠ” 고민을 ν•  수 μžˆλ‹€.

νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μ•„λž˜ 2가지 κ΄€μ μ—μ„œ μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œμ˜ ν’ˆμ§ˆκ³Ό 개발 생산성을 높일 수 μžˆλ‹€.

  • μ—λŸ¬μ˜ 사전 방지

  • μ½”λ“œ κ°€μ΄λ“œ 및 μžλ™ μ™„μ„±(개발 생산성 ν–₯상)

//* νƒ€μž…μΆ”λ‘ 
let aaa = "μ•ˆλ…•ν•˜μ„Έμš”";
//처음 λ“€μ–΄μ˜¨ κ°’μœΌλ‘œ νƒ€μž…μ„ μΆ”λ‘ ν•œλ‹€
// :νƒ€μž… -> ꡳ이 μ•ˆν•΄λ„ λœλ‹€
// aaa = 3; (X)

//* νƒ€μž…λͺ…μ‹œ
let bbb: string = "λ°˜κ°‘μŠ΅λ‹ˆλ‹€";
// bbb = 10; (X)

//* νƒ€μž… λͺ…μ‹œκ°€ ν•„μš”ν•œ 상황
// number λ˜λŠ” string νƒ€μž…
let ccc: number | string = 1000;
ccc = "1000원";

//* μˆ«μžνƒ€μž…
let ddd1 = 10;
let ddd2: number = 10;
// ddd1 = "철수" (X)

//* λΆˆλ¦°νƒ€μž…
let eee: boolean = true;
eee = false;
// eee = "false" ("false" -> true둜 μž‘λ™ν•œλ‹€.)

//* λ°°μ—΄νƒ€μž…
let fff: number[] = [1, 2, 3, 4, 5];
let ggg: string[] = ["철수", "영희", "ν›ˆμ΄"];
let hhh = ["철수", "영희", "ν›ˆμ΄", 1]; // νƒ€μž…μ„ μΆ”λ‘ ν•΄μ„œ μ–΄λ–€ νƒ€μž…μ„ μ‚¬μš©ν•˜λŠ”μ§€ μ•Œμ•„λ³΄κΈ°!!

//* κ°μ²΄νƒ€μž…
interface IProfile {
  name: string;
  age: number | string;
  school: string;
  hobby?: string; // hobby? -> μžˆμ–΄λ„λ˜κ³  없어도됨
}

const profile: IProfile = {
  name: "철수",
  age: 8,
  school: "λ‹€λžŒμ₯μ΄ˆλ“±ν•™κ΅",
};

profile.name = "ν›ˆμ΄"; // νƒ€μž… μΆ”λ‘ μœΌλ‘œλŠ” μ΄κ²ƒλ§Œ κ°€λŠ₯!!
profile.age = "8μ‚΄";
profile.hobby = "수영";

//* anyνƒ€μž…
let qqq: any = "철수"; //μžλ°”μŠ€ν¬λ¦½νŠΈμ™€ 동일!
qqq = 123;
qqq = true;

//* ν•¨μˆ˜νƒ€μž… => μ–΄λ””μ„œ λˆ„κ°€ μ–΄λ–»κ²Œ ν˜ΈμΆœν• μ§€ λͺ¨λ₯΄λ―€λ‘œ, νƒ€μž…μΆ”λ‘  ν•  수 μ—†μŒ (λ°˜λ“œμ‹œ, νƒ€μž…λͺ…μ‹œ ν•„μš”!!)
function add(num1: number, num2: number, unit: string): string {
  // 끝에 :string -> return νƒ€μž…
  return num1 + num2 + unit;
}
const result = add(1000, 2000, "원"); // 결과의 리턴 νƒ€μž…λ„ 예츑 κ°€λŠ₯!!!

//* ν™”μ‚΄ν‘œ ν•¨μˆ˜
const add2 = (num1: number, num2: number, unit: string): string => {
  // 끝에 :string -> return νƒ€μž…
  return num1 + num2 + unit;
};
const result2 = add2(1000, 2000, "원"); // 결과의 리턴 νƒ€μž…λ„ 예츑 κ°€λŠ₯!!!

πŸ“Œ Decorator 원리

λ°μ½”λ ˆμ΄ν„°λŠ” μ‹€ν–‰ν•˜λ €λŠ” μ‚¬μš©μžκ°€ ꡬ쑰λ₯Ό μˆ˜μ •ν•˜μ§€ μ•Šκ³  κΈ°μ‘΄ 객체에 μƒˆλ‘œμš΄ κΈ°λŠ₯을 μΆ”κ°€ν•  수 μžˆλ„λ‘ ν•˜λŠ” λ””μžμΈ νŒ¨ν„΄μ΄λ‹€.

일반적으둜 λ°μ½”λ ˆμ΄νŠΈ ν•˜λ €λŠ” ν•¨μˆ˜μ˜ μ •μ˜ 전에 ν˜ΈμΆœλœλ‹€.

λ°μ½”λ ˆμ΄ν„°λŠ” ν•¨μˆ˜λ₯Ό 인수둜 μ–»κ³  λŒ€κ°€λ‘œ μƒˆλ‘œμš΄ ν•¨μˆ˜λ‘œ λŒλ €μ£ΌλŠ” callable(전달받은 object μΈμžκ°€ 호좜 κ°€λŠ₯ν•œμ§€λ₯Ό νŒλ‹¨)ꡬ쑰 이닀.

μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό ν™•μž₯ν•œ 언어라고 ν•  수 μžˆλŠ” νƒ€μž… μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” μ‹€ν—˜μ μΈ κΈ°λŠ₯으둜 λ°μ½”λ ˆμ΄ν„°λ₯Ό μ œκ³΅ν•˜κ³  μžˆλ‹€.

λ”°λΌμ„œ μ»€λ§¨λ“œ λΌμΈμ΄λ‚˜ tsconfig.jsonμ—μ„œ experimentalDecorators μ˜΅μ…˜μ„ μΆ”κ°€ν•΄ μ€˜μ•Ό ν•œλ‹€.

πŸ“Œ public / private / protected 와 readonly

βœ… public

class Monster2 {
// power;         => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯

  constructor(public power) {
    // this.power = power; 
    // => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯
  }

  attack1 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μ•ˆμ—μ„œ μ ‘κ·Ό κ°€λŠ₯
    this.power = 30; // μ•ˆμ—μ„œ λ³€κ²½ κ°€λŠ₯
  };
}

class 곡쀑λͺ¬μŠ€ν„°2 extends Monster2 {
  attack2 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μžμ‹μ΄ μ ‘κ·Ό κ°€λŠ₯
    this.power = 30; // μžμ‹μ΄ λ³€κ²½ κ°€λŠ₯
  };
}

const myMonster22 = new 곡쀑λͺ¬μŠ€ν„°2(20);
myMonster22.attack1();
myMonster22.attack2();
console.log(myMonster22.power); // μ™ΈλΆ€μ—μ„œ μ ‘κ·Ό κ°€λŠ₯
myMonster22.power = 50; // μ™ΈλΆ€μ—μ„œ λ³€κ²½ κ°€λŠ₯

βœ… private

class Monster2 {
  // power;   => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯

  constructor(private power) {
    // this.power = power;          
    // => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯
  }

  attack1 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μ•ˆμ—μ„œ μ ‘κ·Ό κ°€λŠ₯
    this.power = 30; // μ•ˆμ—μ„œ λ³€κ²½ κ°€λŠ₯
  };
}

class 곡쀑λͺ¬μŠ€ν„°2 extends Monster2 {
  attack2 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μžμ‹μ΄ μ ‘κ·Ό λΆˆκ°€
    this.power = 30; // μžμ‹μ΄ λ³€κ²½ λΆˆκ°€
  };
}

const myMonster22 = new 곡쀑λͺ¬μŠ€ν„°2(20);
myMonster22.attack1();
myMonster22.attack2();
console.log(myMonster22.power); // μ™ΈλΆ€μ—μ„œ μ ‘κ·Ό λΆˆκ°€
myMonster22.power = 50; // μ™ΈλΆ€μ—μ„œ λ³€κ²½ λΆˆκ°€

βœ… protected

class Monster2 {
  // power; => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯

  constructor(protected power) {
    // this.power = power;          
    // => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯
  }

  attack1 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μ•ˆμ—μ„œ μ ‘κ·Ό κ°€λŠ₯
    this.power = 30; // μ•ˆμ—μ„œ λ³€κ²½ κ°€λŠ₯
  };
}

class 곡쀑λͺ¬μŠ€ν„°2 extends Monster2 {
  attack2 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μžμ‹μ΄ μ ‘κ·Ό κ°€λŠ₯
    this.power = 30; // μžμ‹μ΄ λ³€κ²½ κ°€λŠ₯
  };
}

const myMonster22 = new 곡쀑λͺ¬μŠ€ν„°2(20);
myMonster22.attack1();
myMonster22.attack2();
console.log(myMonster22.power); // μ™ΈλΆ€μ—μ„œ μ ‘κ·Ό λΆˆκ°€
myMonster22.power = 50; // μ™ΈλΆ€μ—μ„œ λ³€κ²½ λΆˆκ°€

βœ… readonly

class Monster2 {
  // power; => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯

  constructor(readonly power) {
    // this.power = power;          
    // => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯
  }

  attack1 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μ•ˆμ—μ„œ μ ‘κ·Ό κ°€λŠ₯
    this.power = 30; // μ•ˆμ—μ„œ λ³€κ²½ λΆˆκ°€
  };
}

class 곡쀑λͺ¬μŠ€ν„°2 extends Monster2 {
  attack2 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μžμ‹μ΄ μ ‘κ·Ό κ°€λŠ₯
    this.power = 30; // μžμ‹μ΄ λ³€κ²½ λΆˆκ°€
  };
}

const myMonster22 = new 곡쀑λͺ¬μŠ€ν„°2(20);
myMonster22.attack1();
myMonster22.attack2();
console.log(myMonster22.power); // μ™ΈλΆ€μ—μ„œ μ ‘κ·Ό κ°€λŠ₯
myMonster22.power = 50; // μ™ΈλΆ€μ—μ„œ λ³€κ²½ λΆˆκ°€

βœ… private-readonly

class Monster2 {
  // power; => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯

  constructor(private readonly power) {
    // this.power = power;          
    // => public, private, protected, readonly 쀑 1κ°œλΌλ„ 있으면 μƒλž΅ κ°€λŠ₯
  }

  attack1 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μ•ˆμ—μ„œ μ ‘κ·Ό κ°€λŠ₯
    this.power = 30; // μ•ˆμ—μ„œ λ³€κ²½ λΆˆκ°€
  };
}

class 곡쀑λͺ¬μŠ€ν„°2 extends Monster2 {
  attack2 = () => {
    console.log("κ³΅κ²©ν•˜μž!!");
    console.log("λ‚΄ 곡격λ ₯은" + this.power + "μ•Ό!!!"); // μžμ‹μ΄ μ ‘κ·Ό λΆˆκ°€
    this.power = 30; // μžμ‹μ΄ λ³€κ²½ λΆˆκ°€
  };
}

const myMonster22 = new 곡쀑λͺ¬μŠ€ν„°2(20);
myMonster22.attack1();
myMonster22.attack2();
console.log(myMonster22.power); // μ™ΈλΆ€μ—μ„œ μ ‘κ·Ό λΆˆκ°€
myMonster22.power = 50; // μ™ΈλΆ€μ—μ„œ λ³€κ²½ λΆˆκ°€

🌈 였늘 ν•˜λ£¨

μ˜€λŠ˜μ€ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ— λŒ€ν•˜μ—¬ ν•™μŠ΅ν•œ 날이닀. νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό 톡해 κΈ°μ‘΄ μžλ°”μŠ€ν¬λ¦½νŠΈλ³΄λ‹€ λͺ…ν™•ν•˜κ²Œ μžλ£Œν˜•μ„ μ„ μ–Έν•˜κ³  데이터λ₯Ό λ‹€λ£° 수 있게 λ˜λ©΄μ„œ μ•žμœΌλ‘œ ν•™μŠ΅ν•  λ„€μŠ€νŠΈjs에 λŒ€ν•΄ μ€€λΉ„ν•˜λŠ” λ‚ μ΄μ—ˆλ‹€.

post-custom-banner

0개의 λŒ“κΈ€