본문 바로가기

코드스테이츠

2021년 4월 12일 코드스테이츠 DAY-8(CSS + 계산기)#1

반응형

CSS 기초(Chapter) 

querySelector 과제 제출(Pair)

 

계산기(Pair)


 


계산기 : HTML/CSS/JS를 활용하여 Pair와 함께 계산기를 만들어 내는 것.


1. Bare Minimum Requirements(필수 과제)

   Step1 - CSS 마음껏 수정하여 예쁜 계산기 만들기

   Step2 - 버튼이 잘 동작하는지 확인하기

   Step3 - 기본적인 계산 기능 구현하기

   Step4 - SpecRunner.html의 모든 테스트를 통과 후 Github에 Commit 하기 

 

                               +

 

  Advanced Challges / Nightmare ~ 4월 12일(추가 과제)

  


2. 진행 순서 

   Step2 - 버튼이 잘 동작하는지 확인하기

   Step3 - 기본적인 계산 기능 구현하기

   Step4 - SpecRunner.html의 모든 테스트를 통과 후 Github에 Commit하기 

   Step1 - CSS 마음껏 수정하여 예쁜 계산기 만들기

 

계산기 과제를 새로운 Pair와 함께 시작하였고, CSS는 각자의 취향에 맡기기로 했다.

 

공통적인 부분인 step 2, step 3 , step4를 먼저 시작하게 되었는데,

 

문제 자체는 심플하다.  

 

 이렇게 생긴 계산기(사실... 이건 계산기가 아니지, 0만 떠있는 진짜 계산기는 내일 추가과제로 Pair와 진행하기로 했다.)가

 

기능하도록 만드는 것.

 

저기 있는 모든 버튼을 다 눌러도 아무런 반응이 없다. 

 

과제 파일을 보면 모든 기본 뼈대 코드들은 다 나와있다.

 

step2에 적힌 대로 버튼을 눌러 버튼들이 다 기능하는지 한번 확인해보자. 

 

버튼을 누르면 해당 버튼에 해당하는 콘솔 로그가 콘솔 창에 찍힌다. 

 

우선 step2는 clear.

 

하지만 시키는 대로만 하면 재미가 없지 않겠는가!

 

콘솔 창에 각 버튼의 textContent가 찍히는 원리를 지금부터 분석해보겠다.

 

소스코드에서 모든 button들은 buttons라는 부모 엘리먼트 안에 속해 있었고 자식 엘리먼트 버튼을 불러오기 위하여 

 

'이벤트 위임'이라는 기법을 사용하였다.

 


 

이벤트 위임은 많은 자식 엘리먼트를 조작할 때 각각의 자식 엘리먼트에 addEventListener를 걸어서 사용하게 되면 성능의 저하가 나타날 수 있으므로  부모 엘리먼트에 addEventListener를 걸고 함수의 매개변수에 event객체를 불러와서 target속성을 통해 자식 엘리먼트에 접근하는 기법이다.

 

event.target에 대한 MDN 링크는 아래와 같다.

 

https://developer.mozilla.org/ko/docs/Web/API/Event/target

 

Event.target - Web API | MDN

Event.target Event interface의 target 속성은  event가 전달한 객체에 대한 참조입니다. 이는 이벤트의 버블링 또는 캡처 단계에서 이벤트 핸들러를 호출하는 Event.currentTarget (en-US)와 다릅니다.event.targe

developer.mozilla.org

 

MDN에서 Event.target을 설명하기 위해 만든 예시를 보자.

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
    <script>
        var ul = document.createElement('ul');
        document.body.appendChild(ul);

        var li1 = document.createElement('li');
        var li2 = document.createElement('li');
        ul.appendChild(li1);
        ul.appendChild(li2);

        function hide(e){
        // e.target refers to the clicked <li> element
        // This is different than e.currentTarget which would refer to the parent <ul> in this context
        e.target.style.visibility = 'hidden';
        }

        // Attach the listener to the list
        // It will fire when each <li> is clicked
        ul.addEventListener('click', hide, false);
    </script>
</body>
</html>

 

이를 열어보면 빈창에 li태그의 앞부분이 위아래로 나란히 두 개가 있고,

 

그 두 개의 버튼 중 하나를 누르면 이는 addEventListener('click', hide)에 의해 안 보이게 된다.

 

여기서 ul에 addEventListener를 주목하자. li를 조작하기 위하여 부모 엘리먼트인 ul에 접근한 것이다.

 

이것이 바로 이벤트 위임이다. 

 

클릭 전

 

클릭 후 


이렇게 이벤트 위임을 통해 자식 엘리먼트를 가져왔고,

 

임의의 변수를 선언하여 이에 target.classList[0]로 자식 엘리먼트의 첫 번째 클래스 네임을 할당했다. 

 

숫자일 경우 클래스가 number, 연산자의 경우 operator, AC의 경우 clear ...

 

이렇게 적혀있었기에 자식 엘리먼트를 종류별로 구분할 수 있었다. 

 

그리고 if조건 문안에 target.matches('button')을 넣어서  button이 선택되었는지 확인 후 참이라면 

 

클래스 네임을 가져온 임의의 변수가 조건문을 통해 각각 number라면, operator라면, clear라면

 

{} 속에 console.log('숫자 or  연산자 or clear' + target.textContent + '버튼')을 실행하도록 코드를 짜 놓았다. 

 

여기서 e.target을 통해 이벤트 위임한 것을 또다시 matches로 확인하는 것은 공부하며 처음 봤었기에 참신한 부분이 있었다.

 

 

자 이제 step3이다. 기본적인 계산 기능을 구현하기...

 

기본적인 계산기능을 구현하는 것의 pseudo code는 제공이 되었는데

 

0(화면의 첫 번째 칸 / firstOperend) +(화면의 연산자 칸 / operator) 0(화면의 두 번째 칸 / secondOperend) = 0(마지막 칸 / calculatedResult)

 

화면의 첫 번째 칸에 숫자 나타내기

 

화면의 두 번쨰 칸에 숫자 나타내기

 

화면에 출력된 숫자와 연산자로 계산하기

 

화면 상의 값을 초기화하기

 

위와 같고 각각의 코드를 적어보겠다.

 

 

화면의 첫 번째 칸에 숫자 나타내기

 

화면의 두 번쨰 칸에 숫자 나타내기

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

    if (action === 'number') {
      if(firstOperend.textContent === "0"){
        firstOperend.textContent = `${buttonContent}`;
      }else if(firstOperend.textContent !== "0"){
        secondOperend.textContent = `${buttonContent}`;
      }
      console.log('숫자 ' + buttonContent + ' 버튼');
    }
    
    if (action === 'operator') {
      console.log('연산자 ' + buttonContent + ' 버튼');
      operator.textContent = `${buttonContent}`;
    }

    
//firstOperend의 값이 0이라면 아직 값이 안들어가있는것으로 보고 입력값이 들어가게 했으며
//firstOperend의 값이 0이 아니라면 firstOperend에는 값이 들어가 있는것으로 판단하여
//secondOperend로 값이 들어가게 코드를 짰다.

 

 

화면에 출력된 숫자와 연산자로 계산하기

 

function calculate(n1, operator, n2) {
  let result = 0;
  result = eval(n1 + operator + n2);
  return String(result);
}

    if (action === 'calculate') {
      console.log('계산 버튼');
      calculatedResult.textContent = calculate(firstOperend.textContent, operator.textContent, secondOperend.textContent);
    }
    
//문자열에 있는 식을 계산하기위해 eval을 사용하였으며(mdn에 검색결과 추천되지 않으며 위험하다고한다..)
//calculate 함수를 통해 각각의 argument를 받아서 계산하여 이를 calculatedResult에 넣어주었다. 

 

화면 상의 값을 초기화하기

 

    if (action === 'clear') {
      console.log('초기화 버튼');
      firstOperend.textContent = "0";
      secondOperend.textContent = "0";
      operator.textContent = "+";
      calculatedResult.textContent = "0";
    }

 

step 4 이 코드들은 테스트 케이스를 통과할 수 있을까?

 

 

통과! step4까지 완료하였다. 

 

그리고 막판 40분에 부랴부랴 CSS를 만지기 시작하였다.

 

 

 

css effect 중 하나인 neumorphism을 적용하고 싶었기에 한번 적용을 시도해 보았다. 시간이 부족하여 transition과 hover 할 때 버튼 속의 text가 변하는 것은 구현을 못했지만 내일은 온종일 계산기를 만드는 시간이 잡혀있기에 모두 구현할 수 있을 것이다. 

완벽하지는 않지만 고슴도치도 제 새끼는 함함하다고 했던가 예쁘게 생긴 것 같다. ㅎㅎ

반응형