기본 문법
연산자
!와 !!: !는 부정 연산자, !!는 값을 불리언으로 변환합니다.
==와 ===: ==는 타입 변환 후 비교, ===는 타입과 값 모두 비교합니다.
객체와 프로토타입
모든 함수는 자동으로 prototype 속성을 가지며, 이는 프로토타입 객체를 가리킵니다. 프로토타입 객체는 기본적으로 constructor 속성을 가지고 있으며, 이는 생성자 함수를 가리킵니다. new 키워드로 생성된 인스턴스는 내부 속성 __proto__를 통해 생성자의 프로토타입 객체에 접근합니다.
function Test(val) {
this.val = val;
}
let t = new Test("1");
// t.__proto__ === Test.prototype
this는 호출 방식에 따라 결정됩니다. 생성자 함수 내부의 this는 새로 생성되는 인스턴스를 가리킵니다.
call, apply, bind: 함수의 this를 명시적으로 바인딩하는 메서드입니다.
변수 스코프와 호이스팅
var: 함수 스코프를 가지며, 호이스팅이 발생합니다. 선언이 함수 최상단으로 끌어올려지고, 초기화는 undefined로 이루어집니다.
let, const: 블록 스코프를 가지며, 일시적 사각지대(TDZ)가 존재합니다. 선언 전에 접근하면 ReferenceError가 발생합니다.
function func() {
console.log(a); // undefined (var 호이스팅)
console.log(b); // ReferenceError (let TDZ)
var a = 1;
let b = 2;
}
데이터 타입
undefined는 변수가 선언되었지만 값이 할당되지 않은 상태, null은 값이 의도적으로 비어있음을 나타냅니다.
비동기 처리
JavaScript의 비동기 처리는 이벤트 루프(Event Loop)를 기반으로 동작합니다. 동기 작업은 호출 스택(Call Stack)에서 실행되고, 비동기 작업(예: setTimeout, 네트워크 요청)은 태스크 큐(Task Queue)에 등록되어 이벤트 루프가 처리합니다.
Promise
Promise는 비동기 작업의 결과를 나타내는 객체입니다. resolve와 reject 함수를 통해 성공/실패 상태를 저장하고, .then()과 .catch()로 결과를 처리합니다.
function createAsyncTask(value) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (value > 0.5) {
resolve('성공: ' + value);
} else {
reject('실패: ' + value);
}
}, 1000);
});
}
const task = createAsyncTask(0.8);
task
.then(result => console.log(result))
.catch(error => console.error(error));
.then()과 .catch()는 새로운 Promise를 반환하므로 체이닝이 가능합니다. resolve와 reject는 Promise의 상태를 저장하는 역할을 하며, .then()의 콜백은 성공 결과를 받아 처리합니다.
async/await
async 함수는 항상 Promise를 반환합니다. await는 Promise가 처리될 때까지 함수 실행을 일시 중단하고, 결과를 반환합니다.
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
async function process() {
console.log('시작');
await delay(2000);
console.log('2초 후 실행');
return '완료';
}
process().then(console.log);
모듈
export와 export default는 모듈에서 변수, 함수, 클래스 등을 내보낼 때 사용합니다. import로 가져올 때 export default는 중괄호 없이, export는 중괄호로 감싸서 가져옵니다.
// math.js
export const PI = 3.14;
export default function add(x, y) {
return x + y;
}
// app.js
import add, { PI } from './math.js';
라우팅
프론트엔드 라우팅은 URL에 따라 표시되는 DOM을 제어하는 방식입니다. 해시(Hash) 모드는 URL의 # 부분을, 히스토리(History) 모드는 History API를 사용하여 페이지 전환 없이 UI를 업데이트합니다.
BOM과 DOM
BOM (Browser Object Model)
screen: 전체 화면 정보 제공window: 브라우저 창 정보navigator: 브라우저 자체 정보 (버전 등)location: 현재 URL 정보
DOM (Document Object Model) 노드
HTML 문서는 노드 트리로 구성됩니다.
- 요소 노드: 태그 자체 (예:
<div>) - 속성 노드: 태그의 속성 (예:
class="myClass") - 텍스트 노드: 태그 내부의 텍스트
요소 노드의 속성에 접근할 때, . (점 표기법)은 런타임 값, .getAttribute()는 HTML에 명시된 초기 값을 반환합니다.
<input type="checkbox" checked="checked" id="myCheck" />
const checkbox = document.getElementById('myCheck');
console.log(checkbox.checked); // true (상태 변경 가능)
console.log(checkbox.getAttribute('checked')); // "checked" (고정)
노드 조작 주의사항
replaceChild와 같은 메서드는 새 노드를 기존 위치에서 제거한 후 교체를 수행합니다. 따라서 동일한 부모의 자식 노드를 교체할 때 의도치 않은 결과가 발생할 수 있습니다.
<div id="container">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
<script>
const container = document.getElementById('container');
const children = container.children;
// 의도: 첫 번째를 두 번째로 교체
// 실제: 첫 번째와 두 번째를 교체 (첫 번째는 유지되지 않음)
// container.replaceChild(children[1], children[0]); // 결과: 2, 3
</script>
이벤트
이벤트는 캡처링(Capturing)과 버블링(Bubbling) 단계로 전파됩니다. stopPropagation()은 이벤트 전파를 중단하고, preventDefault()는 기본 동작(예: 폼 제출, 링크 이동)을 막습니다.
document.getElementById('myForm').addEventListener('submit', function(event) {
event.preventDefault(); // 폼 제출 방지
// 직접 AJAX 요청 처리
});
jQuery
선택자와 DOM 조작
$() 함수는 jQuery 객체를 반환하며, 인덱스 [0]으로 네이티브 DOM 요소에 접근 가능합니다. this 키워드는 네이티브 DOM 요소를 가리킵니다.
$('.myButton').click(function() {
console.log(this); // 네이티브 DOM 요소
let $this = $(this);
console.log($this.val()); // jQuery 메서드 사용
});
.prop() vs .attr(): .prop()는 동적 속성 값(예: 체크박스 상태)을, .attr()는 HTML에 명시된 속성 값을 가져옵니다.
이벤트 객체
jQuery의 이벤트 객체는 네이티브 이벤트 객체를 래핑하며, 유사한 인터페이스를 제공합니다.
Node.js
NVM
NVM(Node Version Manager)은 Node.js 버전을 관리하는 도구입니다. 설치 후 다음 명령어로 사용 가능합니다.
nvm install 20 # 특정 버전 설치
nvm use 20 # 버전 전환
nvm alias default 20 # 기본 버전 설정
미러 서버 설정: 환경 변수 NVM_NODEJS_ORG_MIRROR를 설정하여 다운로드 속도를 개선할 수 있습니다.
NPM
NPM(Node Package Manager)은 패키지 관리 도구입니다. package.json은 프로젝트 메타데이터와 의존성을 정의하며, package-lock.json은 정확한 버전을 고정합니다. --save-dev는 개발 의존성에만 추가합니다.
TypeScript
인터페이스와 타입
TypeScript의 인터페이스는 컴파일 후 제거되므로, 런타임에는 영향을 주지 않습니다. 타입을 동적으로 구성할 수 있습니다.
export const StatusValues = ["success", "error", "warning"] as const;
export type StatusType = typeof StatusValues[number]; // "success" | "error" | "warning"
function handleStatus(status: StatusType) {
console.log(status);
}
let current = "success";
handleStatus(current as StatusType); // 타입 단언 필요
클래스
TypeScript의 클래스는 ES6 클래스에 타입 시스템을 추가한 형태입니다.
React
JSX/TSX
JSX는 JavaScript와 XML을 혼합한 문법입니다. TSX는 TypeScript를 적용한 버전입니다.
훅(Hooks)
훅은 함수 컴포넌트에 상태와 부수 효과(Side Effect)를 추가합니다.
useState
useState는 상태를 관리합니다. 조건문이나 반복문 내부에서 호출하면 안 됩니다. 이는 훅의 호출 순서가 항상 동일해야 하기 때문입니다.
useEffect
useEffect는 컴포넌트가 렌더링된 후 실행됩니다. React 18 개발 모드에서는 엄격 모드(Strict Mode)로 인해 두 번 실행될 수 있습니다. 이는 컴포넌트가 마운트-언마운트-재마운트되는 시나리오에서 부수 효과가 올바르게 동작하는지 확인하기 위함입니다.
useEffect(() => {
console.log('컴포넌트 마운트');
return () => {
console.log('클린업: 컴포넌트 언마운트 또는 의존성 변경');
};
}, []); // 빈 배열: 마운트 시에만 실행
부수 효과가 필요하지 않은 데이터 변환은 컴포넌트 본문에서 직접 처리하는 것이 좋습니다.
useRef
useRef는 DOM 요소나 변경 가능한 값을 저장합니다. TypeScript에서는 초기값에 따라 타입이 추론되며, null 가능성을 처리해야 합니다.
const myRef = useRef<HTMLDivElement>(null);
// myRef.current는 HTMLDivElement | null
Key 속성
key는 React가 요소를 식별하는 데 사용됩니다. key가 변경되면 해당 컴포넌트는 완전히 새로 생성됩니다. key는 이전 상태를 기억하지 않습니다.
이벤트
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
console.log(event.currentTarget);
};
Ant Design
Form의 labelCol과 wrapperCol은 레이블과 입력 필드의 레이아웃을 제어합니다. form.setFieldsValue()로 동적으로 값을 설정할 수 있습니다.
기타 라이브러리
Day.js: 가벼운 날짜 처리 라이브러리입니다.
Axios: HTTP 클라이언트로, TypeScript 제네릭을 지원하여 응답 타입을 지정할 수 있습니다. (axios.get<MyType>(url))
EventEmitter3: 이벤트 기반 통신을 위한 모듈입니다.