[JavaScript] Ajax랑 데이트, 비동기 로맨스!

hyeonbin·2023년 4월 29일
0

JS 계란반 스터디

목록 보기
10/12
post-thumbnail

📃 Ajax

⚙️ 기본 개념

  • Ajax = Asynchronous JavaScript and XML

  • 브라우저와 서버의 통신에 의해 브라우저에서 웹페이지를 요청 또는 링크를 클릭하면 화면이 갱신한다.


  • 전통적인 Web Page Lifecycle은 서버가 요청받은 페이지를 반환할 때, HTML에서 로드하는 CSS, JavaScript 파일들도 같이 반환한다. 그리고 클라이언트 요청에 따라 파일을 반환할 수도 있고, 서버 사이드 프로그램이 만들어낸 파일이나 데이터를 반환할 수도 있다. 이를 통해 서버로부터 웹페이지가 반환되면 클라이언트 즉, 웹 브라우저는 렌더링해 화면에 표시한다.

  • Ajax Lifecycle은 자바스크립를 이용해 비동기적으로 서버와 브러우저가 데이터를 교환할 수 있다. 그리고 서버로부터 웹페이지가 반환되면 페이지 전체를 로드해 렌더링할 필요없고 일부만을 갱신하기에 빠른 퍼포먼스와 부드러운 화면 표시가 가능하다.



📃 JSON

⚙️ 기본 개념

  • JSON = JavaScript Object Notation

  • JSON은 클라이언트와 서버 간 데이터 교환을 위한 규칙을 말한다. 일반 텍스트 포맷보다 효과적인 데이터 구조화가 가능하며 XML 포맷보다 가볍고 사용하기 간편하며 가독성도 좋다.

  // 자바스크립트 객체 리터럴과 매우 흡사하지만, 
  // JSON은 순수한 텍스트로 구성된 규칙이 있는 데이터 구조
  // JSON은 일반적으로 큰 따옴표(쌍따옴표)를 사용하여 문자열을 표현

  {
    "name": "kim",
    "gender": "female",
    "age": 25,
    "alive": true
  }

⚙️ JSON.stringify

  • JSON.stringify 메소드는 객체를 JSON 형식 문자열로 변환한다.

✔️ 객체

const info = { name: 'kim', gender: 'female', age: 25, alive: true };

// 1. 객체 => JSON 형식 문자열
const strObject = JSON.stringify(info);
console.log(typeof strObject, strObject);
// 출력: string {"name":"kim","gender":"female","age":25,"alive":true}

// 2. 객체 => JSON 형식 문자열 + prettify
const strPrettyObject = JSON.stringify(info, null, 2);
console.log(typeof strPrettyObject, strPrettyObject);
// 출력:
// string {
//   "name": "kim",
//   "gender": "female",
//   "age": 25,
//   "alive": true
// }


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

// 3. 객체 => JSON 형식의 문자열 + replacer + prettify
const strFilteredObject = JSON.stringify(info, filter, 2);
console.log(typeof strFilteredObject, strFilteredObject);
// 출력:
// string {
//   "name": "kim",
//   "gender": "female",
//   "alive": true
// }

✔️ 배열

const arr = [3, 8, 'false'];

// 1. 배열 객체 => 문자열
const strArray = JSON.stringify(arr);
// console.log(typeof strArray, strArray);
// 출력: string [3,8,"false"]


// replacer
// 모든 값을 대문자로 변환된 문자열을 반환
function replaceToUpper(key, value) {
  return value.toString().toUpperCase();
}

// 2. 배열 객체 => 문자열 + replacer
const strFilteredArray = JSON.stringify(arr, replaceToUpper);
console.log(typeof strFilteredArray, strFilteredArray);
// 출력: string "3,8,FALSE"


⚙️ JSON.parse

  • JSON.parse 메소드JSON 데이터를 가진 문자열을 객체로 변환한다.

  • 서버에서 브러우저로 전송된 JSON 데이터는 문자열인데, 객체로서 사용하려면 객체화해야 한다. 이를 역직렬화라고 하며, 이를 위해 내장 객체 JSON의 static 메소드인 JSON.parse를 사용한다.

  const info = { name: 'kim', gender: 'female', age: 25, alive: true };
  const arr = [3, 8, 'false'];

  // 1. 객체 => JSON 형식 문자열
  const strObject = JSON.stringify(info);
  console.log(typeof strObject, strObject);
  // 출력: string {"name":"kim","gender":"female","age":25,"alive":true}

  // 2. 배열 객체 => 문자열
  const strArray = JSON.stringify(arr);
  console.log(typeof strArray, strArray);
  // 출력: string [3,8,"false"]

  // 3. JSON 형식 문자열 => 객체
  const obj = JSON.parse(strObject);
  console.log(typeof obj, obj);
  // 출력: object { name: 'kim', gender: 'female', age: 25, alive: true }

  // 4. 문자열 => 배열 객체
  const objArray = JSON.parse(strArray);
  console.log(typeof objArray, objArray);
  // 출력: object [ 3, 8, 'false' ]

  • 배열이 JSON 형식 문자열로 변환되어 있는 경우, JSON.parse는 문자열을 배열 객체로 변환한다.

  • 배열의 요소가 객체인 경우, 배열의 요소까지 객체로 변환한다.

  const todos = [
    { id: 1, content: 'HTML', completed: true },
    { id: 2, content: 'CSS', completed: true },
    { id: 3, content: 'JavaScript', completed: false },
  ];

  // 1. 배열 => JSON 형식의 문자열
  const str = JSON.stringify(todos);
  console.log(typeof str, str);
  // 출력:
  // string [{"id":1,"content":"HTML","completed":true},{"id":2,"content":"CSS","completed":true},{"id":3,"content":"JavaScript","completed":false}]

  // 2. JSON 형식의 문자열 => 배열
  const parsed = JSON.parse(str);
  console.log(typeof parsed, parsed);
  // 출력:
  // object [
  //   { id: 1, content: 'HTML', completed: true },
  //   { id: 2, content: 'CSS', completed: true },
  //   { id: 3, content: 'JavaScript', completed: false }
  // ]



📃 XMLHttpRequest

브라우저가 XMLHttpRequest 객체를 이용해 Ajax 요청을 생성하고 전송한다.
그리고 서버가 브라우저 요청에 응답을 반환하면 같은 XMLHttpRequest 객체가 그 결과를 처리한다.

⚙️ Ajax Request

✔️ Ajax 요청 처리

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

// 비동기 방식으로 Request 오픈
xhr.open('GET', '/users');

// Request 전송
xhr.send();

[ XMLHttpRequest.open ]

  • XMLHttpRequest 객체의 인스턴스를 생성하고 open 메소드를 사용하여 서버로의 요청을 준비한다.
  XMLHttpRequest.open(method, url[, async])
  • 매개변수
  method: HTTP method (“GET”, “POST”, “PUT”, “DELETE” 등)
  url: 요청 보낼 URL
  async: 비동기 조작 여부 - 옵션으로 default는 true이며 비동기 방식으로 동작

[ XMLHttpRequest.send ]

  • send 메소드로 준비된 요청을 서버에 전달하고, 메소드에는 Request Body에 담아 전송할 인수를 전달할 수 있다.

  • 요청 메소드가 GET인 경우, send 메소드의 인수는 무시되고 Request Body는 null로 설정된다.

  xhr.send(null);
  // xhr.send('string'); 문자열을 보내는 방법
  // xhr.send(new Blob()); 파일 업로드와 같이 바이너리 컨텐트를 보내는 방법
  // xhr.send({ form: 'data' }); 객체를 보내는 방법
  // xhr.send(document); 문서 객체를 보내는 방법 

  • 기본적으로 서버로 전송하는 데이터는 GET, POST 메소드에 따라 그 전송 방식에 차이가 있다.
  • GET 메소드의 경우, URL 일부분인 쿼리문자열(query string)로 데이터를 서버로 전송
  • POST 메소드의 경우, 데이터(페이로드)를 Request Body에 담아 전송

[ XMLHttpRequest.setRequestHeader ]

  • setRequestHeader 메소드는 HTTP Request Header의 값을 설정하고, 반드시 open 메소드 호출 이후에 호출한다.

  • Request Header인 Content-type, Accept는 자주 사용하니까 알아두자!

  • Content-type은 Request Body에 담아 전송할 데이터의 MIME-type의 정보를 표현한다.

  • 타입  -  서브타입
  text 타입  -  text/plain, text/html, text/css, text/javascript
  Application 타입  -  application/json, application/x-www-form-urlencode
  File을 업로드하기 위한 타입  -  multipart/formed-data
  • Request Body에 담아 서버로 전송할 데이터의 MIME-type을 지정해 보자.
  < 구조화된 데이터를 전송할 때 >

  // json으로 전송하는 경우
  xhr.open('POST', '/users');

  // 클라이언트가 서버로 전송할 데이터의 MIME-type 지정: json
  xhr.setRequestHeader('Content-type', 'application/json');

  const data = { id: 5, title: 'apple pie', author: 'Park', price: 10000 };

  xhr.send(JSON.stringify(data));
  < HTML 폼 데이터와 유사한 형태로 전송할 때 >
    
  // x-www-form-urlencoded으로 전송하는 경우
  xhr.send('POST', '/users');

  // 클라이언트가 서버로 전송할 데이터의  MIME-type 지정: x-www-form-urlencoded
  // application/x-www-form-urlencoded는 key=value&key=value...의 형태로 전송
  xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

  const data2 = { title: 'apple pie', author: 'Park', price: 10000 };

  xhr.send(
    Object.jeys(data)
      .map((key) => `${key}=${data[key]}`)
      .join('&')
  );

  • Accept는 HTTP 클라이언트가 서버에 요청할 때 서버가 센드백할 데이터의 MIME-type을 지정할 수 있다.

  • 만약 Accept 헤더를 설정하지 않으면, send 메소드가 호출될 때 Accept 헤더가 */*으로 전송된다.

  // 서버가 센드백할 데이터의 MIME-type 지정: json
  xhr.setRequestHeader('Accept', 'application/json');


⚙️ Ajax Response

✔️ Ajax 응답 처리

  • send 메소드를 통해 Request를 전송하면 서버는 Response를 반환하지만, 언제 Response가 클라이언트에 도달하는지 알 수 없다. onreadystatechange는 Response가 클라이언트에 도달하여 발생된 이벤트를 감지하고 콜백 함수를 실행해 준다.

  • 이때 이벤트는 Request에 어떠한 변화(readyState 프로퍼티가 변경)가 일어난 경우 발생한다. XMLHttpRequest 객체는 readyState를 통해 Response가 클라이언트에 도달했는지를 추적할 수 있는 프로퍼티를 제공한다.

  • 만일 readyState 값이 4인 경우, 정상적으로 Response가 돌아온 것이다. 그리고 서버 응답이 완료된 상태이기에 status가 200(정상)임을 확인한 뒤, responseText를 취득한다. responseText에는 서버가 전송한 데이터가 담겨 있다.

  • 만약 서버 응답 완료 상태에만 반응하도록 하려면, readystatechange 이벤트 대신 load 이벤트를 사용해도 된다.

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

  // 비동기 방식으로 Request 오픈
  xhr.open('GET', 'data/test.json');

  // Request 전송
  xhr.send();

  // XMLHttpRequest.readyState 프로퍼티가 변경될 때마다 콜백함수 즉, 이벤트 핸들러가 호출됨
  xhr.onreadystatechange = function (e) {
    // 이 함수는 Response가 클라이언트에 도달하면 호출됨

    // readyStates는 XMLHttpRequest의 상태(state)를 반환
    // readyState: 4 => DONE(서버 응답 완료)
    if (xhr.readyState !== XMLHttpRequest.DONE) return;

    // status는 response 상태 코드를 반환 : 200 => 정상 응답
    if (xhr.status === 200) {
      console.log(xhr.responseText);
    } else {
      console.log('Error!');
    }
  };

profile
할 수 있다고 믿는 사람은 결국 그렇게 된다 😄😊

0개의 댓글