GREEN나무 2025. 2. 11. 21:28
728x90

3. async/await 이란 무엇인지 설명해주세요.

답변:

async/await는 JavaScript에서 비동기 코드를 보다 읽기 쉽게 작성할 수 있도록 도와주는 문법입니다.
async 키워드를 함수 앞에 붙이면 해당 함수는 자동으로 Promise를 반환하는 비동기 함수가 됩니다.
await 키워드는 Promise가 처리될 때까지 기다렸다가 그 결과를 반환하도록 만듭니다.
이 방식은 기존의 then/catch 체인보다 코드 가독성을 높이고, 동기 코드처럼 작성할 수 있도록 도와줍니다.

예제 코드:

async function fetchData() {
  try {
    let response = await fetch('https://api.example.com/data');
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error fetching data:', error);
  }
}

위 코드는 fetch를 사용해 데이터를 가져오는 비동기 함수입니다.
await를 사용하면 fetch의 응답을 받을 때까지 기다린 후, 데이터를 JSON으로 변환하는 작업을 수행합니다.
에러가 발생하면 try-catch 문을 활용해 예외 처리를 할 수 있습니다.


 

추가질문 예시

1. async/await과 Promise.then() 방식의 차이점은 무엇인가요?

차이점 정리:

구분 async/await Promise.then()
코드 가독성 동기 코드처럼 자연스럽게 읽힘 then() 체인이 길어지면 가독성 저하
에러 처리 try-catch 블록 사용 가능 .catch()를 사용하여 에러 처리
실행 방식 await은 Promise의 결과를 기다렸다가 반환 then()은 콜백을 사용하여 다음 작업을 수행
병렬 실행 기본적으로 순차 실행 (await이 실행을 차단) .then() 체인은 병렬 실행 가능

예제 비교

✅ async/await 방식 (가독성 좋음)

async function fetchData() {
  try {
    let response = await fetch('https://api.example.com/data');
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}

 

Promise.then() 방식 ( .then() 체인 으로 병렬실행가능)

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

결론: async/await은 코드가 깔끔하고 이해하기 쉬운 반면, Promise.then()은 병렬 실행 시 유리할 수 있음.

 

 

2. async 함수 내부에서 await을 여러 번 사용할 때 성능 문제가 발생할 수 있는 이유는?

 

await은 다음 줄의 코드 실행을 일시 중단(blocking) 하기 때문에, 여러 개의 await을 순차적으로 실행하면 성능 저하가 발생할 수 있습니다.

비효율적인 코드 (순차 실행)

async function fetchData() {
  let user = await fetch('/api/user');   // 1번째 요청
  let posts = await fetch('/api/posts'); // 2번째 요청 (1번째 끝난 후 실행)
  let comments = await fetch('/api/comments'); // 3번째 요청 (2번째 끝난 후 실행)
}

위 코드는 각 요청이 끝날 때까지 기다리므로 실행 시간이 길어짐.

효율적인 코드 (Promise.all()을 사용한 병렬 실행)

async function fetchData() {
  let [user, posts, comments] = await Promise.all([
    fetch('/api/user'),
    fetch('/api/posts'),
    fetch('/api/comments')
  ]);
}

Promise.all()을 사용하면 세 요청이 동시에 실행되어 속도가 빨라짐.

결론: await을 반복적으로 사용하면 불필요한 순차 실행이 발생하여 성능이 저하될 수 있으므로, 동시 실행이 가능한 경우 Promise.all()을 활용하는 것이 좋음.

 

 

3. Promise.all()을 async/await과 함께 사용할 수 있나요? 어떻게 사용하나요?

네, Promise.all()을 async/await과 함께 사용하면 여러 개의 비동기 작업을 병렬로 실행할 수 있음.

사용 예시:

async function fetchMultipleData() {
  try {
    let [user, posts, comments] = await Promise.all([
      fetch('/api/user').then(res => res.json()),
      fetch('/api/posts').then(res => res.json()),
      fetch('/api/comments').then(res => res.json())
    ]);
    console.log(user, posts, comments);
  } catch (error) {
    console.error('Error fetching data:', error);
  }
}

Promise.all()의 장점:

  • 모든 요청을 동시에 실행하여 빠른 응답 가능
  • 단, 하나라도 실패하면 전체가 실패하므로 에러 핸들링이 중요

 

 

 


4. Hoisting이란 무엇인지 설명해주세요.

답변:

Hoisting(호이스팅)이란 JavaScript에서 변수 및 함수 선언이 코드 실행 전에 최상단으로 끌어올려지는 것처럼 동작하는 현상을 말합니다.

예제 코드:

console.log(name); // undefined
var name = "Alice";

위 코드가 실행되면 JavaScript는 다음과 같이 해석합니다.

var name;
console.log(name); // undefined
name = "Alice";

따라서 변수 name이 선언되었지만 초기화되지 않았기 때문에 undefined가 출력됩니다.

 

1. Hoisting(호이스팅)이란

Hoisting(호이스팅)은 컴파일 단계에서 함수와 변수 선언을 렉시컬 환경(Lexical Environment)에 등록하여 실행 컨텍스트가 생성될 때 미리 메모리에 할당되어 변수를 선언하기 전에 사용하더라도 JavaScript 엔진이 선언을 코드의 최상단으로 이동시킨 것처럼 처리합니다.

 

렉시컬 환경에서의 변수 등록 차이

  • var x → 렉시컬 환경에 x: undefined로 저장됨 (Hoisting 후 초기화됨)
  • let y, const z → 렉시컬 환경에는 등록되지만 초기화되지 않아 TDZ(Temporal Dead Zone)에 있음)

 

※ 렉시컬 환경

렉시컬 환경은 크게 두 가지 구성 요소로 이루어져 있어.

  1. 환경 레코드(Environment Record)
    • 현재 실행 중인 스코프(범위) 내에서 선언된 변수, 함수, 클래스 등의 식별자와 그 값을 저장하는 객체
  2. 외부 렉시컬 환경(Outer Lexical Environment Reference)
    • 현재 실행 컨텍스트(Execution Context)에서 외부 스코프를 참조할 수 있도록 연결하는 역할
    • 즉, 상위 스코프(부모 환경)로 접근하는 체인을 형성함 (스코프 체인, Scope Chain)

 

 

2. 변수 선언 방식에 따른 Hoisting 차이

선언 방식 Hoisting 발생 여부 값 할당 이전 접근 시 결과 TDZ(Temporal Dead Zone)
var O (호이스팅됨) undefined 출력 X (존재하지 않음)
let O (호이스팅됨) ReferenceError 발생 O
const O (호이스팅됨) ReferenceError 발생 O

📌 설명:

  • var은 Hoisting 후 undefined로 초기화되므로 접근 가능
  • let, const는 Hoisting되지만 초기화되지 않아 TDZ(일시적 사각지대)에 존재하며, 접근 시 ReferenceError 발생

예제 코드

console.log(a); // undefined
var a = 10;

console.log(b); // ReferenceError (TDZ에 있음)
let b = 20;

 

 

3. 함수와 클래스의 Hoisting 차이

선언 방식 Hoisting 발생 여부 선언 전 호출 가능 여부
함수 선언식 (function foo() {}) O O (선언 전에 호출 가능)
함수 표현식 (const foo = function() {}) X X (선언 전에 호출 불가능)
클래스 선언식 (class Foo {}) O X (TDZ로 인해 호출 불가능)
클래스 표현식 (const Foo = class {}) X X (선언 전에 호출 불가능)

📌 설명:

  • 함수 선언식(function)은 Hoisting되어 선언 전에 호출 가능
  • 함수 표현식(const foo = function() {})과 클래스 선언(class Foo {})은 TDZ의 영향을 받아 선언 전에 호출 불가

예제 코드

sayHello(); // "Hello, world!" (정상 실행)

function sayHello() {
  console.log("Hello, world!");
}

// 함수 표현식 (ReferenceError 발생)
greet(); // ReferenceError
const greet = function() {
  console.log("Hi!");
};

// 클래스 선언 (ReferenceError 발생)
console.log(person); // ReferenceError
class Person {}

 

4. Temporal Dead Zone(TDZ)란?

TDZ(일시적 사각지대, Temporal Dead Zone)는 let과 const로 선언된 변수가 초기화되기 전까지 접근할 수 없는 상태를 의미한다.

예제 코드

console.log(age); // ReferenceError (TDZ에 있음)
let age = 25;

📌 TDZ 특징:

  • let, const에서만 발생 (var에서는 발생하지 않음)
  • 변수가 선언되었지만 초기화되지 않으면 TDZ 상태에 있음
  • TDZ에서는 변수에 접근할 경우 ReferenceError 발생

 

5. var을 지양하는 이유

var을 사용하면 Hoisting 시 undefined로 초기화되므로, 의도치 않은 버그 발생 가능성이 높음
따라서 의도적인 Hoisting 사용이 아니라면 let, const, 함수 표현식을 사용하는 것이 권장됨.

문제 발생 예시 (var의 의도치 않은 Hoisting)

console.log(score); // undefined
var score = 100;

위 코드에서는 score가 선언되기 전에 접근해도 undefined가 출력됨.
반면 let이나 const를 사용하면 TDZ로 인해 ReferenceError가 발생하여 코드 오류를 바로 확인할 수 있다.

 

📌 최종 정리

  1. Hoisting은 변수 및 함수 선언을 코드의 최상단으로 끌어 올리는 과정
  2. var은 undefined로 초기화되지만, let과 const는 TDZ로 인해 ReferenceError 발생
  3. 함수 선언식은 Hoisting되어 선언 전에 호출 가능하지만, 함수 표현식과 클래스 선언은 불가능
  4. 의도하지 않은 버그를 방지하기 위해 var 사용을 지양하고 let, const를 사용하는 것이 좋음

 

추가질문 예시

1. var, let, const의 Hoisting 방식은 각각 어떻게 다른가요?

선언 방식  Hoisting 여부 초기화 여부 TDZ (Temporal Dead Zone)
var O (호이스팅됨) undefined로 초기화됨 X (존재하지 않음)
let O (호이스팅됨) 초기화되지 않음 (사용 시 ReferenceError) O
const O (호이스팅됨) 초기화되지 않음 (사용 시 ReferenceError) O

예제 코드:

console.log(a); // undefined
var a = 10;

console.log(b); // ReferenceError
let b = 20;

console.log(c); // ReferenceError
const c = 30;

정리:

  • var은 undefined로 초기화되기 때문에 사용 가능.
  • let과 const는 일시적 사각지대(TDZ)에 의해 선언 전에 접근 불가.

 

 

2. 함수 선언식(Function Declaration)과 함수 표현식(Function Expression)에서 Hoisting 차이는?

 

여부 선언 전 호출 가능 여부

구분 Hoisting 여부 선언 전 호출 가능 여부
함수 선언식 (function foo() {}) O O (선언 전에 호출 가능)
함수 표현식 (const foo = function() {}) X X (선언 전에 호출 불가능)

예제:

sayHello(); // "Hello!"
function sayHello() {
  console.log("Hello!");
}

greet(); // ReferenceError
const greet = function() {
  console.log("Hi!");
};

정리:

  • function 선언식은 Hoisting이 적용되므로 선언 전에도 호출 가능
  • const, let로 선언한 함수 표현식은 Hoisting되지 않음

 

3. TDZ(Temporal Dead Zone)이란 무엇인가요?

TDZ(일시적 사각지대, Temporal Dead Zone)란 let과 const로 선언된 변수가 초기화되기 전까지 접근할 수 없는 영역을 의미함.

예제 코드:

console.log(x); // ReferenceError (TDZ 영역)
let x = 10;

위 코드는 실행 시 에러가 발생함.
이는 let x가 Hoisting되었지만 초기화되지 않았기 때문임.

TDZ 특징:

  • let과 const에서만 발생
  • 변수가 선언되었지만 초기화되기 전까지는 접근 불가
  • var에는 적용되지 않음 (undefined로 초기화됨)