부트캠프/회고

[TIL] 프로그래머스 프론트엔드 데브코스 DAY13 TIL

Junly_21 2023. 10. 6. 14:39

공부한 내용 📖

 

명령형프로그램

명령형 프로그램은 컴퓨터가 수행할 명령을 순서대로 써놓은 것.

'어떻게 구현하는가' 가 초점이 맞추어져있다.

내가 써본 언어중 C가 대표적이다.

 

 

선언형프로그램

명령형과 반대되는 개념

'어떻게 하느냐' 라기보단 '무엇을 나타내냐'에 초점.

HTML은 대표적인 선언형 방식. 

어떤 태그들을 나열해서 나타낼 것인지에 대해 초점이 맞춰져있고 '어떻게 렌더링을 구현하냐'에 초점을 두었다.

 

가장 간단하게 배열을 예시로 들면

for문과 index를 활용한 반복문에서

forEach를 활용하는 반복 메소드를 활용하는 것이다

 

선언형 프로그래밍 실습

 

버튼을 클릭시 버튼에 삭선이 on/off되는 기능을 

명령형 프로그래밍으로 시작하여 점차 선언형으로 바꿔나가는 작업을 하였다. 다음은 html 뼈대 코드이다.

 

  <body>
    <div id="app"></div>
  </body>

여기서 js만을 사용해 기능 구현을 진행할 것인데 명령형을 보면 다음과 같다.

const $app = document.querySelector("#app");

const $button1 = document.createElement("button");
const $button2 = document.createElement("button");
const $button3 = document.createElement("button");

$button1.textContent = "btn1";
$button2.textContent = "btn2";
$button3.textContent = "btn3";

$app.appendChild($button1);
$app.appendChild($button2);
$app.appendChild($button3);

document.querySelectorAll("button").forEach(($button) => {
  $button.addEventListener("click", (e) => {
    if (e.target.style.textDecoration === "line-through") {
      e.target.style.textDecoration = "none";
    } else {
      e.target.style.textDecoration = "line-through";
    }
  });
});

버튼을 만들고, textContent를 설정해주고, 버튼에 대해 forEach를 돌려서 삭선 속성에 대해 반대로 설정해주었다.

 

이렇게 만들면 다른 종류의 버튼, 다른 버튼을 추가할 때 일일히 추가해주어야하는데, 

 

선언형 프로그래밍의 완성본을 보면 최 하단에 객체 하나만 추가해주면 모든게 끝난다. 코드는 다음과 같다.

const $app = document.querySelector("#app");

function ToggleButton({ $target, text, onClick }) {
  const $btn = document.createElement("button");
  $target.appendChild($btn);
  this.state = {
    cnt: 0,
    toggle: false,
  };

  //appendchild 이후에 그려줄 render함수
  this.render = () => {
    $btn.textContent = text;

    $btn.style.textDecoration = this.state.toggle ? "line-through" : "none";
  };

  this.setState = (nextState) => {
    this.state = nextState;
    this.render();
  };

  $btn.addEventListener("click", () => {
    this.setState({
      cnt: this.state.cnt + 1,
      toggle: !this.state.toggle,
    });

    if (onClick) {
      onClick(this.state.cnt);
    }
  });

  this.render();
}

function ButtonGroup({ $target, buttons }) {
  let $group;
  isInit = false;

  this.render = () => {
    if (!isInit) {
      $group = document.querySelector("div");
      buttons.forEach(({ type, ...rest }) => {
        if (type === "toggle") {
          new ToggleButton({ $target, ...rest });
        } else {
          new TimerButton({ $target, ...rest });
        }
      });
    }
    $target.appendChild($group);
    isInit = true;
  };
  this.render();
}

new ButtonGroup({
  $target: $app,
  buttons: [
    {
      type: "toggle",
      text: "T1",
    },
    {
      type: "toggle",
      text: "T2",
    },
    {
      type: "toggle",
      text: "T3",
    },
    {
      type: "timer",
      text: "M1",
      time: 1000,
    },
  ],
});

ButtonGroup에서 설정된 target, type, text를 받아서 type에 따라 토글버튼인지 타이머버튼인지 넘겨주고 (이 코드에선 타이머 버튼은 삭제)

 

토글버튼에서는 받은 속성을 또 일일히 바꿔주기보단 setState를 통해 왔다갔다 해준다. 이러면 다른 속성을 추가할때도 용이하다. 색을 바꾸는 기능을 추가한다던지...

 

삭제된 timer버튼타입도  이렇게 선언형으로 작성했기 때문에 추가하기 쉬운것이었다.

 

 

 

궁금한 내용/부족한 내용🤔

선언형 방식으로 프로그램을 작성하는 것은 많은 노력과 구현경험이 필요해보인다.

 

 

느낀점✍

 

간단한 기능에서는 선언형이 오히려 어려워보이지만 결국 기능이 커지고 복잡할수록 선언형이 유지보수에 용이하다.

 

기능을 우선 명령형으로 구현하고 하나씩 선언형으로 바꿔나가는 연습이 필요해보인다.