πŸ“Œν”„λ‘ νŠΈμ—”λ“œ μ˜ˆμ‹œλ‘œ μ‚΄νŽ΄λ³΄λŠ” SOLID 원칙 1)단일 μ±…μž„ 원칙

maru5mangoΒ·2022λ…„ 5μ›” 19일
3

λ””μžμΈνŒ¨ν„΄

λͺ©λ‘ 보기
2/4

λ“€μ–΄κ°€λ©°..

λ””μžμΈνŒ¨ν„΄μ€ ν”„λ‘œκ·Έλž˜λ°μ„ ν•˜λ‹€λ³΄λ©΄ λˆ„κ΅¬λ‚˜ ν•œ λ²ˆμ―€μ€ κ·Έ μ€‘μš”μ„±μ„ λ“£κ²Œ λœλ‹€.
그런데 React의 ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈλ‘œ μž‘μ—…ν•˜λŠ”κ²Œ μ΅μˆ™ν•˜λ‹€λ©΄ λ””μžμΈ νŒ¨ν„΄μ˜ μ€‘μš”μ„±μ€ 듀어봀어도, μ–΄λ–»κ²Œ μ μš©ν•΄μ•Ό ν•˜λŠ”μ§€, μ™œ κΌ­ λ°°μ›Œμ•Ό ν•˜λŠ”μ§€ 의문이 λ“€ 수 μžˆλ‹€.

λ””μžμΈ νŒ¨ν„΄ 쀑 κ°€μž₯ 유λͺ…ν•œ GOF의 λ””μžμΈ νŒ¨ν„΄μ€ μ•„λ¬΄λž˜λ„ Class 기반으둜 μ„€λͺ…이 λ˜μ–΄μžˆκ³ , μ„€λͺ…을 찾아봐도 λ³΅μž‘ν•  λΏλ”λŸ¬ Reactλ₯Ό μ‚¬μš©ν•˜λ‹€λ³΄λ©΄ 보톡 ν•¨μˆ˜λ‘œ λͺ¨λ“  것을 μ²˜λ¦¬ν•˜λ‹€λ³΄λ‹ˆ μ•„λ¬΄λž˜λ„ 와닿지가 μ•ŠλŠ”λ‹€.

κ·ΈλŸ¬λ‚˜ λ””μžμΈ νŒ¨ν„΄μ€ OOPλ§Œμ„ μœ„ν•œ 것이 μ•„λ‹Œ 문제 해결을 μœ„ν•œ λ‹€μ–‘ν•œ 아이디어 λΌλŠ” μ ‘κ·Όλ²•μœΌλ‘œ κ³΅λΆ€ν•˜λŠ”κ²Œ μ–΄μšΈλ¦΄ 것 κ°™λ‹€.

πŸ‘€ λ””μžμΈ νŒ¨ν„΄μ΄λž€
"ν”„λ‘œκ·Έλž˜λ°"을 ν•˜λ‹€κ°€ λ§ˆμ£Όν•˜λŠ” μ—¬λŸ¬ 문제λ₯Ό 보닀 "ν˜„λͺ…ν•˜κ²Œ" ν•΄κ²°ν•˜κΈ° μœ„ν•œ μ—¬λŸ¬κ°€μ§€ 접근법을 λ§ν•œλ‹€.
이 μ‹œλ¦¬μ¦ˆμ—μ„œλŠ” GOF의 23가지 λ””μžμΈ νŒ¨ν„΄μ„ ν”„λ‘ νŠΈμ—”λ“œ 예제λ₯Ό 톡해 μ‚΄νŽ΄λ³Ό 것이닀.

πŸ‘ ν˜„λͺ…ν•˜κ²Œ ν•΄κ²°ν•˜κΈ°

  • μΆ”κ°€ κΈ°λŠ₯ κ΅¬ν˜„μ΄ 쉽닀
  • 디버깅이 쉽닀
  • μˆ˜μ • 사항 반영이 쉽닀.

λ―Έμ…˜

힐링 κ²Œμž„μ„ λ§Œλ“€κΊΌμ•Ό.
ν™”λ©΄ κ°€μš΄λ°μ— 고양이가 있고, 마우슀λ₯Ό μ˜€λ²„ν•˜λ©΄ κ³ μ–‘μ΄μ˜ 정보가 λ–΄μœΌλ©΄ μ’‹κ² μ–΄.
κ³ μ–‘μ΄μ˜ μ •λ³΄λŠ” '이름, λ‚˜μ΄'μ•Ό.
κ³ μ–‘μ΄λŠ” λ¨ΉκΈ°, κ±·κΈ°, μΌμ–΄λ‚˜κΈ°, 잠자기, μ”»κΈ°, λ¬Ό λ§ˆμ‹œκΈ°(6가지) 행동을 ν•  수 있고, 5μ΄ˆλ§ˆλ‹€ 랜덀으둜 행동을 μ‹€ν–‰ν• κΊΌμ•Ό.
고양이λ₯Ό ν΄λ¦­ν•˜λ©΄ 무슨 행동을 ν•˜κ³  μžˆλŠ”μ§€ λ§ν’μ„ μœΌλ‘œ μ•Œλ €μ€˜.

STEP1. μš”κ΅¬μ‚¬ν•­ νŒŒμ•…ν•˜κΈ°

  • κ³ μ–‘μ΄λŠ” λ‚˜μ΄μ™€ 이름을 κ°–λŠ”λ‹€.
  • κ³ μ–‘μ΄λŠ” λ¨ΉκΈ°, κ±·κΈ°, μΌμ–΄λ‚˜κΈ°, 잠자기, μ”»κΈ°, λ¬Όλ§ˆμ‹œκΈ°(6가지 행동을 ν•  수 μžˆλ‹€.)
  • ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λ©΄ 고양이λ₯Ό 1마리 μƒμ„±ν•˜κ³ , 5μ΄ˆλ§ˆλ‹€ 랜덀으둜 행동을 ꡐ체해야 ν•œλ‹€.
  • μ‚¬μš©μž μƒν˜Έμž‘μš©μ€ hover, click이 μžˆλ‹€.
  • 말풍선은 κ³ μ–‘μ΄μ˜ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
  • 정보창은 κ³ μ–‘μ΄μ—κ²Œ hoverν–ˆμ„ λ•Œλ§Œ λ‚˜νƒ€λ‚˜κ³  고양이 정보λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

STEP2. ν•  일 λ‚˜λˆ„κΈ°

  • Main
    : λ‚˜μ΄μ™€ 이름을 랜덀으둜 κ°–λŠ” 고양이λ₯Ό λ§Œλ“ λ‹€.

  • Cat
    : 화면에 고양이λ₯Ό κ·Έλ¦°λ‹€.
    : κ³ μ–‘μ΄λŠ” 생성될 λ•Œ λ‚˜μ΄μ™€ 이름을 κ°–λŠ”λ‹€.
    : 총 6가지 행동을 ν•  수 μžˆλ‹€.
    : 5μ΄ˆλ§ˆλ‹€ κ³ μ–‘μ΄μ˜ μƒνƒœλ₯Ό λ°”κΎΌλ‹€.

  • infoToolTip
    : 화면에 정보창을 λ§Œλ“ λ‹€.
    : κ³ μ–‘μ΄μ˜ 정보λ₯Ό 보여쀀닀.

  • stateToolTip
    : 화면에 말풍선을 λ§Œλ“ λ‹€.
    : κ³ μ–‘μ΄μ˜ μƒνƒœλ₯Ό 보여쀀닀.

πŸ“‘ SOLID원칙 1. Single Responsibility(단일 μ±…μž„ 원칙)
: 1가지 μ±…μž„μ„ κ°–λŠ” ν•¨μˆ˜λ‚˜ 클래슀λ₯Ό μž‘μ„±ν•  것
고양이 정보λ₯Ό 정보창에 좜λ ₯을 ν•˜λŠ” 것은 고양이가 ν•˜λŠ” 일이 μ•„λ‹ˆλ‹€.
단일 μ±…μž„ 원칙은 μ‰½κ²Œ 말해 '이름값을 ν•˜λŠ” μ½”λ“œ'λ₯Ό λ§Œλ“œλŠ” 것이닀.

🎈 ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ 단일 μ±…μž„ 원칙
ν”„λ‘ νŠΈμ—μ„œ ν•˜λŠ” 일을 λ‚˜λˆ λ³΄μž
단일 μ±…μž„ 원칙을 μ μš©ν•œλ‹€λ©΄ 폴더λ₯Ό μ–΄λ–»κ²Œ λ‚˜λˆ„κ³ , νŒŒμΌμ„ μ–΄λ–»κ²Œ λ‚˜λˆ„λŠ”κ²Œ μ’‹μ„κΉŒ? ( 닡은 μ—†μœΌλ‹ˆ 같이 κ³ λ―Όν•΄λ³΄μž. 쒋은 방법이 μƒκ°λ‚œλ‹€λ©΄ λŒ“κΈ€λ‘œ κ³΅μœ ν•΄λ„ μ’‹μ•„μš”πŸ˜ )

  • DOM create, update ( UI λ³€κ²½ )
    • ν™”λ©΄ ꡬ성( html )
    • μ‚¬μš©μžμ™€ μƒν˜Έμž‘μš©( eventListener )
    • 화면에 μ–΄λ–»κ²Œ 그릴까( css )
  • API 호좜 ( data κ°€μ Έμ˜€κΈ° )
    • μ„œλ²„μ— 데이터 μš”μ²­
    • ν”„λ‘ ν„°μ—μ„œ μ“°κΈ° μ‰½κ²Œ data convert
  • 데이터 κ΄€λ¦¬ν•˜κΈ° ( Logic )
    • μ„œλ²„ 정보에 따라 κ·Έλ¦¬λŠ” 방식이 λ‹¬λΌμ§€λŠ” 경우
    • μ‚¬μš©μž interaction이 data에 영ν–₯을 λ―ΈμΉ˜λŠ” 경우
    • .......

STEP3. κ΅¬ν˜„ν•˜κΈ°

const

const CAT_NAME_LIST = ["λƒμ˜Ή", "ν•˜λŠ˜", "여름", "λ‚˜λΉ„", "봄이", "μ‚¬λž‘"];
const CAT_ACT = ["eat", "walk", "wake", "sleep", "shower", "drink"];
const CAT_RANDOM_TIMER = 5000;

util

function getRandomNumber(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

function trigger(eventType, data) {
  const event = new CustomEvent(eventType, { detail: data });
  document.dispatchEvent(event);
}

function addEventListener(eventType, listener) {
  document.addEventListener(eventType, listener);
}

main

function main() {
  const $parent = document.getElementById("playground");
  const randomAge = getRandomNumber(1, 14);
  const randomName = CAT_NAME_LIST[randomAge % 6];
  new Cat($parent, {
    name: randomName,
    age: randomAge,
  });
  new InfoToolTip();
  new StateToolTip();
}

cat class

class Cat {
  constructor($parent, data) {
    const idx = getRandomNumber(1, 100) % 6;
    const dataController = new CatData({ ...data, state: CAT_ACT[idx] });
    this._domController = new CatDom($parent, dataController);
  }
}

class CatData {
  constructor({ name, age, state }) {
    this.name = name;
    this.age = age;
    this.state = state;
    setInterval(this.randomAct.bind(this), CAT_RANDOM_TIMER);
  }

  getProfile() {
    return {
      name: this.name,
      age: this.age,
    };
  }

  getState() {
    return this.state;
  }

  randomAct() {
    const state = getRandomNumber(1, 100) % 6;
    const actName = CAT_ACT[state];
    this[actName]();
  }

  eat() {
    this.state = "eat";
  }

  walk() {
    this.state = "walk";
  }

  wake() {
    this.state = "wake";
  }

  sleep() {
    this.state = "sleep";
  }

  shower() {
    this.state = "shower";
  }

  drink() {
    this.state = "drink";
  }
}

class CatDom {
  constructor($parent, dataController) {
    this.$parent = $parent;
    this.dataController = dataController;
    this.createDom();
    this.setEvent();
  }

  createDom() {
    this.$parent.innerHTML += `<div class="cat">고양이</div>`;
  }

  setEvent() {
    const $targetEl = Array.from(this.$parent.getElementsByClassName("cat"));
    $targetEl.forEach(($el) => {
      if (!$el) return;
      $el.addEventListener("click", () => {
        this.click();
      });
      $el.addEventListener("mouseover", () => {
        this.hover();
      });
      $el.addEventListener("mouseleave", () => {
        this.leave();
      });
    });
  }

  click() {
    const state = this.dataController.getState();
    trigger("onCatClick", { state });
  }

  hover() {
    const info = this.dataController.getProfile();
    trigger("onCatHover", { info });
  }

  leave() {
    trigger("onCartLeave");
  }
}

infoToolTip

class InfoToolTip {
  constructor() {
    this.$el = document.getElementById("info");
    this.setEvent();
  }

  setEvent() {
    addEventListener("onCatHover", (e) => {
      const { info } = e.detail;
      const { name, age } = info;
      this.$el.classList.remove("hide");
      this.$el.innerHTML = `이름: ${name}, λ‚˜μ΄: ${age}`;
    });

    addEventListener("onCartLeave", (e) => {
      this.$el.classList.add("hide");
    });
  }
}

stateToolTip

class StateToolTip {
  constructor() {
    this.$el = document.getElementById("state");
    this.setEvent();
  }

  setEvent() {
    addEventListener("onCatClick", (e) => {
      const { state } = e.detail;
      this.$el.classList.remove("hide");
      this.$el.innerHTML = `고양이가 ${state}ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.`;
      setTimeout(() => {
        this.$el.classList.add("hide");
      }, 700);
    });
  }
}

마치며..

μ˜€λŠ˜μ€ SOLIDνŒ¨ν„΄ 쀑 첫번째 원칙, 단일 μ±…μž„ 원칙을 배우고 μ˜ˆμ‹œλ₯Ό λ§Œλ“€μ–΄λ³΄μ•˜λ‹€. μ΅œμ’… μ½”λ“œλŠ” λ‹€μŒ githubμ—μ„œ 확인할 수 μžˆλ‹€.
μ•žμœΌλ‘œλŠ” μš”κ΅¬μ‚¬ν•­μ„ μΆ”κ°€ν•˜κ³ , λ””μžμΈ νŒ¨ν„΄μ„ μ μš©ν•΄ 보며 μ½”λ“œλ₯Ό 점점 닀듬어 보도둝 ν•˜μž.

μ½”λ“œ λ³΄λŸ¬κ°€κΈ° > github

0개의 λŒ“κΈ€