[Browser] AJAX, SSR / CSR, CORS

윤태영 | Taeyoung Yoon·2022년 3월 14일
0

TIL (Today I Learned)

목록 보기
28/53
post-thumbnail

AJAX (Asynchronous JavaScript And XHR)

JavaScript, DOM, Fetch, XMLHttpRequest, HTML 등의 다양한 기술을 사용하는 웹 개발 기법이다.

가장 큰 특징은 웹 페이지에 필요한 부분필요한 데이터비동기적으로 받아와 화면에 그려낼 수 있다는 것이다.

JS DOM과 Fetch

AJAX를 구성하는 핵심 기술은 JavaScript와 DOM, 그리고 Fetch이다.

Fetch를 사용하면, 페이지를 이동하지 않아도 서버로부터 필요한 데이터를 받아올 수 있다.
Fetch는 사용자가 현재 페이지에서 작업을 하는 동안 서버와 통신할 수 있도록 한다.
브라우저는 Fetch가 서버에 요청을 보내고 응답을 받을 때까지 모든 동작을 멈추는 것이 아니라, 계속해서 페이지를 사용할 수 있게 하는 비동기적인 방식을 사용한다.

자바스크립트에서 DOM을 사용해 조작할 수 있기 때문에, Fetch를 통해 전체 페이지가 아닌 필요한 데이터만 가져와 DOM에 적용시켜 새로운 페이지로 이동하지 않고 기존 페이지에서 필요한 부분만 변경할 수 있다.

XHR (XMLHTTPRequest)

Fetch 이전에는 XHR를 사용했다.
오늘날에는 XHR보다 Fetch를 많이 사용한다.

var xhr = new XMLHttpRequest();
xhr.open('get', 'http://52.78.213.9:3000/messages');

xhr.onreadystatechange = function(){
	if(xhr.readyState !== 4) return;

	if(xhr.status === 200) {
		console.log(xhr.responseText);
	} else {
		console.log('error: ' + xhr.status);
	}
}

xhr.send();

Fetch

Fetch는 XHR의 단점을 보완한 새로운 Web API이며, XML보다 가볍고 JavaScript와 호환되는 JSON을 사용한다.

fetch('http://52.78.213.9:3000/messages')
	.then (function(response) {
		return response.json();
	})
	.then(function (json) {
		...
});

AJAX의 장점

  • 서버에서 HTML을 완성하여 보내주지 않아도 필요한 데이터를 비동기적으로 가져와 브라우저 화면의 일부만 업데이트 하여 렌더링 할 수 있다.
  • XHR의 표준화로 브라우저에 상관없이 AJAX를 사용할 수 있다.
  • 빠르고 더 많은 상호작용이 가능한 유저 중심 애플리케이션을 만들 수 있다.
  • 필요한 데이터만 보내면 되기 때문에 대역폭이 작다.

AJAX의 단점

  • 검색 엔진 최적화 (SEO)에 불리하다.
  • AJAX에선 이전 상태를 기억하지 않기 때문에 뒤로가기 기능을 구현하기 위해서는 별도로 History API를 사용해야 한다.

SSR (Server Side Rendering)

서버쪽에서 렌더링 준비를 끝마친 상태로 클라이언트에 전달하는 방식이다.

SSR의 단계

  1. 사용자가 웹사이트 요청을 보낸다.
  2. 서버는 리소스를 체크하고 컴파일 후 렌더링 가능한 HTML파일을 만든다.
  3. 클라이언트에게 전달되는 순간 HTML은 즉시 렌더링 된다. (사용자가 사이트 조작 불가능)
  4. 클라이언트가 JavaScript를 다운 받는다.
  5. JavaScript를 다운 받는 중에 사용자는 컨텐츠를 볼 수 있지만 사이트는 조작할 수 없다. 이때의 사용자 조작을 기억하고는 있는다.
  6. 브라우저가 JavaScript 프레임워크를 실행한다.
  7. JavaScript 까지 컴파일이 되면 기억하고 있던 사용자 조작이 실행되고 웹 페이지는 상호작용이 가능해진다.

SSR의 특징

  • SEO(Search Engine Optimization) 가 우선순위인 경우, 일반적으로 SSR(Server Side Rendering) 을 사용한다.
  • 웹 페이지의 첫 화면 렌더링이 빠르게 필요한 경우에도, 단일 파일의 용량이 작은 SSR 이 적합하다.
  • 웹 페이지가 사용자와 상호작용이 적은 경우, SSR 을 활용할 수 있다.

예제

const express = require("express");
const app = express();
const infoArr = [
  "information1",
  "information2"
];
app.get("/", (req, res) => {
  res.send(
    "<html><body><h1>" +
      infoArr[Math.floor(Math.random() * infoArr.length)] +
      "</h1><h1>SSR</h1>" +
      "<h2>What is Server Side Rendering?</h2>" +
      "</body></html>"
  );
});
app.listen(8080);

CSR (Client Side Rendering)

서버에서 받은 HTML과 JavaScript를 클라이언트에서 렌더링하는 방식이다.

CSR의 단계

  1. 사용자가 웹사이트 요청을 보낸다.
  2. CDN이 HTML 파일과 JavaScript로 접근할 수 있는 링크를 클라이언트로 보낸다.
  3. 클라이언트는 HTML과 JavaScript를 다운로드 받는다. (사용자는 웹사이트의 아무것도 볼 수 없다.)
  4. 다운로드가 완료된 JavaScript가 실행되고 데이터를 위한 API가 호출된다 (사용자는 placeholder를 보게된다.)
  5. 서버가 API로부터의 요청에 응답한다.
  6. 클라이언트가 API로 부터 받아온 데이터를 placeholder 자리에 넣고 웹 페이지는 상호작용이 가능해진다.

CSR의 특징

  • 사이트에 풍부한 상호 작용이 있는 경우, CSR 은 빠른 라우팅으로 강력한 사용자 경험을 제공한다.
  • 웹 애플리케이션을 제작하는 경우, CSR을 이용해 더 나은 사용자 경험(빠른 동적 렌더링 등)을 제공할 수 있다.

예제

const express = require("express");
const app = express();
const port = process.env.PORT || 5000;
const infoArr = [
  "information1",
  "information2"
];
app.get(`/`, (req, res) =>
  res.send(infoArr[Math.floor(Math.random() * infoArr.length)])
);
app.get(`/csr`, (req, res) =>
  res.send(infoArr[Math.floor(Math.random() * infoArr.length)])
);
app.listen(port, () =>
  console.log(`Example app listening at http://localhost:${port}`)
);

CORS (Cross-Origin Resource Sharing)

다른 도메인으로부터 리소스를 요청할 경우 해당 리소스는 cross-origin HTTP request에 의해 요청된다.
이 때 브라우저는 보안적인 이유로 스크립트 안에서 시작되는 cross-origin HTTP request를 제한한다.
브라우저가 자발적으로 사용자를 보호하기 위한 조치이다.
서버에서 서버로 보내는 요청은 CORS가 적용되지 않는다.

다른 도메인의 img파일이나 css파일을 가져오는 것은 모두 가능하지만
<scpipt></script>로 감싸진 스크립트에서 생성된 cross-origin HTTP 요청은 Same-origin policy를 적용받아 cross-origin HTTP reauest가 제한된다.

Preflight Request

브라우저는 먼저 서버에 사전 요청(Preflight request)을 전송하여 실제 요청을 보내는 것이 안전한지 OPTIONS method로 확인한다.
서버로부터 유효하다는 응답을 받으면 HTTP request method와 함께 본 요청(Actual request)을 보낸다.
서버로부터 유효하지 않다는 응다을 받으면 에러를 발생시키고 본 요청은 서버로 전송하지 않는다.

Simple Request

사전 요청(Preflight request)을 발생시키지 않는 요청을 Simple request라고 한다.
아래 세가지 조건이 모두 만족되는 경우를 말한다.

  • GET / HEAD / POST 중 한 가지 메소드를 사용해야 한다.
  • User agent에 의해 자동으로 설정되는 헤더를 제외하고
    Fetch spec에서 CORS-safelisted request-header라고 정의되어 있고 수동 설정이 허용된 헤더만 사용해야 한다.

    Accept
    Accept-Language
    Content-Language
    Content-Type (but note the additional requirements below)
    DPR
    Downlink
    Save-Data
    Viewport-Width
    Width

  • 아래의 Content type만 지정해야 한다.

    application / x-www-form-urlencoded
    multipart/form-data
    text/plain

0개의 댓글