스터디/KAKAOCLOUDSCHOOL

[JavaScript] 개발자 지망생 스터디 - 8일차

shineIT 2022. 11. 11. 20:39

 

  • DOM 객체의 공통 속성과 메서드
    • appendChild(), removeChild(), createElement(), createTextNode(), getAttribute(), setAttribute()
    • style 속성 : 스타일 지정하기 위한 속성
    • innerHTML 속성 : 태그와 태그 사이의 텍스트와 관련된 속성
    • value 속성 : 입력된 데이터 확인, 이벤트와 함께 많이 사용
    • DOM 객체 마다 속성은 다름
<body>
    <h1 id="header">getdom.html - JavaScript2</h1>
    <p id="content">11/11</code></p>
    <input type="text" id="alias" value="수업이 끝났나요?"/>

    <!-- form 안에 있으면 submit 기능 -->
    <button>네</button>
    <input type="button" value="아니요" id="btn"/>

    <script>
        let h1 = document.getElementById("header");
        let p = document.getElementById("content");

        h1.style.color = "white";
        h1.style.border = "2px Solid Black";
        h1.style.background = "black";

        p.innerHTML += " [1]교시"+"<텍스트 수정됨>";
        alert(document.getElementById("alias").value);

        /*
        document.getElementById("btn").onclick = function(){
            alert("고전적 이벤트 처리 모델");
        }
        */

        document.getElementById("btn").addEventListener("click",
        ()=>{
            alert("집중 하세요");
        })
    </script>
</body>

■ Event Handling

  • Event & Event Handler
    • Event : 상태 변화
      • 사용자가 발생시키는 것(버튼 클릭이나 마우스를 올려 놓은 것 등)도 있고 시스템이 발생시키는 것(타이머 나 데이터를 전부 다운도르 받으면)도 있음
    • Event Handing : Event 가 발생했을 때 수행할 동작을 설정
      • 이러한 Event Handing을 수행하는 객체를 Event Handler 또는 Listener 라고 함
  • JavaScript 이벤트 처리 방법
    • inline
      • 태그 안에서 이벤트 속성에 스크립트 코드를 직접 작성 ( 권장하지 않음)
    • 고전적 이벤트 처리 모델
      • 객체.이벤트이름 = 함수(함수 이름이 될 수 있고 함수를 만드는 코드도 될수 있음)
    • 표준 이벤트 모델
      • 객체.addEventListener("이벤트이름", 함수 이름이나 함수를 만드는 코드)
      • 표준 이벤트 모델에서는 이벤트 이름 앞에 on을 붙이지 않음
      • 하나의 이벤트에 여러 함수를 연결하는 것이 가능
        • 이벤트 처리 코드를 제거할 때는 removeEventListener를 호출
  • 이벤트 객체
    • 이벤트를 처리하는 함수에는 event 객체가 1개가 전달됨
    • 이 객체에 이벤트와 관련된 정보가 전달됨
      • 이벤트 객체의 속성은 이벤트마다 다름
    • IE 하위 버전에서는 이벤트 처리 함수에서 이벤트 객체를 받을 수 없고 window.event로 이벤트 객체를 가져옴
      • (e) => {let event = e || window.event;} // IE 하위 버전때문에 작성
    • 이벤트 처리 함수 내에서 this는 이벤트가 발생한 객체임
      • 전에는 많이 사용했지만 최근 화살표 함수를 사용하여 잘 사용하지는 않음.
      • this 대신에 document 객체를 이용해서 DOM을 찾아와서 사용함.
    • 속성
      • data : Drag & Drop 할 때 Drop 된 객체들의 URL을 문자열 배열로 반환 (네이버 메일 파일 드래그엔 드랍)
      • height
      • layerX, layerY
      • modifier : 같이 누른 조합키(Alt, Ctrl, Shift 나 마우스 왼쪽, 오른쪽 판별)
      • pageX, pageY
      • screenX, screenY
      • target : 이벤트가 전달된 객체
      • type : 이벤트의 타입
      • which : 마우스 버튼의 ASCII 코드 값이나 키보드의 키 값(window.event.keyCode)
      • width
      • x
      • y
<body>
    <p id="paragraph">문단 태그</p>
    <script>
        document.getElementById("paragraph").addEventListener("click",
        (e) => {
            for(attr in e){
                console.log(attr + ":" + e[attr]);
            }
        });
    </script>
</body>

  • Event Trigger
    • 이벤트를 강제로 발생시키는 것
    • 객체.이벤트이름()
<body>
    <p id="paragraph">문단 태그</p>
    <button id="btn">버튼</button>
    <script>
        document.getElementById("paragraph").addEventListener("click",
        (e) => {
            for(attr in e){
                console.log(attr + ":" + e[attr]);
            }
        });

        document.getElementById("btn").addEventListener("click",
        // 문단 태그의 클릭이 발생하도록 강제로 이벤트 발생 시키기
        (e) => {
            document.getElementById("paragraph").click();
        })
    </script>
</body>
  • Default Event Handler
    • 특정한 태그 들에는 기본적인 이벤트 처리 코드가 포함되어 있음
      • a 태그는 다른 URL 이나 책갈피로 이동
      • input type 이 submit 이면 form 의 action 으로 요청을 전송
      • input type 이 reset 이면 form 을 clear
      • button 이 form 안에 존재하면 submit 기능을 수행
      • keydown 이 발생하면 누른 키를 input 에 출력
    • 기본 기능을 수행하지 않도록 할 떄는 event 객체의 preventDefault()를 호출하면 됨
      • submit 과 reset은 form 에 발생하는 이벤트임
      • 버튼을 누르지만 실제로는 form 의 이벤트
  • Event Bubbling
    • 부모 와 자식 태그 관계에서 양쪽에 동일한 이벤트에 대한 핸들러가 존재하면 자식 태그에서, 이벤트가 발생하면 자식 태그의 핸들러를 수행하고 부모 태그의 핸들러도 수행함
    • 이 때 이벤트 버블링을 막고자 하면 이벤트 객체의 stopPropagation 메서드를 호출하면 됨
  • 여러 종류의 이벤트
    • click, dblclick
      • 누른 좌표는 screenX 와 screenY
    • keydown, keypress, keyup
      • which 속성을 이용해서 누른 키의 ASCII 코드 값을 찾아올 수 있고 code로 상수 형태로 가져올 수 있고 key로 문자를 가져올 수 있음
    • mousemove, mouseout, mouseover, mouseup
    • focusin(focus), focusout(blur)
      • focusout 이벤트에서 유효성 검사를 하기도 함
    • load : 메모리에 적재되면
      • window에서는 body에 있는 TAG를 모두 읽어서 메모리에 적재하면 호출되는 이벤트
      • img 나 file 의 경우는 내용을 모두 읽었을 때 호출되는 이벤트
      • ajax에서는 서버에서 응답을 받았을 때 호출되는 이벤트
    • beforeunload : 브라우저의 내용이 사라지기 직전
      • 세션을 이용해서 로그인 처리를 하는 경우 로그라웃을 할 때 세션을 초기화하는데 브라우저 창을 닫아버리면 세션 초기화를 하지 못하는 경우가 있음
        • 이 이벤트를 이용해 브라우저가 닫히는 시점을 찾아 세션을 초기화 하면 됨.
    • change : 값이 변경될 때
      • 비밀번호 같은 것을 변경할 때 메시지를 출력하는 형태로 많이 이용함.
    • form 에는 submit 과 reset 이벤트가 있음
    • scroll
    • Mobile에는 터치 이벤트와 방향 전환 이벤트가 있음.
    <script>
        // window 의 Load 이벤트는 파일을 전부 읽어서 태그들을 모두 메모리에 적재한 후 발생
        window.addEventListener("load", (e) => {
            document.getElementById("display").innerHTML = "이벤트 처리";
            for(let i=0; i<50; i++){
                document.getElementById("body").innerHTML += 
                    "<h1>무한 스크롤</h1>";
            }
            window.addEventListener("scroll", (e) => {
                // 스크롤하는 위치와 문서의 높이가 같을 때
                // 가장 아래에서 스크롤을 할 때

            
                var supportPageOffset = window.pageXOffset !== undefined;
                var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
                var scrollTop = supportPageOffset ? window.pageYOffset : 
                    isCSS1Compat ? document.documentElement.scrollTop : 
                        document.body.scrollTop;

                // 스크롤하는 높이
                var scrollHeight = scrollTop + window.innerHeight;
                // 문서의 높이
                var documentHeight = document.body.clientHeight;
                

                // 스크롤하는 위치가 문서의 높이보다 크거나 같다면
                // 스크롤 하는 위치가 문서의 높이보다 크거나 같다면
                if(scrollHeight >= documentHeight){
                    for(let i =0; i<50; i++){
                        document.getElementById("body").innerHTML +=
                        "<h1>무한 스크롤</h1>";
                    }
                }
            })
        })
    </script>
</head>
<body>
    <div id="display"></div>
    <div id="body"></div>
</body>

■ 비동기 처리

  • 동기(Synchronous) 와 비동기(Astnchronous)
    • 동기 : 순차적으로 처리
      • 하나의 처리가 끝나야 다음을 처리하는 형태
    • 비동기
      • 하나의 처리가 끝나기 전에 다른 처리를 할 수 있는 형태
      • 이 와 유사한 형태로는 스레드를 만들어서 처리하는 것
      • 시간이 오래걸리는 작업의 경우 작업을 순차적으로 처리하게 되면 뒤의 작업이 너무 오래 기달려야 하고 동일한 자원을 사용하지 않는 작업을 순서대로 처리하게 되면 자원의 낭비가 발생하게 됨.
      • 알림을  어떻게 줄 것인가를 고민해야 함
      • 비동기로 동작한 작업이 끝나고 난 후 작업을 어떻게 할 것인가 하는 문제
  • callback
    • 상태 변화가 생기면 호출되는 함수를 callback function 이라고 함.
    • 비동기 처리는 언제 작업이 종료될 지 알 수 없기 때문에 작업이 종료되면 다른 작업을 수행할 수 있도록 콜백 함수를 등록 할 수 있게 해줌.
      • 브라우저가 html 파일을 전부 읽어서 메모리에 적재를 하고 나면 함수를 호출함
      • 함수는 로드가 끝나면 호출되기 때문에 콜백 함수라고 함
      • 모든 이벤트 처리는 비동기 방식임 
      • window.addEventListener("load", 함수);
      • 처리 내용
  • 비동기 처리를 수행해야 하는 경우
    • 입출력 작업
      • 파일에 읽고 쓰기
      • 서버에 요청하고 응답을 받는 것 - 느리기 때문
      • Processor(작업 수행 - CPU, GPU) 
        • ↔  Main Memory(RAM) 
          • ↔  I/O(키보드,모니터,마우스)
          • ↔  보조기억장치(디스크...)
    • 암호화/복호화 작업 ?
      • 오랜 시간이 걸리기 때문에 비동기적으로 처리하는 것을 기본으로 함
  • Promise
    • 비동기 처리를 수행한 후 다음 작업을 진행하고자 할 때 callback 함수를 이용할 수 있음.
    • callback을 이용하는 경우 2가지 문제점이 발생할 수 있음.
      • 가독성이 떨어질 수 있음 - callback 안에서 다시 비동기 작업을 하는 경우 callback 안에 callback 이 계속 만들어지는 상황이 발생 - callback hell
      • 예외처리의 한계 - 콜백 안에서 예외가 발생하면 콜백 외부에서는 처리할 수 없음
    • callback 함수의 단점을 보완하기 위해서 등장한 개념이 Promise
const promise = new Promise((resolve,reject) => {
	비동기 작업을 수행
    if(비동기 작업 수행에 성공했다면){
    	resolve;
    }else{
    	reject;
    }
});
  • chinning(연쇄적으로 동작) 가능 then 함수에 성공했을 때 수행할 작업을 연속 지정 가능

Promise 

        .then(수행할 작업)
        .then(수행할 작업)
        ...
        .catch(에러가 발생했을 때 수행할 작업)

 

>> then의 개수는 무제한이지만 catch는 1번만 나와야함.

>> 앞에서 수행한 작업의 리턴되는 데이터가 다음 수행할 작업의 함수의 매개변수로 전달 됨.

 

  • async/await
    • 가장 최근에 등장한 콜백 처리 방식으로 가독성을 높일 목적으로 추가
async function 함수이름(){
	변수 = await 비동기로 동작할 코드
    비동기 코드가 작업을 완료하면 수행할 코드
}

>> async 와 await 는 반드시 쌍으로 등장해야 함.

 

■ Communication

- 최근의 Front End 변화 : 모바일에서 접속을 많이 하고 사용자에서 가까운 쪽에서 많은 것을 할 수 있도록 함

- Mobile은 언제든지 네트워크에 변화가 생겨서 서버와의 연결이 끊어질 수 있음.

- 화면 전환은 최소화 해야함. 때문에 Single Page Application을 만듬 (화면전환을 안하는 것)

- 화면 전환을 하지 않는 대신 하나의 화면에 2개 이상의 컨텐츠를 보여줄 수 있어야 함.

- 로컬에 저장해서 출력하는 부분에 대해서도 고민을 해야 함.

  • ajax(Asynchronous Javascript XML - eXtensible Markup Language)
    • XML(eXtensible Markup Language)
      • HTML은 마크업 형태로 작성을 해서 해석을 브라우저가 함.
      • HTML에서는 태그의 기능이 고정임.
      • 확장 마크업 언어로 태그의 기능을 개발자가 정하는 것임.
      • XML의 목적은 서로 간의 데이터를 교환하기 위해 만든 포맷임.
    • ajax는 비동기적으로 xml을 주고 받기 위한 Javascript 기술임.
      • 최근에는 xml 뿐만 아니라 json 이나 csv(text)도 데이터 포맷으로 사용됨.
      • 최근에는 자바스크립트를 이용해서 비동기적으로 데이터를 받아로는 것을 ajax라고 함.
    • JavaScript에서는 ajax를 XHTMLHttpRequest 라는 객체를 이용해서 구현을 함.
    • ajax는 예전에 나와서 가독성이 떨어지기 때문에 Fetch API가 추가되었음.
    • HTML5에서는 Sever Sent Events(Web Push) 와 Web Socket API 가 추가됨
      • 기본적으로 클라이언트와 서버의 통신 방식은 클라이언트가 서버에게 요청을 하면 서버가 응답을 보내는 방식임.
      • Push 는 클라이언트의 요청이 없어도 서버가 클라이언트에게 데이터를 전송하는 것임.
      • HTTP 나 HTTPS 는 데이터 이외에 헤더 정보를 같이 전송하고 한 번 응답이 오면 연결이 끊어짐.
      • 짧은 메시지를 보낼 때 HTTP 나 HTTPS를 사용하면 오버헤드가 큼.
      • 상태 유지가 안되기 때문에 쿠키와 세션을 이용해 상태유지를 하였음.
      • 이 문제를 해결하기 위해 연결형 서비스이며 오버헤드가 작은 Web Socket이 HTML5에 추가되었음.
    • 작업 순서
      1. XMLHttpRequest 객체 생성
      2. 서버에게 보낼 데이터를 준비
      3. 서버에게서 응답이 왔을 때 처리할 callback 함수를 등록하고, 드 안에서 처리하는 코드를 작성
      4. open 메서드를 호출해서 연결 요청을 준비
      5. send 메서드를 호출해서 요청을 전송
    • XMLHttpRequest 의 속성
      • readyState : 상태를 나타내는 속성
        • 0 : 객체를 생성한 직후
        • 1 : open()을 호출한 상태
        • 2 : send()를 호출한 상태
        • 3 : 서버에게 응답이 오기 시작한 상태
        • 4 : 응답이 완료된 상태
      • status : 서버에게 응답을 보냈을 때 응답의 상태임
        • 100번대 : 처리 중
        • 200번대 : 정상 응답
        • 300번대 : redirect 중 (처리는  끝나고 응답을 전송하고 있는 경우)
        • 400번대 : 클라이언트 오류
          • 401 : 권한 없음
          • 404 : 요청한 URL을 처리할 수 없음.
        • 500번대 : 서버 오류
      • responseXML : 서버가 XML로 전송한 경우 XML 데이터
      • responseText
        • 서버가 XML 이외의 형식으로 전송한 경우의 문자열
        • JSON 데이터의 경우 JSON 파싱을 해서 사용
    • XMLHttpRequest 의 메서드
      • abort() : 요청 취소
      • open(요청 방식, 요청, URL, 비동기 전송 여부) : 연결 요청 준비
      • send(데이터) : 요청 전송
      • setRequestHeader(인자, 값) : 헤더 설정하는 것으로 인증(로그인)에서 중요
      • sendasBinary(데이터) : 요청을 전송하는 것으로 파일을 업로드하고자 할 때 사용
    • XMLHttpRequest 의 이벤트
      • abort : 취소할 때
      • error : 에러가 발생했을 때
      • load : 응답이 전부 왔을 때
    • SOP (Same Origin Policy - 동일 출처 정책)
      • 동일한 출처에서 불러온 데이터만 사용할 수 있도록 하는 브라우저의 보안 정책
      • ajax와 Fetch API에는 적용이 되지만, img, link, script, video, audio, object, embed 등에는 적용 되지 않음.
      • ajax와 Fetch API에서는 동일한 도메인의 데이터만 사용할 수 있음
        • 다른 출처의 데이터를 ajax 와 Fetch API에서 사용하려면 서버에서 CORS(교차 출처 리소스 공유) 설정을 하거나 클라이언트 쪽에서 Proxy(웹에서 데이터를 받아올 수 있는 언어의 프로그래밍을 이용해야 하는데 react나 vue에서는 설정만으로 가능)를 이용해야함,
          • 네트워크  →  proxy  →  외부 네트워크
          • 네트워크  ← firewell ← 외부 네트워크

※ csv 읽어서 파싱하기

  • data.csv 파일 생성하고 작성
    • 네이버, 카카오, 라인, 쿠팡, 배달의민족, 당근마켓, 토스

data.csv 파일 생성하고 작성

  • data1.json 파일 생성하고 작성
    • 네이버, 카카오, 라인, 쿠팡, 배달의민족, 당근마켓, 토스 

data1.json 파일 생성하고 작성

  • data2.json 파일 생성하고 작성

<!DOCTYPE html>
<html lang="ko">
<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>ajax-text</title>
    <script>
        window.addEventListener("load", (e) => {
            // 필요한 DOM 찾아오기
            let csv = document.getElementById("csv");
            let json1 = document.getElementById("json1");
            let json2 = document.getElementById("json2");
            let content = document.getElementById("content");

            json1.addEventListener("click", (e) => {
                let request = new XMLHttpRequest();
                request.open('GET', 'data1.json');
                request.send('');
                request.addEventListener("load", () => {
                    let result = JSON.parse(request.responseText);
                    content.innerHTML +=
                        "<p> 회사명 : " + result.company1 + "</p>";
                    content.innerHTML +=
                        "<p> 회사명 : " + result.company2 + "</p>";
                    content.innerHTML +=
                        "<p> 회사명 : " + result.company3 + "</p>";
                    content.innerHTML +=
                        "<p> 회사명 : " + result.company4 + "</p>";
                    content.innerHTML +=
                        "<p> 회사명 : " + result.company5 + "</p>";
                        
                });
                request.addEventListener("error", () => {
                    alert(request.status);
                });
            })

            json2.addEventListener("click", (e) => {
                let request = new XMLHttpRequest();
                request.open('GET', 'data2.json');
                request.send('');
                request.addEventListener("load", () => {
                    // JSON 파싱을 해서 Javascript 데이터로 만들어 준 것
                    let result = JSON.parse(request.responseText);
                    // 필요한 데이터만 추출해서 사용 - parsing
                    let count = result.count;
                    let documents = result.documents;
                    
                    content.innerHTML = "데이터 개수 : " + count;
                    for (doc of documents){
                        content.innerHTML += "<p>" + doc.company + " - " + doc.info + "</p>";
                    }

                });
                request.addEventListener("error", () => {
                    alert(request.status);
                });
            })

            // csv 버튼을 눌렀을 때 처리
            csv.addEventListener("click", (e) => {
                // ajax 요청 객체 생성
                let request = new XMLHttpRequest();

                // 연결 준비 - 1st : 요청 방식, 2nd : URL
                request.open('GET', 'data.csv');

                // 요청 - 데이터와 함께 전송해야 하는데 현재는 없음.
                request.send('');

                // 요청을 받기 위한 콜백 등록
                // 정상 응답이 온 경우
                request.addEventListener("load", () => {
                    // XML 이외의 데이터 읽기
                    // 읽은 데이터 ,로 구분된 csv 형식
                    let ar =request.responseText.split(",");
                    // 배열은 of를 이용해서 순회
                    for(name of ar){
                        content.innerHTML +=
                            '<p> 회사명 : ' + name + '</p>';
                    }
                });
                // 에러가 발생 했을 때 처리
                request.addEventListener("error", () => {
                    alert(request.status);
                });
            })
        })
    </script>
</head>
<body>
    <button id="csv">csv 읽기</button>
    <button id="json1">json1 읽기</button>
    <button id="json2">json2 읽기</button>
    <div id="content">출력 영역</div>
</body>
</html>

  • XML 파싱
    • RSS(Rich Site Summary)에 많이 이용
      • 신문사 등에서 실시간으로 변경되는 데이터를 제공하는 용도로 주로 이용
    • 태그 형태로 데이터를 구성
    • 파싱
XML 데이터 = ajax객체.responseXML;

// 필요한 태그 추출
태그들 = XML데이터.getElementsByTagName("태그 이름");

// 태그를 순회하면서 작업
for(var i=0; i<태그들.length; i++){
	// 태그 1개 가져오기
    var 태그 = 태그들[i].childNodes[0].nodeValue;
    // 태그 사용
}