JavaScript
1. JavaScript는 어떤 언어일까?
- JavaScript는 웹 브라우저에서 동작하는 인터프리터 기반의 객체지향 스크립트 언어입니다. 웹 페이지에 동적인 기능과 상호작용을 추가하는 역할을 하며, 브라우저 뿐만 아니라 Node.js 환경에서도 서버 개발에 사용되는 범용 언어로 발전했습니다. 또한 JavaScript는 싱글 스레드 언어로, 한 번에 하나의 작업만 처리할 수 있는 구조를 가지고 있습니다. 하지만 이벤트 루프와 비동기 처리 메커니즘을 통해 동시에 여러 작업이 수행되는 것처럼 효율적으로 동작합니다.
2. 이벤트 버블링, 캡쳐링, 위임에 대해 설명해 주세요.
- 이벤트 버블링은 이벤트가 타깃 요소에서 시작해 상위 요소로 전파되는 단계입니다. 즉 자식에서 부모 방향으로 이벤트가 올라갑니다. 이벤트 캡쳐링은 이벤트가 가장 상위 요소에서 시작해 타깃 요소까지 내려가는 단계입니다. 즉, 부모에서 자식 방향으로 이벤트가 전파됩니다. addEvetListener의 세 번째 인자를 true로 설정하면 캡쳐링 단계에서 이벤트를 감지할 수 있습니다. 이벤트 위임은 버블링 특성을 이용해 여러 자식 요소에 각각 이벤트를 붙이지 않고 부모 요소 하나에 이벤트를 등록해서 하위 요소들의 이벤트를 한 번에 처리하는 기법입니다. 주로 동적으로 추가되는 요소나 리스트 항목 관리 등에 사용됩니다.
3. this에 대해 설명해주세요
- JavaScript에서 this는 함수를 호출한 주체를 참조하는 키워드입니다. 즉, 함수가 어디서 정의됐는지가 아니라 어떻게 호출됐는지에 따라 값이 달라집니다. 전역 컨텍스트에서 브라우저에서는 this가 window 객체를 Node.js에서는 global 객체를 가리킵니다. 일반 함수 호출시 기본적으로 this는 전역 객체(window)를 가리킵니다. 단 'use strict' 모드에서는 undefined가 됩니다. 메서드 호출 시 객체의 메서드 내부에서 this는 그 메서드를 호출한 객체 자신을 가리킵니다. 생성자 함수(new) 호출 시 this 는 새로 생성되는 인스턴스 객체를 가리킵니다. 화살표 함수는 자신만의 this를 가지지 않고 선언된 위치의 상위 스코프의 this를 그대로 참조합니다.(Lexical this)
4. var, let, const 를 중복 선언 허용, 스코프, 호이스팅 관점에서 서로 비교해 주세요.
- var는 중복 선언이 가능하며 함수 스코프를 가집니다. 블록 안에서 선언해도 함수 전체에서 접근할 수 있습니다. 호이스팅 시 선언만 끌어올려지고, 초기화는 나중에 이루어집니다. 즉, 선언 전에 접근하면 undefined가 출력됩니다. let은 중복 선언은 허용되지 않으며 블록 스코프를 가지기 때문에 블록 내부에서만 유효합니다. 호이스팅은 되지만, TDZ때문에 선언 전에 접근하면 ReferneceError가 발생합니다. const는 중복 선언 불가며 블록 스코프를 가집니다. 선언과 동시에 초기화가 반드시 필요합니다. 호이스팅은 let과 동일하게 일어나지만 TDZ로 인해 선언 전 접근이 불가능합니다.
5. 이벤트 루프란?
- JavaScript는 단일 스레드로 동작하기 때문에 한 번에 하나의 작업만 처리할 수 있습니다. 하지만 비동기 코드를 실행하기 위해 이벤트 루프가 사용됩니다. 이벤트 루프는 콜 스택과 태스크 큐를 감시하면서 스택이 비었을 때 큐에 콜백함수를 꺼내 실행시켜 비동기 작업을 순차적으로 처리합니다.
6. 비동기 처리란?
- 비동기 처리는 코드가 실행되는 동안 작업이 완료될 때까지 기다리지 않고, 다른 작업을 동시에 진행할 수 있도록 하는 방식입니다.
7. 콜백함수란?
- 콜백함수란 다른 함수의 인자로 전달되어 특정 시점에 실행되는 함수를 의미합니다. 하지만 콜백이 중첩되면 콜백 지옥이 생겨 코드 가독성과 에러 처리가 어려워집니다.
8. Promise란?
- Promise는 비동기 작업의 상태를 표현하는 객체롤, peding, fulfilled, rejected의 세 가지 상태를 가집니다. then, catch, finally를 사용해 콜백보다 더 깔끔하게 비동기 흐름을 관리할 수 있습니다.
9. async/await란?
- async/await는 Promise를 더 직관적으로 사용할 수 있게 하는 문법입니다. await 키워드를 사용하면 Promise가 처리 될때까지 기다렸다가 결과를 반환받을 수 있습니다. 코드가 동기식처럼 보이지만, 실제로는 비동기적으로 동작합니다.
10. JavaScript에서 비동기 처리를 하는 Event Loop의 동작 원리
- JavaScript는 단일 스레드 언어라서 한 번에 하나의 작업만 처리합니다. 그럼에도 비동기 작업을 처리할 수 있는 이유는 브라우저(Web API)와 이벤트 루프(Event Loop) 구조 덕분입니다.
자바스크립트 코드가 실행되면 함수들은 콜 스택(Call Stack)에 쌓여 순서대로 실행됩니다. 동기 코드는 즉시 실행되지만, setTimeout, fetch 같은 비동기 작업은 콜 스택에서 Web API 영역으로 넘겨져 별도로 처리됩니다.
비동기 작업이 완료되면 해당 콜백 또는 resolve 함수는 Task Queue 또는 Microtask Queue로 이동합니다.
이벤트 루프는 콜 스택이 비었는지 계속 확인하다가, 스택이 비면 큐에서 대기 중인 작업을 스택으로 옮겨 실행합니다.
11. 마이크로태스크 큐와 태스크 큐 차이
- JavaScript의 이벤트 루프는 비동기 코드를 처리할 때 작업을 두가지 큐로 분류해 관리합니다. 태스트 큐와 마이크로태스크 큐입니다. 태스크 큐는 setTimeout, setInterval, setImmediate, DOM 이벤트 등이 여기에 들어갑니다. 즉, 브라우저 API에 의해 예약된 일반적인 비동기 작업이 저장되는 공간입니다. 마이크로태스크 큐는 Promise.then, catch, finally, queueMicrotask, MutationObserver 등이 여기에 들어갑니다. 태스크 큐보다 우선적으로 실행되는 짧은 비동기 작업들을 처리합니다. 이벤트 루프는 태스트 큐를 하나 실행한 뒤, 그 즉시 마이크로태스트 큐에 쌓인 모든 작업을 먼저 비워냅니다 이후 다시 태스트 큐로 넘어가는 순서로 반복됩니다.
12. JavaScript의 이벤트 루프와 비동기 처리 방식에 대해 설명해주세요. 콜백, Promise, async/await 차이도 함께요.
- JavaScript는 단일 스레드 언어이기 때문에 동시에 여러 작업을 직접 처리할 수 없습니다. 하지만 이벤트 루프를 통해 비동기 작업을 효율적으로 처리합니다. 이벤트 루프는 콜 스택이 비었을 때 태스크 큐의 콜백 함수들을 하나씩 꺼내 실행하며 비동기 코드를 순차적으로 관리합니다. 비동기 처리를 구현하는 방식에는 3가지가 있습니다. 콜백은 함수가 끝난 뒤 실행될 함수를 인자로 전달하는 방식이지만, 중첩 구조로 인해 콜백 지옥이 생길 수 있습니다. 이를 개선하기 위해 Promise가 도입되었고 then() 체이닝을 통해 비동기 흐름을 구조적으로 관리할 수 있게 되었습니다. 마지막으로 async/await은 Promise를 더 직관적으로 사용할 수 있는 문법으로, 코드를 동기식처럼 읽히게 하면서도 비동기 동작을 유지할 수 있습니다.