Unit6 - 간단한 웹앱 만들기

강성일·2023년 4월 21일
0
post-thumbnail

✅ TIL


오늘은 계산기 샘플을 받아 진행하였다.


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JavaScript Calculator</title>
    <link
      href="https://fonts.googleapis.com/css?family=Righteous"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="./yourStyle.css" />
  </head>
  <body>
    <div class="container">
      <div class="calculator">
        <div class="calculator__display--bare">
          <span class="calculator__operend--left">0</span>
          <span class="calculator__operator">+</span>
          <span class="calculator__operend--right">0</span>
          <span class="calculator__equal">=</span>
          <span class="calculator__result">0</span>
        </div>
        <div class="calculator__display--for-advanced">0</div>
        <div class="calculator__buttons">
          <div class="clear__and__enter">
            <button class="clear">AC</button>
            <button class="calculate">Enter</button>
          </div>
          <div class="button__row">
            <button class="number">7</button>
            <button class="number">8</button>
            <button class="number">9</button>
            <button class="operator">+</button>
          </div>
          <div class="button__row">
            <button class="number">4</button>
            <button class="number">5</button>
            <button class="number">6</button>
            <button class="operator">-</button>
          </div>
          <div class="button__row">
            <button class="number">1</button>
            <button class="number">2</button>
            <button class="number">3</button>
            <button class="operator">*</button>
          </div>
          <div class="button__row">
            <button class="number double">0</button>
            <button class="decimal">.</button>
            <button class="operator">/</button>
          </div>
        </div>
      </div>
      <img class="logo" src="data/codestates-logo.png" />
    </div>
    <script src="./script.js"></script>
  </body>
</html>

const calculator = document.querySelector('.calculator'); // calculator 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const buttons = calculator.querySelector('.calculator__buttons'); // calculator__keys 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.

const firstOperend = document.querySelector('.calculator__operend--left'); // calculator__operend--left 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const operator = document.querySelector('.calculator__operator'); // calculator__operator 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const secondOperend = document.querySelector('.calculator__operend--right'); // calculator__operend--right 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const calculatedResult = document.querySelector('.calculator__result'); // calculator__result 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.

function calculate(n1, operator, n2) {
  let result = 0;
  // TODO : n1과 n2를 operator에 따라 계산하는 함수를 만드세요.
  // ex) 입력값이 n1 : '1', operator : '+', n2 : '2' 인 경우, 3이 리턴됩니다.
  return String(result);
}

buttons.addEventListener('click', function (event) {
  // 버튼을 눌렀을 때 작동하는 함수입니다.

  const target = event.target; // 클릭된 HTML 엘리먼트의 정보가 저장되어 있습니다.
  const action = target.classList[0]; // 클릭된 HTML 엘리먼트에 클레스 정보를 가져옵니다.
  const buttonContent = target.textContent; // 클릭된 HTML 엘리먼트의 텍스트 정보를 가져옵니다.
  // ! 위 코드(Line 19 - 21)는 수정하지 마세요.

  if (target.matches('button')) {
    // TODO : 계산기가 작동할 수 있도록 아래 코드를 수정하세요. 작성되어 있는 조건문과 console.log를 활용하시면 쉽게 문제를 풀 수 있습니다.
    // 클릭된 HTML 엘리먼트가 button이면
    if (action === 'number') {
      // 그리고 버튼의 클레스가 number이면
      // 아래 코드가 작동됩니다.
      console.log('숫자 ' + buttonContent + ' 버튼');
    }

    if (action === 'operator') {
      console.log('연산자 ' + buttonContent + ' 버튼');
    }

    if (action === 'decimal') {
      // console.log('소수점 버튼');
    }

    if (action === 'clear') {
      console.log('초기화 버튼');
    }

    if (action === 'calculate') {
      console.log('계산 버튼');
    }
  }
});


// ! Advanced Challenge test와 Nightmare test를 위해서는 아래 주석을 해제하세요.

const display = document.querySelector('.calculator__display--for-advanced'); // calculator__display 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
let firstNum, operatorForAdvanced, previousKey, previousNum;

buttons.addEventListener('click', function (event) {
  // 버튼을 눌렀을 때 작동하는 함수입니다.

  const target = event.target; // 클릭된 HTML 엘리먼트의 정보가 저장되어 있습니다.
  const action = target.classList[0]; // 클릭된 HTML 엘리먼트에 클레스 정보를 가져옵니다.
  const buttonContent = target.textContent; // 클릭된 HTML 엘리먼트의 텍스트 정보를 가져옵니다.
  // ! 위 코드는 수정하지 마세요.

  // ! 여기서부터 Advanced Challenge & Nightmare 과제룰 풀어주세요.
  if (target.matches('button')) {
    if (action === 'number') {}
    if (action === 'operator') {}
    if (action === 'decimal') {}
    if (action === 'clear') {}
    if (action === 'calculate') {}
  }

});



📝 풀이 과정


거의 만물 .textContent 썰이라고 해도 무방하다.

생각나는 특이한 점이 있다고 하면, eval 함수를 쓰지 않고 문자열을 가지고 하드코딩 했다는 점이다.

때문에 문자열을 받아서 Number()로 숫자열로 바꾼 후, 계산을 진행하고 다시 문자열로 돌려보내는 과정이 있었다.


const calculator = document.querySelector(".calculator");
const buttons = calculator.querySelector(".calculator__buttons"); 
const firstOperend = document.querySelector(".calculator__operend--left");
const operator = document.querySelector(".calculator__operator");
const secondOperend = document.querySelector(".calculator__operend--right"); 
const calculatedResult = document.querySelector(".calculator__result");

function calculate(n1, operator, n2) {
  let result = 0;
  if (operator === "+") {
    result = n1 + n2;
  } else if (operator === "-") {
    result = n1 - n2;
  } else if (operator === "*") {
    result = n1 * n2;
  } else if (operator === "/") {
    result = n1 / n2;
  }
  return String(result);
}

buttons.addEventListener("click", function (event) {

  const target = event.target; 
  const action = target.classList[0]; 
  const buttonContent = target.textContent; 

  if (target.matches("button")) {
    if (action === "number") {
      if (firstOperend.textContent === "0") {
        firstOperend.textContent = buttonContent;
      } else {
        secondOperend.textContent = buttonContent;
      }
    }

    if (action === "operator") {
      operator.textContent = buttonContent;
    }

    if (action === "decimal") {
      // console.log('소수점 버튼');
    }

    if (action === "clear") {
      firstOperend.textContent = "0";
      secondOperend.textContent = "0";
      operator.textContent = "+";
      calculatedResult.textContent = "0";
    }

    if (action === "calculate") {
      let n1 = Number(firstOperend.textContent);
      let n2 = Number(secondOperend.textContent);
      let inputOperator = operator.textContent;
      calculatedResult.textContent = calculate(n1, inputOperator, n2);
    }
  }
});


💬 풀이 후기


일단 간단하게 JS 파일을 한 번 훑고, 조금 당황스러웠다.

querySelector, addEventListener 등등 많은 JS 용어가 있었다.

나는 그나마 노마드코딩을 하면서 한 번은 지나간 과정이지만, 처음 보는 분들이라면 굉장히 당황스러웠을 것 같다.
이것들이 무슨 기능을 하는지 써져있지 않아, 그런 부분들이 추가되면 좋을 것 같다는 생각을 했다.

그래도 주석으로 다 설명을 달아주셔서, 말 그대로 잘 읽어보고 따라갈 수 있었다.

난이도는 조건문 if 만 쓰면 계산기 프로그램이 진행되는데 문제가 없는 정도였다.

덕분에 나는 내가 자신있게 치고 나갈 줄 알았는데 아니었다.

현실은 순서가 정해져있는 것을 풀어나가서 그런건지는 모르겠지만, 처음부터 턱 막히는 느낌이었다.

처음부터 번호가 이벤트리스너로 연결되어 있는 것 알겠고, 뭐가 뭐로 연결되어 있는지는 알겠는데
첫 발걸음을 어떻게 떼어야할지 너무 고민이었다.

그렇게 고민을 하다가 알게 된 것은 .textContent 라는 오브젝트였다.
기존에 알고 있던 .innerText 와 비슷한데 숨겨진 히든까지 모든 텍스트 값을 다 가져오는 것이 특징이었다.

처음엔 그냥 아무렇게나 지정해준 이름인 줄 알았는데 아니었다니.. 당황스러웠고 내가 부끄러웠다.

그렇게 (화면에 나타날 클래스 이름).textContent = target.textContent; 으로 첫 발을 떼었다.

그 후에는 추가적인 Advanced Challenge test 단계까지 어려움 없이 모든 기능을 구현 가능하게 할 수 있었다 :)

계산기 eval 함수를 많이 쓰던데, 이는 추천하지 않는 추세라서 생으로 하드코딩한 것이 특징이었다 !

내일은 Advanced Challenge test 단계에 대해서 자세한 풀이 과정을 다뤄보겠다 😚

오늘 나 자신도 고생했어 💪

profile
아이디어가 넘치는 프론트엔드를 꿈꿉니다 🔥

0개의 댓글