16. HTTP제어 (ajax)

16.1 HTTP통신

16.1.1 HTTP란

HTTP(Hyper Text Transfer Protocol) :
웹 브라우저와 웹서버간의 프로토콜(통신규약)
HTTPS: SSL로 암호화하여 보안성을 확보한것

16.1.2 HTTP 통신

클라이언트가 서버에 요청메시지를 보내고 서버가 응답메시지를 반환함
서버는 클라이언트의 상태를 저장하지 않음

16.1.3 HTTP 요청 메시지

요청메시지의 구조

구조
요청행
요청 헤더
공백 행
메시지 본문

요청 예 : GET http://www.gilbut.co.kr HTTP/1.1

GET : 요청메서드

http://gilbut.co.kr : URL

HTTP/1.1 : HTTP의 버전

요청 메서드

  • GET : 서버에 페이지 요청. 요청데이터는 URL에 덧붙이며 텍스트로만 전송 가능
  • POST : 서버 데이터 갱신, 데이터가 많을 경우, 개인정보를 보낼때 사용.

요청 헤더

  • 제어정보, 본문의 데이터정보 등이 텍스트형식으로 저장됨.
    필드이름 : 내용 의 형태로 구성된 필드집합

메시지 본문

  • 데이터(클라이언트->서버)가 저장됨. 형식은 요청헤더에 지정된 타입을 따름

16.1.4 HTTP 응답 메시지

응답 메시지의 구조

구조
응답 행
응답 헤더
공백 행
메시지 본문

응답 행

  • HTTP/1.1 200 OK

HTTP/1.1 : HTTP 버전

200 : 상태코드

OK : 보충메시지

코드 상태
| 분류 | 상태코드 | 상태 설명 | 내용 |
| --- | --- | --- | --- |
| 성공 | 200 | OK | 요청을 성공함 |
| 클라이언트 오류 | 401 | unauthrized | 인증되지 않음 |
| | 403 | Forbidden | 액세스가 허용되지 않음 |
| | 404 | Not Found | 요청한 리소스랄 찾지 못함 |
| | 408 | Reqeust Timeout | 요청 시간 초과 |
| 서버오류 | 500 | Internal Server Error | 서버 내부 오류 발생 |
| 서버오류 | 503 | Service Unavailable | 서비스 일시 사용 불가 |

응답 헤더

  • 메시지의 제어정보, 본문 저장 데이터의 형식

메시지 본문

  • 데이터(서버->클라이언트)가 저장됨. 형식은 요청헤더에 지정된 타입을 따름

16.2 Ajax

16.2.1 Ajax란

Ajax(Asynchrous JavaScript + XML)는 XMLHttpRequest라는 자바스크립트 객체를 이용하여 서버와 비동기로 통신하고 웹페이지를 동적으로 갱신하는 기법

16.2.2 특징

  1. 최소한의 데이터통신으로 속도가 빠르고 서버 부하와 트래픽 부하가 적다

  2. 비동기로 통신하므로 클라이언트 측에서 다른 작업을 할 수 있다.

  3. 웹 갱신을 클라이언트측이 담당한다. 페이지전환 없이 일부분만 변경하므로 고속 렌더링이 가능하다.

16.3 XMLHttpRequest

16.3.1 처리흐름

  1. XMLHttpRequest 객체 생성

  2. 서버와 통신 처리 방법 설정1225

  1. 요청 전송 -> 통신 시작
window.onload = function() {
    const xhr = new XMLHttpRequest();
    xhr.readystatechange = function() {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                // ajax요청으로부터 반환받은 데이터
                const data = req.responseText;
            }
        }
    }
}

16.3.2 XMLHttpRequest 객체의 생성

const req = new XMLHttpRequest();
  • XMLHttpRequest 객체의 프로퍼티
프로퍼티설명읽기전용
readyStateHTTP통신 상태(0~4사이의 값).
response응답 내용.
responseText텍스트형식의 응답 내용.
responseType응답 타입쓰기 가능
responseXMLXMLDcoument객체의 응답내용.
status요청에 대한 HTTP 상태코드(200, 404 등).
statusText상태에 대한 설명.
timeout요청이 자동으로 끝나는데 걸린 시간(ms)쓰기가능
withCredentialscors에 대해 인증정보를 사용할지 여부쓰기가능
onreadystatechangereadyState값이 바뀔때마다 실행되는 이벤트 처리기쓰기가능
ontimeout요청시간초과시 호출되는 이벤트 처리기쓰기가능
  • XMLHttpRequest 객체의 메서드
메서드설명
abort()실행중인 비동기 통신 중단
getAllResponseHeaders()수신한 모든 HTTP 응답 헤더 가져옴
getResponseHeader(header)특정 HTTP 응답 헤더 가져옴
open(...)HTTP요청 초기화
send(data)HTTP 요청을 보냄
setRequestHeader(header, value)요청 헤더에 정보 추가

16.3.3 서버와 통신 시 사용할 처리 방법 등록

통신상태 변경에 따라 특정 처리를 추가할 수 있다.
상태가 바뀌면 readyState 프로퍼티의 값이 변경되고
readystatechange이벤트가 발생됨

// XMLHttpRequest의 프로퍼티로 추가
req.onreadystatechange = function () {...};

// 이벤트 리스너로 등록
req.addEventListener('readystatechange', function() {})
  • readyStaet 프로퍼티의 값
설명
0초기화되기 전 : open()이 호출되기 전
1로드중 : open() 호출 됨. send() 호출 전
2로드 완료 : send() 호출됨. 응답은 오지 않음
3응답수신중 : 응답행,헤더는 가져왔지만 본문을 가져오지 않음
4수신 완료 : 모든 응답메시지 수신 완료
const req = new XMLHttpRequest();

req.onreadystatechange = function() {
    // 상태 변경시마다 onreadystatechange 호출
    
    // 상태가 4(수신 완료)일때
    if (req.readyState === 4) {

        // HTTP 상태코드가 성공(200)일때
        if (req.status === 200) {
            //응답을 text로 가공하여 콘솔에 출력
            console.log(req.resposneText);
        }
    }
}
  • XMLHttPRequest 객체의 이벤트

XMLHttpRequest의 readystatechanage 이벤트 외에도 아래의 이벤트를 사용할 수 있음

이벤트이벤트 발생 시기
abort요청 취소 시
error요청 실패 시
loadend요청 완료시(성공,실패 상관없이)
load요청 성공 후 응답을 가져올 수 있을 때
loadstartstart 요청 보낼 때
progress데이터 주고받는 중
timeout요청 시간 초과 시
req.addEventListener('load', () => {
    console.log(req.responseText);
})

req.addEventListener('abord', () => {
    console.log('요청 취소됨');
})

req.addEventListener('loadend', () => {
    console.log('요청완료됨');
})

16.3.4 요청을 전송하여 통신 시작

open메서드로 요청 초기화 후 send메서드를 통해 서버에 요청을 보냄

  • 요청초기화하기
req.open(method, url[,async [,user [,password]]]);

method : HTTP 메서드

url : 접근 url

async? : 비동기 통신 여부(default true)

user? : 인증 시 사용자 이름

password? : 인증 시 암호

xhr.open('GET', 'data.txt');
// GET method로 data.txt라는 url에 요청하는 ajax를 초기화
  • GET 요청 보내기

데이터를 쿼리문자열로 만들어서 URL 마지막에 덧붙임
url끝에 ?를 붙여 시작을 표시하고,
이름1=값1&이름2=값2 형식으로 붙여줌
모든 값은 URL인코딩 해야함

req.open(
    'GET',
    `example.php?name=${encodeURIComponent(value)}`,
    true);
  • POST 요청 보내기

보내고자 하는 데이터를 send()의 인수로 넘김.
보낼 데이터가 쿼리문자열이라면 전송 전에
setRequestHeader메서드로 Content-Type을 'application/x-www-form-urlencoded'로 설정

req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(`name=${encodeURIComponent(value)}`);

POST로 보낼 수 있는 주요 데이터

데이터 타입설명
DOMString문자열 데이터
FormData폼데이터
ArrayBufferView바이너리 데이터
BlobBlob 객체, File 객체
DocumentHTML의 Document 객체

16.4 응답받기

요청성공시 responseText, responseXML, response 프로퍼티로 값을 받을 수 있음

16.4.1 응답 데이터 타입

응답을 텍스트 데이터 외에도 다양한 타입이 가능
send메서드로 데이터를 보내기 전 responseType프로퍼티에 응답으로 받고자하는 데이터 타입을 설정

response데이터 타입설명responeType의 값
DOMString텍스트"text" (기본값)
JSON 객체JSON"json"
ArrayBuffer형식화 배열 (TypedArray)"arraybuffer"
BlobBlob 객체"blob"
DocumentHTML의 Document 객체"document"

16.4.2 JSON 데이터 받기

  • responseText 프로퍼티 활용
const req = new XMLHttpRequest();

let jsonObj;

req.addEventListener('load', () => {
    jsonObj = JSON.parse(req.responseText);
    console.log(jsonObj);
}, false);

req.open('GET', 'data.json', true);
req.send(null);
  • response 프로퍼티 활용
let jsonObj;

req.addEventListener('load', () => {
    jsonObj = req.response;
    console.log(jsonObj);
}, false);

16.5 크로스 오리진

XMLHttpRequest는 동일 출처 정책을 준수하기 때문에 크로스 오리진 통신을 할 수 없으나
다음 기법을 통해 크로스 오리진 통신을 할 수 있음

  • JSONP
  • CORS
  • postMessage

16.5.1 JSONP

JSONP(JSON with Padding) :
'script요소의 src속성이 가리키는 자바스크립트 파일은 다른 도메인에 위치해도 읽을 수 있다'라는 특성을 이용한 기법.

  1. 외부 서버가 아래와 같은 jsonp.js를 제공하게 만듦. JSON데이터를 show라는 함수의 인수로 지정한 JSONP데이터가 들어있음
show({
    "name" : "apple",
    "price" : 100
})
  1. 클라이언트에서 이벤트가 발생했을 때 DOM을 사용해 script요소 생성, (1)에서 외부 서버에 마련해둔 자바스크립트파일인 jsonp.js를 script의 src주소에 대입

  2. 외부서버가 jsonp.js파일을 클라이언트로 보냄

  3. 클라이언트에 show함수가 정의되어있다면 (3)의 클라이언트가 자바스크립트 파일을 받아서 실행함

<script>
    function show(data) {
        console.log("name : " + data.name);
        console.log("price : " + data.price);
    }

    window.onload = () => {
        const url = 'jsonp.js';
        const script = document.createElement('script');
        script.setAttribute('src', url);
        document.getElementsByTagName('head')[0].appendChild(script);
    }
</script>

16.5.2 CORS

데이터를 불러오는곳이 신뢰할 수 있다면 데이터 읽기,쓰기를 허용

  • .htaccess 파일 사용
    서버의 읽기 쓰기를 관리하는 디렉터리 안에 있는 .htaccess파일에
    `Header append Access-Control-Allow-Origin : "http://example/com:8000"

해당 URL의 읽기,쓰기 허용한다는 의미
모든 사이트에 대해 허용하려면 '*'을 입력

  • CGI에서 응답헤더 설정

\<?php
header('Access-Control-Allow-Origin: *')
>

  • postMessage

출처가 다른 창,오리진에서도 통신할 수 있음.
상호간의 프로퍼티 참조와 메서드 실행은 할 수 없지만 메시지를 비동기적으로 주고받을 수 있음

taget.postMessage(message, origin);

target.postMessage('hello', 'http://www.example.com');

target : 메시지를 받을 윈도우의 Window객체. open메서드로 연 윈도우에 메시지를 보내려면 open메서드가 반환한 값을 넘김. iframe요소의 윈도우 안이라면 iframe요소 객체의 contentWindow프로퍼티의 값을 넘김

message : 보내는 메시지

origin : 메시지를 받을 윈도우 출처. URL스킴, 호스트 이름 지정, 출처를 명시하지 않을 경우 * 를 입력
보내는곳과 받는곳의 윈도우가 동일하다면 /를 지정

서로 다른 출처일 때 postMessage에 2번째 인수로 지정한 출처가 다를 경우 메시지를 보내지 않음

만약 올바르게 동작했다면 받는쪽의 window객체에서 message이벤트가 발생.

window.addEventListener('message', () => {}, false);
  • message 이벤트, 이벤트객체의 프로퍼티

| 프로퍼티 | 설명 |
| data | postMessage 메서드의 첫번째 인수로 전달된 메시지의 원본 |
| source | 메시지를 보낸 Window객체 |
| origin | 보낸곳의 웹사이트 출처 |

profile
큐큐익규

0개의 댓글

Powered by GraphCDN, the GraphQL CDN