Hoisting과 Temporal Dead Zone(TDZ)은 JavaScript에서 변수 선언과 초기화 동작과 관련된 개념이다.
Hoisting (호이스팅)
호이스팅은 JavaScript에서 변수와 함수 선언이 해당 스코프의 최상단으로 끌어올려지는 동작을 말한다.
즉, 변수나 함수를 선언하기 전에 사용하더라도 오류가 발생하지 않는다.
하지만 변수는 실제 선언 부분까지 초기화되지 않으며,
함수도 변수와 마찬가지로 선언부만 끌어올려지고 함수의 정의는 끌어올려지지 않는다.
console.log(x); // undefined (변수 호이스팅, 선언은 되었지만 초기화되지 않음)
var x = 5;
foo(); // "Hello" (함수 호이스팅, 함수 정의가 끌어올려짐)
function foo() {
console.log("Hello");
}
Temporal Dead Zone (TDZ) (일시적 사각 지대)
TDZ는 let, const 키워드를 사용한 변수의 선언이 해당 스코프에 도달할 때까지 변수를 참조할 수 없는 현상을 말한다.
즉, 변수가 선언되기 전까지의 구간에서 변수를 사용하면 참조 에러(ReferenceError)가 발생한다.
console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 5;
💬 요약하면, Hoisting과 TDZ는 변수 선언과 초기화의 시점을 관리하는데 영향을 미친다.
호이스팅으로 인해 변수가 선언되기 전에 참조할 수 있지만, TDZ로 인해 let과 const 변수가 선언되기 전까지는 변수를 사용할 수 없다. 따라서 코드의 가독성과 예측 가능성을 위해 변수를 해당 스코프의 시작 부분에서 선언하고 초기화하는 것이 권장된다.
Virtual DOM은 리액트(React)와 같은 일부 UI 라이브러리에서 사용되는 개념으로, 가상의 DOM(Document
Object Model)을 메모리에 유지하고 실제 DOM과 비교하여 최소한의 변경사항만을 반영하는 방식을 말한다.
일반적으로 웹 애플리케이션은 사용자의 상호작용에 따라 DOM이 동적으로 변경된다.
DOM은 웹 페이지의 구조와 콘텐츠를 나타내는 객체 모델로, DOM이 변경되면 브라우저는 변경사항을 처리하고 화면을 다시 그려야 한다. 이러한 DOM 변경은 비용이 크고, 복잡한 웹 애플리케이션에서는 성능 문제를 야기할 수 있다.
Virtual DOM은 이러한 문제를 해결하기 위해 도입된 개념이다. 리액트와 같은 라이브러리는 실제 DOM 대신 가상의 DOM을 사용하여 웹 애플리케이션의 상태 변화를 추적한다. 가상 DOM은 메모리에 유지되므로, 실제 DOM과 비교하는 과정에서 렌더링 최적화를 수행할 수 있다.
Virtual DOM의 장점
성능 향상: 가상 DOM은 변경사항을 실제 DOM에 반영하기 전에 최적화된 방식으로 변화를 적용한다.
이로 인해 불필요한 DOM 조작을 최소화하여 성능을 향상시킨다.
간결성과 유지보수성: 가상 DOM을 사용하면 개발자는 상태 변화를 추적하는 데 집중할 수 있으며,
복잡한 DOM 조작 코드를 작성하지 않아도 된다. 이로 인해 코드의 간결성과 유지보수성이 향상된다.
크로스 플랫폼 지원: 가상 DOM은 브라우저 독립적으로 작동하므로, 리액트와 같은
라이브러리를 사용하여 여러 플랫폼에서 일관된 사용자 경험을 제공할 수 있다.
선언적 프로그래밍: 가상 DOM 기반의 리액트와 같은 라이브러리는 선언적 프로그래밍을 지원한다.
개발자는 원하는 결과물을 선언적으로 기술하고, 라이브러리가 상태 변화를 관리하고 적절한 DOM 업데이트를 수행한다.
💬 요약하면, Virtual DOM은 성능 향상과 간결성을 제공하여
웹 애플리케이션의 사용자 경험을 향상시키는 데 도움이 됩니다.
Class Component와 Function Component는 리액트(React)에서 컴포넌트를 작성하는 두 가지 주요 방법이다.
주요 차이점
Class Component: Class Component에서는 상태(state)를 클래스의 멤버 변수로 관리할 수 있다.
this.state
를 사용하여 상태를 선언하고, this.setState()
메서드를 통해 상태를 업데이트한다.
Function Component: Function Component에서는 React Hooks 중 하나인 useState
를 사용하여
상태를 관리한다. useState
훅을 사용하여 상태 변수와 해당 상태를 업데이트하는 함수를 얻을 수 있다.
Class Component: Class Component에서는 라이프사이클 메서드를 사용하여
컴포넌트의 마운트, 업데이트, 언마운트 등의 상태 변화를 감지하고 처리할 수 있다.
Function Component: Function Component는 React Hooks를 통해 라이프사이클과 관련된 로직을 작성할 수 있다. 예를 들어, useEffect
훅을 사용하여 마운트, 업데이트, 언마운트 등의 상태 변화를 처리할 수 있다.
💬 요약하면, Class Component는 클래스로 작성되고 상태와 라이프사이클을 관리하는 반면, Function Component는 함수로 작성되며 상태는 Hooks를 사용하여 처리한다. 최신의 React 프로젝트에서는 주로 Function Component와 Hooks를 사용하여 개발하고 있다.
React Hook은 함수형 컴포넌트에서 상태(state)와 라이프사이클 기능을 사용할 수 있도록 도와주는 함수이다.
React Hook 사용 규칙
최상위에서만 Hook 호출: Hook은 반드시 함수형 컴포넌트의 최상위 레벨에서 호출되어야 한다.
반복문, 조건문, 중첩 함수 등 내부에서 호출하면 안 된다.
컴포넌트 내에서 같은 순서로 Hook 호출: 컴포넌트의 각 렌더링마다 Hook 호출 순서는 동일해야 하다.
즉, 조건문에 따라 Hook을 호출하면 안 된다.
이를 위해 조건문 내에서 Hook을 호출하려면 useState
의 초기값으로 함수를 사용하면 된다.
커스텀 Hook은 'use'로 시작: 커스텀 Hook 함수는 반드시 'use'로 시작해야 한다.
이는 리액트가 커스텀 Hook을 식별하고 이를 특별한 용도로 다루기 위함이다.
Hook은 함수형 컴포넌트 내에서만 호출: Hook은 함수형 컴포넌트 내에서만 호출되어야 하며,
일반 JavaScript 함수나 클래스 컴포넌트에서는 사용되면 안 된다.
useEffect에서 비동기 함수 처리: useEffect
에서 비동기 함수를 호출할 경우,
async/await
을 사용하면 안 된다. 대신, 함수 내에서 비동기 처리를 해야 한다.
Stack(스택)과 Queue(큐)는 두 가지 다른 자료 구조로, 데이터를 저장하고 관리하는 방식에 차이가 있다.
Stack(스택)
Queue(큐)
💬 요약하면, Stack은 후입선출(LIFO) 방식으로 동작하며, Queue는 선입선출(FIFO) 방식으로 동작한다. 두 자료 구조는 다른 용도와 동작 방식을 가지고 있으며, 각각 적절한 상황에 사용된다.
Tree(트리)와 Graph(그래프)는 두 가지 다른 자료 구조로, 데이터의 관계를 나타내는 방식에 차이가 있다.
Tree(트리)
Graph(그래프)
💬 요약하면, Tree는 계층적이고 비순환적인 구조로 루트 노드에서 시작하여 자식 노드들로 연결된다. 그래프는 비선형적이고 순환적인 구조로 노드와 간선으로 이루어진다. Tree는 특별한 종류의 그래프로 볼 수 있다.
이진 탐색(Binary Search)은 정렬된 배열에서 특정 값을 빠르게 찾는 알고리즘이다.
배열의 중간 값과 찾고자 하는 값을 비교하여 찾고자 하는 값이 중간 값보다 크면 오른쪽 절반,
작으면 왼쪽 절반을 다시 탐색하는 방법을 반복하여 원하는 값을 찾아낸다.
이진 탐색은 선형 탐색과 비교하여 훨씬 빠른 탐색 속도를 제공한다.
이진 탐색 알고리즘의 동작 방식
이진 탐색은 반복적인 방법과 재귀적인 방법으로 구현할 수 있다.
배열이 정렬되어 있어야만 이진 탐색을 사용할 수 있으며, 탐색 시간 복잡도는 O(log n)이다.
이는 배열의 크기에 비례하지 않고, 배열을 절반씩 줄여가면서 탐색하기 때문에 매우 효율적이다.
💬 요약하면, 이진 탐색은 대량의 데이터를 빠르게 탐색해야
할 때 유용하며, 자료가 정렬되어 있을 때 효과적으로 활용된다.
TypeScript(타입스크립트)는 Microsoft에서 개발한 오픈 소스 프로그래밍 언어로, JavaScript의 상위 집합이다.
TypeScript는 정적 타입 시스템을 도입하여 JavaScript의 기능을 확장하고 개선한 언어이다.
기본적으로 TypeScript는 JavaScript의 문법과 기능을 모두 지원하며,
추가적으로 타입 어노테이션을 사용하여 변수, 함수, 객체 등의 타입을 명시할 수 있다.
TypeScript와 JavaScript의 주요 차이점
정적 타입 체크:
타입 어노테이션:
클래스와 인터페이스:
컴파일:
💬 요약하면, TypeScript는 JavaScript의 상위 집합으로, 정적 타입 체크, 타입 어노테이션, 클래스와 인터페이스 등의 기능을 제공하여 코드의 안정성과 가독성을 향상시키는 언어이다. TypeScript는 JavaScript의 모든 기능을 지원하며, JavaScript로 작성된 코드를 TypeScript로 쉽게 이전할 수 있다.
TypeScript 사용 장점
정적 타입 체크: TypeScript는 정적 타입 언어로서, 변수와 함수의 타입을 미리 명시하고 타입 검사를 수행한다.
이로 인해 런타임에 발생할 수 있는 타입 관련 에러를 사전에 방지할 수 있다.
또한 코드의 안정성과 신뢰성을 향상시키는 데 도움이 됩니다.
가독성과 유지보수성: 명시적인 타입 어노테이션과 클래스, 인터페이스 등의 기능을 사용하면 코드의
가독성이 향상된다. 또한 타입 정보를 통해 다른 개발자가 코드를 이해하고 유지보수하기 쉬워진다.
IDE 지원: TypeScript는 강력한 타입 추론 기능과 IDE(Integrated Development Environment)와의
연동으로 개발 환경을 향상시킨다. 코드 자동 완성, 타입 오류 표시 등의 기능을 통해 개발 생산성이 향상된다.
코드 예측성: TypeScript를 사용하면 개발자가 의도한 타입을 명시하므로 코드의 의도를
더 명확하게 전달할 수 있다. 이로 인해 잘못된 타입 사용으로 인한 버그를 줄일 수 있다.
TypeScript 사용 단점
추가 작업 필요: TypeScript를 사용하면 타입 어노테이션을 추가해야 하고,
타입 정의에 시간을 할애해야 한다. JavaScript보다 더 많은 작업이 필요할 수 있다.
런타임 오버헤드: TypeScript의 타입 체크와 타입 정보를 위해 런타임 오버헤드가 발생할 수 있다.
이는 TypeScript 파일을 JavaScript로 컴파일하는 과정과 브라우저에서 실행하는 과정에서 추가적인 부하를 초래할 수 있다.
타입 정의 충돌: 일부 라이브러리나 외부 모듈의 타입 정의가 충돌하거나 불완전할 수 있다.
이러한 경우에는 직접 타입 정의를 수정해야 하는 번거로움이 있을 수 있다.
💬 요약하면, TypeScript는 코드의 안정성과 가독성을 향상시키는 데 도움이 되지만, 추가 작업과 런타임 오버헤드 등의 부분에서 비용이 발생할 수 있다. 따라서 프로젝트의 특성과 개발 환경을 고려하여 TypeScript를 도입할지 여부를 결정하는 것이 중요하다.
TypeScript의 인터페이스(Interface)는 변수, 함수, 객체 등의 타입을 명시적으로 정의하는 역할을 한다.
인터페이스를 사용하여 코드의 가독성을 향상시키고, 타입 검사를 강화하여 코드의 안정성을 높일 수 있다.
interface MyInterface {
prop1: number;
prop2: string;
prop3?: boolean;
prop4: (param: number) => void;
}
인터페이스의 주요 특징과 사용법
속성 정의: 인터페이스 내에서 각 속성은 이름과 해당 속성의 타입을 명시적으로 지정한다.
속성의 타입은 기본 자료형이나 사용자 정의 타입(인터페이스, 클래스 등)이 될 수 있다.
선택적 속성: prop3?: boolean
와 같이 속성 이름 뒤에 ?
를 붙이면 해당 속성은 선택적으로 정의된다.
즉, 해당 속성을 포함하거나 포함하지 않을 수 있다.
함수 정의: 인터페이스는 함수 타입을 정의할 수 있다. prop4
속성은 (param: number) => void
와
같이 함수의 타입을 명시하고 있다. 이는 매개변수 타입과 반환값 타입을 함께 명시하는 것을 의미한다.
객체와의 호환성: 인터페이스를 사용하여 객체의 타입을 명시할 수 있다.
이로 인해 객체가 인터페이스를 구현하고 있는지를 검사하여 코드의 안정성을 높일 수 있다.