프론트엔드 면접 질문 리스트 - JS

Javascript 인터뷰 질문 리스트 1

면접!

프론트엔드 면접 준비를 위한 질문 리스트 정리

Javascript

아래질문 리스트를 기반으로 면접 질문 & 답변 목록을 작성할 예정이고, 지속적으로 보충 or 보수할 계획입니다.

업데이트 날짜

  • 2020-10-26
  • 2021-07-02
    • Javascript 질문 목록 수정
  • 2021-07-23
  • 2021-07-24
  • 2021-07-25
    • Javascript 질문 추가 및 수정
    • 답변 추가 및 수정

질문 목록

  • 질문 목록

    1. 자바스크립트의 원시 타입(Primitive Data Type)은 몇가지이며, 전부 말해달라

      • Number, String, Boolean, Null, Undefined, Symbol
      • Null vs Undefined
    2. Pass by Value & Pass by Reference

    3. function foo() {}var foo = function() {} 에서 foo 의 차이가 무엇인지 설명해보세요.

      • 함수 선언식과 함수 표현식의 차이
    4. 이벤트 루프와 동시성 모델에 대해서 설명해달라

    5. 실행 컨텍스트(Execution Context)에 대해 설명해달라

    6. Javascript Scope Chaining이란 무엇인가

    7. scope란 무엇이며 var, let, const에 대해 설명해달라

    8. 전역 scope를 사용했을 때 장단점에 관해 설명해달라

    9. 자바스크립트의 호이스팅(Hoisting)은 어떻게 이루어져 있는가

    10. 클로저(Closure)란 무엇이며, 어떻게 사용하는지, 왜 이러한 패턴을 사용하는가

    11. This

      • 자바스크립트에서 This는 몇가지로 추론 될수 있는가, 아는대로 말해달라
      • 일반함수의 this와 화살표 함수의 this는 어떻게 다른가?
      • use strict모드에서의 this?
    12. Call, Apply, Bind 함수에 대해 설명해달라

    13. 객체 지향 프로그래밍(Object Oriented Programming)과 프로토타입이란 무엇인가

      • OOP에 특징에 대해 설명해달라(상속, 캡슐화 등등…)
        • 현실에 상황을 예로 들어 OOP의 개념으로 설계과정을 설명해달라
        • ex) 축구를 게임으로 만든다거나, 기타 어떠한 상황이라도 좋다
      • 프로토타입 상속이 이루어지는 법
    14. OOP와 함수형 프로그래밍의 차이

      • 함수형 프로그래밍에 대해 설명해달라

      • 함수형 프로그래밍에 개념에서 순수함수란 무엇인가

      • OOP와 함수형 프로그래밍의 가장 큰 차이점은 무엇인가

    15. 즉시 실행 함수(IIFE)란 무엇이며 언제 사용하는 것인가

    16. 비동기 프로그래밍

      • 동기 함수와 비동기 함수란 무엇인가
        • Callback, Promise 란 무엇이며 각각의 장단점에 대해 설명해달라
      • Promise 코드가 어떻게 구성되어있는가
      • Async, Await는 무엇이며 Promise의 차이는

1. 자바스크립트의 원시 타입(Primitive Data Type)은 몇가지이며, 전부 말해달라

프로그래밍 언어에서 자료형(types) 또는 데이터 타입(data type) 이란 숫자형(정수형, 실수형), 논리값(Boolean), 문자(String) 등의 데이터를 식별하는 분류 (indentifier) 로써, Javascript에서는 다음과 같이 Boolean, Null, Undefined, Number, String, Object 데이터 유형이 있으며 Symbol은 ECMAScript 6에 신규 추가되었습니다. 이 데이터 유형은 원시형(Primitives)과 참조형(Reference)으로 구분할 수 있으며 원시형 데이터 타입 (Primitives) 으로는

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol

이 있습니다.

원시형(Primitives) 데이터 타입의 특징은 아래와 같습니다.

  • 단 하나의 값만 가질 수 있음
  • 변수에 할당될 때 스택 메모리 상에 고정된 크기로 저장
  • 모든 원시 값은 불변 (immutable)의 성질로 변형 불가
    • 즉, 원시값을 교체할 수는 있지만, 직접 변형할 수는 없음
      • 객체가 아니면서 메서드도 가지지 않는 데이터
      • Null의 경우, 겉보기엔 원시 값처럼 보이는 있지만, 사실 Object 이며, 모든 구조화된 자료형은 prototype chain 에 따라 Null의 자손이다.
      • 대부분의 경우, 원시 값은 언어 구현체의 가장 저수준(low level) 에서 나타남.
      • 원시 값 자체와, 원시값을 할당한 변수를 혼동하지 않는 것이 중요!
    • 변수: 새로운 값을 다시 할당 가능
    • 원시값: 객체, 배열, 함수와 달리 변형 불가능
      • 값에 의한 전달 (pass-by-value) 방식으로 전달
      • Number, String, Boolean, Null, Undefined, (Symbol)

부록 - Reference Type (참조형)

  • 객체는 데이터와 그 데이터에 관련한 동작(절차, 방법, 기능)을 모두 포함할 수 있는 개념적 존재
    • 즉, PropertyMethod를 포함할 수 있는 독립적 주체이자 복합적 구조의 데이터
  • 데이터가 동적 바인딩 되므로 실행중에도 그 값이 변동될 수 있으며, 선언될때 크기가 정해져 있지 않음
  • JavaScript는 객체 기반의 스크립트 언어로써 JavaScript를 이루고 있는 거의 모든 것이 객체이다.
    • 원시 타입을 제외한 나머지 값들(배열, 함수, 정규표현식 등)은 모두 객체이다.
  • 참조 타입은 변수의 값이 저장된 메모리 블럭의 주소를 가지고 있고 자바스크립트 엔진이 변수가 가지고 있는 메모리 주소를 이용해서 변수의 값에 접근한다.
    • 변수에 할당이 될 때 값이 직접 해당 변수에 저장될 수 없으며 변수에는 데이터에 대한 참조만 저장
    • 변수의 값이 저장된 힙 메모리의 주소값을 저장
  • 객체함수 는 언어의 다른 기본 요소임.
    • 객체 => 값을 위한 컨테이너
    • 함수 => 어플리케이션이 수행할 수 있는 절차 (procedure)

Null vs Undefined

Undefined는 변수를 선언하고 값을 할당하지 않은 상태, Null은 변수를 선언하고 빈 값을 할당한 상태(빈 객체)이다. 즉, Undefined는 자료형이 없는 상태이다.
따라서 typeof 를 통해 자료형을 확인해보면 nullobject로, undefinedundefined가 출력되는 것을 확인할 수 있다.

1
2
3
4
5
6
7
8
9
typeof null // 'object'
typeof undefined // 'undefined'
null === undefined // false
null == undefined // true
null === null // true
null == null // true
!null // true
isNaN(1 + null) // false
isNaN(1 + undefined) // true
  • Null
    • null원시값(Primitive Type) 중 하나 로, 어떤 값이 의도적으로 비어있음을 표현 한다.
    • undefined는 값이 지정되지 않은 경우를 의미하지만, null의 경우에는 해당 변수가 어떤 객체도 가리키고 있지 않다는 것을 의미한다.
    • nullundefined 처럼 전역 객체의 속성 중 하나가 아니라 리터럴 값 이다.
  • Undefined
    • undefined원시값(Primitive Type) 으로, 선언한 후에 값을 할당하지 않은 변수나 값이 주어지지 않은 인수에 자동으로 할당된다. 이 값은 전역 객체의 속성 중 하나 로, 전역 스코프에서의 변수이기도 하다.
    • 따라서 undefined 변수의 초기 값은 undefined 원시 값이다.
    • 아래의 경우에 변수가 undefined를 반환한다.
      • 값을 할당하지 않은 변수
      • 메서드와 선언에서 변수가 할당받지 않은 경우
      • 함수가 값을 return 하지 않았을 때

2. Pass by Value & Pass by Reference

Pass by Value, Pass by Reference 는 인수(Arguements)를 함수에 전달할때 데이터 유형에 따라 어떻게 넘겨줄지 결정하는 것으로, Call by ~ 는 함수의 입장에서, Pass by ~ 는 인수의 입장에서 설명되는 차이가 있다.

Pass by Value (값의 복사에 의한 전달)

Pass by Value는 인자로 넘기는 값을 그대로 복사해서 함수에 전달하는 방식입니다. 주로 Javascript 데이터 유형 중 원시값의 데이터 유형이 Pass by Value가 일어납니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function callByValue(varOne, varTwo) { 
console.log("Inside Call by Value Method");
varOne = 100;
varTwo = 200;
console.log("varOne =" + varOne +"varTwo =" +varTwo);
}

let varOne = 10;
let varTwo = 20;

console.log("Before Call by Value Method");
console.log("varOne =" + varOne +"varTwo =" +varTwo);

callByValue(varOne, varTwo)
console.log("After Call by Value Method");
console.log("varOne =" + varOne +"varTwo =" +varTwo);

output will be :
---------------
Before Call by Value Method
varOne = 10 varTwo = 20
Inside Call by Value Method
varOne = 100 varTwo = 200
After Call by Value Method
varOne = 10 varTwo = 20

Pass by Reference (참조에 의한 전달)

Pass by Reference는 인자로 넘기는 값의 메모리상의 주소 를 복사해 함수에 전달하는 방식입니다. 주로 Javascript 데이터 유형 중 객체 유형의 데이터가 Pass by Reference가 일어납니다. 만약 우리가 메서드에 인자로써 객체 또는 배열을 전달한다면 객체의 값을 변경할 수 있는 가능성이 생깁니다.

3. function foo() {}var foo = function() {} 에서 foo 의 차이가 무엇인지 설명해보세요.

함수 선언식(Function Declarations)과 함수 표현식(Function Expressions)의 차이

함수 선언식(Function Declarations)

일반적 함수 선언과 비슷한 형태

1
2
3
4
5
6
// 예시
function funcDeclarations() {
return 'A function declaration';
}

funcDeclarations(); // 'A function declaration'

함수 표현식(Function Expressions)

유연한 자바스크립트 언어의 특징을 활용한 선언 방식

1
2
3
4
5
// 예시
var funcExpression = function () {
return 'A function expression';
}
funcExpression(); // 'A function expression'

함수 선언식(Function Declarations)과 함수 표현식(Function Expressions)의 차이

  • 함수 선언식은 호이스팅에 영향을 받지만, 함수 표현식은 호이스팅에 영향을 받지 않는다.

함수 선언식은 코드를 구현한 위치와 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어 올려진다.

예를 들어, 아래의 코드를 실행할 때

1
2
3
4
5
6
7
8
9
10
11
// 실행 전
funcDeclarations();
funcExpression();

function funcDeclarations() {
return 'worked';
}

var funcExpression = function () {
return 10 + 20;
};

Javascript 해석기에 의해 분석된 코드는 호이스팅이 적용되 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// 실행 시
function funcDeclarations() {
return 'It/'s func Declarations';
}

var funcExpression;

funcDeclarations(); // 'It/'s func Declarations'
funcExpression(); // Uncaught TypeError: funcExpression is not a function

funcExpression = function () {
return 'It/'s func Expression';
};

funcExpression 에 할당될 function 로직은 호출된 이후에 선언되므로, funcExpression 는 함수로 인식하지 않고 변수로 인식한다. 즉, 선언은 위에서 됐지만 할당이 아래에서 이루어집니다.

함수 표현식(Function Expressions)의 장점

  • 함수 표현식이 호이스팅에 영향을 받지 않는다
  • Closure 로 사용 (With Scope)
  • Callback 으로 사용 (다른 함수의 인자로 넘길 수 있음)
함수 표현식을 사용한 Closure 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
function tabsHandler(index) {
return function tabClickEvent(event) {
// 바깥 함수인 tabsHandler() 의 index 인자를 여기서 접근할 수 있다.
console.log(index); // 탭을 클릭할 때 마다 해당 탭의 index 값을 표시
};
}

var tabs = document.querySelectorAll('.tab');
var i;

for (i = 0; i < tabs.length; i += 1) {
tabs[i].onclick = tabsHandler(i);
}

위 코드는 .tab class를 가진 DOM 요소에 tabsHandler 함수를 onClick 이벤트로 바인드하는 예제로 각 탭을 클릭했을때 tabsHandler의 인자로 전달된 i 를 반환하도록 설계되어 있다.
여기서 주목할 점은 탭을 클릭했을때 tabsHandler의 내부 tabClickEvent에서 console.log(index) 하기 위해 클로저 속성을 이용해 tabsHandler 함수가 가지고 있는 index 변수에 접근하며 각 탭을 클릭할때마다 서로 다른 클로저로써 서로 다른 변수 i를 참조 및 할당하고 있습니다.

그러나 만약 아래와 같이 각 탭을 클릭했을때 console.log(i) 하는 코드를 실행한다면 스코프틑 for loop문의 스코프에 존재하는 변수 i를 참조할 것이며 이에 따라 loop 문의 최종 i 값인 3을 반환할 것입니다.

1
2
3
4
5
6
7
8
var tabs = document.querySelectorAll('.tab');
var i;

for (i = 0; i < tabs.length; i += 1) {
tabs[i].onclick = function (event) {
console.log(i); // 어느 탭을 클릭해도 항상 tabs.length (i 의 최종 값) 이 출력
};
}
함수 표현식을 사용한 Callback 사용

일반적으로 함수 표현식은 특정 변수에 할당해 사용하지만 그렇지 않은 경우 아래와 같이 콜배감함수로 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
var arr = ["a", "b", "c"];
arr.forEach(function (ele) {
console.log(ele)
});

var digits = [1, 2, 3];
var sum = arr.reduce(function (sum, ele) {
sum += ele
return sum
}, 0);

4. 이벤트 루프와 동시성 모델에 대해서 설명해달라

이벤트 루프는 Javascript의 동시성(Concurrency)을 지원하기 위한 개념 으로, 웹 브라우저에서는 애니메이션 효과를 보여주면서 마우스 이벤트를 입력 받아서 처리하고, Node.js기반의 웹서버에서는 동시에 여러 개의 HTTP 요청을 처리하기도 하는데 이는 Javascript가 이벤트 루프를 이용해서 비동기 함수 로직에 대한 동시성을 지원하기 때문이다.

이벤트 루프를 설명하기 위해서는 Javascript Engine이나 런타임 환경을 먼저 설명해야 합니다. Javascript의 대표적인 엔진으로 V8을 예로 들면, V8 엔진의 Memory Heap과 Call Stack으로 구성되어 있으며

브라우저의 Javascript 구동 환경

Memory Heap은 메모리 할당이 일어나는 곳으로 구조화 되지 않은 넓은 개념의 메모리 영역을 지칭하고, Call Stack은 코드 실행 순서에 따라 호출 스택이 쌓이는 곳으로 하나의 작업을 완료하기 위해 제공되는 환경입니다. 그리고 Web APIs는 DOM Event, AJAX, Timer Event와 같은 사용자 인터렉션 또는 비동기 처리를 담당하며 Task Queue는 비동기 함수들이 완료된 후 실행될 콜백들이 대기하는 부분으로 FIFO의 큐 형태의 배열입니다.

이러한 구조적 메커니즘에서 Event Loop의 역할을 설명하면 만약 Timer 또는 AJAX 비동기 로직이 실행됐을 경우, 비동기 함수가 실행되고 콜백함수가 Task Queue로 이동 및 대기하는데, 비동기 함수의 작업이 완료된 후 Call Stack이 비었을 경우, Event Loop가 이를 감지해 Task Queue에서 비동기 로직 이후 실행될 콜백함수를 불러와 Call Stack에 삽입하는 역할을 합니다.

즉, Event Loop는 Javascript Engine, Web APIs 그리고 Task Queue를 지속적으로 관찰하며 동시성(Concurrency)을 지원하는 핵심개념입니다.

이런 식으로 이벤트 루프‘현재 실행중인 태스크가 없는지’와 ‘태스크 큐에 태스크가 남아있는지’ 를 반복적으로 확인합니다. 정리하면,

  • Event Loop: (함수)호출 스택이 비워질 때마다 큐에서 콜백 함수를 꺼내와서 실행하는 역할을 함
    • ‘현재 실행중인 태스크가 없을 때’(주로 호출 스택이 비워졌을 때) 태스크 큐의 첫 번째 태스크를 꺼내와 실행한다.
    • 언제나 그렇듯이, 함수를 호출하면 그 함수의 사용을 위한 새로운 스택 프레임이 생성된다.

자세한 내용은 아래 링크 참조

5. 실행 컨텍스트(Execution Context)에 대해 설명해달라

실행 컨텍스트“실행 가능한 코드를 형상화 하고 구분하는 추상적인 개념으로 코드가 실행되고 있는 구역 또는 범위” 로 정의할 수 있습니다. Javascript 엔진은 코드를 실행하기 위해서는 변수, 인자 객체, 스코프 그리고 This에 대한 정보를 알고 있어야 하는데 이와 같은 정보는 실행 컨텍스트에 따라 달라지며 실행 컨텍스트 또한 실행 구역 또는 범위에 따라 전역 실행 컨텍스트함수 실행 컨텍스트로 구분됩니다. 전역 실행 컨텍스트전역 환경에서 실행되고 있는 코드의 환경 이고, 함수 실행 컨텍스트전역 컨텍스트에서 호출 및 실행된 함수의 영역에서 실행되고 있거나 함수가 실행될때마다 생성되는 코드의 환경 입니다.

모든 실행 컨텍스트는 공통된 구조로 Lexical Environment (렉시컬 환경)과 Variable Environment (변수 환경)를 갖으며 이 둘은 변수의 참조를 기록하는 환경 이라고 할 수 있습니다.

1
2
3
4
ExecutionContext = {
LexicalEnvironment = <ref. to LexicalEnvironment in memory>,
VariableEnvironment = <ref. to VariableEnvironment in memory>
}

Lexical Environment 는 Javascript 코드에서 변수 또는 함수 식별자를 맵핑하기 위해 사용되는 객체로, 식별자란 참조 대상에 대한 식별자로써 변수나 함수의 이름을 참조하며 변수는 함수 객체, 배열 객체를 포함한 실제 객체 또는 원시값에 대한 참조 입니다. Lexical Environment의 내부는 Outer Environment ReferenceEnvironment Record 로 구성되어 있습니다. Outer Environment Reference 는 식별자 검색을 위해 외부 Lexical Environment를 참조하는 포인터로 중첩된 Javascript 코드에서 스코프 탐색을 위해 사용됩니다. Environment Record 는 현재 유효범위 내의 값에 식별자들의 바인딩을 기록하는 객체로 모든 지역변수를 프로퍼티로 저장하며 this 와 같은 기타 정보도 여기에 저장됩니다.

1
2
3
4
5
6
7
8
9
10
11
Lexical Environment = {
Outer Environment Reference,
Environment Record: {
Object Environment Record,
Declarative Environment Record: {
Function Environment Record,
Module Environment Record
},
This Binding
}
}

Variable Environment 은 Lexical Environment와 같이 function, 변수 식별자가 바인딩된다는 점이 동일하지만 만들어진 변수 선언 및 함수 선언에 대한 바인딩을 유지합니다. 또한, Lexical Environment는 코드 실행중에 실행 컨텍스트 내에서 변경될 수 있지만 Variable Environment는 항상 그 값을 초기화 및 선언 상태로 유지하며 일시적으로 Lexical Environment 하위에 새로운 환경을 가리키며 임시 바인딩을 보유합니다.

1
2
3
4
5
6
7
8
EnvironmentRecord: {
Outer Environment Reference,
Environment Record: {
Object Environment Record,
Declarative Environment Record,
This Binding
}
}

Lexical EnvironmentVariable Environment 의 또다른 차이점으로는 Lexical Environmentletconst 키워드에 의한 함수 및 변수 선언의 바인딩을 저장하고, Variable Environmentvar 키워드로 선언된 바인딩을 저장합니다.

자세한 내용은, 아래 링크 참조.

6. Javascript Scope Chaining이란 무엇인가

Javascript의 스코프 체인이란 현재 렉시컬 스코프에서 선언된 변수 또는 함수의 식별자를 검색할때, 식별자가 없는 경우 상위 렉시컬 스코프로 식별자를 연쇄적으로 찾아가는 식별자 조회 방식을 말합니다. 상위 렉시컬 스코프를 참조하기 위해 Javascript에서는 실행 컨텍스트에서 Lexical Environment 를 활용하는데 실행 컨텍스트“실행 가능한 코드를 형상화 하고 구분하는 추상적인 개념으로 코드가 실행되고 있는 구역 또는 범위” 로써, 실행 컨텍스트는 새로운 실행문이 생성될때 마다 공통된 구조로 Lexical Environment (렉시컬 환경)과 Variable Environment (변수 환경)를 생성합니다.

1
2
3
4
ExecutionContext = {
LexicalEnvironment = <ref. to LexicalEnvironment in memory>,
VariableEnvironment = <ref. to VariableEnvironment in memory>
}

여기서 Lexical Environment 란 Javascript 코드에서 변수 또는 함수 식별자를 맴핑하기 위해 사용되는 객체로 식별자란 참조 대상에 대한 식별자로써 변수나 함수의 이름을 참조하며 원시값과 함수 객체, 배열 객체를 포함한 실제 객체에 대한 참조로써, 내부에는 Outer Environment ReferenceEnvironment Record 가 있습니다. 바로 이 Outer Environment Reference 가 식별자 검색을 위해 외부 Lexical Environment를 참조하는 포인터로써 중첩된 Javascript 코드에서 스코프 탐색을 위해 사용됩니다.

1
2
3
4
Lexical Environment = {
**Outer Environment Reference**,
Environment Record
}

7. scope란 무엇이며 var, let, const에 대해 설명해달라

Scope란 Javascript에서 ‘변수에 접근할 수 있는 범위’ 로, 자바스크립트 엔진이 참조의 대상이 되는 식별자 (Identifier)를 검색할때 사용하는 규칙의 집합입니다. 선언되는 환경에 따라 전역 스코프지역 스코프로 구분할 수 있으며 전역 스코프는 말 그래도 전역환경에 선언되어 어느 곳에서든지 해당 변수에 접근할 수 있는 범위이고, 지역 스코프 는 해당 범위에서만 접근할 수 있으며 범위를 벗어난 곳에서는 접근할 수 없다는 의미입니다.

지역 스코프의 경우 함수 스코프가 있으며 ES6(ES2015) 에서 letconst 키워드가 추가되면서 블록 스코프가 추가됐습니다. Javascript는 대부분의 프로그래밍 언어가 블록 레벨 스코프(Block-level Scope)를 따르는 것과 다르게 함수 레벨 스코프(Function-level Scope) 를 따르는데

  • 함수 레벨 스코프(Function-level Scope)
    함수를 선언할 때마다 새로운 스코프를 생성하며 함수 내에서 선언된 변수는 함수 내에서만 유효하고 함수 외부에서는 참조할 수 없음을 의미합니다. 즉, 함수 내부에서 선언한 변수는 지역 변수라는 뜻입니다.
  • 블록 레벨 스코프(Block-level Scope)
    모든 코드 블록(함수, if 문, while 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없습니다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수라는 뜻입니다.

함수 레벨 스코프와 블록 레벨 스코프의 차이는 변수를 선언하는 var, let, const 키워드의 호이스팅 방식에 있는데, var 키워드의 경우, 선언 단계와 초기화 단계가 한번에 이루어지기 때문에 해당 함수 스코프의 영역에서 선언되기 전에 접근할 수 있지만 undefined 를 반환하고, let 이나 const 키워드의 경우, 호이스팅의 선언 단계와 초기화 단계가 분리되어 진행되며 해당 선언문에 도달했을때 이루어지기 때문에 TDZ(일시적 사각지대) 로 인해 해당 스코프의 최상위로 끌어올려지지(hoisting) 않아 해당 블록 스코프에서만 접근할 수 있습니다.

또한, Javascript의 실행 컨텍스트를 언급할때 등장하는 스코프로 렉시컬 스코프 가 있는데, 렉시컬 스코프함수를 어디에 선언했는지에 따라서 상위 스코프가 결정된다는 뜻 으로 함수의 Outer Lexical Scope 가 함수의 호출이 아니라 함수의 선언에 따라 결정된다는 것입니다.

예를 들자면, 전역변수 var x = 1 이 있고, 전역 함수 function first() , function second() 가 있습니다. first 함수 내부에서는 var x = 10 전역변수 x의 값을 재할당하며 second() 함수가 호출되면 console.log(x) 가 실행되며 호출은 first 함수 에서 호출된다고 할때 second() 함수에서 실행될 console.log(x)x 는 선언 당시의 전역변수 x 의 값인 1 입니다. 왜냐하면 second 함수에서 렉시컬 스코프에 따라서 함수를 선언한 시점의 상위 스코프인 전역 환경을 참조하기 때문입니다.

var, let, and const 차이점

JavaScript는 변수를 선언하기 위해 언어의 복잡성을 더하는 세개의 다른 키워드가 있습니다. 3개의 키워드 차이점은 스코프(scope), 호이스팅(hoisting) 그리고 재할당(reassignment)에 바탕을 두고 있습니다.

Keyword Scope Hoisting Can Be Reassigned Can Be Redeclared
var Function scope Yes Yes Yes
let Block scope No Yes No
const Block scope No No No

8. 전역 scope를 사용했을 때 장단점에 관해 설명해달라

전역 scope를 사용했을시의 장점 으로는 어플리케이션 수준에서 장점이 있을수 있는데,

절대 불변의 고정값을 가진 변수를 전역 환경에서 const 로 선언했을 경우, 모듈 또는 함수에서 일일이 선언해주지 않아도 Javascript 엔진이 Scope Chain에 따라서 변수값을 자동으로 참조할 수 있습니다.

기본값을 가지는 변수를 전역 환경에서 const 로 또는 let 으로 선언했을 경우, 기본값을 참조하는 함수의 경우 전역환경에서 자동으로 참조할 것이며 이를 만약 수정해줄경우 전역변수의 값만 수정하면 자동으로 다른 함수에서도 변수의 값을 참조하기 위해 전역변수의 값을 추적해 참고할 것입니다.

단점 으로는 전역 변수를 선언할 경우 다른 개발자와의 협업에서 우연히 같은 변수 이름을 사용해서 이전의 변수를 덮어쓴다는 불상사가 발생할 수 있으며 변수 값에 대한 불필요한 메모리를 소모할 가능성이 크다는 것입니다.

9. 자바스크립트의 호이스팅(Hoisting)은 어떻게 이루어져 있는가

호이스팅이란 인터프리터가 자바스크립트 코드를 해석함에 있어서, 전역(Global) 스코프 또는 함수 스코프 안에서 var 로 선언한 변수나 함수 선언식 등을 해당 스코프의 최상위로 옮기는 동작을 말합니다. 호이스팅은 3단계에 걸쳐 생성되는데,

  • 선언 단계(Declaration phase)
    변수를 실행 컨텍스트의 변수 객체(Variable Object)에 등록한다. 이 변수 객체는 스코프가 참조하는 대상이 된다.
  • 초기화 단계(Initialization phase)
    변수 객체(Variable Object)에 등록된 변수를 위한 메모리 공간을 확보한다. 이 단계에서 변수는 undefined로 초기화된다.
  • 할당 단계(Assignment phase)
    undefined로 초기화된 변수에 실제 값을 할당한다.

var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다.

  1. (선언 및 초기화 단계) 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화(초기화 단계)한다.
  2. 따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다.
  3. (할당 단계) 이후 변수 할당문에 도달하면 비로소 값이 할당된다.

이러한 현상을 변수 호이스팅(Variable Hoisting) 이라 한다.

1
2
3
4
5
6
7
8
9
// 스코프의 선두에서 선언 단계와 초기화 단계가 실행된다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 있다.
console.log(foo); // undefined

var foo;
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다. 즉, 스코프에 변수를 등록(선언단계)하지만 초기화 단계는 변수 선언문에 도달했을 때 이루어진다.

  1. 초기화 이전에 변수에 접근하려고 하면 참조 에러(ReferenceError)가 발생한다. 즉, 변수를 위한 메모리 공간이 아직 확보되지 않았기 때문이다. 따라서 스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다.
  2. 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 ‘일시적 사각지대(Temporal Dead Zone; TDZ)’ 라고 부른다.
1
2
3
4
5
6
let foo = 1; // 전역 변수

{
console.log(foo); // Uncaught ReferenceError: Cannot access 'foo' before initialization
let foo = 2; // 지역 변수
}

위 예제의 경우, 전역 변수 foo의 값이 출력될 것처럼 보이지만 ES6의 선언문도 여전히 호이스팅이 발생하기 때문에 참조 에러(ReferenceError) 가 발생한다.

ES6의 let으로 선언된 변수는 블록 레벨 스코프를 가지므로 코드 블록 내에서 선언된 변수 foo는 지역 변수이다. 따라서 지역 변수 foo도 해당 스코프에서 호이스팅되고 코드 블록의 선두부터 초기화가 이루어지는 지점까지 일시적 사각지대(TDZ)에 빠진다. 따라서 전역 변수 foo의 값이 출력되지 않고 참조 에러(ReferenceError) 가 발생한다.

10. 클로저(Closure)란 무엇이며, 어떻게 사용하는지, 왜 이러한 패턴을 사용하는가

클로저(Closure) 는 주변 상태에 대한 참조와 함께 번들로 묶인 또는 포함된 함수와 변수의 조합인 렉시컬 환경(lexical environment)입니다. 다른 말로, 클로저는 내부 함수에게 외부 변수의 스코프에 접근할 수 있도록 해주는 것이다. Javascript에서 클로저는 함수가 생성될 때마다 생성된다.

자바스크립트 실행 컨텍스트(Execution Context) 에 대해 알고 있다면 대략 무슨 뜻인지 이해할 수 있다. 즉, 함수와 함수의 참조 환경인 Lexical Environment의 조합으로 구성된 함수 로써 자식함수가 부모함수의 Scope를 Outer Lexical Environment 로 참조(Reference)함으로써 Closer의 장점인 은닉화, 캡슐화 등의 장점을 통해 Public/Private 메서드를 흉내 낼 수 있다.

11. This; 자바스크립트에서 This란 무엇인가?

this의 값은 함수가 호출되는 방식에 따라 달라집니다.

  1. 함수를 호출할 때 new 키워드를 사용하는 경우,
    함수 내부에 있는 this는 완전히 새로운 객체입니다.
  2. apply, call, bind가 함수의 호출/생성에 사용되는 경우,
    함수 내의 this는 인수로 전달된 객체입니다.
  3. obj.method()와 같이 함수를 메서드로 호출하는 경우,
    this는 함수가 프로퍼티인 객체입니다.
  4. 함수가 전역 스코프에서 익명함수로 호출되는 경우,
    위의 조건 없이 호출되는 경우 this는 전역 객체입니다. 브라우저에서는 window 객체입니다. 엄격 모드(‘use strict’) 일 경우, this는 전역 객체 대신 undefined 가 됩니다.

위의 규칙 중 다수가 적용되면 더 상위 규칙이 승리하고 this 값을 설정합니다.

일반함수의 this와 화살표 함수의 this는 어떻게 다른가?

함수가 ES2015 화살표 함수인 경우, 위의 모든 규칙을 무시하고 생성된 시점에서 주변 스코프의 this 값을 받습니다.

화살표 함수와 일반 함수는 this가 다른 곳을 가리키는데,

  • 화살표 함수의 this는 바로 상위 스코프의 this를 가리킨다.
  • 일반 함수는 this가 동적으로 바인딩 됩니다.
    일반 함수의 this는 내부 함수, 콜백 함수: 전역 객체, 객체의 메소드, 생성자 함수 입니다.

use strict 모드에서의 this?

엄격 모드(‘use strict’) 일 경우, this는 전역 객체 대신 undefined 가 됩니다.

12. Call, Apply, Bind 함수에 대해 설명해달라

(구분해서 알고있자)

  • Call과 Apply
  • Bind

Call, Apply 함수

1
2
3
4
5
6
function add(a, b) {
return a + b;
}

console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3

Call과 Apply는 함수를 호출하는데 사용하며 , 첫 번째 매개변수는 함수 내에서 this의 값으로 사용됩니다. 그러나 이 둘의 차이점은

  • .Call은 쉼표로 구분된 인수를 두 번째 인수로 취하고

  • .Apply는 인수의 배열을 두 번째 인수로 취합니다.

  • CallC: Comma 로 구분되며, Apply인수 배열인 A: arguments 라고 기억하면 쉽습니다.

    그냥 실행하는 것이 아닌 첫 번째 this로 setting 하고싶은 객체를 넘겨주어 this를 바꾸고 나서 실행한다. call과 apply의 차이점은 첫 번째 인자(this를 대체할 값)를 제외하고, 실제 함수 호출에 필요한 파라미터를 넣어야 한다. call 과 다르게 apply 함수는 두 번째 인자부터 모두 배열에 넣어야 한다.

Bind 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const module = {
x: 42,
getX: function() {
return this.x;
}
};

const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42

Bind 함수가 call과 apply와 다른 점은 함수를 실행하지 않으며 새로운 바인딩한 함수를 만듭니다 . 바인딩한 함수는 원본 함수 객체를 감싸는 함수로, ECMAScript 2015에서 말하는 특이 함수 객체(exotic function object) 입니다. 바인딩한 함수를 호출하면 일반적으로 래핑된 함수가 호출 됩니다.

13. 객체 지향 프로그래밍(Object Oriented Programming)과 프로토타입이란 무엇인가

객체 지향 프로그래밍(Object Oriented Programming, 이하 OOP) 이란?

객체 지향 프로그래밍이란 “누가 어떤 일을 할 것인가” 를 중심으로 구현된 프로그래밍 패러다임으로써, 객체 지향의 “객체”는 현실 세계의 사물을 나타내는데 각 객체는 자신의 정보를 가지고 있는 독립적인 개체(Entity)로써 각각의 성격을 띄고 있으며 이 객체가 유기적으로 상호작용 하여 작게는 하나의 기능, 크게는 하나의 어플리케이션을 프로그래밍 하는 방법 입니다.

OOP의 기본 요소

  1. 클래스 (class)
    클래스란 1개 이상의 유사 객체의 공통된 특성(속성과 메서드)을 데이터 추상화 과정을 통해 구현한 하나의 틀(template) 로써, 객체지향 프로그램의 기본적인 사용자 정의 데이터 타입(user defined data type)이라고 할 수 있다.

    • 다른 클래스 또는 외부 요소와 독립적으로 디자인하여야 한다.
    • 클래스에 의해 생성된 새로운 객체(object)를 클래스의 인스턴스라 하며, 클래스로부터 새로운 객체를 생성하는 것을 인스턴스화 라고 한다.
  2. 객체 (object)

    • 클래스의 인스턴스를 객체(object)라고 하며
    • 필요한 속성(Attribute)과 속성을 처리하기 위한 메서드(Method)를 가진 하나의 소프트웨어 모듈이며
    • 다른 객체들과 구별될 수 있는 이름이 있고,
    • 실제 메모리상에 할당된 것으로 실제 프로그램에서 사용되는 데이터이다.
    • 속성(Attribute)
      • 객체가 가지고 있는 정보 또는 상태를 나타내며 객체의 속성, 데이터, 변수, 상수 또는 자료구조
    • 메서드(Method)
      • 객체가 가진 기능으로 객체의 속성을 처리하는 하나의 알고리즘이다.
      • 객체가 메시지를 받아 실행해야 할 객체의 구체적인 연산을 정의한 것, 전통적 시스템의 함수(Function)나 프로시저(Procedure)에 해당하는 연산 기능을 수행한다.
      • 메소드는 다른 객체로부터 메시지를 받았을 때 수행하게 된다.
  1. 메시지 (message)
    • 메시지는 객체 간의 상호작용을 하는 데 사용되는 수단으로,
    • 객체에게 어떤 행위를 하도록 지시하는 명령 또는 요구 사항이다.
    • 클래스로부터 생성된 객체를 사용하는 방법으로서 객체에 명령을 내리는 것이 메시지라 할 수 있다.
    • 메시지의 구성 요소 :
      • 메시지를 받는 객체의 이름, 객체가 수행할 메소드 이름, 메소드를 수행할 때 필요한 인자
      • 메시지를 받은 수신 객체는 요구된 메소드를 수행하여 결과를 반환하게 된다.

OOP의 장/단점

  1. 장점

    • 자연적인 모델링이 가능함
    • 코드의 재사용성 증가
    • 소프트웨어의 유지보수성 향상
    • 대형 프로젝트 개발에 적합
  2. 단점

    • 처리속도가 상대적으로 느림
    • 다중 객체 생성에 따른 메모리 사용량 증가
    • 객체 설계의 복잡도에 따른 설계시간 소용 시간

OOP에 특징에 대해 설명해달라(상속, 캡슐화 등등…)

( 실제 예제는 https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/Object-oriented_JS 를 참고하자 )

객체 지향 프로그래밍이란 “누가 어떤 일을 할 것인가” 이며 1개 이상의 유사 객체의 공통된 특성(속성과 메서드) 가진 클래스를 통해 객체를 생성하고 상호 유기적으로 메시지를 주고 받으며 결과를 반환한다고 정리해볼 수 있으며 총 6가지 있습니다.

  • 캡슐화 (Encapsulation)
  • 은닉화 (Information Hiding)
  • 추상화 (Abstraction)
  • 상속성 (Inheritance)
  • 다형성 (Polymorphism)
  • 연관성 (Relationship)
  1. 캡슐화 (Encapsulation)

    • 자료 부분과 연산(또는 함수) 부분 등 정보처리에 필요한 기능을 한 테두리로 묶는 것
    • 연관된 데이터와 함수를 함께 묶어 외부와 경계를 만들고 필요한 인터페이스만을 밖으로 드러내는 과정
    • 객체지향 기법의 정보 은닉 과 밀접한 기법
    • 장점
      • 높은 재사용성
      • 인터페이스의 단순화
      • 변경 또는 수정이 발생할때 오류의 파급효과가 적음
      • 응집력이 향상됨
  2. 은닉화 (Information Hiding)

    • 캡슐화에서 가장 중요한 개념으로, 다른 객체에게 자신의 정보를 숨기고 자신의 연산만을 통하여 접근을 허용하는 것
    • 정보 은닉은 고려되지 않은 영향(side effect)들을 최소화함을 목적으로 함
    • 따라서, 외부 객체가 접근하거나 사용하지 못하므로 유지보수와 소프트웨어 확장 시 오류를 최소화 할 수 있음
  3. 추상화 (Abstraction)

    • 자료 추상화는 불필요한 정보는 숨기고 중요한 정보만을 표현함으로써 프로그램을 간단히 만드는 것으로, 모델화하는 것을 의미
    • 자료 추상화를 통해 정의된 자료형을 추상 자료형이라고 함
    • 추상 자료형은 자료형의 자료 표현과 자료형의 연산을 캡슐화한 것으로 접근 제어를 통해서 자료형의 정보를 은닉할 수 있다.
    • 객체 지향 프로그래밍에서 일반적으로 추상 자료형을 클래스, 추상 자료형의 인스턴스를 객체, 추상 자료형에서 정의된 연산을 메소드(함수), 메소드의 호출을 생성자라고 한다.
  4. 상속성 (Inheritance)

    • 상속은 새로운 클래스가 기존의 클래스의 자료와 메서드를 이용할 수 있게 하는 기능
    • 상속을 받는 새로운 클래스를 부클래스, 파생 클래스, 하위 클래스, 자식 클래스라고 하며 새로운 클래스가 상속하는 기존의 클래스를 기반 클래스, 상위 클래스, 부모 클래스라 함
    • 상속을 통해서 기존의 클래스를 상속받은 하위 클래스를 이용해 프로그램의 요구에 맞추어 클래스를 수정할 수 있고, 클래스 간의 종속 관계를 형성함으로써 객체를 조직화할 수 있다.
    • 다중 상속
      • 클래스가 2개 이상의 클래스로부터 상속받을 수 있게 하는 기능
      • 클래스들의 기능이 동시에 필요할 때 용이하나 클래스의 상속 관계에 혼란을 줄 수 있음 (예: 다이아몬드 상속)
      • 프로그래밍 언어에 따라 사용 가능 유무가 다르므로 주의해서 사용해야 한다. JAVA는 지원하지 않음
  5. 다형성 (Polymorphism)

    • 상이한 클래스들이 동일한 메서드명을 갖는 것 또는 한 메시지가 객체에 따라 다양한 방식으로 응답할 수 있는 것을 의미함
    • 일반적으로 오버라이딩이나 오버로딩을 의미함
      • 오버라이딩: 같은 이름의 메소드가 여러 클래스에서 다른 기능을 하는 것
      • 오버로딩: 같은 이름의 메소드가 인자의 개수나 자료형에 따라서 다른 기능을 하는 것
    • 다형 개념을 통해서 프로그램 안의 객체 간의 관계를 조직적으로 나타낼 수 있음
  6. 연관성 (Relationship)

    • 두 개 이상의 엔티티 형에서 데이터를 상호 참조하는 클래스간의 연관관계를 정의
    • 객체간의 관계를 세부적으로 정의하여 구현 용이
    • 관계성의 종류
    • 관계성의 종류 의미 특성
      is-member-of 연관화 링크 개념과 유사
      is-instance-of 분류화 객체 및 클래스의 인스턴스를 표현
      is-part-of 집단화 상향식, 단일 상속, 복합 객체 (composite object) 표현에 유용
      is-a 특수화, 일반화 하향식, 다중 상속, 복잡한 객체 표현에 유용

프로토타입 상속이 이루어지는 법

상속 이란 부모 생성자의 기능을 물려받으면서 새로운 기능도 추가하는 것을 의미합니다. 그렇다면 Prototype 기반의 Javascript는 어떻게 상속을 지원할까요? 정확히 얘기하자면, Prototype 기반의 Javascript는 상속 보다는 위임에 가깝습니다.

JavaScript는 흔히 **프로토타입 기반 언어(prototype-based language)**라 불립니다. 모든 객체들이 메소드와 속성들을 상속 받기 위한 템플릿으로써 **프로토타입 객체(prototype object)**를 가진다는 의미입니다. 프로토타입 객체도 또 다시 상위 프로토타입 객체로부터 메소드와 속성을 상속 받을 수도 있고 그 상위 프로토타입 객체도 마찬가지입니다. 이를 **프로토타입 체인(prototype chain)**이라 부르며 다른 객체에 정의된 메소드와 속성을 한 객체에서 사용할 수 있도록 하는 근간입니다.

정확히 말하자면 상속되는 속성과 메소드들은 각 객체가 아니라 객체의 생성자의 prototype이라는 속성에 정의되어 있습니다.

JavaScript에서는 객체 인스턴스와 프로토타입 간에 연결(많은 브라우저들이 생성자의 prototype 속성에서 파생된 __proto__ 속성으로 객체 인스턴스에 구현하고 있습니다.)이 구성되며 이 연결을 따라 프로토타입 체인을 타고 올라가며 속성과 메소드를 탐색합니다.

객체의 프로퍼티에 접근할 때, 해당 객체에 해당 프로퍼티가 없으면 JavaScript 엔진은 객체의 __proto____proto____proto__ 등을 보고 프로퍼티 정의가 있을 때까지 찾고, 만약 객체의 프로퍼티에 접근할 때 해당 객체에 해당 프로퍼티가 없으면 프로토타입 체인 중 하나에 있거나 프로토타입 체인의 끝에 도달할 때까지 찾습니다. 이 동작은 고전적인 상속을 흉내내지만, 실제로 상속보다 위임에 더 가깝습니다.

자바스크립트에서 상속을 진행할 때는 프로토타입끼리 연결을 하는데, 부모 프로토타입을 Object.create()setPropertyOf() 메서드를 사용하여 자식 프로토타입과 연결할 수 있습니다.

이런 이유로 직접적인 상속을 구현 할수는 없지만 프로토타입 확장을 이용한 상속과 같은 의미를 구현할 수 있다고 말하곤 합니다.

14. OOP와 함수형 프로그래밍의 차이

함수형 프로그래밍에 대해 설명해 주세요.

순수함수와 보조함수의 조합을 통해 로직내에 존재하는 조건문과 반복문을 제거하여, 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임이다.

  • 함수형 프로그래밍에 개념에서 순수함수
    순수함수는 같은 입력이 주어지면 같은 출력을 반환해야하고, side effect(부작용)이 없어야한다. 결국, 함수형 프로그래밍은 순수함수를 통해 side effect를 최대한 억제하여 오류를 피하고 프로그램의 안전성을 높이려는 노력의 한 방법이다.

OOP와 함수형 프로그래밍의 차이

객체지향과 함수형의 차이는 상태를 관리하는 점 입니다.

객체지향은 동작하는 부분을 캡슐화해서 이해할 수 있게 하고, 함수형 프로그래밍은 동작하는 부분을 최소화해서 코드 이해를 돕는다. 마이클 페더스 - ‘레거시 코드 활용 전략’ 저자

  • 객체 지향: 상태를 저장하는 필드와 필드를 이용해 기능을 제공하는 메소드를 붙여서 클래스를 만든다. 즉, 항상 새로운 자료구조를 사용하게 되는 셈입니다.
  • 함수형 프로그래밍: 몇몇 자료구조(list, set, map)를 이용해 최적화된 동작을 만들어냅니다.

15. 즉시 실행 함수(IIFE)란 무엇이며 언제 사용하는 것인가

즉시 실행 함수(IIFE)란 정의되자마자 즉각적으로 실행되는 자바스크립트 함수(Function) 중 하나로, 종류는 기명 즉시 실행 함수 (함수의 이름이 있는 즉시 실행 함수)익명 즉시 실행 함수 (함수의 이름이 없는 즉시 실행 함수) 가 있다.

형태

1
2
3
4
5
6
7
8
9
10
11
// 익명 즉시 실행 함수
(function(arg) {
// statements
})(params);

// 기명 즉시 실행 함수
var print = (function (arg) {
// statements
})(params);

console.log(print);

언제 사용하나

  1. 불필요한 충돌을 최소화하고 단 한번만 실행하는 초기화 코드에 많이 사용한다.
    변수를 전역 스코프에서 변수를 선언하지 않기 때문에 전역 내 또는 내부 함수 또는 블록 스코프와 충돌 없이 구현할 수 있다.
  2. 특정 스코프를 만들 때 사용한다
    익명 함수로써 레퍼런스 없이 즉각적으로 실행되기 때문에 특정 스코프를 만들 때 유용하게 사용할 수 있다.

15. 비동기 프로그래밍

동기 함수(Synchronous)와 비동기 함수(Asynchronous)이란

  • 동기 함수블로킹 인 반면, 비동기 함수논블로킹 처리이다.
  • 동기 함수 에서는 다음 명령문이 실행되기 전에 앞 명령문이 완료됩니다. 이 경우, 프로그램은 명령문의 순서대로 정확하게 평가되고 명령문 중 하나가 매우 오랜 시간이 걸리면 프로그램 실행이 일시중지 될 가능성이 있습니다.
  • 비동기 함수 는 일반적으로 파라미터를 통해서 콜백을 받고, 비동기 함수가 호출된 후 즉시 다음 줄 실행이 계속됩니다. 콜백은 비동기 작업이 완료되고 호출 스택이 비어 있을 때만 호출됩니다. 웹 서버에서 데이터를 로드하거나 데이터베이스를 쿼리하는 등의 무거운 작업을 비동기식으로 수행하여, 메인 스레드가 긴 작업을 완료할 때까지 블로킹하지 않고 다른 작업을 계속할 수 있습니다(브라우저의 경우 UI가 중지됨).

Callback, Promise 란 무엇이며 각각의 장단점에 대해 설명해달라

정의
  • Callback Function
    자바스크립트의 비동기성을 표현하는 가장 일반적인 기법으로, 호출된 함수를 알려줘서 다른 프로그램이나 다른 모듈에서 함수를 호출하게 하는 방법입니다.
    특정 함수에 매개변수로 전달되는 함수를 의미하며 함수를 전달받은 함수 안에서 호출됩니다.
    단점으로는 콜백지옥에 빠지면 로직이 어려워지고 가독성이 떨어지며 error 처리가 어려워질 수 있습니다.
  • Promise
    Promise는 비동기 처리 로직을 추상화한 객체와 그것을 조작하는 방식으로, Callback 함수의 단점인 콜백지옥을 해결하며 동기 처리 시점을 명확하게 표현할 수 있도록 도와줘 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있습니다.
Callback 대신에 Promise를 사용할 때의 장점과 단점은 무엇인가요
  • 장점
    가독성이 떨어질 수 있는 콜백 지옥을 피할 수 있습니다.
    .then()을 이용하여 가독성 좋은 연속적인 비동기 코드를 쉽게 작성할 수 있습니다.
    Promise.all()을 사용하여 병렬 비동기 코드를 쉽게 작성할 수 있습니다.

  • 단점
    약간 더 복잡한 소스코드(논쟁의 여지가 있음).
    ES2015를 지원하지 않는 이전 브라우저에서 이를 사용하기 위해서는 polyfill을 로드해야 합니다.

Promise 코드가 어떻게 구성되어있는가

Promise 는 비동기 연산이 종료된 이후의 결과값이나 실패 이유를 처리하기 위한 처리기를 연결할 수 있도록 하며 프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있습니다. 다만 최종 결과를 반환하지는 않고, 대신 프로미스를 반환해서 미래의 어떤 시점에 결과를 제공합니다.

Promise 의 작동방식을 이해하기 위해서는 Promise의 가장 뛰어난 장점 중의 하나인 chaining 에 대해 이해할 필요가 있습니다. Promise 는 비동기 작업의 최종 완료 또는 실패를 나타내는 객체로써, 기본적으로 promise는 함수에 콜백을 전달하는 대신에, 콜백을 첨부하는 방식의 객체입니다.

promise가 성공했을때는 .then(successCallback) 와 같이 .then() 메서드를 통해 비동기 처리가 성공했을때 반환된 결과값을 처리할 콜백함수를 전달하면 되고, 실패했을시에는 .catch(failureCallback) 와 같이 .catch() 메서드를 통해 실패햇을때 에러 핸들링할 콜백함수를 전달해주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Case: 콜백 함수로 처리
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);

// Case: Promise로 처리
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

Async & Await는 무엇이며 Promise의 차이는 무엇인가

Async & Await 는 비동기 코드를 동기식으로 표현하는 더 나은 방법으로 ES8(ES2017) 에 등장했습니다. async 함수는 async 키워드로 선언된 함수이며 그 안에 await 키워드가 허용됩니다. asyncawait 키워드를 사용하면 프로미스 체인을 명시적으로 구성할 필요 없이 비동기식 프라미스 기반 동작을 보다 깔끔한 스타일로 작성할 수 있습니다. await 키워드는 Promise 객체를 받아 처리하고, 만약 비동기 함수가 아닌 동기적 함수라면 리턴 값을 그대로 받는다. Async 함수는 Promise 객체를 통해 비동기적으로 처리된 내용을 동기적인 코드 진행 순서로 보여주는 역할을 합니다.

Async & Await 구문의 반환값은 비동기 함수에 의해 반환된 값으로 해결되거나 비동기 함수 안에서 다뤄지지 않은 또는 예외처리로 거부된 Promise 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Case: Promise로 처리
function getProcessedData(url) {
return downloadData(url) // returns a promise
.catch(e => {
return downloadFallbackData(url) // returns a promise
})
.then(v => {
return processDataInWorker(v) // returns a promise
})
}

// Case: Async & Await 처리
async function getProcessedData(url) {
try {
let v = await downloadData(url)
return processDataInWorker(v)
} catch (e) {
throw (e) // error handling
}
}

참고