글 작성자: bbangson
반응형

카운터 만들기

 

"간단한 카운터 만들기" 실습을 해보겠습니다. 

 

 

카운터 사진

왼쪽 +1 버튼을 누르면 위에 있는 숫자가 올라가고, 오른쪽 -1 버튼을 누르면 숫자가 내려가는 실습입니다. 

숫자의 초기 값은 0으로 설정해뒀습니다.  코딩은 CodeSandbox에서 진행했습니다. 

 

어떻게 이걸 만들 수 있을까요? 

우선 중요한 것은 HTML5과 JS를 연동시켜야 합니다. 어떻게 연동 시킬 수 있을까요? 

 

코드를 보면서 설명해 드리겠습니다. 

 

먼저 html 코드입니다.

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <h2 id="number">0</h2>
    <div>
      <button id="increase">+1</button>
      <button id="decrease">-1</button>
    </div>

    <script src="src/index.js"></script>
  </body>
</html>

HTML 파일에서 JS파일을 연동 시키는 방법은 <body>태그 안에 <script src="파일명.js">을 넣어주는 것으로 연동은 끝납니다. 

 

HTML 파일의 역할은 간단한 초기 화면을 구상해주는 역할을 합니다. <body>태그 안에 <h2>태그로 초기 숫자 0을 만들고, <div> 태그 안에 두 개의 버튼을 생성합니다. 버튼에는 각각 +1, -1이 적혀있습니다. 

 

또한, id를 설정해주면 나중에 JS파일에서 쉽게 HTML의 DOM 객체들을 제어할 수 있습니다. 

 

다음은 JS 파일입니다. 

// getElementById로 html에 있는 id 태그에 접근할 수 있게 해준다.
const number = document.getElementById("number");
const increase = document.getElementById("increase");
const decrease = document.getElementById("decrease");


// 이벤트 연결.
increase.onclick = () => {
  const current = parseInt(number.innerText, 10);
  number.innerText = current + 1;
};

decrease.onclick = () => {
  const current = parseInt(number.innerText, 10);
  number.innerText = current - 1;
};


// 여기서 부터는 추가 설명 부분입니다.

// getElementById로 제대로 접근 했는지 알아보자.
console.log(number);
// <h2 id="number">0</h2> 출력
console.log(increase);
// <button id="increase">+1</button>
console.log(decrease);
// <button id="decrease">-1</button>


// 접근한 객체로 또 무엇을 할 수 있는지 알아보자. 
console.log(number.innerText);
// 0 출력.
console.log(increase.offsetTop);
// 74 출력. 상대적으로 가장 가까운 부모 엘리먼트를 기준으로 top 좌표.
console.log(decrease.id);
// decrease 출력.


// 만약에 id가 없을 수도 있다. 그런 경우는 어떻게 해야되나?
const btns = document.querySelectorAll('button');
console.log(btns);

위 JS 파일에서 h2 태그와 button 태그에 대한 DOM을 선택해줘야 합니다. 그래야 html 파일 안에 있는 각각의 태그에 접근할 수 있습니다. 

 

참고로 DOM이란? 

각 태그의 대한 정보를 지니고 있는 자바스크립트 객체를 뜻합니다. 

 

 

각각의 태그에 접근 하는 방법은 getElementById() 메소드로 html에 있는 id 태그에 접근하면 됩니다.

 

밑에 추가 설명해도 작성해놨지만, getElementById() 메소드로 접근한 변수들을 출력해보면, html에 있는 각자 해당되는 태그들이 잘 출력되는 것을 확인할 수 있습니다.

 

이벤트를 설정할 때는 dom.on~ 이런식으로 해주면 됩니다. dom은 각 태그를 담고 있는 자바스크립트 객체를 뜻합니다. 즉, 위의 코드에서는 number, increase, decrease가 됩니다. on~이것은 onclick, onfocu 등등 on으로 시작하는 모든 이벤트들을 나타냅니다.  

 

이벤트 연결하는 코드를 살펴보면, parseInt() 메소드는 문자열을 숫자(Int)형으로 변환해주는 메소드입니다.

parseInt()의 두 번째 파라미터인 숫자 10은 진수를 나타냅니다. 즉, 문자열 형태인 현재 값을 10진수의 숫자로 변환한 후, 그 값에 +1 혹은 -1을 해서 number(dom 객체)에 그 값을 넣어줍니다. 

 

 

 

모달 만들기

 

이번에도 JS와 html을 연동하여 모달 실습을 해보겠습니다. 

모달은 기존의 UI를 가리고 나타나는 열고 닫을수 있는 형태의 UI를 의미합니다. 

 

모달을 만들려면 위에 있는 counter와는 달리 css가 필요합니다. 

 

먼저 완성본과 최종 코드 부터 모여드리고 차근차근 설명해가겠습니다. 

모달 열기 버튼을 눌렀을 때입니다. 

모달 열기 버튼 눌렀을 때

다음은 닫기 버튼을 눌렀을 때입니다. 

 

닫기 버튼을 눌렀을 때

 

최종 코드를 보여드리면서 설명하겠습니다. 

 

먼저 html 코드입니다.

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <h1>안녕하세요!</h1>
    <p>내용내용내용</p>
    <button id="open">모달 열기</button>

    <div class="modal-wrapper" style="display: none;">
      <div class="modal">
        <div class="modal-title">안녕하세요</div>
        <p>모달 내용은 어쩌고 저쩌고..~~</p>

        <div class="close-wrapper">
          <button id="close">닫기</button>
        </div>
      </div>
    </div>

    <script src="src/index.js"></script>
  </body>
</html>

여기서 알아야 할 점은 div 태그 안에서 style은 줄 수 있다는 것과 display: none을 줌으로서 초기 설정은 안보이게 만든다는 것입니다. 당연합니다. 모달은 버튼을 클릭해야 보이는 것이니까 클릭하지 않았을 때는 안보이게끔 설정해줍니다. 

 

 

js 코드입니다. 

import "./styles.css";

// id는 getElementById
const open = document.getElementById('open');
const close = document.getElementById('close');

// class는 querySelector을 쓰면 된다. 찾을 때 앞에 .붙이는거 유의하자
const modal = document.querySelector('.modal-wrapper');

open.onclick = () => {
  modal.style.display = 'flex';
}

close.onclick = () => {
  modal.style.display = 'none';
}

js 파일에다가 css파일 import시켜줘야 html, js, css 이 세가지의 파일들이 연동이 됩니다. 물론 html파일 head 태그 안에 style을 넣어주는 방법도 있습니다. 방법은 여러가지 입니다. 

 

위의 Counter실습과 차이점이 있다면, querySeletor() 메소드도 사용한다는 점입니다.

id에 접근하고자할 때는 getElementById() 이지만 class에 접근할 때는 querySelector() 메소드를 사용합니다.

 

참고로 querySeletor()를 사용할 때는 클래스명 앞에 꼭 "."을 붙여야합니다.

 

open과 close버튼에 이벤트를 걸어둡니다. 

.Modal-wrapper 클래스에는 이미 display="none"이 설정되어 있기 때문에, open을 클릭할 때는 "flex"로 변경하여 보이게끔 하고, close 버튼을 눌렀을 때는 다시 "none"으로 설정하여 사라지게 합니다. 

 

 

css 코드입니다. 

body {
  font-family: sans-serif;
}

.modal-wrapper {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal {
  background: white;
  padding: 24px 16px;
  border-radius: 4px;
  width: 320px;
}

.modal-title {
  font-size: 24px;
  font-weight: bold;
}

.modal p {
  font-size: 16px;
}

.close-wrapper {
  text-align: right;
}

각각의 클래스명에 접근하여 css를 편집하고 싶을 경우, querySelector와 마찬가지로 앞에 "."을 붙여 접근하면 됩니다. 

 

.modal-wrapper 클래스는 modal과 modal을 제외한 바깥도 포함하고 있습니다. width와 height를 100으로 준 것은 화면 전체를 의미합니다. background 색깔은 모달을 포함한 모든 영역 색깔을 나타냅니다. 짙은 회색입니다.

 

display : flex;  align-items: center;  justify-content : center; 를 통해 모달의 위치를 정중앙에 맞춥니다.  

정중앙으로 맞추는 기준은 position:fixed;  top: 0;  left: 0; 의 영향을 받습니다. 

 

.modal 클래스는 모달 자체를 의미합니다. 하지만 부모 dom이 .modal-wrapper 클래스이기 때문에 부모 dom의 영향도 받습니다. background 색을 white로 하여 모달쪽만 흰색으로 변경하였습니다. padding과 width는 크기에 영향을 주며, border-radius는 모서리를 둥글게 하는 정도를 나타냅니다.

 

.modal p는 modal 클래스 안에 있는 p 태그에 접근하는 것입니다. 이런 식으로도 나타낼 수 있다는 것을 보여줍니다. 

 

.close-wrapper 클래스의 text-align: right는 부모 dom을 기준으로 우측 정렬입니다. 

 

모달은 굉장히 중요한 UI입니다. 

 

웹 프로젝트를 하면 Modal은 빼놓을 수 없습니다. 유저와 서비스가 상호작용하도록 만드는 굉장히 유용한 방법이기 때문이죠.

front-end 직군에서 가장 많이 쓰이는 ui이기도 합니다. 

연습을 많이 해두는게 좋을 것 같습니다. 

 

 

궁금증!

 

저는 여기서 한가지 궁금한 게 생겼습니다. modal-wrapper 클래스가 꼭 필요할까? 그냥 modal 클래스의 색깔을 흰색과 대비되는 색깔로 지정해도 상관없지 않을까? 라는 의문이 생겼습니다. 

 

일단 결론부터 말씀드리면 안됩니다! 그리고 사실 계속 작성한 위와 같이 만드는 Modal도 좋지 못한 방법입니다. 

 

이유를 말씀드리겠습니다.

Modal-wrapper(실제 modal과 modal창 밖 화면 전체를 감싸는 부분)
    ㄴ Modal(실제 modal창)

 

사실 이 포스팅에서 작성할만한 내용은 아니지만 훗날 이 내용에 대해 다시 포스팅할 예정이기 때문에, 참고 용도로만 적어놓겠습니다. 

 

현재 modal은 이런 식으로 구현하였습니다. 

물론 단순한 modal창을 만든다면 신경을 안써도 됩니다. 하지만 

 

- Modal 내부에서 여러 가지 이벤트가 존재할 경우.

- Modal 외부를 클릭했을 때 Modal을 숨기고자 할 경우. 

 

와 같은 상황에는 이벤트 전파에 의해 불편한 상황을 초래할 것입니다.

 

다시 돌아와 위와 같은 방식의 Modal을 구현하였을 경우, Modal 밖을 클릭하여 Modal을 숨기고자 한다면 Modal-wrapper에 클릭 이벤트를 걸어야 합니다. 하지만 이렇게 하면 Modal 내부에서 클릭 이벤트가 발생했을 때 이벤트 버블링이 발생하여 Modal-Wrapper의 클릭 이벤트도 작동시켜 Modal이 숨겨지게 됩니다. 

 

그럼 어떻게 Modal을 만들어야 할까?

간단합니다.

Modal-wrapper(실제 modal과 modal창 밖 화면 전체를 감싸는 부분)
	ㄴ Overlay (Modal-Wrapper 위에서 화면 전체를 감싸는 부분)
    	ㄴ Modal(실제 modal창)

이런 식으로 구성한다고 하면, 이벤트 전파는 부모-자식 간에만 발생하기 때문에 Overlay라는 형제를 두고 Modal 숨기기 이벤트를 걸어두는 것입니다. 그러면 Modal을 클릭했을 때, 버블링은 일어나지만 이벤트가 Overlay에 걸려있기 때문에 창은 꺼지지 않습니다. 

 

지금 당장 이해하기엔 어려운 개념이지만 차근차근히 공부해나가면 좋을 것 같습니다. 

 

 

 

 

참고 블로그

velog.io/@hyeon930/Modal-%EB%A7%8C%EB%93%A4%EA%B8%B0-Event-propagation

 

Modal 만들기 : Event propagation

프로그래머스 2020 Dev-Matching : 웹 프론트엔드 과제 복기 https://github.com/woohyeonjo/ilovecat

velog.io

 

참고 강의 

프론트엔드 개발 올인원 패키지 with React Online. | 패스트캠퍼스 (fastcampus.co.kr)

 

프론트엔드 개발 올인원 패키지 with React Online. | 패스트캠퍼스

프론트엔드 개발 러닝패스, 이 강의 패키지 하나로 끝낼 수 있습니다. 총 90시간 분량의 평생 소장 온라인 강의로 프론트엔드 개발자가 되세요.

www.fastcampus.co.kr

 

반응형