[230424] 최적화 | Ajax

윤지수·2023년 4월 24일
0
post-thumbnail

🪄 최적화

반응 시간

* 크롬 개발자도구 Network 탭
https://developer.chrome.com/docs/devtools/network/
https://googlechrome.github.io/devtools-samples/jank/

  1. DOM 접근과 업데이트는 가능한 적게 한다.
  • DOM 접근은 가능한 좁은 범위에서 적게 사용한다.
<article class="parent">
	<figure>
		<img class="figImg"
			src="https://pds.joongang.co.kr/news/component/htmlphoto_mmdata/202112/13/e4725896-2596-44f0-8b95-ab3faaa76d7d.jpg"
			alt="">
		<figcaption class="figCap">
			유재석씨가 코로나에 돌파 감염되었다는 소식입니다.
		</figcaption>
	</figure>
</article>
<script>
	const parent = document.querySelector('.parent');
	parent.querySelector('.figImg').setAttribute('src', 'https://file.mk.co.kr/meet/neds/2021/07/image_readtop_2021_654175_16256093474708254.jpg');
	parent.querySelector('.figCap').textContent = '유재석씨가 수상식에서 환하게 웃고 있다.'
</script>
  • DocumentFragment를 사용해서 한번에 DOM을 업데이트한다.
    • DocumentFragment : 오직 메모리 상에서만 존재하는 경량화된 DOM 트리(미니돔)
<main></main>
<script>
	const frag = document.createDocumentFragment();

	const article = document.createElement('article');
	article.classList.add('parent');
	article.innerHTML = `		<figure>
		<img class="figImg" src="https://file.mk.co.kr/meet/neds/2021/07/image_readtop_2021_654175_16256093474708254.jpg" alt="">
		<figcaption class="figCap">
			유재석씨가 수상식에서 환하게 웃고 있다.
		</figcaption>
	</figure>`;

	for (let i = 0; i < 10; i++) {
		frag.append(article.cloneNode(true));
	}

	document.querySelector('main').append(frag.cloneNode(true));
	document.querySelector('main').append(frag.cloneNode(true));
</script>

* Node.cloneNode(): 메서드를 호출한 Node의 복제된 Node를 반환

  • 메모리

메모리 생명주기
메모리 생명주기(이미지 출처 - 멋쟁이사자처럼 프론트엔드스쿨 5기 교안)

메모리 누수
메모리 누수: 프로그램이 필요하지 않은 메모리 공간을 계속해서 점유하는 현상
이러한 현상을 방지하기 위해 자바스크립트나 자바, 파이썬 같은 고수준 언어에는 가비지 컬렉터가 존재한다.
사용하지 않는 메모리는 자바스크립트 엔진이 추정하여 삭제(Garbage Collection)한다. 참조 카운팅(reference counting)으로 메모리에 존재하는 값을 몇 개의 변수와 함수가 참조하고 있는지 살펴보는 것이다. 참조가 0이 되면 값을 메모리에서 삭제한다.

자바스크립트에서 메모리 관리에 신경써야하는 경우 중 하나는 제때 메모리를 해제해주지 못하는 경우

  • 클로저
function outer() {
	let privateVal = ['test'];

	function getPrivate() {
		return privateVal;
	}

	return getPrivate;
}

const getPrivate = outer();
let secretVal = getPrivate();

console.log(secretVal);

secretVal = null;	// 해주지 않으면 영원히 존재한다
  • 전역변수는 프로그램이 종료되기 전까지 계속 메모리에 존재

좋은 습관 기르기

  • 배열이나 객체를 불변하는 객체처럼 다루기

배열 데이터를 수정해야 한다면 기존에 사용했던 원본 데이터는 그대로 두고 새로운 배열을 만들어 사용하기

  • 엄격모드(strict mode)로 사용하기

선언하지 않은 변수에 값을 할당할 수 없다.

str = 'hello';	// str is not defined

읽기 전용 객체에 값을 할당하면 에러가 발생한다. (일반 모드에서는 조용한 에러 -> 무시 처리)

undefined = 10;	// Cannot assign to read only property 'undefined' of object '#<Window>'
Infinity = 10;	// Cannot assign to read only property 'Infinity' of object '#<Window>'
Math.PI = 0;	// Cannot assign to read only property 'PI' of object '#<Object>'

지울수 없는 값을 지우려고 하면 에러가 발생한다. (일반 모드에서는 조용한 에러 -> 무시 처리)

const obj = {
  firstName: 'mallang',
  lastName: 'yoon'
}

delete obj.lastName
console.log(obj);			// {firstName: 'mallang'}

delete Object.prototype;	// Cannnot delete property 'prototype' of function Object() { [native code] }

함수 파라미터에 중복된 이름을 사용할 수 없다.

function myFunc(a, a, b) {	// Duplicate parameter name not allowed in this context
  console.log(a + a + b);
}

// 일반 모드에서는 7
myFunc(1, 2, 3)
  • 일치연산자 사용하기

🪄 Ajax

JS 기술을 이용해 비동기적으로 서버와 통신할 수 있는 방법

💡 Ajax가 나오기 이전에 서버와 통신하던 방법
브라우저 주소창에 특정 URL을 입력하거나 HTML 요소인 <a> 혹은 <form>을 이용하여 클라이언트가 데이터를 서버에 요청하면 서버는 요청받은 데이터와 함께 데이터가 포함되어 있는 HTML 파일을 같이 전송하였다.
-> 필요한 데이터만 받아오는 것에 비해 엄청나게 비효율적이었다.
-> HTML 파일 자체가 교체되는 방식이기 때문에 화면이 랜더링되면서 번쩍이는 현상도 함께 나타났다.

XMLHttpRequest

서버와의 비동기 통신을 가능하게 하는 여러 기능들을 가진 자바스크립트 객체

// XHR 객체 생성
const requestObj = new XMLHttpRequest();
// 요청 초기화. 통신 방법, 요청을 발신할 대상의 주소를 전달
requestObj.open('GET', 'url'); 
// readystate가 변화하면 실행되는 이벤트리스너
requestObj.onreadystatechange = () => {
를 의미합니다.
	// readystate: 서버와의 통신 상태
    // 0 (UNSENT) - XHR 객체가 생성되었지만 아직 초기화되지 않았다
    // 1 (OPENED) - open() 함수가 호출되어 요청이 초기화되었다
    // 2 (HEADERS_RECEIVED) - send() 함수가 호출되었다
    // 3 (LOADING) - 데이터를 다운받는 중이다
    // 4 (DONE) - 통신이 완료되었다

	// status: 서버의 응답 상태
	// 200 - 요청한 내용이 성공적으로 완료되었다
    if (requestObj.readyState == 4 && requestObj.status == "200") {
        const result = requestObj.responseText;
    }
};
// 서버로 요청 보내기
// send 메소드가 실행되어야만 위에서 설정한 내용들이 의미를 가지게 된다
requestObj.send();

💡 웹 서버에 데이터를 요청할 때
get은 URL 주소에 데이터를 입력하는 방식이고 전달할 수 있는 데이터의 양에 제한이 있다.
post는 URL 주소에 데이터 내용이 나타나지 않도록 하고 전송할 수 있는 데이터의 양에 제한이 없다.

콜백지옥(callback hell)

Ajax가 널리 쓰이게 되면서 비동기 처리방법이 매우 중요해졌다.
Ajax는 기본적으로 비동기적으로 서버와의 통신을 처리하기 때문에 Ajax와 기존의 동기식 코드를 함께 작성하면 코드의 실행순서에 문제가 발생한다. 자바스크립트 엔진은 비동기 코드가 끝날 때까지 기다리지 않고 다른 코드의 실행을 멈추지 않기⬇️ 때문이다!

let result;
function xhrRequest() {

    const requestObj = new XMLHttpRequest();
    requestObj.open('GET', 'message.txt');
    requestObj.onreadystatechange = () => {
        if (requestObj.readyState == 4 && requestObj.status == "200") {

            result = requestObj.responseText;
            console.log(result); // 2. result
        }
    };
    requestObj.send();
}

xhrRequest();
console.log(result); // 1. undefined

그래서 통신이 끝난 다음에야 다음 함수가 실행되도록 콜백함수로 코드를 작성해야 한다. 결국 일반적인 동기식 코드처럼 비동기 함수 실행 후 다음 라인에서 다른 함수를 실행하는, 순차적으로 함수들을 나열하는 방식이 불가능하다. 비동기 함수가 끝나기 전에 필요한 콜백함수를 실행시키는 형태가 되어야한다.
-> 콜백 함수를 연속해서 사용하게 되면 콜백지옥🔥

0개의 댓글