웹 프론트 언어로서 자바스크립트

KODYwiththeK·2022년 12월 11일
0

JavaScript

목록 보기
21/32

웹 프론트 언어로서 자바스크립트

Class: 제로베이스
Created: December 6, 2022 5:34 PM
Type: Javascript
강의 명: 입문자를 위한 자바스크립트 실습

자바스크립트 엔진

자바스크립트 코드를 실행하는 프로그램

자바스크립트 런타임

자바스크립트 실행 환경

자바스크립트 엔진을 포함하고 있음

node.js는 자바스크립트를 실행할 수 있는 환경이고, 내부적으로 chrome 브라우저에서 사용하는 v8이라는 자바스크립트 엔진을 포함하고 있다.


디버깅

컴퓨터 프로그램 개발 단계 중 발생한 시스템의 논리적 오류나 버그를 찾아내고 수정하는 작업.

  • 웹 프로그래밍 시 디버깅은 console.log

chrome 개발자 도구

  • Element
    • 사이트의 DOM 확인을 위해 사용
    • 프론트 개발시 스타일을 조정하기 위해 많이 본다.
  • console
    • Javascript 로그가 찍히는 곳.
    • 코드 상 기재한 콘솔로그들은 해당 창에 기재된다.
  • Sources
    • 다운로드 받은 Asset들 표기
  • Network
    • 통신과 관련된 정보. 서버와 주고받은 데이터들 표시. 해당 요청이 실패했는지 성공했는지에 대한 status 값 출력
  • Application
    • Local Storage, Session Storage 등 데이터 저장공간 확인 가능
  • Lighthouse
    • 성능 최적화를 위해 사이트를 분석해서 속도가 느린 부분을 알려주는 등의 기능을 한다.

debugger

디버깅이 필요한 곳을 표시할 수 있다.

자바스크립트 파일 중간에 debugger; 를 넣으면, 해당 구간에서 실행이 중단된다.


DOM 다루기

자바스크립트가 웹브라우저 환경에서 실행될 떄는, 최상위 객체로 window가 존재한다.

window는 DOM 트리에 접근할 수 있도록 도와주고, 브라우저의 기능을 활용할 수 있는 객체에 접근할수 있도록 도와주며, 자바스크립트 코드의 전역변수들을 포함하고 있다.

document

DOM이라는 document object(문서 객체) 모델의 진입점 역할

document 객체를 통해 자바스크립트로 페이지 내의 요소들을 변화 생성 삭제 가능하다.

document 역시 전역 객체기 때문에, window.document 가 아닌 document 자체 접근 가능하다.

특정 요소 찾기

  • document.getElementById(’아이디’)
  • document.querySelector(’css’)
  • document.getElementsByClassName(’class’)
  • document.getElentsByTagName(’tag’)

인접 노드 접근

  • Node.children: 자식들
  • Node.firstElementChild, Node.lastElementChild: 첫번째, 마지막 자식
  • Node.previousElementSibling, Node.nextElementSibling: 이전 형제, 이후 형제
  • Node.parentElement: 부모
<header>
    <a href="/">로고</a>
    <ul id="navigation-menu">
      <li>상점</li>
      <li>커뮤니티</li>
      <li>마이페이지</li>
    </ul>
    <button>로그인</button>
    <button>회원가입</button>
  </header>

  <script>
    const navigationMenu = document.getElementById('navigation-menu');
    for(let menu of navigationMenu.children) {
      console.log(menu.innerHTML)
      // 출력 값 : 상점 커뮤니티 마이페이지
    }
    console.log(navigationMenu.firstElementChild.innerHTML) 
    // 출력 값 : 상점
    console.log(navigationMenu.previousElementSibling.innerHTML)
    // 자기 이전의 형제요소를 찾아서 출력
    // 출력 값 : 로고
  </script>

요소 만들기

  • document.createElement(tag)
    • 특정 DOM을 만드는 함수
  • Node.appendChild(Node)
    • DOM의 특정 요소의 자식으로 DOM을 붙여주는 함수
    • 부모 노드의 마지막에 매개변수로 주어진 자식요소를 넣어줌
  • Node.insertBefore
    • 특정 위치에 자식 요소를 넣어줌
<script> // <div> 마지막 </div>
    const dom = document.createElement('div')
    dom.innerHTML = '마지막';
    document.body.appendChild(dom);
  </script>

요소 노드의 주요 프로퍼티

Node {

tagName : ‘div’,

id : ‘test’,

innerHTML : ‘테스트용’,

style : 스타일 객체,

}

<div id="test">
    테스트용
  </div

DOM 변경하기

Node. innerHTML = ‘테스트용 수정’

Node.style.color = ‘red’

Node.hiddem = true;


브라우저 객체

DOM 에 접근할 수 있는 진입점 객체

브라우저 기능을 이용할 수 있는 진입점 객체

자바스크립트 코드의 전역 객체

브라우저와 운영체제에 대한 정보

  • language: 선호하는 언어
  • maxTouchPoints : 동시 터치 지점 수
  • userAgent : 브라우저 정보
  • platform : 운영체제 정보

Location

현재 URL의 정보를 읽고 변경할 수 있는 객체

  • href : 현재 URL을 읽고, 해당 값을 덮어씌워서 페이지를 이동시킬 수 있따.
    • location.href = ‘이동할 URL’
  • Pathname, hash, postname 등 - 전체 URL에서 각 부분이 담당하는 부분을 따로 가져올 수 있다.
  • reload : 새로고침 함수

History

브라우저의 사이트 방문 기록을 가지고 있고, 사용자의 방문 기록을 기반으로 뒤로가기, 앞으로가기 수행 가능

  • back
  • forward

window 객체를 통해 사용자와 상호작용할 수 있는 기능

  1. alert : 접근 불가 페이지에 사용자가 접근했다면, 페이지에서의 동작을 막고 다른페이지를 보낸다. 사용자가 확인 버튼을 누를 때 까지 메세지 창만 뜨기 때문에, 페이지와 상호작용할 수 없고, 경고메세지를 출력한다.

  2. confirm : 매개변수로 받은 텍스트를 표시하고, 확인과 취소 버튼으로 사용자의 응답을 얻을 수 있는 메세지 기능

    if(confirm("정말 삭제하시겠습니까?")) {
      console.log('삭제됨');
    } else {
      console.log('삭제 취소됨');
    }
  3. pompt : 사용자에게 메세지를 입력할 수 있는 필드를 제공해서 사용자의 메세지를 받는다. 확인을 누르면, 사용자가 입력한 메세지가 반환되고, 취소를 누르면 null 값을 반환한다.

    const name = prompt('이름이 무엇인가요?');
    ⇒ 입력 : KODY
    name
    ⇒ name 변수에 'KODY'가 할당되어 있는 것 확인.

  4. setTimeout : n초 후에 함수를 실행하는 타이머 함수

    let timer = setTimeout(() => {
      console.log('3secs')
    }, 3000); 
    // 3초 후에 함수 실행
    clearTimeout(timer);
    // timer 정지
  5. setInterval : n초 마다 함수를 실행하는 타이머 함수

    let timer = setInterval(() => {
      console.log('3secs')
    }, 3000);
    clearInterval(timer)

이벤트

이벤트: 활동이 발생했다는 신호. 이 신호가 발생하면 동작할 함수(핸들러)를 등록할 수 있다.
트리거: 신호가 발생하면 동작하게 되는 것
이벤트 핸들러 : 이벤트를 처리하는 자바스크립트 코드. 이벤트에 의해서 실행되는 메소드 혹은 이벤트 함수
즉, 이벤트는, 이벤트 핸들러를 트리거하는 신호.

자바스크립트에서 웹브라우저의 내장객체들은 계층구조를 이루고 있으며, 이벤트가 발생하면 해당 이벤트 핸들러에 의해서 이벤트를 전달할 때 계층구조를 따라 전달되는 경로로 해당되는 이벤트 핸들러에게 전달됩니다.

이벤트는 그냥 발생하기도 하지만, 대부분 사용자에 의해 발생

대표적인 DOM 이벤트 종류

분류이벤트 핸드러 설명
마우스onClick링크나 폼 양식을 마우스로 클릭할 때 발생하는 이벤트
마우스onDblClick마우스를 더블 클릭할 때 발생하는 이벤트
마우스onDragDrop마우스를 드래그할 때 발생하는 이벤트
마우스onMouseDown사용자가 마우스 버튼을 누르는 순간 발생하는 이벤트
마우스onMouseMove마우스가 움직일 때마다 발생하는 이벤트
마우스onMouseOut이미지나 링크위에 마우스 커서가 떠날 경우 발생하는 이벤트
마우스onMouseOver이미지나 링크위에 마우스 커서가 올라오는 경우 발생하는 이벤트
마우스onMouseUp사용자가 마우스를 눌렀다 놓는 순간 발생하는 이벤트
포커스onBlur커서를 다른 곳으로 이동할 때 발생하는 이벤트
포커스onFocus커서가 위치할 때 발생하는 이벤트
키보드onKeyDown사용자가 키를 누르는 순간 발생하는 이벤트
키보드onKeyPress사용자가 키를 누른 채 유지하는 동안 발생하는 이벤트
키보드onKeyUp사용자가 키를 눌렀다가 놓은 순간 발생하는 이벤트
onChange입력 폼 양식을 변경할 때 발생하는 이벤트
onReset리셋 버튼을 눌렀을 때 발생하는 이벤트
onSelect입력 양식의 하나가 선택될 때 발생하는 이벤트
onSubmit폼을 전송할 때 발생하는 이벤트
윈도우onAbort사용자의 작업을 강제로 중단할 때 발생하는 이벤트
윈도우onError문서나 이미지에서 에러를 만났을 때 발생하는 이벤트
윈도우onLoad문서가 브라우저로 읽혀질 때 발생하는 이벤트
윈도우onUnload문서가 브라우저에서 닫힐 때 발생하는 이벤트
윈도우onMove윈도우나 프레임을 움직일 때 발생하는 이벤트
윈도우onResize윈도우나 프레임의 사이즈를 조정할 때 발생하는 이벤트

Event 객체 프로퍼티

e.target; 					// 이벤트가 발생한 요소를 가져온다
e.type; 						// 발생한 이벤트의 종류 (click, mouseenter)
e.cancelable 				// 요소의 기본 동작을 취소할 수 있는지 여부 (true/false)
e.bubbles 					// 버블링 발생 여부 (true/false)
e.preventDefault() 	// 이벤트의 기본 동작을 취소한다.
e.stopPropagation() // 이벤트의 캡처링이나 버블링을 중단한다.
e.screenX 					// 모니터 상에서 커서의 X 위치
e.pageX 						// 문서 페이지를 기준으로 한 커서의 X 위치
e.pageY 						// 문서 페이지를 기준으로 한 커서의 Y 위치
e.clientY 					// 웹브라우저 내부 화면에서 커서의 Y 위치
e.keyCode 					// 각 키의 ASCII 코드
e.eventPhase				// 1= capture, 2= target, 3= bubbling
e.currentTarget			// 캡처링/버블링 시 리스너 대상

EXAMPLES

<body>
  <button id="count-up-button">+1</button>
  <span>0</span>

  <input type="text">
  <input type="text">

  <div id="result"></div>

	<span id='test'></span>  
  
  <script src="./main.js"></script>
</body>

예 1) onclick , onmouseover

const [count] = document.getElementsByTagName('span');
// 구조분해 할당으로 첫번째 span 태그만 count 변수에 할당
const countUpButton = document.getElementById('count-up-button');
// id가 count-up-button인 요소를 변수에 할당

// 클릭했을때 이벤트 발생
countUpButton.onclick = () => {
  if (isNaN(Number(count.innerHTML))) return;
	// count의 innerHTML을 명시적으로 숫자변환한 값이 숫자가 아니라면 그냥 return
  count.innerHTML = Number(count.innerHTML) + 1;
	// 숫자면, + 1
};

// count에 마우스 올렸을 때(이벤트 발생) 스타일 변경
count.onmouseover = () => {
  count.style.backgroundColor = 'red';
  count.style.color = 'white';
}

예 2) onfocus, onchange

const input = document.getElementsByTagName('input')[0];
input.onfocus = () => {
  input.value = '자동 입력';
} // input 태그중 첫째 요소를 변수에 할당한 후, 클릭해서 focus 되었을 때, 
	// input value 값을 '자동입력'으로 변경

const input2 = document.getElementsByTagName('input')[1];
const result = document.getElementById('result');
input2.onchange = (event) => {
  result.innerHTML = event.target.value;
	// input2 에 입력한 값을 result의 innerHTML로 받음
  // event.target -> 이벤트가 발생한 DOM
  // event.target.value
}

onchange - 폼 필드의 상태가 변경되었을 때 발생한다. 라디오 버튼을 클릭하거나 셀렉트 박스에서 값을 선택하는 경우를 예로 들수 있다.

예 3) addEventListener( )

const test = document.getElementById('test');

new Array(10).fill(0).forEach((_,index) => {
  // 길이가 10개인 배열을 생성.
  // fill 함수를 이용해 모두 0으로 채움.
  // forEach를 통해, 10번 출력되도록 .
  test.addEventListener('click', () => {
    console.log(`test clicked ${index + 1}`);
  })
})

이벤트 리스너 (addEventListener)

  • DOM 객체에서 이벤트가 발생할 경우 해당 이벤트 처리 핸들러를 추가할 수 있는 오브젝트
  • 이벤트 리스너를 이용하면 특정 DOM에 위에 말한 Javascirpt 이벤트가 발생할 때 특정 함수를 호출

특정 DOM요소에 이벤트 리스너를 등록할 때는 addEventListener를 사용한다.

DOM객체. addEventListener(이벤트명, 실행할 함수명, 옵션)

  • 이벤트명 : Javascript에서 발생할 수 있는 이벤트 명을 입력한다.
  • 함수명 : 해당 변수는 생략 가능하며, 해당 이벤트가 발생할 때 실행할 함수 명을 입력한다.
  • 옵션: 옵션은 생략이 가능하며, 자식과 부모 요소에서 발생하는 버블링을 제어하기 위한 옵션이다.

이벤트 버블링

이벤트 버블링이란 한 요소에 이벤트가 발생하면 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작하고 최상단의 부모 요소를 만날 때까지 반복되면서 핸들러가 동작하는 현상을 말한다.

예외

  • focus, blur, mouseenter, mouseleave는 버블링이 발생하지 않음
  • 버블링을 원한다면
    • focusin, focusout, moseover, mouseout을 사용하면 됨

event.stopPropagation( )

이벤트의 버블링을 막는다. 더이상 이벤트가 부모 노드로 전달되지 않고, 버튼 태그의 이벤트 핸들러에서 끝나게 된다.

/* 버블링 */
const button = document.getElementById('count-up-button')
const buttonWrapper = document.getElementById('button-wrapper');
const buttonSubWrapper = document.getElementById('button-subWrapper');

button.onclick = (event) => {
  event.stopPropagation();
  //이벤트의 버블링 끊어주기
  console.log('button event triggered');
}
buttonWrapper.onclick = () => {
  console.log('wrapper event triggered');
}
buttonSubWrapper.onclick = () => {
  console.log('subWrapper event triggered');
}

에러 핸들링

에러가 발생했을 때 실제로 유저에게 에러처럼 보이지 않도록 코드상에서 처리하는 기술

실제로 에러처럼 보이지 않도록, 기본값을 할당한다던지, 에러페이지로 이동해서 망가진 페이지를 보여주지 않도록 하는 것.

try … catch 문

‘try…catch’ 문법은 'try’와 'catch’라는 두 개의 주요 블록으로 구성됩니다.

try {
  // 코드...
} catch (err) {
  // 에러 핸들링
}

try…catch 동작 알고리즘은 다음과 같습니다.

  1. 먼저, try {...} 안의 코드가 실행됩니다.
  2. 에러가 없다면, try 안의 마지막 줄까지 실행되고, catch 블록은 건너뜁니다.
  3. 에러가 있다면, try 안 코드의 실행이 중단되고, catch(err) 블록으로 제어 흐름이 넘어갑니다. 변수 err(아무 이름이나 사용 가능)는 무슨 일이 일어났는지에 대한 설명이 담긴 에러 객체를 포함합니다.

에러 객체

에러가 발생하면 자바스크립트는 에러 상세내용이 담긴 객체를 생성.

그 후, catch 블록에 이 객체를 인수로 전달

내장 에러 전체와 에러 객체는 두 가지 주요 프로퍼티를 가집니다.

  1. name에러 이름.

    정의되지 않은 변수 때문에 발생한 에러라면 "ReferenceError"가 이름이 됩니다.

  2. message에러 상세 내용을 담고 있는 문자 메시지

  3. stack현재 호출 스택. 에러를 유발한 중첩 호출들의 순서 정보를 가진 문자열로 디버깅 목적으로 사용.

    표준은 아니지만, name과 message 이외에 대부분의 호스트 환경에서 지원하는 프로퍼티도 있다. stack은 가장 널리 사용되는 비표준 프로퍼티 중 하나.

try … catch … finally

try..catch는 finally라는 코드 절을 하나 더 가질 수 있다.

finally안의 코드는 다음과 같은 상황에서 실행.

  • 에러가 없는 경우: try 실행이 끝난 후
  • 에러가 있는 경우: catch 실행이 끝난 후

이렇게 finally 절은 무언가를 실행하고, 실행 결과에 상관없이 실행을 완료하고 싶을 경우 사용

예제 1 )

const obj = {};
let result = '';

try {
  result = obj.property.a; // 에러 발생
} catch (error) {
  result = 'idk'; //기본값
  console.dir(error); // 에러 객체에 어떤 값이 들었는지 표현
  // TypeError: Cannot read properties of undefined (reading 'a')
} finally {
  console.log(`result = ${result}`); 
  // 에러의 발생 여부와 관계없이 항상 출력되는 값
}

예제 2 ) 특정 경우, 필요에 의해 개발자가 에러를 직접 발생시킬 수 있음

try {
  throw new Error('이건 커스텀 에러입니다.');
  // 에러를 발생시키는 throw 키워드를 이용한 new Error 라는 생성자 함수 생성
} catch (error) {
  console.dir(error)
  // Error: 이건 커스텀 에러입니다.
}

비동기

동기(동시에 발생함)의 반의어로, 동시에 발생하지 않음을 뜻함. → 순차적으로 발생

비동기로 코드를 짜야하는 이유는, a 작업이 수행된 후에 얻게된 데이터를 이용해서 b 작업을 수행해야 하기 때문

동기 코드

  • 작업 A를 수행함과 동시에 작업 B 가 실행됨
  • B의 작업은 데이터 a가 필요한 작업임
  • 아직 작업A가 진행중이므로 데이터 a가 존재하지 않음(에러)

비동기 코드

  • 작업 A가 실행된 후, 데이터 a를 가지고 작업 B 정상적으로 수행됨.

비동기 코드의 발전 과정

콜백 함수

  • 다른 함수의 인자로 넘겨져서 호출되는 함수
  • 비동기 코드로서 콜백함수를 많이 사용했지만, 작업이 5개만 되어도, 5개의 함수를 매개변수로 계속 넘겨줘야하고, 이런 코드 작성은 코드 파악을 어렵게한다.
const A = (callback) => {
  const a = 'A 함수 실행 후 생기는 데이터';
  callback(a);
}; 

const B = (a) => {
  console.log(`${a}를 이용하는 B`)
};

A(B); // 출력 : A 함수 실행 후 생기는 데이터를 이용하는 B
// A 함수가 실행되며 데이터 a가 생성되고, 
// a 데이터를 인자로 받는 B 함수가 순차적으로 실행

프라미스(Promise)

구독이라는 방법을 이용하는 비동기 구현 방법.

new Promise 생성자 함수를 통해 생성 가능. 매개변수로 함수를 받는다.

resolve와 reject 함수가 그 매개변수.

  • 성공시 resolve 호출
  • 실패시 reject 호출

then 메서드 - 성공시 넘어오는 값을 result로 코드 구현

catch 메서드 - 실패시 넘어오는 에러 error 로 코드 구현

하지만, 프라미스 역시 then 절이 계속 이어지는 식으로 체이닝이 발생하기 때문에 복잡해질수록 코드 파악 어렵.

const A2 = () => new Promise((resolve, reject) => {
  const a = 'A 함수 실행 후 생기는 데이터';
  resolve(a);
})

const B2 = (a) => {
  console.log(`${a}를 이용하는 B`);
};

A2()
.then((a) => {
  console.log('A2 실행 성공!');
  B2(a);
})
.catch((error) => {
  console.log(error.message);
})
  1. A2 함수 실행했을 때, A2 함수는 프라미스 객체를 반환받기 때문에, a라는 데이터가 정의되고,
  2. resolve(a)라는 함수가 실행되어서, a 라는 값을 가진 프라미스 객체가 A2 변수에 할당되고
  3. 프라미스 객체의 then 메서드 사용하면 메서드 내부의 함수로 정의된 매개변수에 그 성공한 값 들어감
  4. a 값이 B2에 매개변수로 들어가게 되고, B2가 실행됨

async 와 await

프라미스의 개념을 사용한 문법이지만, 보다 가독성 있게 코드를 표현할 수 있다.

비동기로 표현할 함수 앞에 async 라는 키워드를 붙이면, 해당 함수는 항상 프라미스를 반환.

비동기 함수를 호출하며, 호출 코드 앞에 await를 붙이면, 프라미스가 값을 반환하기 기다렸다가 반환되는 값을 변수에 할당해 준다.

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("완료!"), 1000)
  });

  let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)

  alert(result); // "완료!"
}

f();

자바스크립트는 await 키워드를 만나면 프라미스가 처리될 때까지 기다립니다(await는 '기다리다’라는 뜻을 가진 영단어입니다 – 옮긴이). 결과는 그 이후 반환. await는 async 함수 내부에서만 동작한다.

함수를 호출하고, 함수 본문이 실행되는 도중에 (*)로 표시한 줄에서 실행이 잠시 '중단’되었다가 프라미스가 처리되면 실행이 재개됩니다. 이때 프라미스 객체의 result 값이 변수 result에 할당.

따라서 위 예시를 실행하면 1초 뒤에 '완료!'가 출력

const A3 = async() => {
  const a = 'A 함수 실행 후 생기는 데이터';
  return a;
};
const B3 = (a) => {
  console.log(`${a}를 이용하는 B`)
};

const func = async () => {
  const b = await A3();
  console.log('A3 실행 성공!!!');
  B3(b);
};
func(); // A 함수 실행 후 생기는 데이터를 이용하는 B
  1. 변수 a를 정의하고 리턴하는 A3 함수
  2. 그 변수 a를 활용하는 B3 함수
  3. async를 통해 func를 실행하면, A3함수가 실행될 때 까지 기다렸다가 리턴되는 a 값을 변수 b가 받음
  4. A3 실행 성공!!! 출력
  5. A3의 리턴값을 받은 변수 b를 매개변수로 넣어 B3 함수 실행
  6. A 함수를 실행 후 생기는 데이터를 이용하는 B 출력

네트워크 요청

참고 URL : https://velog.io/@longroadhome/모던JS-심화-네트워크-요청-1

클라이언트가 서버에 데이터를 요청하거나 보내는 일련의 통신 과정

웹사이트를 띄우는 것 조차, 서버에 있는 웹사이트의 데이터를 요청해서 렌더링하는 것이다.

웹사이트 내부에서 일어나는 여러 데이터 변환 행위 등이 모두 네트워크를 거치고 있다.

자바스크립트를 사용해서 네트워크 요청을 보내고 새로운 정보를 받아오는 작업을 할 수 있다. 네트워크 요청은 주로 다음과 같이 다양한 상황에서 일어날 수 있다.

  • 주문 전송
  • 사용자 정보 읽기
  • 서버에서 최신 정보 가져오기
  • 기타 등등

그런데 이러한 모든 작업을 별도의 페이지 새로고침 없이 현재 페이지에서 수행할 수 있다. 가령 서버로부터 정보를 가져와 테이블을 만들어주는 버튼이 있다고 가정해보자. 이런 버튼을 누를때마다 페이지가 새로고침 된다면 유저 경험에 안 좋은 영향을 끼칠 수 있을 것이다. 그러나 AJAX 기술을 활용하면 데이터를 받아오고, 이 데이터를 기반으로 테이블을 다시 그려주는 작업만 수행하여 현재 페이지를 떠나지 않고도 최신 정보를 반영할 수 있다. 이러한 흐름에서 더 나아가 발전한 형태의 형태가 SPA(Single Page Application)이라고 볼 수 있다. 오늘날 웹 프론트엔드 프레임워크/라이브러리 대부분 최종 빌드의 형태로 SPA를 지원한다.

이를 흔히 비동기 네트워크 통신으로 이야기 하기도 하는데 정확히는 AJAX(Asynchronous Javascript And XML)라는 용어를 사용한다. AJAX는 서버에서 추가 정보를 비동기적으로 가져올 수 있게 해주는 포괄적인 기술을 나타내는 용어이다. AJAX는 아주 오래전부터 있었던 기술이기 때문에 용어에 XML이 포함되어 있다. 보통 JQuery에서 ajax로 비동기 네트워크 요청을 다룰 수 있기 때문에 AJAX라고 하면 JQuery의 그것을 떠올리는 경우가 많다.

그러나 엄연히 AJAX 용어 자체는 기술을 의미하는 상위 개념의 용어이다. 다만 JQuery는 이를 보다 사용하기 쉽게 라이브러리 자체적으로 구현한 함수를 ajax라고 표현한 것이다.

자바스크립트에서는 XMLThhpRequest(XHR) 객체를 사용해서 이러한 비동기 네트워크 통신이 가능했다. 그러나 해당 객체를 사용한 통신은 사용하기 복잡하고 가독성이 좋지 않다는 단점이 있었다. 때문에 조금 더 모던하고 다재다능한 fetch메서드가 ES6에서 도입되었다. 몇몇 구식 브라우저는 이를 지원하지 않지만 관련 폴리필이 잘 마련되어 있고, 대부분의 모던 브라우저는 이를 지원하고 있다.

Fetch

자바스크립트에서 공식적으로 지원하는 함수

fetch() 는 비동기 통신을 하기 때문에 관련 네트워크 요청은 웹 브라우저의 네트워크 API가 도맡아 처리한다. 또한 요청이 반환하는 값은 보통 Promise이기 때문에 이들은 마이크로태스크 큐에 적재되어 작업이 처리된다.

1) 문법

fetch() 기본 문법은 다음과 같다.

let promise = fetch(url, [options]);
  • url : 접근하고자 하는 url
  • options : 선택 매개변수, method나 header 등을 지정할 수 있음

만약 options에 아무것도 넘기지 않으면 GET 메서드로 진행되어 url로 부터 컨텐츠가 다운로드 된다. 이때 fetch()가 호출되면 브라우저는 네트워크 요청을 해당 url로 보내고 프라미스를 반환한다. 반환되는 프라미스를 사용해서 다음 작업을 수행할 수 있다.

Methood - 네트워크 요청을 보낼 때의 요청의 종류를 의미

  • GET - 사이트의 데이터를 불러오기
  • POST - 옵션에 body라는 필드에 데이터를 싣어서 서버로 보내고, 서버에서는 이 데이터를 이용해서 새로운 객체를 생성할 때 사용한다. 게시물을 생성하기 위해 게시물 제목이나 내용 등을 넘기는 요청.
  • PUT - post 처럼 body 필드에 데이터를 싣어서 서버로 보내는데, 다른점은 서버에서 이 데이터를 이용해서 객체를 수정할 때 사용한다는 것. 이미 생성되어있는 게시물을 수정하는 행위
  • DELETE - 서버에 있는 객체 삭제할 때 사용
  • headers - 서버에 부가ㅓㄱ으로 전달할 정보.
    • cookie : 브라우저의 쿠키를 서버에 싣어서 보내고, 보통 쿠키에 저장된 인증정보가 필요한 API에 인증할 수 있도록 한다.
    • userAgent : error 등을 서버에서 기록할 때, 어떤 환경에서 발생했는지 쉽게 파악하기 위해, 서버 로깅 시 활용할 수 있다.
  • body - POST, PUT 메소드처럼 서버에 전달해야 할 데이터가 있을 떄, 데이터를 싣어 보내는 필드
  • fetch - 프라미스를 반환하기 때문에, then async await 문법을 통해 데이터를 받으면 된다.
    • fetch의 결과는 status와 ok로 이루어진 Response 객체 ⇒ 네트워크 요청이 성공했는지를 나타냄
    • 네트워크 요청에 싣려온 결과 데이터를 받으려면, 받아온 결과 객체(response)를 객체에 있는 json 메서드를 호출하면 된다.
      • json 메서드 또한 프라미스를 반환하므로, async await 같이 프라미스를 읽을 수 있는 비동기 문법을 사용해서 값을 받아야 한다.
fetch("/sampler.json")
.then(async (result) => {
  console.log('result', result);
// result Response {type: 'basic', url: 'http://127.0.0.1:5500/sampler.json', …}
  if(result.ok) {
    const data = await result.json();
    console.log(data)
	// {date: '2022-01-26T00:00:00+09:00'} => json 파일에 설정해줬던 값
  }
});

CORS 정책

fetch("https://ohou.se")
.then((res) => {
  console.log('success', res);
})
.catch((err) => {
  console.log('error',err);
})

자체 생성 json 파일에는 접근할 수 있었지만, 오늘의 집에서 내보내 준 api는 접근할 수 없는 이유?

CORS 정책에 따라 다른 도메인의 사이트에 요청을 보낼 떄, 미리 허용된 호스트가 아니라면 요청이 거부된다.

  • 해커로부터 유저를 보호하기 위해 만들어짐.
  • 우리의 도메인에서 오늘의 집 도메인에 요청을 보냈을 떄, 허용된 호스트인지 오늘의집에서 측정하고, 아니라면 CORS ERROR을 내게 하고, 맞다면 응답 헤더로 Access-Control-Allow-Origin과 함꼐 정상 응답
  • CORS ERROR 가 일어나지 않게 하려면, 서버에서는 요청을 허락할 호스트를 정해놓아야 하고, 허용된 호스트에 요청한 클라이언트가 속한다면, 응답헤더를 포함하여 정상응답을 하는 것.

브라우저 기능(쿠키)

브라우저에 저장되는 작은 크기의 문자열

쿠키의 구성요소

NameValueDomainPathExpires / max-ageHttpOnlySecure
쿠키에 접근 가능한 도메인 지정쿠키에 접근 가능한 경로요효일자 / 쿠키 만료일HTTP외의 통신으로 쿠키를 조정할 수 있는지 여부HTTPS 로만 통신하는 경우 쿠키가 전송되도록 하는 옵션.

쿠키는 보통 인증정보를 저장하기 위해 사용하므로, 서버에서 내려주고 브라우저에 할당된다.

서버에서 내려주는 response header(응답헤더)_에 set cookie 라는 필드가 있으면, 클라이언트에서 쿠키를 받아서 굳이 저장하지 않아도, 자동으로 브라우저에 해당 쿠키의 정보가 저장된다.

유저가 사이트에 로그인하면, 서버에서 아이디 비밀번호와 같은 로그인 정보를 이요해 유저의 정보를 찾고, 해당 정보를 뭉쳐놓은 값을 쿠키로 내려줘서 브라우저에 전달한다.

이렇게 브라우저에 저장해둔 쿠키는, ㅂ매 요청시마다 요청헤더에 포함되어, 서버에 전달되고, 이런 방식으로 회원권한이 필요한 API도 호출할 수 있게된다.

서버에서 클라이언트의 쿠키를 세팅해주는 방식이나, 클라이언트가 쿠키를 포함해서 요청보내는 방식을 살펴보자

쿠키 쓰기

  1. 클라이언트 코드에서는 도큐먼트 객체에 쿠키라는 프로퍼티에 값을 할당함으로서 쿠키를 설정한다.

    document.cookie = “name=heeun;path=/; max-age=3600”

    • 쿠키 설정할 떄는 세미콜론( ; )을 기준으로 옵션값을 나누어 설정한다.
    • 해당 쿠키 세팅은, name이라는 키를 가지고 heeun이라는 값을 가지는 쿠키가, paths는 지금 루트 도메인을 기준으로 설정하고, max-age(유효기간)은 3600초(1시간)을 기준으로 한다는 코드다.
  2. 서버는 클라이언트의 API 요청을 받았을 때, 내려주는 응답 헤더에 set cookie라는 필드를 싣어서 보냄.

    response.header {

    Set-Cookie: “name=heeun; path=/; max-age=3600; httpOnly”

    }

    • 해당 필드에 실려오는 쿠키 값들은 자동으로 브라우저에 쿠키로 저장된다.
    • 이 때 쿠키의 옵션 값 중, httpOnly라고 설정되어있다면, 클라이언트 코드에서 도큐먼트 객체를 통한 쿠키 갱신이나, 쿠키 쓰기, 쿠키 읽기 등이 불가능하다는 것

쿠키 접근

document.cookie → 쿠키에 접근할 때는, 도큐먼트 객체에 쿠키 필드를 읽기만 하면 된다.

쿠키 삭제

document.cookie = “같은 정보 … max-age=0” → 쿠키를 삭제할 떄는, max-age라는 옵션 값을 0으로 설정해서 쿠키가 파기되도록 하면 된다.

  • 만약 인증이 필요한 API를 활용한다면, 서버에 쿠키를 보내 요청할 때 fetch(URL, { credentials: ‘include’ }); → 요청 헤더에 쿠키값을 실어준다. ⇒ 해당 옵션이 켜져있지 않으면 쿠키가 요청에 함께 전달되지 않는다.
    • 서버에서는 해당 쿠키에 있는 인증 정보를 보고 유저를 판단한다.

브라우저 기능(웹 스토리지)

웹스토리지는 브라우저에 저장되는 키-값의 쌍이다.

  1. 로컬 스토리지: 브라우저에 저장되어, 브라우저 종료 후 브라우저를 재 시작할 대도 유지되는 데이터
  2. 세션 스토리지: 브라우저 종료 시에는 삭제되지만 새로 고침시에 유지되는 데이터. 각각의 탭마다 별도로 존재하기 때문에, 같은 페이지를 별도에 탭으로 열어도 세션 스토리지의 값이 유지되지 않는다.

특정 시간옹안 데이터가 삭제되지 않고, 이후 삭제하고 싶다면 쿠키로 설정하면 된다.

쿠키와 다른점

  • 요청시 쿠키는 헤더에 포함된다. 네트워크 요청시 전달해야하는 정보가 많아지는것이므로 응답속도가 느려질 수 있다. 따라서 쿠키에는 많은 정보가 아닌 단순한 문자열만 저장. 웹스토리지는 요청 헤더에 포함되지 않기 때문에 보다 많은 정보 저장 가능.
  • 쿠키는 클라이언트에서 조정 가능하지만, 서버에서 할당해 주는 것이 기본적인 데에 반해, 스토리지는 클라이언트에서만 조정할 수 있다.
  • 또한 쿠키는 서버 도메인이 달라도 옵션만 잘 설정하면 유지될 수 있는 반면, 웹 스토리지는 서버 도메인이 같아야 해당 URL에서만 접근이 가능하다.

웹스토리지를 보려면

  • 개발자 도구 - Application 탭 - Storage - Local Storage / session Storage

웹 스토리지 쓰기

웹 스토리지는 둘다 전역 객체로 존재한다. 따라서 로컬 스토리지와 세션스토리지 객체로 바로 접근 가능.

웹스토리지를 쓰기 위해서는 setItem 이라는 메소드를 사용해도 되고, 객체처럼 취급해서 프로퍼티로 바로 추가해도 된다.

  1. 로컬 스토리지

    localStorage.setItem(’key’, value); ⇒ 로컬 스토리지 객체에 키와 값을 넘길 수 있다.

    localStorage.key = value;

  2. 세션 스토리지

    sessionStorage.setItem(’key’, value);

    sessionStorage.key = value;

웹 스토리지 접근

  1. 로컬 스토리지

    localStorage.getItem(’key’);

    localStorage.key

  2. 세션 스토리지

    sessionStorage.getItem(’key’);

    sessionStorage.[key]

웹 스토리지 삭제

  1. 로컬 스토리지

    localStorage.removeItem(’key’);

    localStorage.clear( );

  2. 세션 스토리지

    sessionStorage.removeItem(’key’);

    sessionStorage.clear( );

데이터 포맷 JSON

JSON(JavaScript Objext Notation)

  • 자바스크립트에서 객체를 저장, 표현하기 위해서 만들진 데이터 포맷이다.
  • 현재는 범용적으로 사용되고 있고, 다른 언어에서도 라이브러리를 통해 사용 가능함
  • 클라이언트 코드에 데이터를 저장해 둘 때나, 서버와에 통신에서 데이터를 전달하고 받는 목적으로 주로 사용

기본 형태

파일 확장자로 json 지정. 객체의 형태

키 값은 쌍 따옴표(” “)로 감싸져야함

문자열 역시 쌍 따옴표(” “)로만 가능.

자바스크립트에서는 맨 마지막에도 콤마(,)를 붙이는 문법을 허용하지만 JSON에서는 사용할 수 없다.

주석 사용할 수 없다.

자바스크립트에서는 JSON 이라는 전역 객체를 사용하여, JSON을 다루고 있다.

JSON.parse(JSON string) : JSON을 객체로 변환

JSON.stringify(객체 변수) : 객체 변수를 JSON으로 변환

변환된 JSON은 객체를 인코딩된 문자열로 그대로 나타낸 형태. 직렬화된 객체라고 부르기도 함

만약 JSON.stringify에 넘긴 객체의 변수에, 함수나 undefined 값을 가진 프로퍼티가 있다면 이를 무시하고 직렬화 한다.

예 )

const obj = {
  "student" : [
    {
      "name" : "Kody",
      "age" : 20,
    },
  ]
};
console.log(obj)
// { student: [ { name: 'Kody', age: 20 } ] }

const jsonData = JSON.stringify(obj);
console.log(jsonData);
// {"student":[{"name":"Kody","age":20}]}

const objData = JSON.parse(jsonData);
console.log(objData) 
// { student: [ { name: 'Kody', age: 20 } ] }

obj.noValueField = undefined
obj.functionField = () => {};
console.log(obj)
// {
//   student: [ { name: 'Kody', age: 20 } ],
//   noValueField: undefined,
//   functionField: [Function (anonymous)]
// }
console.log(JSON.stringify(obj))
// {"student":[{"name":"Kody","age":20}]}
// => JSON에서는 값이 있는 value만 취급함. undefined, 빈 함수 취급 안함.

데이터 포맷 JSON

  • text : 기본 문자열
  • CSV : comma-Separated Values, 콤마로 필드를 구분한 텍스트 파일
  • XML : eXtensible Markup Language
profile
일상 속 선한 영향력을 만드는 개발자를 꿈꿉니다🧑🏻‍💻

0개의 댓글

관련 채용 정보