많은 부분을 아래 링크들에서 퍼왔다.
퍼온 답변도 많아서 중간에 존댓말 섞여있다.
✅ 기술 스택 단위로 쪼갤라 했는데 그냥 한 번에 보는게 내가 편해서 안 쪼갬
✅ 내용은 계속 추가될듯
댓글 알림이 안 떠서 급한 건은 rainy_waltz@naver.com 으로
자바스크립트는 개발자가 별도의 컴파일 작업을 수행하지 않는 인터프리터 언어(Interpreter language)이다.
자바스크립트는 명령형(imperative), 함수형(functional), 프로토타입 기반(prototype-based) 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어다.
컴파일러(compiler) (C
, C++
, C#
, JAVA
)
고급 언어로 작성 된 소스 코드를 저급 언어로 번역하는 프로그램을 가리킨다.
인터프리터(interpreter) (Python
, Javascript
, Ruby
)
프로그래밍 언어의 소스 코드를 바로 실행하는 컴퓨터 프로그램을 말한다.
Ref
브라우저 엔진: ECMAScript + WebAPI(DOM, Canvas, XMLHttpRequest, Fetch, ...)
nodejs: ECMAScript + Nodejs 고유 API
Ref
ECMAScript는 자바스크립트의 표준 명세인 ECMA-262를 말하며 프로그래밍 언어의 타입, 값, 객체와 프로퍼티, 함수, 빌트인 객체 등 핵심 문법(core syntax)을 규정한다. 각 브라우저 제조사는 ECMAScript를 준수하여 브라우저에 내장되는 자바스크립트 엔진을 구현한다.
자바스크립트는 일반적으로 프로그래밍 언어로서 기본 뼈대를 이루는 ECMAScript와 브라우저가 별도 지원하는 클라이언트 사이드 Web API, 즉 DOM, BOM, Canvas, XMLHttpRequest, Fetch, requestAnimationFrame, SVG, Web Storage, Web Component, Web worker 등을 아우르는 개념이다.
클라이언트 사이드 Web API는 ECMAScript와는 별도로 World Wide Web Consortium (W3C)에서 별도의 명세로 관리하고 있다. 클라이언트 사이드 Web API의 자세한 내용은 MDN web docs: Web API를 참고하기 바란다.
Ref
자바스크립트 면접 질문은 사실상 실행 컨텍스트에서 끝난다. 맨날 나오는 그 놈의 클로저랑 호이스팅도 결국 실행 컨텍스트와 관련이 있다. 반드시 이해하고 면접장에 들어가자.
실행 컨텍스트의 생성 기준
ECMAScript 사양은 소스코드를 4가지 타입으로 구분한다. 이 4가지 타입의 소스코드는 실행 컨텍스트를 생성한다.
이 중 실제로 마주하는 코드는 대부분 전역코드 및 함수 코드이다.
소스코드 평과와 실행
자바스크립트 엔진은 소스코드를 2개의 과정,"소스코드 평가"와 "소스코드의 실행"과정으로 나누어서 처리한다.
소스코드 평가 과정에서는 실행 컨텍스트를 생성한다.
소스코드 실행 단계에서는 실행에 필요한 정보를 실행 컨텍스트에서 얻으며 소스 코드의 실행 결과는 다시 실행 컨텍스트가 관리한다. (소스코드 실행 단계를 런타임이라고 한다.)
실행 컨텍스트의 구성
실행 컨텍스트가 생성이 되면 LexicalEnvironment
와 VariableEnvironment
를 생성한다.
VariableEnvironment
는 변하지 않지만, LexicalEnvironment
는 코드가 실행됨에 따라 변하기도 한다.
⚠
Lexical & Variable Env
까지 설명하면 날 샐 수 있으니 그냥 실행 컨텍스트로 퉁치는게 좋다. 지금부터는LexicalEnvironment
를 그냥 실행 컨텍스트라고 부를 것이다.
실행 컨텍스트는 변수들을 저장하는 EnvironmentRecord
와 상위 스코프의 레퍼런스인 OuterLexicalEnvironmentReference
로 구성되어있다.
변수 저장 (호이스팅)
혼란을 막기위해 const
, let
을 제외하고 var 변수
와 함수 선언문
에 대해서만 먼저 설명한다.
함수 평가단계에서 자바스크립트 엔진은 스코프 내에 선언된 var 변수와 함수 선언문으로 정의한 함수를 EnvironmentRecord
에 저장한다.
이 때, var 변수는 변수의 생성 3단계인 선언 - 초기화 - 할당
중 초기화 단계까지 처리되며 함수 선언문은 할당까지 전부 처리된다.
이러한 특징 때문에 자바스크립트 런타임에서 해당 선언부까지 가지 않아도 var 변수와 함수에 접근할 수 있는 것이다. 다만, var 변수는 할당되기 전까지는 undefined로 존재하며 함수는 바로 실행이 가능하다.
이러한 특징을 자바스크립트의 호이스팅이라고 부른다.
const, let 변수의 저장 (const, let 의 호이스팅)
앞서 설명한 바와 같이 실행 컨텍스트는 특별한 경우를 제외하고는 전역 코드, 함수 코드에서 생성된다. 이 말인즉 블록 스코프에서는 실행 컨텍스트가 생성되지 않는다는 뜻이다.
사실 Environment Record
는 var 변수
와 함수 선언문
을 저장하는 Object Enviroment Record
와 const, let 변수
를 저장하는 Declarative Environment Recored
로 나누어져있다.
이 중 Declarative Environment Recored
는 스택의 형태로 관리 되며, 자바스크립트 런타임에서 블록을 만나면 새로운 레코드가 생성되어 스택에 쌓이게 된다.
Declarative Environment Recored
가 생성되면 블록 스코프 내의 const 와 let 변수가 레코드에 저장된다. 이 때 선언
단계까지만 처리가 되는데, 이 때문에 const, let 변수의 선언문에 도달하기 전에 해당 변수를 호출하면 초기화가 되지 않았다는 에러가 발생한다.
참고로 블록 스코프 시작부터 변수 선언문 까지를 TDZ(temporal dead zone) 라고 부른다.
스코프 체이닝
자바스크립트 런타임중 변수를 사용하는 코드를 만나면 실행 컨텍스트의 Environment Recored
에서 해당 변수를 검색한다. 이 때, 현재 실행 컨텍스트의 레코드에서 변수가 발견되지 않으면 상위 스코프의 실행 컨텍스트를 검색하는데 이 것을 스코프 체이닝이라고 한다.
실행 컨텍스트는 상위 스코프에 대한 레퍼런스를 가지고 있기 때문에 이와 같은 동작이 가능하다. 이러한 특징은 클로저와 아주 밀접하게 관련이 되어있다.
Ref
클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수이다.
자바스크립트는 런타임에서 변수를 사용할 때에 위에서 설명한 스코프 체이닝을 통해 변수를 검색한다. 예를들어 outer 함수에서 정의한 변수를 inner 함수에서 사용할 경우, inner 함수의 Lexical Environment에 저장된 OuterLexicalEnvironmentReference
를 통해서 outer 함수의 Lexical Environment 에 접근해서 값을 가져온다.
비록 outer 함수는 종료되어서 실행 컨텍스트가 제거되었지만, outer 함수의 Lexical Environment 는 inner 함수의 Lexical Environment 에 의해 참조가 되고 있으므로 가비지 컬렉터에 의해 제거 되지 않고 있게 된다.
이러한 원리로 outer 함수가 종료되어 실행 컨텍스트가 제거된 이후에도 outer 함수의 Lexical Environment 에 접근하여 outer 함수에서 정의한 변수를 사용할 수 있는 것이다.
이러한 원리를 클로저라고 부른다.
Ref
실행 컨텍스트에서 설명했다.
Ref
자바스크립트의 경우 함수 호출 방식에 의해 this에 바인딩할 어떤 객체가 동적으로 결정된다. 다시 말해, 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정되는 것이 아니고, 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정된다.
화살표 함수의 this
화살표 함수는 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정된다. 동적으로 결정되는 일반 함수와는 달리 화살표 함수의 this 언제나 상위 스코프의 this를 가리킨다. 이를 Lexical this라 한다.
Ref
js 의 참조값들은 언제든지 property 에 접근하여 값을 변경할 수 있다.
Object.freeze()
메소드를 사용하면 진짜 상수를 만들수 있다.
Ref
자바스크립트는 원시 값의 메서드와 프로퍼티에 접근할 수 있도록 언어 차원에서 허용합니다. 이를 가능하게 하기 위해, 원시값이 메서드나 프로퍼티에 접근하려 하면 추가 기능을 제공해주는 특수한 객체, "원시 래퍼 객체(object wrapper)"를 만들어 줍니다. 이 객체는 메서드를 실행하거나 프로퍼티를 반환한 후 삭제됩니다.
let str = "Hello";
alert( str.toUpperCase() ); // HELLO
위의 코드는 다음과 같이 동작합니다.
1. 문자열 str
은 원시값이므로 원시값의 프로퍼티(toUpperCase)에 접근하는 순간 특별한 객체가 만들어집니다. 이 객체는 문자열의 값을 알고 있고, toUpperCase()
와 같은 유용한 메서드를 가지고 있습니다.
2. 메서드가 실행되고, 새로운 문자열이 반환됩니다(alert
창에 이 문자열이 출력됩니다).
3. 특별한 객체는 파괴되고, 원시값 str
만 남습니다.
Ref
ESM
ES6 에 추가된 ECMA Script공식 모듈 시스템이다. ES6 이전에는 js에 모듈 시스템이 없어서 commonjs, amd 등의 방식이 나왔으나, 현재는 노드에서 채택한 commonjs 방식 정도만 사용한다.
Common JS
이 방식은 노드에서 채택한 방식으로 매우 유명합니다. 노드 강좌에서도 다뤘습니다. 보통 서버사이드에서는 CommonJS를 더 자주 씁니다.
AMD
AMD는 Asynchronous Module Definition으로 비동기적 모듈 선언이란 뜻입니다.
AMD가 목표로 하는 것은 필요한 모듈을 네트워크를 이용해 내려받아야 하는 브라우저 환경에서도 모듈을 사용할 수 있도록 표준을 만드는 일이다.
UMD
모듈 시스템을 개발한 것 까지는 좋은데 문제는 다양한... 이라는 것이죠. AMD와 CommonJS를 쓰는 두 그룹으로 나누어지다보니 서로 호환이 안 되게 되었습니다. 그래서 나온 것이 UMD입니다. 어떤 모듈을 쓰든지 동작되게 하기 위한 것이죠.
필요한 파일이 모두 로컬 디스크에 있어 바로 불러 쓸 수 있는 상황, 즉 서버사이드에서는 CommonJS 명세가 AMD 방식보다 간결하다. 반면 필요한 파일을 네트워크를 통해 내려받아야 하는 브라우저와 같은 환경에서는 AMD가 CommonJS보다 더 유연한 방법을 제공한다.
Ref
Ref
Ref
1. Top-Level await
2. .at() method
console.log([1, 2, 3].at(-1)) // 3
3. Object.hasOwn
4. Error Cause
try{
throw new Error("Failed", {cause:"some reason"})
} catch (e){
console.log(e.cause)
}
5. Private class fields
class Circle {
// private field
#radius;
constructor(value) {
// You can access private field from constructor
this.#radius = value;
}
get area() {
return Math.PI * Math.pow(this.#radius, 2);
}
}
Ref
Ref
Ref
Ajax는 JavaScript의 라이브러리중 하나이며 Asynchronous Javascript And Xml(비동기식 자바스크립트와 xml)의 약자이다. 브라우저가 가지고있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법이다. Ajax를 한마디로 정의하자면 JavaScript를 사용한 비동기 통신, 클라이언트와 서버간에 XML 데이터를 주고받는 기술이라고 할 수 있다.
ajax는 html 페이지 전체가아닌 일부분만 갱신할수 있도록 XML HttpRequest객체를 통해 서버에 request한다.
Ref
제네릭은 타입을 일반화하여 재사용 가능한 코드를 작성하는 기술이다. 함수나 클래스에서 사용될 타입을 미리 지정하지 않고, 호출할 때 지정할 수 있게 해준다. 제네릭을 사용하면 코드의 유연성과 재사용성이 높아진다.
function identity<T>(arg: T): T {
return arg;
}
const result = identity<string>("hello");
인터페이스의 상속은 이미 정의된 인터페이스를 확장하여 새로운 인터페이스를 만드는 것이다. 상속받은 인터페이스의 속성과 메서드를 그대로 사용할 수 있으며, 추가적인 속성과 메서드를 정의할 수도 있다.
교차 타입 (Intersection Types)
interface Shape {
color: string;
}
interface Size {
width: number;
height: number;
}
type ShapeAndSize = Shape & Size;
const square: ShapeAndSize = { color: "red", width: 10, height: 10 };
유니온 타입 (Union Types)
function padLeft(value: string, padding: string | number) {
// ...
}
타입 가드와 차별 타입 (Type Guards and Differentiating Types)
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
pet is Fish는 이 예제에서의 타입 서술어이다. 서술어는 parameterName is Type 형태이고, parameterName는 반드시 현재 함수 시그니처의 매개변수 이름이어야 한다.
조건부 타입 (Conditional Types)
Ref
Object
Contains stuff (like toString(), hasOwnProperty()) that is present in all JavaScript objects. Any value (primitive, non-primitive) can be assigned to Object type.
{}
{}는 빈 오브젝트이다. Object 와 기본적으로 비슷하지만 컴파일 타임에서 다르게 동작한다. {} 는 Object 의 멤버들을 가지고 있지 않다.
object
object 는 Typescript 2.2 에 추가되었다. object는 모든 참조값 타입들에 적용이 가능하다. bool, number, string, symbol 과 같은 원시 값들에는 사용할 수 없다.
Ref
1. Function을 설정하는 방법이 조금 다르다.
interface
interface SetPoint {
(x: number, y: number): void;
}
type
type SetPoint = (x: number, y: number) => void;
2. type은 interface와 달리 원시값, union, tuples 을 사용할 수 있다.
// primitive
type Name = string;
// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];
3. syntax는 다르지만 둘 다 Extend 기능을 사용할 수 있으며, 상호 extend 가 가능하다.
Interface extends interface
interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }
Type alias extends type alias
type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };
Interface extends type alias
type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }
Type alias extends interface
interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };
4. class 는 interface, type 모두 implements 할 수 있지만, union 타입은 불가하다.
interface Point {
x: number;
y: number;
}
class SomePoint implements Point {
x = 1;
y = 2;
}
type Point2 = {
x: number;
y: number;
};
class SomePoint2 implements Point2 {
x = 1;
y = 2;
}
type PartialPoint = { x: number; } | { y: number; };
// FIXME: can not implement a union type
class SomePartialPoint implements PartialPoint {
x = 1;
y = 2;
}
5. Declaration merging - interface 는 여러번 선언이 가능하다.
// These two declarations become:
// interface Point { x: number; y: number; }
interface Point { x: number; }
interface Point { y: number; }
const point: Point = { x: 1, y: 2 };
Ref
unknown 은 any의 일부분이라고 볼 수 있다. 아무 값이나 할당이 가능하다.
다만, any로 선언된 변수는 아무 타입에나 할당 가능하지만, unknown 으로 선언된 변수는 unknown 타입에만 할당이 가능하다.
let vAny: any = 10; // We can assign anything to any
let vUnknown: unknown = 10; // We can assign anything to unknown just like any
let s1: string = vAny; // Any is assignable to anything
let s2: string = vUnknown; // Invalid; we can't assign vUnknown to any other type (without an explicit assertion)
Ref
https://stackoverflow.com/questions/51439843/unknown-vs-any
Ref
Ref
Virtual DOM은 실제 DOM의 구조와 비슷한, React 객체의 트리다. 개발자는 직접 DOM을 제어하지 않고 Virtual DOM을 제어하고, React에서 적절하게 Virtual DOM을 DOM에 반영하는 작업을 한다.
state에 변경사항이 발생하면, 새로운 Virtual DOM이 생성된다. 새롭게 생성된 Virtual DOM tree는 real DOM tree 와 "diffing" 과정을 거쳐 real DOM에 변경 사항을 반영할 수 있는 최적의 방법을 계산한다. 계산이 끝나면 한 번에 real DOM을 갱신한다.
모든 변경사항은 묶어서 한 번에 real DOM을 갱신되기 때문에 레이아웃 계산과 리렌더링의 규모는 커지지만, 딱 한 번만 일어나기 때문에 전체 연산의 수를 줄일 수 있다.
Virtual DOM을 이용하여 real DOM 을 갱신하는 방법의 가장 큰 장점은 DOM 갱신의 추상화이다. 개발자는 atrribute 조작, 이벤트 처리 또는 수동 DOM 업데이트가 백그라운드에서 어떻게 수행되는지 알 필요가 없다. 또한 기존 값 중 어떤게 바뀌었고 어떤게 바뀌지 않았는지 계속 파악하고 있지 않아도 된다.
Ref
트리를 새로 만들게 되면 최첨단의 알고리즘을 이용하더라도 O(n3)의 복잡도를 가지게 된다.
이는 너무 비싼 연산이기 때문에, React는 대신, 두 가지 가정을 기반하여 O(n) 복잡도의 휴리스틱 알고리즘을 구현한다.
리액트에서 DOM이 업데이트 되는 과정
Diffing Algorithm
DOM 노도의 처리가 끝나면, React는 이어서 해당 노드의 자식들을 재귀적으로 처리한다.
자식들이 key를 가지고 있다면, React는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인한다. 이 때 key 값이 일치하면 이전 element 를 그대로 사용하고, 새롭게 추가되었거나 제거된 element 들의 변경사항을 반영한다. 만약, index 를 키 값으로 사용한다면, state가 엉망이 되거나 의도치 않은 방식으로 변경될 수 있다.
Ref
1. Marking the component dirty
DOM 이벤트가 발생하면 이를 감싸고 있는 React event listeners가 this.setState를 실행시킨다. setState 를 이용하여 state 를 변경시킨다. setState 는 해당 컴포넌트(this)를 변경 대상 컴포넌트(dirty component)로 마킹한다.
2. 새 virtual DOM element 생성(dirty한 component 업데이트)
React의 flushBatchedUpdates 함수가 수행한다. dirty로 마킹된 컴포넌트들과 하위 노드들을 업데이트한다. 그리고 shouldComponentUpdate를 확인하여 해당 컴포넌트가 re-rendering 될지 말지를 체크한다.
3. use the diffing algorithm to do the reconciliation
Virtaul DOM과 real DOM을 비교(diffing)하여 어떤 노드를 어떻게 업데이트할지 판단한다. 이 과정은 render 단계에서 진행된다.
4. update the actual DOM
재조정 후 수정 대상이 되는 값들을 한 번에 batch 적용
Ref
Props는 리액트에서 불변(immutable) 값이다. 하지만, this는 변경 가능하며(mutable), 조작할 수 있다. 이것이 this가 클래스에서 존재하는 목적이다. 리액트가 시간이 지남에 따라 이를 변경하기 때문에 render나 라이프사이클 메서드를 호출할 때 업데이트된 값들을 읽어 올 수 있는 것이다.
반면 함수형 컴포넌트의 경우 props는 보존된다. 클래스의 this와는 다르게, 함수가 받는 인자는 리액트가 변경할 수 없다.
클래스형 컴포넌트의 props 는 this 에 바인딩 되어있기 때문에, this.props 자체가 변경되면 props 또한 변경될 수 밖에 없다.
다음은 비슷한 예시이다. 실제 예시는 ref 의 링크를 참고하자.
class
class Messenger{
constructor(message){
this.message = message;
}
showMessage = ()=>{
console.log(this.message);
};
delayedMessage = ()=>{
setTimeout(this.showMessage, 1000);
};
}
var m = new Messenger('hi');
m.showMessage();
// hi
m.delayedMessage();
m.message = 'bye'
// bye
function
function Messenger(message){
this.showMessage = ()=>{
console.log(message);
};
this.delayedMessage = ()=>{
setTimeout(this.showMessage, 1000);
};
}
var m = new Messenger('hi');
m.showMessage();
// hi
// m 의 message를 바꿀 방법이 없음
ref
훅은 리액트 컴포넌트에서 상태와 이펙트를 도입하고 관리하는 효과적인 매커니즘입니다.
react hook 을 도입한 계기
컴포넌트 사이에서 상태 로직을 재사용하기 어렵습니다.
React는 컴포넌트간에 재사용 가능한 로직을 붙이는 방법을 제공하지 않습니다. (예를 들어, 스토어에 연결하는 것) 이전부터 React를 사용해왔다면, render props이나 고차 컴포넌트와 같은 패턴을 통해 이러한 문제를 해결하는 방법에 익숙할 것입니다. 그러나 이런 패턴의 사용은 컴포넌트의 재구성을 강요하며, 코드의 추적을 어렵게 만듭니다.
Hook을 사용하면 컴포넌트로부터 상태 관련 로직을 추상화할 수 있습니다. 이를 이용해 독립적인 테스트와 재사용이 가능합니다. Hook은 계층의 변화 없이 상태 관련 로직을 재사용할 수 있도록 도와줍니다. 이것은 많은 컴포넌트 혹은 커뮤니티 사이에서 Hook을 공유하기 쉽게 만들어줍니다.
복잡한 컴포넌트들은 이해하기 어렵습니다.
상태 관련 로직들과 사이드 이펙트가 있는 컴포넌트들을 유지보수해야 합니다. 각 생명주기 메서드에는 자주 관련 없는 로직이 섞여들어가고는 합니다. 예시로 componentDidMount 와 componentDidUpdate는 컴포넌트안에서 데이터를 가져오는 작업을 수행할 때 사용 되어야 하지만, 같은 componentDidMount에서 이벤트 리스너를 설정하는 것과 같은 관계없는 로직이 포함되기도 하며, componentWillUnmount에서 cleanup 로직을 수행하기도 합니다. 함께 변경되는 상호 관련 코드는 분리되지만 이와 연관 없는 코드들은 단일 메서드로 결합합니다. 이로 인해 버그가 쉽게 발생하고 무결성을 너무나 쉽게 해칩니다.
Class은 사람과 기계를 혼동시킵니다.
JavaScript의 this키워드는 대부분의 다른 언어에서와는 다르게 작동함으로 사용자에게 큰 혼란을 주었으며, 코드의 재사용성과 구성을 매우 어렵게 만들고는 했습니다.
기본 훅
훅 규칙
custom hook
커스텀 훅을 사용하면 기존 컴포넌트 로직을 재사용할 수 있도록 별도의 함수로 추출할 수 있습니다.
ref
- https://ko.reactjs.org/docs/hooks-intro.html
- https://ko.reactjs.org/docs/hooks-overview.html
- https://green-labs.github.io/rescript-in-korean/ReScript-React/03-Hooks-and-State-Management/01-Hooks-and-State-Management-Overview
- Hooks FAQ
- https://green-labs.github.io/rescript-in-korean/ReScript-React/03-Hooks-and-State-Management/07-Build-A-Custom-Hook
controlled compoennt
<input>
, <select>
, <textarea>
의 value(checked)를 state로 직접 관리하는 방법이다.uncontrolled component
Ref
New Feature
Ref
"문서 형식 선언"(Document Type Declaration), 또는 doctype이란 문서의 유형을 정의하기 위해 사용하는 선언문이다.
문서 타입 정의는 HTML5, XHTML, HTML의 세가지 문서 유형이 존재하며, 기술한 유형에 따라 마크업 문서의 요소와 속성들ㅇ르 처리하는 기준이 되며 유효성 검사에 이용된다.
웹 문서의 시작을 알려주며 태그보다 먼저 선언한다. DOCTYPE은 웹 브라우저에서 처리할 문서가 HTML이며 어떠한 버전으로 사용했으니, 해당 방식대로 해석하라는 의미를 갖는다.
Ref
의미를 가진 태그. HTML5에서는 처음 등장하였으며 <header>
나 <footer>
같은 태그들을 말한다.
장점
1. HTML 문서의 가독성과 유지보수가 쉬워지기 때문입니다
2. 웹 브라우저가 HTML만 보고도 어느 영역인지 쉽게 알 수 있다 이는 웹 접근성 시각에서 볼 때도 중요하게 사용된다. (시각 장애인용 스크린 리더를 사용할 때 등)
3. 검색엔진이 검색을 수행할 때 HTML내의 태그를 분석할 수 있다.
웹 사이트 구성 예시
시맨틱 태그 종류
Ref
Ref
Ref
일반적인 실행
<script src="script.js">
async
HTML 구문 분석과 병행하여 스크립트를 가져온 후 스크립트가 준비 될 때마다 즉시 실행이 가능하다.
실행의 순서가 다운로드 완료 시점의 결정되므로 실행 순서가 중요한 스크립트들에 async를 사용할 때는 유의해야 한다
<script async src="script.js">
defer
defer 속성은 HTML 구문 분석이 완전히 완료되면 스크립트 파일을 실행하도록 브라우저에 지시한다.
async와는 다르게 호출된 순서대로 실행된다.
<script defer src="script.js">
Ref
사용 예시
Ref
CORS란 Cross Origin Resource Sharing의 줄임말로, Cross-Site Http Request를 가능하게 하는 표준 규약이다.
CORS는 도메인 혹은 포트가 다른 서버의 자원을 요청할 때 생긴다. 그러나 동일 출처 정책으로 인해 CORS같은 상황이 발생하면 외부서버에 요청한 데이터를 브라우저에서 보안목적으로 차단을 한다.
문제를 해결하는 방법은 두 가지가 있다.
보통은 2번 방법을 사용하는데 리액트 개발 환경에서는 package.json 의 proxy 필드를 추가하거나, 'http-proxy-middleware' 라이브러리를 사용함으로써 해결이 가능하다.
실제 배포 환경에서는 배포 장비의 nginx에서 proxy 처리를 해주면 된다.
Ref
프레임 vs 라이브러리 + 제어의 역전
객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임중 하나로, 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.
출처: https://jeong-pro.tistory.com/95 [기본기를 쌓는 정아마추어 코딩블로그]
추상화: 객체들의 공통적인 특징을 뽑아내는 것이다. 즉, 우리가 구현하는 객체들이 가진 공통적인 데이터와 기능을 도출해 내는 것을 의미한다. 즉, "공통의 속성이나 기능을 묶어 이름을 붙이는 것"
캡슐화: 객체의 속성(data fields)과 행위(메서드, methods)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉한다.
상속성: 상속이란 상위개념의 특징을 하위 개념이 물려받는 특징을 말한다. 하나의 클래스가 가지고 있는 특징들을 그대로 다른 클래스가 돌려주고자 할 때 상속성의 특징을 사용한다.
다형성: 약간 다른 방법으로 일을 하는 함수의 동일한 이름으로 호출해 주는 것을 말한다. 예를 들어 홍길동과 김철수가 있다고 하자. 그런데 선생님이 길동이를 바라 보면서 칠판을 지우라고 했다. 그럼 길동 나름의 방법대로 칠판을 지울것이다. 그리고 선생님은 다시 철수에게 칠판을 지우라고 명령을 했다. 철수도 철수의 방식대로 칠판을 지울것이다. 이처럼 표현은 같지만 칠판을 지우는 행위는 다르게 나타난다. 이것이 다형성이다. 같은 하나의 명령이 다른 결과로 나타나는 것을 말한다. 오버로딩이 다형성에 해당된다.
primitive type과 reference type
결합도가 높은 예시: 바리스타와 매니저가 전역 변수를 공유한다. 매니저가 바리스타의 특정 값을 직접 참조한다.