43장 Ajax

43.1 Ajax란?

  • Ajax란 자바스크립트를 사용하여 브라우저가 서버에게 비동기 방식으로 데이터를 요청하고, 서버가 응답한 데이터를 수신하여 웹페이지를 동적으로 갱신하는 프로그래밍 방식을 의미

  • 브라우저에서 제공하는 Web API인 XMLHttpRequest 객체 기반으로 동작. HTTP 비동기 통신을 위한 메소드, 프로퍼티를 제공

  • 장점이 불필요한 렌더링이 필요없이 필요한 부분만 렌더링 한다는 점과 블로킹이 없다는점(비동기니까)

43.2 JSON

  • JSON은 클라이언트와 서버 간의 HTTP 통신을 위한 텍스트 데이터 포맷 독립형 데이터 포맷으로, 대부분의 프로그래밍 언어에서 사용 가능

43.2.1 JSON 표기 방식(43-01)

  • 키와 값으로 구성

  • 키는 꼭 큰따옴표를 사용해야함

{
  "name": "Lee",
  "age": 20,
  "alive": true,
  "hobby": ["traveling", "tennis"]
}

43.2.2 JSON.stringify(43-02)

  • JSON.stringify 메서드는 객체를 JSON 포맷의 문자열로 변환

  • 사용법은 예제를 확인

const obj = {
  name: 'Lee',
  age: 20,
  alive: true,
  hobby: ['traveling', 'tennis']
};

// 객체를 JSON 포맷의 문자열로 변환한다.
const json = JSON.stringify(obj);
console.log(typeof json, json);
// string {"name":"Lee","age":20,"alive":true,"hobby":["traveling","tennis"]}

// 객체를 JSON 포맷의 문자열로 변환하면서 들여쓰기 한다.
const prettyJson = JSON.stringify(obj, null, 2);
console.log(typeof prettyJson, prettyJson);
/*
string {
  "name": "Lee",
  "age": 20,
  "alive": true,
  "hobby": [
    "traveling",
    "tennis"
  ]
}
*/

// replacer 함수. 값의 타입이 Number이면 필터링되어 반환되지 않는다.
function filter(key, value) {
  // undefined: 반환하지 않음
  return typeof value === 'number' ? undefined : value;
}

// JSON.stringify 메서드에 두 번째 인수로 replacer 함수를 전달한다.
const strFilteredObject = JSON.stringify(obj, filter, 2);
console.log(typeof strFilteredObject, strFilteredObject);
/*
string {
  "name": "Lee",
  "alive": true,
  "hobby": [
    "traveling",
    "tennis"
  ]
}
*/

43-03

  • 배열도 JSON으로 변환 가능
const todos = [
  { id: 1, content: 'HTML', completed: false },
  { id: 2, content: 'CSS', completed: true },
  { id: 3, content: 'Javascript', completed: false }
];

// 배열을 JSON 포맷의 문자열로 변환한다.
const json = JSON.stringify(todos, null, 2);
console.log(typeof json, json);
/*
string [
  {
    "id": 1,
    "content": "HTML",
    "completed": false
  },
  {
    "id": 2,
    "content": "CSS",
    "completed": true
  },
  {
    "id": 3,
    "content": "Javascript",
    "completed": false
  }
]
*/

43.2.3 JSON.parse(43-04)

  • JSON.parse 메서드는 JSON 포맷의 문자열을 객체로 변환
const obj = {
  name: 'Lee',
  age: 20,
  alive: true,
  hobby: ['traveling', 'tennis']
};

// 객체를 JSON 포맷의 문자열로 변환한다.
const json = JSON.stringify(obj);

// JSON 포맷의 문자열을 객체로 변환한다.
const parsed = JSON.parse(json);
console.log(typeof parsed, parsed);
// object {name: "Lee", age: 20, alive: true, hobby: ["traveling", "tennis"]}

43-05

  • 배열이 JSON 포맷의 문자열로 변환되어 있는 경우 배열로 반환 다시해줌
const todos = [
  { id: 1, content: 'HTML', completed: false },
  { id: 2, content: 'CSS', completed: true },
  { id: 3, content: 'Javascript', completed: false }
];

// 배열을 JSON 포맷의 문자열로 변환한다.
const json = JSON.stringify(todos);

// JSON 포맷의 문자열을 배열로 변환한다. 배열의 요소까지 객체로 변환된다.
const parsed = JSON.parse(json);
console.log(typeof parsed, parsed);
/*
 object [
  { id: 1, content: 'HTML', completed: false },
  { id: 2, content: 'CSS', completed: true },
  { id: 3, content: 'Javascript', completed: false }
]
*/

43.3 XMLHttpRequest

  • 브라우저에서 주소창, form, a태그 등으로 HTTP 요청 전송 기능을 기본 제공. 자바스크립트는 ? Web API인 XMLHttpRequest 객체 사용

43.3.1 XMLHttpRequest 객체 생성(43-06)

  • 당연히 Web API이므로 브라우저 환경에서만 정상 실행
// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

43.3.2 XMLHttpRequest 객체의 프로퍼티와 메서드

중요한 것들은 볼드체로 표시

  • 1.XMLHttpRequest 객체의 프로토타입 프로퍼티
    • readyState : HTTP 요청의 현재 상태를 나타내는 정수(예 : 정적 프로퍼티. 0,1,2,3,4) status : HTTP 요청에 대한 응답 상태 나타내는 정수(예 : 200) statusText : HTTP 요청에 대한 응답 메시지를 나타내는 문자열(예 : “OK”) responseType : HTTP 응답 타입(예 : document, json, text, blob, arraybuffer) response : HTTP 요청에 대한 응답 몸체. responseType에 따라 타입이 다름 responseText : 서버가 전송한 HTTP 요청에 대한 응답 문자열
  • 2.XMLHttpRequest 객체의 이벤트 핸들러 프로퍼티
    • onreadystatechange : readyState 프로퍼티 값이 변경된 경우 onloadstart : HTTP 요청에 대한 응답을 받기 시작한 경우 onprogress : HTTP 요청에 대한 응답을 받는 도중 주기적으로 발생 onabort : abort 메서드에 의해 HTTP 요청이 중단된 경우 onerror : HTTP 요청에 에러가 발생한 경우 onload : HTTP 요청이 성공적으로 완료한 경우 ontimeout : HTTP 요청 시간이 초과한 경우 onloadend : HTTP 요청이 완료한 경우. HTTP 요청이 성공 또는 실패하면 발생
  • 3.XMLHttpRequest 객체의 메서드
    • open : HTTP 요청 초기화 send : HTTP 요청 전송 abort : 이미 전송된 HTTP 요청 중단 setRequestHeader : 특정 HTTP 요청 헤더의 값을 설정 getResponseHeader : 특정 HTTP 요청 헤더의 값을 문자열로 반환
  • 4.XMLHttpRequest 객체의 정적 프로퍼티
    • UNSENT : open 메서드 호출 이전(0) OPENED : open 메서드 호출 이후(1) HEADERS_RECEIVED : send 메서드 호출 이후(2) LOADING : 서버 응답 중(3) DONE : 서버 응답 완료(4)

43.3.3 HTTP 요청 전송(43-07)

  • 다음 순서를 따름

  • open의 인수 3개 method : GET, POST, PUT, DELETE 등 url : HTTP 요청을 전송할 URL async : 비동기 요청 여부. 기본값 true(비동기)

// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// 1. HTTP 요청 초기화
xhr.open('GET', '/users');

// 2. HTTP 요청 헤더 설정
// 클라이언트가 서버로 전송할 데이터의 MIME 타입 지정: json
xhr.setRequestHeader('content-type', 'application/json');

// 3. HTTP 요청 전송
xhr.send();

43-08

  • send에서 요청 몸체에 담아 전송할 데이터(페이로드)가 객체인 경우 직렬화 해주기

  • HTTP 요청 메서드가 GET인 경우 send 메서드에 페이로드로 전달한 인수는 무시되고 요청 몸체는 null로 설정. 왜냐?

  • GET 요청 메서드는 데이터를 URL의 일부분인 쿼리 문자열로 서버에 전송 POST 요청 메서드는 데이터(페이로드)를 요청 몸체에 담아 전송

xhr.send(JSON.stringify({ id: 1, content: 'HTML', completed: false }));

43-09

  • setRequestHeader 메서드는 open 메서드 호출 이후에 꼭 호출 주 사용 HTTP 요청 헤더는 Content-type, Accept

  • Content-type은 MIME 타입의 정보를 표현. 주 사용 MIME 타입은? text : text/javascript, text/css 등등 application : application/json, 등등 multipart : multipart/formed-data

// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// HTTP 요청 초기화
xhr.open('POST', '/users');

// HTTP 요청 헤더 설정
// 클라이언트가 서버로 전송할 데이터의 MIME 타입 지정: json
xhr.setRequestHeader('content-type', 'application/json');

// HTTP 요청 전송
xhr.send(JSON.stringify({ id: 1, content: 'HTML', completed: false }));

43-10

  • 서버가 응답할 데이터의 MIME 타입은 Accept로 지정 가능
// 서버가 응답할 데이터의 MIME 타입 지정: json
xhr.setRequestHeader('accept', 'application/json');

43.3.4 HTTP 응답 처리(43-11)

  • readystatechange 이벤트는 HTTP 요청의 현재 상태를 나타내는 readyState 프로퍼티가 변경될 때마다 발생. 이를 활용

  • 참고로 HTTP 요청을 전송하고 응답을 받으려먼 서버가 필요. 아래 예제는 가상 REST API사용

// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// HTTP 요청 초기화
// https://jsonplaceholder.typicode.com은 Fake REST API를 제공하는 서비스다.
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');

// HTTP 요청 전송
xhr.send();

// readystatechange 이벤트는 HTTP 요청의 현재 상태를 나타내는 readyState 프로퍼티가
// 변경될 때마다 발생한다.
xhr.onreadystatechange = () => {
  // readyState 프로퍼티는 HTTP 요청의 현재 상태를 나타낸다.
  // readyState 프로퍼티 값이 4(XMLHttpRequest.DONE)가 아니면 서버 응답이 완료되지 상태다.
  // 만약 서버 응답이 아직 완료되지 않았다면 아무런 처리를 하지 않는다.
  if (xhr.readyState !== XMLHttpRequest.DONE) return;

  // status 프로퍼티는 응답 상태 코드를 나타낸다.
  // status 프로퍼티 값이 200이면 정상적으로 응답된 상태이고
  // status 프로퍼티 값이 200이 아니면 에러가 발생한 상태다.
  // 정상적으로 응답된 상태라면 response 프로퍼티에 서버의 응답 결과가 담겨 있다.
  if (xhr.status === 200) {
    console.log(JSON.parse(xhr.response));
    // {userId: 1, id: 1, title: "delectus aut autem", completed: false}
  } else {
    console.error('Error', xhr.status, xhr.statusText);
  }
};
  • load 이벤트를 캐치해도 좋다. 애초에 load 이벤트는 HTTP 요청이 성공적으로 완료된 경우 발생하기 때문

43-12

// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// HTTP 요청 초기화
// https://jsonplaceholder.typicode.com은 Fake REST API를 제공하는 서비스다.
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');

// HTTP 요청 전송
xhr.send();

// load 이벤트는 HTTP 요청이 성공적으로 완료된 경우 발생한다.
xhr.onload = () => {
  // status 프로퍼티는 응답 상태 코드를 나타낸다.
  // status 프로퍼티 값이 200이면 정상적으로 응답된 상태이고
  // status 프로퍼티 값이 200이 아니면 에러가 발생한 상태다.
  // 정상적으로 응답된 상태라면 response 프로퍼티에 서버의 응답 결과가 담겨 있다.
  if (xhr.status === 200) {
    console.log(JSON.parse(xhr.response));
    // {userId: 1, id: 1, title: "delectus aut autem", completed: false}
  } else {
    console.error('Error', xhr.status, xhr.statusText);
  }
};

댓글남기기