다른 서버에 있는 자원을 요청해서 사용하는 것. 기본적으로 보안상 이유로 브라우저에서는 cors를 제한한다.
cors가 제한되는 문제는 서버사이드에서 해결해준다. 서버에서 클라이언트 보내는 response 헤더에 cors가능하다는 내용을 추가해주면, 브라우저는 해당 cors를 막지 않는다.
클라이언트(브라우저)는 cors 요청을 보내기 전 OPTIONS 메서드로 preflight 요청을 서버에 보내고, 해당 서버에서 오류없는 응답을 받으면 진짜 cors 요청을 다시 서버로 보낸다.
아래와 같이 모든 응답에 헤더를 추가하거나 cors
라이브러리를 활용한다.
const defaultCorsHeader = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Accept',
'Access-Control-Max-Age': 10
};
const module = {
x: 42,
getX: function(y) {
return this.x + y;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
// 선행될 인수를 설정하여 함수를 생성합니다.
var leadingThirtysevenList = list.bind(null, 37);
var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
function addArguments(arg1, arg2) {
return arg1 + arg2
}
var result1 = addArguments(1, 2); // 3
// 첫 번째 인수를 지정하여 함수를 생성합니다.
var addThirtySeven = addArguments.bind(null, 37);
var result2 = addThirtySeven(5); // 37 + 5 = 42
// 두 번째 인수는 무시됩니다.
var result3 = addThirtySeven(5, 10); // 37 + 5 = 42
declare
의 this는 window가 되므로 window.petalCount는 undefined가 된다.function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// 1초 지체 후 bloom 선언
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
// 1초 뒤, 'declare' 메소드 유발
http 모듈을 직접 활용해서 코딩할 필요는 없겠지만, 저수준의 코드를 다루면서 노드와 웹서버에 대한 이해가 조금은 깊어졌다고 생각한다.
예시를 통해서 스트림와 이벤트 에미터, cors에 대해 조금 더 깊이 학습할 수 있었다.
이벤트생성 객체는 EventEmitter를 상속받는 객체의 인스턴스로 생성할 수 있다.
이벤트를 발생시키는 인스턴스는 메서드로 emit()
을 가지고, 이를 통해 이벤트가 발생했음을 알려준다. 이벤트 발생과 동시에 매개변수도 전달 가능하다.
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (...args) => {
console.log('an event occurred!');
if (args.length !== 0) {
console.log('args are ', ...args);
}
});
myEmitter.emit('event');
myEmitter.emit('event','arg1', 'arg2');
myEmitter.once()
로 한번만 실행되는 이벤트 정의 가능
myEmitter.on('error', callback)
을 정의하지 않으면
myEmitter.emit('error')
발생시 에러 객체가 던져지고, 프로세스가 멈출 수 있다.
싱글스레드 기반 노드에서는 에러처리를 철저하고, 꼼꼼하게 해주자.
스트림이란 streaming data를 다루기 위해 노드에서 제공하는 인터페이스다. stream의 종류는 writable, readable, duplex, transform 네 가지가 있다.
http 모듈에서 request 객체가 Readable Stream
이다. ReadableStream
은 EventEmitter
이므로, on 메서드로 Emitted 이벤트를 수신 가능하다.
ReadableStream
이 스트림의 소비자로 해당 청크의 데이터 소유권을 포기할 때 발생하는 이벤트가 'data'다. 'data' 이벤트는 스트림이 pipe()
,resume()
,read()
될때 발생한다. 아래의 코드에서는 'data' 이벤트가 발생시 body라는 배열에 해당하는 청크의 데이터를 지속적으로 푸쉬한다.
'end'이벤트는 스트림에 더 이상 소비될 데이터가 없을때 발생한다.
아래에서 request 스트림이 'end' 이벤트를 방출하면, 헤더와 바디에 데이터를 response객체에 실어 클라이언트로 쏴준다.
request
.on("data", (chunk) => body.push(chunk))
.on("end", () => {
body = Buffer.concat(body).toString();
response.writeHead(200, defaultCorsHeader);
response.end(body.toUpperCase());
});
CORS 요청에는 origin 헤더가 붙는다. origin 헤더는 사용자가 임의로 변경할 수 없다.
Origin: https://javascript.info
안전하지 않은 CORS에는 preflight요청이 선행된다.
2-1. 서버가 preflight 요청에 대해서 아래와 같이 응답하면 OK
200 OK
Access-Control-Allow-Origin: https://javascript.info
Access-Control-Allow-Methods: PUT,PATCH,DELETE
Access-Control-Allow-Headers: API-Key,Content-Type,If-Modified-Since,Cache-Control
Access-Control-Max-Age: 86400
브라우저는 실제요청을 서버로 보낸다.
실제 응답에는 Access-Control-Allow-Origin: https://javascript.info
이라는 헤더가 들어간다.
쿠키와 같은 credential은 CORS요청에 포함되지 않는다.(대부분의 HTTP 요청은 쿠키도 함께 송한다.)
fetch('http://another.com', {
credentials: "include"
});
200 OK
Access-Control-Allow-Origin: https://javascript.info
Access-Control-Allow-Credentials: true
nodemon --inpect app.js
nodemon --inspect-brk app.js
vscode debugger also works well
edit launch.json for detailed settings