관리 메뉴

Jerry

JavaScript 모의면접 질문 리스트 본문

Interview/모의 면접 질문 리스트

JavaScript 모의면접 질문 리스트

juicyjerry 2021. 6. 10. 16:26
반응형

 

 

Q1. 스코프에 대해서 설명하세요.

스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같은 대상을 다른 대상과 구별하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙입니다. 변수는 전역 또는 코드 블록(if, for, while, try/catch 등)이나 함수 내에 선언하며 코드 블록이나 함수는 중첩될 수 있다. 식별자는 자신이 어디에서 선언됐는지에 의해 유효한(다른 코드가 자신을 참조할 수 있는) 범위를 갖습니다. 

 

자바스크립트에서 스코프는 전역 스코프와 지역 스코프로 구분할 수 있습니다. 지역 스코프는 함수 코드 블록이 만든 스코프입니다.

 

변수는 전역 변수와 지역 변수로 구분할 수 있습니다. 지역 함수는 함수 내에서 선언된 변수입니다.

 

C언어와 다르게 자바스크립트는 함수 레벨 스코프(function-level scope)를 따릅니다. 함수 코드  블록 안에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 외부는 유효하지 않다는 것입니다. 대표적인 블록 레벨 스코프는 let keyword가 있습니다. (ECMAScript 6)

 

렉시컬 스코프(lexical scope): 함수를 어디서 선언하였는지에 따라 결정됩니다. 자바스크립트는 렉시컬 스코프를 따르기에 함수를 선언한 시점에 상위 스코프가 결정됩니다.

 

*프로그래밍 언어의 함수 상위 스코프 결정 방식 2가지

1. 함수를 어디서 호출하였는지에 딸 상위 스코프를 결정하는 것

2. 함수를 어디서 선언하였는지에 따라 상위 스코프를 결정하는 것

 

출처: poiemweb | https://poiemaweb.com/js-scope

 

 

Q2. 클로져에 대해서 설명하세요.

클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경과의 조합이다. 

클로저는 반환된 내부 함수가 자신이 선언됐을 때의 환경(lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수를 말합니다. 

(간단히 말해서, 클로저는 자신이 생성될 때의 환경(lexical environment)을 기억하는 함수입니다.)

 

자신을 포함하고있는 외부 함수보다 내부 함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부 함수가 호출되더라도 외부 함수의 지역 변수에 접근할 수 있는데 이러한 함수를 클로저라고 부른다.

 

출처: poiemweb | https://poiemaweb.com/js-closure

 

 

Q3. 클로져의 사용 예제를 알려주세요.

클로저가 가장 유용하게 사용되는 상황은 현재 상태를 기억하고 변경된 최신 상태를 유지하는 것이다.

화면에 BOX 요소의 표시 상태를 나타내야 할 경우에, box 표시 상태를 기억하고 변경되어도 최신 상태를 유지해야 하는 상황을 예로 들 수 있다. 

 

만약 자바스크립트에 클로저가 없다면, 상태 유지를 위해 전역변수를 사용할 수밖에 없다. 하지만, 전역 변수는 언제든 누구나 접근 가능하며 변경 가능하기에 많은 부작용과 오류의 원인이 된다. 

 

 

출처: poiemweb | https://poiemaweb.com/js-closure

 

 

Q4. 변수 선언, 초기화, 할당의 차이점에 대해서 설명하세요.

 

변수는 3단계에 걸쳐 생성된다.

선언 단계(Declaration phase): 변수 객체에 변수를 등록한다. (변수 객체는 스코프가 참조하는 대상이 된다)

 

초기화 단계(Initialization phaze): 변수 객체에 등록된 변수를 메모리에 할당한다. 변수는 undefined로 초기화된다.

 

할당 단계(Assignment phase): undefined로 초기화된 변수에 실제값을 할당한다.

 

 

출처: poiemweb | https://poiemaweb.com/js-data-type-variable

 

 

 

Q5. 호이스팅과 Temporal Dead Zone이 어떻게 연관되어있는지 설명하세요.

자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, class)을 호이스팅한다.

 

호이스팅이란, 임의의 선언문을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다. var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한 번에 이루어지기 때문에, 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다.

 

하지만, 블록 레벨 스코프인 let keyword로 선언된 변수는 선언문 이전에 참조 시, 참조 에러(ReferenceError)가 발생한다. 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.

 

출처: poiemweb | https://poiemaweb.com/es6-block-scope

 

 

 

Q6. ES6의 주요 변화점에 대해서 설명하세요

var 키워드 -> let, const 키워드 

- 함수 스코프를 가지는 var로 의도하지 않은 곳에서 변수 변경가 가능하여 에러가 발생할 수 있는데, 블록 스코프인 let, const를 사용하면 이러한 실수와 버그를 줄일 수 있다.

- ES5 변수 호이스팅의 문제점 개선
(호이스팅: var 키워드로 변수 선언하면 선언 이전에 변수를 사용할 수 있는 현상)

 

*let과  const 차이점

변수 선언 시, 변하지 않는 값은 const / 변할 수 있는 값은 let을 사용한다.

하지만, 프로퍼티는 수정 가능하다!

 

 

 

화살표 함수

화살표 함수는 this 바인딩 이슈를 해결과 함수 표현식의 긴 문법을 단축시켜준다.

ES5에서는 DOM 이벤트 핸들러 함수를 실행할 때 핸들러가 의도한 대로 동작하지 않는다.

(ES5: 엘리먼트에 등록된 이벤트 핸들러 함수 실행될 때,

non-strict 모드로 동작해 핸들러에서 this 객체에 접근하면 이벤트 처리하는 엘리먼트 객체가 탐색된다

= > ES6: 해당 콘텍스트의 this 객체를 바인드 한 함수 표현식처럼 동작한다)

 

 

 

클래스

자바스크립트는 프로토타입 기반 언어다. 자바스크립트에서 프로토타입 객체를 재사용하면서 클래스와 유사한 형태의 API를 만들어 사용해왔다.

 

ES5 환경에서 클래스를 구현하는 방법은 라이브러리마다 달랐다. ES6에서는 클래스 문법이 추가되어, 라이브러리도 클래스 문법을 사용하면서 구현과 사용법도 통일되었다. 어느 코드가 클래스이고 생성자 함수인지 쉽게 확인할 수 있고, 메서드도 클래스 내부에 캡슐화되어 가독성이 좋아진 것을 확인할 수 있다.

 

 

 

개선된 객체 리터럴(Object literal)

- 짧아진 객체 리터럴: 반복적으로 입력했던 콜론과 변수명을 한 번의 입력으로 해결

- 축약형 메서드 이름: function 키워드와 메서드 이름 뒤 콜론 생략

- 계산된 값 사용 가능: [ ] 접근자를 이용한 동적 할당에서 표현식의 연산 값을 객체 키로 사용

 

 

 

 

템플릿 리터럴(Template literal)

- 백 틱으로 감싸진 문자열로 이루어 표현식을 + 연산자 대신 바로 작성하여 간결한 문법을 구현

 

 

 

 

 

 

 

 

디스트럭처링(Destructuring) 

전달받은 객체 프로퍼티를 변수로 선언하려면 독립된 할당문을 작성해야 했다. 디스트럭처링은 변수 선언이 편해지고 코드가 간결해졌다. 

 

 

 

함수 매개변수의 디폴트 값 설정

함수의 오작동을 막기 위해 특정 타입 혹은 값을 가져야 할 매개변수가 undefined로 전달될 경우, 이 대신 사용할 수 있는 값을 할당하는 것

 

ES5에서는 디폴트 값 설정하기 위해 if 문으로 undefined 인지 여부 확인했다.

 

 

 

Rest 파라미터, Spread 표현식

 Spread 표현식:  배열이나 객채 리터럴 내부에... ids와 같이 작성하면 해당 위치에 ids의 각 배열 요소나 프로퍼티를 풀어낸다.

따라서, 배열 복사나 불변(immutable) 객체 생성도 손쉽게 할 수 있다. 

- 배열을 함수 파라미터들로 변경하기

- 배열 및 객체 확장 예제

 

Rest 파라미터: 파라미터의 개수가 가변적인 함수에서 파라미터들을 파라미터로 사용하려면 arguments 객체를 배열처럼 접근해서 사용해야 했지만,  someFunction(target, ...params) 형태로 Rest 파라미터 연산자 작성으로 params 배열로 쉽게 바꿀 수 있다. 

 

 

 

모듈(ES Module) 

import, export문을 사용해서 모듈을 가져올 수 있다. 

자바스크립트 모듈은  .js 확장자로 만들어진 파일을 뜻하며 기본적으로 strict 모드로 동작한다. 

export문을 통해 함수, 클래스, 변수 들을 모듈 외부로 내보낼 수 있다.

- Named export: 여러 번 사용할 수 있다.

- Default export: 한 번만 사용할 수 있다.

 

 

for ... of

for...of문은 반복 가능한 객체에 대해서 반복한다.

 

for...of와 for...in의 차이

for...in루프는 객체의 모든 열거 가능한 속성에 대해 반복한다.

for...of는 컬렉션 전용이다. 속성이 있는 모든 컬렉션 요소에 대해 이 방식을 반복한다.

 

 

let iterable = [3, 5, 7];
iterable.foo = "hello";

for (let i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i of iterable) {
  console.log(i); // logs 3, 5, 7
}

 

 

 

출처:

TOAST UI | https://bit.ly/2RvBZWi

MDN | https://mzl.la/3g1tZ8X

 

 

Q7. 원시 자료형과 참조 자료형의 대표적인 차이는 무엇인가요?

참조 타입의 경우 원본이 바뀌면 복사본도 똑같이 따라 바뀌는 반면, 원시 타입은 그렇지 않다.

원시 타입은 해당 값을 복사하여 서로 독립된 값을 가지며, 

참조 타입은 해당 주소를 참조하여 메모리에 저장된 값을 가지고 온다.

 

자바스크립트에서 제공하는 7개의 데이터 타입은 크게 원시 타입(primitive data type)객체 타입(object / reference type)으로 구분할 수 있다. 객체 타입과 참조 타입과 동의어다.

 

ex) [원시 타입] boolean, null, undefined, number, string, symbol  / [객체 타입, 참조 타입] object

 

원시 타입

원시 타입의 값은 변경 불가능한 값(immutle value)이며 pass-by-value(값에 의한 전달)이다.

- number: 자바스크립트는 독특하게 하나의 숫자 타입만 존재한다. 배정밀도 64비트 부동소수점 형(double-precision 64-bit floating-point format : -(253 -1)와 253 -1 사이의 숫자 값)을 따른다.

 

- string: 텍스트 데이터 나타내는 데 사용한다.

 

C와 같은 언어와 다르게 자바스크립트 문자열은 원시 타입이며 변경 불가능(immutable)하다.

 

var str = 'Hello';
str = 'world';

 

첫 번째 구문이 실행되면 메모리에 문자열 ‘Hello’가 생성되고 식별자 str은 메모리에 생성된 문자열 ‘Hello’의 메모리 주소를 가리킨다. 그리고 두 번째 구문이 실행되면 이전에 생성된 문자열 ‘Hello’을 수정하는 것이 아니라 새로운 문자열 ‘world’를 메모리에 생성하고 식별자 str은 이것을 가리킨다. 이때 문자열 ‘Hello’와 ‘world’는 모두 메모리에 존재하고 있다. 변수 str은 문자열 ‘Hello’를 가리키고 있다가 문자열 ‘world’를 가리키도록 변경되었을 뿐이다.

 

 

var str = 'string';
// 문자열은 유사배열이다.
for (var i = 0; i < str.length; i++) {
  console.log(str[i]);
}

// 문자열을 변경할 수 없다.
str[0] = 'S';
console.log(str); // string

 

문자열은 배열처럼 인덱스를 통해 접근할 수 있다. 이와 같은 특성을 갖는 데이터를 유사 배열이라 한다.

 

str[0] = 'S'처럼 이미 생성된 문자열의 일부 문자를 변경해도 반영되지 않는다(이때 에러가 발생하지 않는다). 한번 생성된 문자열은 read only로서 변경할 수 없다. 이것을 변경 불가능(immutable)이라 한다.

 

그러나 새로운 문자열을 재할당하는 것은 물론 가능하다. 이는 기존 문자열을 변경하는 것이 아니라 새로운 문자열을 새롭게 할당하는 것이기 때문이다.

 

 

-boolean: 논리적 참, 거짓을 나타내는 true와 false 뿐이다.

* 비어있는 문자열과 null, undefined, 숫자 0은 false로 간주된다.

 

-undefined: 이 타입의 값은 undefined가 유일하다. 선언 이후 값을 할당하지 않은 변수는 undefined값을 가진다.

* 변수 선언에 의해 확보된 메모리 공간을 처음 할당이 이루어질 때까지 빈 상태로 내버려 두지 않고 자바스크립트 엔진이 undefined로 초기화하기 때문이다.

 

-null: 이 타입의 값은 null이 유일하다. 자바스크립트는 case-sensitive 하므로 null은 Null, NULL 등과 다르다.

null 의도적으로 변수에 값이 없다는 것을 명시한다. 이는 변수가 기억하는 메모리 어드레스의 참조 정보를 제거하는 것을 의미한다.(자바스크립트 엔진은 누구도 참조하지 않는 메모리 영역을 가비지 컬렉션을 수행한다)

 

-symbol: 심벌은 주로 이름 충동 위험이 없는 유일한 객체 프로퍼티 키를 만들기 위해 사용한다. 

심볼은 Symbol 함수를 호출해 생성한다. 이때 생성된 심벌 값은 유일한 값이다.

 

 

 

객체(참조) 타입

이름과 값을 가지는 데이터를 의미하는 프로퍼티와 동작을 의미하는 메서드를 포함할 수 있는 독립적 주체이다.

자바스크립트는 객체 기반의 스크립트 언어로서 자바스크립트를 이루고 있는 거의 모든 것이 객체이다. (배열, 함수, 정규표현식...)

객체는 pass-by-reference(참조에 의한 전달) 방식으로 전달된다.

 

 

출처: 

Poiemaweb | https://poiemaweb.com/js-data-type-variable

Howdy | https://kim-mj.tistory.com/175

 

 

Q8. ==과 ===은 어떤 차이가 있나요?

일치 연산자(strict equality operator) ===를 사용하면 형 변환 없이 값을 비교할 수 있습니다.

일치 연산자는 엄격한(strict) 동등 연산자입니다. 자료형의 동등 여부까지 검사하기 때문에 피연산자 a와 b의 형이 다를 경우 a === b는 즉시 false를 반환합니다.

 

동등 연산자 '=='은 값만 비교하지만

일치 연산자 '==='은 값과 타입을 같이 비교한다.


출처:

JAVASCRIPT.INFO | https://ko.javascript.info/comparison
 Code Playground | https://bit.ly/3g2WwLo

 

 

 

Q9. 자바스크립트 배열의 타입은 왜 object인가요?

 자바스크립트에는 2가지 타입이 있다.

1. 원시형 타입 2. 참조형(객체) 타입

 

여기서 2번은 함수, 배열과 정규 표현식이 포함된다. 자바스크립트의 'Object'에서 파생되었다.

 

To add some background, there are two data types in JavaScript:
    1. Primitive Data types - This includes null, undefined, string, boolean, number and object.
    2. Derived data types/Special Objects - These include functions, arrays and regular expressions. And yes, these are all derived from "Object" in JavaScript.

 

 

 

출처: Stackoverflow | https://bit.ly/34Y9UKp

 

 

Q10. null과 undefined의 차이에 대해서 설명하세요.

null은 "no value"라는 의미의 값이고 typeof 리턴 값이 '객체'라고 하기 때문에 특별한 객체라고 한다.

 

반면에, undefined는 선언되지 않다는 걸 의미한다. 혹은 변수가 할당되지 않았다는 걸 의미한다.

 

 

 

 

출처: Stackoverflow | https://bit.ly/3w3ikMB

 

 

 

Q11. callback, promise, async/await의 특징과 차이점에 대해서 설명하세요.

callback

자바스크립트는 비동기 처리를 위한 하나의 패턴으로 콜백 함수를 사용한다. 

하지만, 전통적인 콜백 패턴은 콜백 헬로 인해 가독성이 나쁘고, 비동기 처리에서 발생한 에러 처리가 곤란하며, 여러 개의 비동기 처리를 한 번에 처리하는 데도 한계가 있다.

 

*콜백헬 발생 이유:

- 비동기 처리를 위해 콜백 패턴을 사용하면 처리 순서를 보장하기 위해 여러 콜백 함수가 nesting(중첩)되어 복잡도가 높아져 콜백 헬이 발생

- 실행 완료를 기다리지 않는 비동기 처리 모델 특징상, 즉시 다음 태스크를 실행하여 기대한 대로 동작하지 않는다.

- catch~then 구문의 catch 블록에서 에러가 캐치되지 않는다.

 

 

promise

- 프로미스는 Promise 생성자 함수를 통해 인스턴스화한다.

- Promise 생성자 함수는 비동기 작업을 수행할 콜백 함수를 인자로 전달받는데 이 콜백 함수는 resolve와 reject 함수를 인자로 전달받는다. 

- Promise는 비동기 처리가 성공(fullfilled) 했는지 또는 실패(rejected) 했는지 상태 정보를 갖는다.

비동기 처리 결과에 대한 후속 처리는 Promise 객체가 제공하는 후속 처리 메서드 then, catch, finally가 수행한다.

-  비동기 처리 시 발생한 에러는 then메서드의 두 번째 콜백이나 catch 메서드를 이용해 처리할 수 있는데, 보통 catch 메서드를 많이 사용한다.

- 프로미스는 후속 처리 메서드를 체이닝(chaninning)하여 여러 개의 프로미스를 연결하여 사용할 수 있다. (=> 콜백 헬 해결!)

 

 

 

async/await

async와 await로 프라미스를 좀 더 편하게 사용할 수 있다. 

async 키워드는 function 앞에 붙이면 해당 함수는 항상 프라미스를 반환합니다. 만약 프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스로 값을 감싸 이행된 프라미스가 반환됩니다.

 

await는 promise.then 보다 좀 더 세련되게 프라미스의 결괏값을 얻을 수 있도록 해주는 문법입니다.

await 키워드가 붙은 값은 async 함수 안에서 프라미스가 처리(settled) 될 때까지 기다린 후 결과가 반환됩니다.

프라미스가 처리되길 기다리는 동안엔 엔진이 다른 일(다른 스크립트 실행, 이벤트 처리 등)을 할 수 있기 때문에,  CPU 리소스가 낭비되지 않습니다.

 

 

 

 

출처: 

poiemaweb | https://poiemaweb.com/es6-promise

JAVASCRIPT.INFO | https://ko.javascript.info/async-await

 

 

 

Q12. event loop에 대해서 설명하세요.

이벤트(event)는 어떤 사건을 의미합니다. 

브라우저에서의 이벤트는 사용자가 버튼을 클릭했을 때, 웹 페이지가 로드되었을 때 같은 것인데 DOM 요소와 관련이 있습니다.

근데, 이런 이벤트가 발생하는 시점이나 순서를 사전에 인지할 수 없으므로 일반적인 제어 흐름과는 다르게, 이벤트가 발생하면 이를 감지와 대응하는 처리를 해주어야 합니다. (사용자와 웹페이지의 상호작용)

 

*이벤트 핸들러: 이벤트가 발생하면 실행되는 함수

 

브라우저는 단일 스레드에서 이벤트 드리븐 방식으로 동작합니다. 

단일 스레드라는 이름의 의미대로 스레드가 하나이며 하나의 작업만을 처리할 수 있다는 것을 알 수 있습니다. 

그렇지만, 평소에 느끼는 브라우저는 하나의 스레드가 하나의 작업뿐만 아니라 여러 작업을 병렬적으로 하는 것 같이 느껴집니다. 

그렇게 느껴지게  자바스크립트의 동시성(concurrency)을 지원해주는 것이 이벤트 루프(event loop)입니다.

 

 

 

 

 

출처; https://poiemaweb.com/js-event,이벤트 루프와 브라우저 환경

 

 

 

 

[tip] 자바스크립트 엔진은 Heap영역과 call stack영역으로 나뉩니다. 
Heap은 동적으로 생성된 객체 인스턴스가 할당되는 영역이고, call stack은 작업 요청(함수 호출)이 순차적으로 콜스택에 쌓이면서 실행됩니다. 콜스택은 blocking 처럼 동기적으로 앞의 task가 종료되지 않으면 다음 작업으로 넘어가지 않습니다. 
Event Queue(Task Queue)에선 콜백 함수, 이벤트 핸들러, Timer 함수 같은 비동기 처리 함수가 보관되는 영역으로, 이벤트 루프에 의해 특정 시점(when 콜스택 is empty)에 순차적으로 콜스택으로 이동되어 실행됩니다.

Event Loop는 콜스택에서 실행 중인 task가 있는지, Event Queue에 task가 있는지 반복 확인합니다. 콜스택이 비어있다며 Event Loop의 task가 콜스택으로 이동하고 실행됩니다.

 

 

 

 

이 동시성을 지원하는 이벤트 루프는 자바스크립트 엔진을 구동하는 환경(runtime)인 브라우저(Node.js)가 담당합니다.

 

 

 

 

 

출처: Poiemaweb | https://poiemaweb.com/js-event

 

 

 

Q13. rest syntax와 spread syntax의 차이에 대해서 설명하세요.

Rest 파라미터는 반드시 마지막 파라미터이어야 하지만, Spread 문법을 사용한 인수는 자유롭게 사용할 수 있습니다.

 

Rest 파라미터는 매개 변수 이름 앞에 점 세 개를 붙여서 정의한 매개 변수를 의미한다. 함수의 전달된 인수들의 목록을 배열로 전달받습니다. Rest 파라미터는 Spread 문법을 사용해 파라미터를 정리했습니다.

 

Spread 문법은 사용한 배열을 인수로 함수에 전달하면 배열의 요소를 분해하여 순차적으로 파라미터에 할당합니다.

 

Spread 문법은 대상을 개별 요소로 분리하며 그 대상은 이터러블(iterable) 해야합니다. 
Rest / Spread 프로퍼티는 일반 객체에 Spread 문법 사용을 허용합니다. 그래서 객체를 병합이나 변경할 수 있습니다.(Object.assign)

* 이터러블 프로토콜을 준수한 객체를 이터러블이라 합니다. Symbol.iterator 메서드를 구현하거나 프로토타입 체인에 의해 상속한 객체 (링크)

 

 

 

출처: Poiemaweb | https://poiemaweb.com/es6-extended-parameter-handling

 

 

 

 

Q14. Blocking과 Non-Blocking의 차이점은 무엇인가요?

 

Blocking model은 예를 들어, 서버에서 데이터를 가져와 화면에 표시하는 작업을 수행할 때,

서버에 데이터를 요청하고 데이터가 응답될 때까지 이후 태스크들은 Blocking(작업 중단) 됩니다. (동기적으로 동작)

 

 

synchronous processing model

 

 

 

이에 반해, Non-blocking model은 병력적으로 task를 수행합니다. 태스크가 종료되지 않은 상태라도 대기하지 않고 다음  task를 실행합니다. 예를 들어, 서버에서 데이터를 가져와 화면에 표시하는 태스크를 수행할 때,  서버에 데이터를 요청한 이후 서버로부터 데이터가 응답될 때까지 대기하지 않고(non-blocking) 즉시 다음 task를 수행합니다.

 

 

asynchronous processing model

 

 

출처: Poiemaweb | https://poiemaweb.com/js-async

 

 

 

 

Q15. Synchronous execution과 Asynchronous execution의 차이점은 무엇인가요?

동기적 실행(synchronous execution)은 서브루틴 간에 명확한 실행 순서가 존재한다. A, B, C의 세 가지 서브루틴이 존재하고 A, B, C 순으로 실행되기를 기대한다면 반드시 A->B->C의 순서로 실행되어야 한다. 즉, B는 A가 실행 완료되기를 기다리며, C는 A와 B가 실행 완료되기를 기다린다.

 

비동기적 실행(asynchronous execution)에서는 서브루틴 간에 명확한 실행 순서가 존재하지 않는다. 즉 A->B->C의 순서로 실행될 수도 있고, B->C->A의 순서로 실행될 수도 있다. 따라서 프로그래밍 시에 반드시 이점을 고려하여야 한다. 이러한 경우에는 서브루틴이 완료되었다는 것을 전달하기 위해 callback 패턴을 사용하기도 한다. 

 

혼동하지 말아야 할 것이, 동기/비동기적 실행은 멀티 스레딩과 전혀 관련이 없다. 즉 하나의 스레드에서도 비동기적 실행을 할 수 있고, 멀티 스레드에서도 동기적 실행을 할 수 있다. 스레드 혹은 코어의 개수가 중요한 것이 아니라, 서브루틴 간의 실행 순서가 정해져 있는지가 중요하다. 이와 관해선, 이 링크의 그림을 참고하자.

 

출처:

Stackoverflow | https://bit.ly/3g7tnyE

BlackStar | https://showx123.tistory.com/62

 

 

 

Q16. nodejs는 싱글 스레드인가요?

정확하게 말하면 자바스크립트의 메인 스레드인 이벤트 루프가 싱글 쓰레드이기 때문에 자바스크립트를 싱글 쓰레드 언어라고 부른다. 하지만 이벤트 루프만 독립적으로 실행되지 않고 웹 브라우저나 NodeJS같은 멀티 쓰레드 환경에서 실행된다. 즉, 자바스크립트 자체는 싱글 스레드가 맞지만 자바스크립트 런타임은 싱글 쓰레드가 아니다.

 

만약 자바스크립트가 멀티 스레드로 실행되는 언어였다면 웹페이지에서 발생하는 동시성 문제에 대해 해결해야 했다. 실제로 멀티 쓰레드로 구현된 서비스에서는 이 동시성 문제에 대해 정말 많은 신경을 쓴다. 하지만 자바스크립트는 단일 쓰레드로 실행되므로 인해 교착 상태와 같은 다중 쓰레드 환경에서 발생할 수 있는 복잡한 시나리오를 신경 쓸 필요가 없으며 비동기 처리를 통해 쉽게 여러 요청을 처리할 수 있다.

 

실제로 구글의 Chrome 브라우저마저도 기존 웹 페이지에서 엄청난 동시성 문제를 일으킬 수 있다는 이유로 단일 웹 사이트 페이지의 자바스크립트 코드가 동시에 실행되는 것을 허용하지 않는다.

 

 

 

출처: CHANYEONG | https://chanyeong.com/blog/post/44

 

 

Q17. nodejs는 event-driven architecture인가요?

 

네. Node.js는 싱글 스레드 애플리케이션입니다. 하지만 event와 callback을 통해 동시성을 지원할 수 있습니다. Node.js에선 Event를 매우 많이 사용하고, 이것 때문에 다른 비슷한 기술들보다 훨씬 빠른 속도를 자랑합니다. Node.js 기반으로 만들어진 서버가 가동되면, 변수들을 initialize 하고, 함수를 선언하고 이벤트가 일어날 때까지 기다립니다.

 

이벤트 위주 (Event-Driven) 애플리케이션에서는, 이벤트를 대기하는 메인 루프가 있습니다. 그리고 event들을 listen 하고 하나의 이벤트가 감지되었을 시 Callback함수를 호출합니다.

 

 

 

 

 

 

 

이벤트가 콜백과 비슷해 보이지만, 차이점이 있습니다. 차이점은, 콜백 함수는 비동기식 함수에서 결과를 반환할 때 호출되지만, 이벤트 핸들링은 옵저버 패턴에 의해 작동 된다는점 입니다. EventListeners 함수들이 옵저버 역할을 합니다. event가 실행될 때까지 기다리다가 실행되면 listener(이벤트 처리 함수) 기능이 실행됩니다. 

 

 

 

출처: 이영규의 개발 블로그 | https://lygggg.github.io/blog/nodejs/

 

반응형