콜백 헬을 개선하기위해 등장.
자바스크립트 비동기 처리에 사용되는 객체이다.

작업이 성공적으로 수행되면 resolve 호출, 에러가 발생할 경우 reject 호출
const time = new Promise((resolve, reject) => {resolve(response)})
time.then((num)=>console.log(num), ()=>console.log('error'))
// 두번째 인자(reject)보다 catch()를 사용하는 것이
// resolve 내 발생하는 에러도 처리하기위해 더 효율적!!
time.then(function(result) {
console.log(result); // hi
throw new Error("Error in then()");
}).catch(function(err) {
console.log('then error : ', err); // then error : Error: Error in then()
});
라이브러리인 axios는 axios.post(), axios.get( )처럼 바로 request 요청 방식을 메소드의 이름으로 구분해 fetch보다 조금 더 직관적이다.
또한, axios는 body 키 값이 생략 가능하고, body에 포함할 데이터를 JSON.stringify()로 직접 변환해주지 않아도된다.
var name = "fee";
var sayName = function () {
var name = "foo";
console.log(this.name); // fee
};
sayName(); // undefined
=⇒ sayName()은 window.sayName()이 생략된 것이므로 this는 전역 객체인 window다.
=⇒ 따라서, function() 속 지역 변수 var name = "foo" 가 아니라,
함수 밖, window.name 인 "fee" 가 출력된다.
// myObj
var myObj = {
name: "foo",
sayName: function () {
console.log(this.name)
},
};
myObj.sayName(); // foo
// otherObj
var otherObj = {
name: "other",
};
otherObj.sayName = myObj.sayName;
otherObj.sayName(); // other
=⇒ myObj.sayName()은 myObj에 의해 호출되어 this는 myObj이다.
=⇒ otherObj.sayName()은 otherObj에 의해 호출되었으므로 this는 otherObj이다.
// 화살표 함수의 this는 상위스코프인 window
const myObj = {
name: "foo",
sayName: () => console.log(this.name) // undefined
};
myObj.sayName(); // undefined
=⇒ arrow function의 this는 언제나 상위스코프의 this이므로, sayName의 this는 myObj의 상위 스코프인 window를 가리킨다. (window.name === undfined)
function() {}은 해당 함수를 호출한 객체(. 앞이 객체)가 this로 전달된다.
sayName()은 window.sayName()이 생략된 것!!
() ⇒ {}은 해당 함수가 선언된 상위 스코프의 this가 전달된다.
참고
호이스팅은 var 키워드로 생성된 변수, 함수를 javascript 엔진이 스코프의 최상위로 끌어올리는 것을 말한다.
var 키워드는 전역 스코프를 가지기 때문에 변수의 선언 + 초기화(undefined)가 실행되어 코드의 제일 위로 끌려 올려지게된다.
(출력 시 undefined)
함수는 function showName()과 같이 function키워드로 선언된 함수에만 호이스팅이 동작하고
(함수 선언 위에서 실제 사용 가능),
var func = function(){} 처럼 변수에 할당된 함수는 undefined를 출력한다.
(var 변수이므로 선언 + 초기화가 이루어짐)
변수는 아래와 같이 3단계의 과정을 통해 생성된다.
console.log(name); // undefined (호이스팅 작동)
var name = "shon";
console.log(aa); // undefined; (호이스팅 작동)
var aa;
console.log(afafa); // ReferenceError: afafa is not defined
{
console.log(name) // ReferenceError: Cannot access 'name' before initialization
let name = "shon" // (호이스팅 작동)
console.log(sir) // ReferenceError: Cannot access 'name' before initialization
let sir // (호이스팅 작동)
console.log(afafa) // ReferenceError: afafa is not defined
}
위의 결과를 보면 let 키워드도 블록 내에서 선언은 Hoisting은 되지만,
변수가 선언되기 전(TDZ)에 접근하면 let 키워드는 아직 초기화(undefined)가 되지 않았으므로,
undefined를 리턴하는 var 달리 에러를 발생시킨다.
const age = 25; // 선언과 동시에 초기화(할당) 필요
//const age; // const 변수를 선언만 할 경우 에러 발생
//age = '25';
var 변수의 사용은 전역으로 메모리에 계속 축적됨으로,
블록 스코프의 범위를 가지는 let과 const의 사용이 더 바람직하다.

types
any vs unknown
unknown은 Typescript 3.0에 추가되었다.
타입 unknown은 any처럼 모든 타입의 값이 할당될 수 있다.
let variable: unknown
variable = true // OK (boolean)
variable = 1 // OK (number)
variable = 'string' // OK (string)
variable = {} // OK (object)
But, unknown은 any를 제외한 다른 타입에는 할당할 수 없다.
let variable: unknown
let anyType: any = variable
let booleanType: boolean = variable
// Error: Type 'unknown' is not assignable to type 'boolean'.(2322)
let numberType: number = variable
// Error: Type 'unknown' is not assignable to type 'number'.(2322)
let stringType: string = variable
// Error: Type 'unknown' is not assignable to type 'string'.(2322)
let objectType: object = variable
// Error: Type 'unknown' is not assignable to type 'object'.(2322)
'unknown' 이라는 단어가 의미하듯이 아직 타입을 모르는 타입이기 때문이다.
따라서 아래와 같이 객체, 배열, 함수로서의 사용도 불가능하다.
let variable: unknown
variable.foo.bar // Error: Object is of type 'unknown'.(2571)
variable[0] // Error
variable.trigger() // Error
variable() // Error
new variable() // Error
unknown은 어떤 타입도 될 수 있는 다른 타입을 포괄하는 타입이기 때문에,
유니온(|)과 인터섹션(&)의 결과는 다음과 같다.
type unknownType = unknown | string // unknown
type stringType = unknown & string // string
프레임워크 : 개발을 편하게 도와주는 틀. 프레임워크는 우리의 코드를 불러온다.
라이브러리 : 우리의 코드 상에서 라이브러리를 불러와 사용한다.
쿠키와 세션은 HTTP의 클라이언트가 reqeuest를 보내고 서버로부터 response를 받으면 통신의 끝으로, 서버에서 클라이언트의 상태 정보를 유지하지 않는 Stateless 특징을 보완하기 위해 사용된다.
참고

JWT는 BASE64로 인코딩 된 헤더, 내용, 서명의 3구조로 이루어진다.
헤더: 토큰의 무결성 검증에 사용될 알고리즘과 토큰의 타입이 JSON 타입으로 정의되어있다.
내용: 토큰에 담을 정보가 JSON타입으로 정의되어있다.
=> 아이디, 회원 정보 등은 private claim에 포함된다.
서명: 헤더와 내용에 해당하는 BASE64 스트링을 헤더에 명시된 해시 알고리즘으로 해시한 HMAC(Hashed Message Authentication Code)으로 이루어진다.
=> 토큰의 위,변조 방지
유저가 로그인에 성공하면 향후 서비스 사용에 필요한 private claim 을 담아 JWT을 만들어 유저에게 전송한다.
유저는 해당 토큰을 request 헤더 또는 URL에 담아 서버로 전송한다.
서버는 이 토큰의 private claim을 유저의 인증, 권한 확인에 사용한다.
stateless 적합 : 토큰은 클라이언트 사이드에 저장되므로 stateless 기반 서비스에 적합하다.
scalability : 서버 기반 인증시스템에 비해서 서버의 scalability(확장성)이 높다.
보안성 : 세션 인증을 위한 쿠키 전달이 필요 없으므로 보안성 향상된다.
extensibility : scalability와는 조금 다른 확장성, 서버의 확장성이 아닌
로그인이 사용되는 분야, 토큰에 포함되는 정보의 종류 등에 대한 확장성이 높다.
CORS : 어떤 디바이스와 도메인에서도 토큰이 유효하면 정상적으로 처리된다.
다양한 환경과 언어를 지원한다.
Header와 Payload가 단순히 BASE64로 인코딩되어있기 때문에
클라이언트 사이드에 토큰 내부의 정보가 노출된다.
서비스가 커지면 토큰이 필요로하는 데이터가 커져 토큰이 커지고
이에 따라 매 HTTP요청의 트래픽 양에 영향을 미칠 수 있다
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = new Node(0);
}
find(data) {
let curNode = this.head;
while (curNode.data != data) {
curNode = curNode.next;
}
return curNode;
}
insert(item, data) {
let newNode = new Node(data);
let curNode = this.find(item);
newNode.next = curNode.next;
curNode.next = newNode;
}
display() {
let curNode = this.head;
while (!(curNode.next == null)) {
console.log(curNode.data);
curNode = curNode.next;
}
}
findPrevious(data) {
let curNode = this.head;
while (!(curNode.next == null) && (curNode.next.data != data)) {
curNode = curNode.next;
}
return curNode;
}
remove(data) {
let prevNode = this.findPrevious(data);
if (!(prevNode.next == null)) {
prevNode.next = prevNode.next.next;
}
}
}
const ll = new LinkedList();
ll.insert(0, 1); // 0->1
ll.insert(1, 3); // 0->1->3
ll.insert(3, 4); // 0->1->3->4
ll.insert(1, 2); // 0->1->2->3->4
ll.display(); // 0->1->2->3->4
ll.remove(3);
ll.display();// 0->1->2->4