JavaScript 공부하기_생활코딩 클라이언트편 정리

Lina Hongbi Ko·2023년 4월 13일
0

JavaScript-studying

목록 보기
6/6
post-thumbnail

🐶 생활코딩님의 자바스크립트 - 웹클라이언트편 공부하고 정리.

(구체적인 언어적인 부분은 따로 정리 - 드림코딩님강의랑 같이 정리할 것!)

1. 웹브라우저와 JavaScript

: 자바스크립트는 html를 프로그래밍적으로 제어한다.

2. html에서 Javascirpt 로드하기

:
2-1. inline방식

<!DOCTYPE html>
<html>
<body>
    <input type="button" onclick="alert('Hello world')" value="Hello world" />
</body>
</html>

2-2. script를 내부문서에서 실행

<!DOCTYPE html>
<html>
<body>
    <input type="button" id="hw" value="Hello world" />
    <script type="text/javascript">
        const hw = document.getElementById('hw');
        hw.addEventListener('click', function(){
            alert('Hello world');
        })
    </script>
</body>
</html>

2-3. 외부파일로 분리

<!DOCTYPE html>
<html>
<body>
    <input type="button" id="hw" value="Hello world" />
    <script type="text/javascript" src="script2.js"></script>
</body>
</html>
const hw = document.getElementById('hw');
hw.addEventListener('click', function(){
    alert('Hello world');
})

2-4. script 파일은 위치에 따라 오류가 발생
script 파일은 head 태그 보다 페이지의 하단에 위치시키는 것이 더 좋은 방법이다.

3. Object Model

: 웹브라우저의 구성요소들이 하나하나 객체화되어있는데 이것을 Object Model이라고 한다. 즉, html과 여러 브라우저의 요소들을 자바스크립트로 제어할 수 있게 객체로 만들어서 제어한다는 내용이다.

사진첨부

3-1. Window 객체
: 모든객체가 소속된 객체(전역객체) & 창이나 프레임을 의미
전역변수와 함수는 window객체의 프로퍼티와 메소드이다. 그리고 모든 객체는 window의 자식이고 Global객체라고 부를 수 있다.

3-2. JavaScript Core
: JavaScript 언어 자체에 정의되어 있는 객체

3-3. BOM
: Browser Object Model. 웹페이지의 내용을 제외한 브라우저의 각종 요소들을 객체화시킨것. 전역객체 Window의 프로퍼티에 속한 객체들

  • Location 객체 : 문서의 주소와 관련된 객체 -> url을 변경하고 문서의 위치와 관련해 다양한 정보를 얻을 수 있다.
    💡 url 순서: location.protocol, location.host, location.port, location.pathname, location.search, location.hash
    ex) https://opentutorials.org:80/module/1?id=1#hash

  • Navigator 객체 : 브라우저의 정보를 제공하는 객체이고, 호환성 문제 등을 위해서 사용
    Navigator.appName -> 웹브라우저의 이름, Navigator.appVersion -> 브라우저의정보, Navigator.userAgent -> 브라우저가 서버측으로 전송하는 user-agent http 헤더의 내용, Navigator.platForm -> 브라우저가 동작하고 있는 운영체제에 대한 정보

💡 호환성 문제를 해결하기 위한 코드

// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
  Object.keys = (function () {
    'use strict';
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
        dontEnums = [
          'toString',
          'toLocaleString',
          'valueOf',
          'hasOwnProperty',
          'isPrototypeOf',
          'propertyIsEnumerable',
          'constructor'
        ],
        dontEnumsLength = dontEnums.length;
 
    return function (obj) {
      if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
        throw new TypeError('Object.keys called on non-object');
      }
 
      var result = [], prop, i;
 
      for (prop in obj) {
        if (hasOwnProperty.call(obj, prop)) {
          result.push(prop);
        }
      }
 
      if (hasDontEnumBug) {
        for (i = 0; i < dontEnumsLength; i++) {
          if (hasOwnProperty.call(obj, dontEnums[i])) {
            result.push(dontEnums[i]);
          }
        }
      }
      return result;
    };
  }());
}

3-4. DOM
: Document Object Model. 웹페이지의 내용을 제어. Window의 프로퍼티에 할당된 document객체가 담당. (document객체의 프로퍼티는 문서 내의 주요 엘리먼트에 접근할 수 있는 객체와 메소드를 제공한다. ex - document.images, document.getElementByTagName())

  • 제어대상 찾기
  1. document.getElementsByTagName
  2. document.getElementByClassName
  3. document.getElementById
  4. document.querySelector
  5. document.querySelectorAll
  • HTMLElement: 실행결과 element가 하나 / HTMLCollection: 실행결과 element가 여러개(유사배열로 배열과 비슷한 방법을 가지고 있지만 배열은 아님)

  • DOM Tree
    사진첨부

  • Element객체
    : Element객체는 엘리먼트를 추상화한 객체.
    사진첨부

  1. 식별자 (문서 내에서 특정한 엘리먼트를 식별하기 위한 용도로 사용되는 API)
    -> Element.classList
    -> Element.className
    -> Element.id
    -> Element.tagName
  2. 조회 (엘리먼트의 하위 엘리먼트를 조회하는 API)
    -> Element.getElementsByClassName
    -> Element.getElementsByTagName
    -> Element.querySelector
    -> Element.querySelectorAll
  3. 속성 (엘리먼트의 속성을 알아내고 변경하는 API)
    -> Element.getAttribute(name)
    -> Element.setAttribtue(name, value)
    -> Element.hasAttribute(name)
    -> Element.removeAttribute(name)
  • Node객체
  1. Node 간의 관계정보 API
    Node.childNodes, Node.firstChild, Node.lastChild, Node.nextSibling, Node.previousSibling

  2. 노드 종류 API
    Node.nodeType : node의 타입
    Node.nodeName : node의 이름(태그명)

// Node.nodeType을 의미하는 숫자
ELEMENT_NODE 1 
ATTRIBUTE_NODE 2 
TEXT_NODE 3 
CDATA_SECTION_NODE 4 
ENTITY_REFERENCE_NODE 5 
ENTITY_NODE 6 
PROCESSING_INSTRUCTION_NODE 7 
COMMENT_NODE 8 
DOCUMENT_NODE 9 
DOCUMENT_TYPE_NODE 10 
DOCUMENT_FRAGMENT_NODE 11 
NOTATION_NODE 12 
DOCUMENT_POSITION_DISCONNECTED 1 
DOCUMENT_POSITION_PRECEDING 2 
DOCUMENT_POSITION_FOLLOWING 4 
DOCUMENT_POSITION_CONTAINS 8 
DOCUMENT_POSITION_CONTAINED_BY 16 
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32
  1. 노드 변경 API
    -> 노드추가
    : appendChild(child) - 노드의 마지막 자식으로 주어진 엘리먼트 추가됨
    insertBefore(newElement, referenceElement) - referenceElement 앞에 newElement가 추가됨
    -> 엘리먼트생성
    : document.createElement(tagename) - 엘리먼트 노드를 추가 document.createTextNode(data) - 텍스트 노드를 추가
    -> 노드제거 (참고사항 : 삭제대상의 부모 노드 객체에서 실행해야함)
    : removeChild(child)
    -> 노드 바꾸기
    : replaceChild(newChild, oldChild)

  2. 문자열로 노드제어
    -> innerHTML : 자식노드를 만들고, 그 값 또한 읽어올 수 있다. 코드를 포함해서 리턴.
    -> outerHTML : 선택한 엘리먼트를 포함해서 처리된다. 코드를 포함해서 리턴.
    -> innerText : innerHTML과 같지만 HTML코드를 제외한 문자열을 리턴한다.
    -> outerText : outerHTML과 같지만 HTML코드를 제외한 문자열을 리턴한다.
    -> insertAdjacentHTML : 좀 더 정교하게 문자열을 이용해서 노드를 변경하고 싶을때 사용.
    (beforebegin, afterbegin, beforeend, afterend)

  • Document객체
    : HTMLDocument객체로 사용된다. HTMLDocument객체는 문서전체를 대표하는 객체이고 window 객체의 소속이다. (document객체의 자식은 Doctype과 html이 있다.)
  1. 노드생성 API
    -> creatElement()
    -> createTextNode()

  2. 문서정보 API
    -> title
    -> URL
    -> referrer
    -> lastModified

  • Text객체
    : 텍스트 노드에 대한 DOM객체로 CharacterData를 상속 받는다. 그리고 공백이나 줄바꿈도 텍스트 노드.

  1. -> data
    -> nodeValue

  2. 조작
    -> appendData()
    -> deleteData()
    -> insertData()
    -> replaceData()
    -> subStringData()

  3. 생성
    -> document.createTextNode()

4. 문서의 기하학적 특성

  • 요소의 크기와 위치
    사진첨부
    : Element.getBoundingClientRect api를 이용하면 엘리먼트의 크기와 위치를 알 수 있다. (IE는 제공하지 않음) 그리고 top, right의 위치 기준은 엘리먼트의 부모가 아니라 뷰포트가 기준이 된다. (body기준)
    알 수 있는 방법은 offsetParent 속성을 호출하면 되는데 만약 부모 중 css position 값이 static이면서 td, th, table 엘리먼트가 있으면 이 엘리먼트가 offsetParent가 된다.
    그리고 테두리를 제외한 엘리먼트의 크기를 알려면 ClientWidth, ClientHeight를 사용한다.

  • 스크롤에 따라서 달라지는 뷰포트의 좌표
    : 뷰포트는 문서의 내용 중 사용자에게 보여주는 영역인데 앞서 말한것처럼 getBoundingClientRect은 viewport의 좌표를 사용한다. 그래서 스크롤을 하게되면 getBoundingClientRect의 정보는 달라지게 된다. 예를 들면 top의 정보가 200px이었는데 스크롤을 40px만큼 하게 되면 top은 160px이 된다.
    그렇다면 문서의 좌표는 어떻게 알까? -> 뷰포트의 좌표에 스크롤 된 정보를 더하면 알 수 있다.(pageYOffset을 사용하면 스크롤의 정도를 알 수 있다)

-> 그럼 스크롤 값을 변경하는 것은 어떻게 할까? : scrollTo 프로퍼티를 이용하면 된다.

<input type="button" id="scrollBtn" value="scroll(0, 1000)" />
<script>
    document.getElementById('scrollBtn').addEventListener('click', function(){
        window.scrollTo(0, 1000); // 앞의 인수는 x값, 뒤의 인수는 y값
    })
</script>
  • 스크린의 크기 : screen.width, screen.height
  • 뷰포트의 크기 : window.innerWidth, window.innerHeight

5. 이벤트

: 이벤트(event)는 어떤 사건을 의미한다. 브라우저에서의 사건이란 사용자가 클릭했을 때, 스크롤 했을 때, 등 '어떤 사건이 일어났을 때'를 의미한다.

<!DOCTYPE html>
<html>
<body>
    <input type="button" onclick="alert(window.location)" value="alert(window.href)" />
    <input type="button" onclick="window.open('bom.html')" value="window.open('bom.html')" />
</body>
</html>

onclick속성의 자바스크립트 코드는 사용자가 이버튼을 클릭했을 때가 실행된다. 즉, 개발자는 어떤 일이 발생했을 때 실행 되어야하는 코드를 등록하고, 브라우저는 그 등록된 코드를 실행한다. 이것을 이벤트 프로그래밍이라고 한다.

  • event target : target은 이벤트가 일어날 객체를 의미. 여기서는 button이 타겟.
<input type="button" value="alert(window.href)" /
  • event type : 이벤트의 종류를 의미. 예를 들면 click이 이벤트 타입이다. 그외에도 scroll, mousemove 등이 있다.
  • event handler : 이벤트가 발생했을 때 동작하는 코드를 의미한다. alert(window.location)이 여기에 해당한다.

-> 이벤트 프로그래밍을 하기 위해서는 이벤트의 대상에 이벤트 핸들러를 등록해주면 된다. 웹브라우저에서는 크게 3가지의 종류의 등록방법을 제공한다.

  1. 인라인(inline)방식 : 이벤트를 이벤트대상의 태그 속성으로 지정하는 것. 인라인방식은 태그에 이벤트가 포함되기 때문에 이벤트의 소재를 파악하는 것이 편리하지만 정보를 포함하는 HTML과 제어를 하는 JavaScript가 혼재된 형태이기 때문에 바람직한 방법이라고 할 수 없다.
<input type="button" onclick="alert('Hello world');" value="button" />
  1. 프로퍼티(property)방식 : 이벤트 대상에 해당하는 객체의 프로퍼티로 이벤트를 등록하는 방식이다. 인라인 방식에 비해 HTML과 JavaScript를 분리할 수 있다.
<input type="button" id="target" value="button" />
<script>
    var t = document.getElementById('target');
    t.onclick = function(){
        alert('Hello world');
    }
</script>

-> 그리고 이벤트가 실행된 맥락의 정보가 필요할때는 이벤트객체를 사용한다. 이벤트객체는 이벤트가 실행될때 이벤트 핸들러의 인자로 전달된다. (ie8 이하 버전에서는 이벤트 객체를 핸들러의 인자가 아니라 전역객체의 event 프로퍼티로 제공하고, target 프로퍼티도 지원하지 않는다.)

<body>
    <input type="button" id="target" value="button" />
<script>
    var t = document.getElementById('target');
    t.onclick = function(event){
        alert('Hello world, '+event.target.value)
    }
</script>
// 크로스브라우정 이슈문제를 위한 참고_ 이벤트를 전달하는 방식(ie8 이하 버전)
<input type="button" id="target" value="button" />
<script>
    var t = document.getElementById('target');
    t.onclick = function(event){
        var event = event || window.event;
        var target = event.target || event.srcElement;
        alert('Hello world, '+target.value)
    }
</script>
  1. addEventListener()
    : 이벤트를 등록하는 가장 권장되는 방식이고, 이 방식을 이요하면 여러개의 이벤트 핸들러를 등록할 수 있다.
<input type="button" id="target1" value="button1" />
<input type="button" id="target2" value="button2" />
<script>
    var t1 = document.getElementById('target1');
    var t2 = document.getElementById('target2');
    function btn_listener(event){
        switch(event.target.id){
            case 'target1':
                alert(1);
                break;
            case 'target2':
                alert(2);
                break;
        }
    }
    t1.addEventListener('click', btn_listener);
    t2.addEventListener('click', btn_listener);
</script>

6. 이벤트 전파(버블링과 캡쳐링)

: 중첩되어 있는 태그들에게 이벤트가 등록되어 있을 때의 처리되는 과정.

  • 캡쳐링(Capturing) : 이벤트가 부모에서부터 발생해 자식으로 전파되고 있다. 이러한 방식을 capturing이라고 한다.
  • 버블링(Bubling) : 이벤트가 자식부터 부모로 전파는되는 것. 이벤트 전파를 중간에 가로막을 수도 있다. (event.stopPropagation() api를 쓰면 되는데, 이 방법은 권장하지 않는다. -> why? 드림코딩아카데미에서 배우길, 자식 이벤트가 발생했을 때, 가장 최상의 브라우저인 window객체가 얻어야하는 정보를 얻지 못할 수도 있고 버블링을 함으로써 얻게되는 기능들을 할 수 없으므로 조건문을 통해 제어하는 것이 좋다. [이 부분은 따로 정리해둘것])

7. 이벤트 기본동작 취소

  • inline방식 : 이벤트의 리턴값이 false이면 기본동작이 취소됨.
<p>
    <a href="http://opentutorials.org" onclick="if(document.getElementById('prevent').checked) return false;">opentutorials</a>
</p>
<p>
    <form action="http://opentutorials.org" onsubmit="if(document.getElementById('prevent').checked) return false;">
            <input type="submit" />
    </form>
</p>
  • property방식 : 리턴값이 false이면 기본동작이 취소됨.
<p>
    <label>prevent event on</label><input id="prevent" type="checkbox" name="eventprevent" value="on" />
</p>
<p>
    <a href="http://opentutorials.org">opentutorials</a>
</p>
<p>
    <form action="http://opentutorials.org">
            <input type="submit" />
    </form>
</p>
<script>
    document.querySelector('a').onclick = function(event){
        if(document.getElementById('prevent').checked)
            return false;
    };
     
    document.querySelector('form').onclick = function(event){
        if(document.getElementById('prevent').checked)
            return false;
    };
 
</script>
  • addEventListener 방식 : 이벤트 객체의 prevenDefault() 메소드를 실행하면 기본 동작이 취소된다.
<p>
	<label>prevent event on</label><input id="prevent" type="checkbox" name="eventprevent" value="on" />
</p>
<p>
	<a href="http://opentutorials.org">opentutorials</a>
</p>
<p>
	<form action="http://opentutorials.org">
    	<input type="submit" />
    </form>
</p>
<script>
	document.querySelector('a').addEventListener('click', function(event){
    	if(document.getElementById('prevent').checked)
			event.preventDefault();
		});
    document.querySelector('form').addEventListener('submit', function(event){
    	if(document.getElementById('prevent').checked)
			event.preventDefault();
        });
</script>

8. 이벤트 동작 타입

  • Form
  1. submit
  2. change
  3. blur, focus
  • 문서로딩
  1. load (이벤트 문서내의 모든 리소스_이미지, 스크립트 등의 다운로드가 끝난 후에 실행되도록 함)
  2. DOMContentLoaded (태그의 렌더링만 끝난 상태에서 실행할 수 있게 하는데 문서에서 스크립트의 작업을 할 수 있을때 실행되기 때문에 이미지 다운로드를 기다릴 필요가 없다)
  • 마우스
  1. click : 클릭했을 때 발생하는 이벤트
  2. dbclick : 더블클릭했을 때 발생하는 이벤트
  3. mousedown : 마우스를 누를 때 발생
  4. mouseup : 마우스버튼을 땔 때 발생
  5. mousemove : 마우스를 움직일때
  6. mouseover : 마우스가 엘리먼트에 진입할 때 발생
  7. mouseout : 마우스가 엘리먼트에서 빠져나갈 때 발생
  8. contextmenu : 컨텍스트 메뉴가 실행될 때 발생
  • 키보드 조합
  1. event.shiftKey
  2. event.altKey
  3. event.ctrlKey
  • 마우스 포인터 위치
    : 마우스 이벤트와 관련한 작업에서는 마우스 포인터 위치를 아는 것이 중요하다. 이런 경우, 이벤트 객체의 clientX와 clientY를 사용한다.

9. 네트워크 통신

: 자바스크립트를 이용해 웹브라우저의 통신 기능을 사용

  • JSON (서버와 클라이언트 간의 데이터를 주고 받는 형식)
    : JSON은 JavaScript Object Notation의 약자로, JavaScript에서 객체를 만들 때 사용하는 표현식을 의미한다. 이 표현식은 사람과 기계가 이해하기 쉽고 데이터의 용량도 작아서 최근에는 JSON이 XML을 대체해서 설정의 저장이나 데이터를 전송하는 등 여러 곳에 많이 사용된다. 쉽게 말해 JSON은 정보들을 묶어 놓은 객체이다.

-> JSON API
1. JSON.parse() : 인자로 전달된 문자열을 자바스크립트의 데이터로 변환한다.
2. JSON.stringify() : 인자로 전달된 자바스크립트의 데이터를 문자열로 변환한다.

ex) 서버에서 JSON 데이터 가져오기

// time.php
<?php
$timezones = ["Asia/Seoul", "America/New_York"];
echo implode(',', $timezones);
?>

// 결과 : Asia/Seoul,America/New_York
<p id="timezones"></p>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
    var xhr = new XMLHttpRequest();
    xhr.open('GET', './time2.php');
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200){
            var _tzs = xhr.responseText;
            var tzs = JSON.parse(_tzs);
            // 서버에 전송한 JSON 데이터를 JavaScript의 배열로 만들 수 있다.
            
            var _str = '';
            for(var i = 0; i< tzs.length; i++){
                _str += '<li>'+tzs[i]+'</li>';
            }
            _str = '<ul>'+_str+'</ul>';
            document.querySelector('#timezones').innerHTML = _str;
        }
    }
    xhr.send(); 
}); 
</script>

ex) 서버로 JSON 데이터 전송하기

<p>time : <span id="time"></span></p>
<select id="timezone">
    <option value="Asia/Seoul">asia/seoul</option>
    <option value="America/New_York">America/New_York</option>
</select>
<select id="format">
    <option value="Y-m-d H:i:s">Y-m-d H:i:s</option>
    <option value="Y-m-d">Y-m-d</option>
</select>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
    var xhr = new XMLHttpRequest();
    xhr.open('POST', './time3.php');
    xhr.onreadystatechange = function(){
        document.querySelector('#time').innerHTML = xhr.responseText;
    }
    var data = new Object();
    data.timezone = document.getElementById('timezone').value;
    data.format = document.getElementById('format').value;
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.send(JSON.stringify(data)); 
});
</script>
<?php
$data = json_decode(file_get_contents('php://input'), true);
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone($data['timezone']));
echo $d1->format($data['format']);
?>
  • Ajax (페이지 리로드 없이 웹페이지의 내용을 변경할 수 있음)
    : 웹브라우저에서 내용이 바뀌면 새로고침을 해서 새롭게 내용을 변경해야했는데 Ajax 개념이 도입되고 웹브라우저와 웹서버거 내부적으로 데이터 통신을 하게 되면서 웹페이지의 로딩 없이 서비스를 할 수 있게 되었다. Ajax는 Asynchronous JavaScript and XML의 약자로 비동기적 자바스크립트와 XML정도로 직역할 수 있는데 자바스크립트를 이용해서 비동기적으로 서버와 브라우저가 데이터를 주고 받는 방식을 의미한다. 이 때 사용하는 API가 XMLHttpRequest이다. 그리고 XML보다 JSON을 더 많이 사용해서 통신하므로 이 API로 꼭 통신해야 하는 것은 아니다.

ex)

// time.php
// 현재 시간을 출력
<?php
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone("asia/seoul"));
echo $d1->format('H:i:s');
?>
// demo1.html
// time.php에 접속해서 현재 시간을 페이지에 표시한다.
<p>time : <span id="time"></span></p>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
    var xhr = new XMLHttpRequest();
    // XMLHttpRequest 객체를 생성한다.
    
    xhr.open('GET', './time.php');
    // 접속하려는 대상을 지정한다.
    // 첫번째 인자는 form태그의 method이고 GET/POST방식을 주로 사용한다.
    // 두번째 인자는 접속하고자 하는 서버쪽 리소스의 주소로 form태그의 action에 해당한다.
    
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200){
            document.querySelector('#time').innerHTML = xhr.responseText;
        }
    }
    // onreadystatechange 이벤트는 서버와의 통신이 끝났을 때 호출되는 이벤트이다.
    // readyState는 통신의 형재상태를 알려주는데 4는 통신이 완료되었음을 의미하고
    // status는 통신의 결과를 의미하는데 200은 통신이 성공했음을 의미한다.
    // responseText 프로퍼티는 서버에서 전송한 데이터를 담고 있다.
    xhr.send(); 
}); 
</script> 
profile
프론트엔드개발자가 되고 싶어서 열심히 땅굴 파는 자

0개의 댓글