이번 포스트에서는 Section 3가 끝나고 배운 내용을 토대로 기술면접을 연습했습니다.
이번에도 모든 질문에 대한 답변리스트만 작성하였습니다.
호이스팅(hoisting)이란, 변수와 함수의 메모리 공간이 선언 전에 미리 할당되는 것을 말합니다.
자바스크립트 엔진이 코드를 한줄씩 차례대로 실행하지만, 변수와 함수의 선언은 미리 저장하고 값을 undefined로 초기화합니다.
이 때 var키워드로 변수에 값을 할당하기 전에 참조하면 값이 레퍼런스 에러가 아니라 undefined로 출력되지만, let과 const로 선언한 변수는 할당 하기 전에 참조하면 참조 에러, 즉 ReferenceError가 발생합니다.
여기서 함수를 선언하고 값을 할당하기 전, 초기화된 시점까지의 변수를 Temporal Dead Zone, 즉 "시간상 사각지대"에 들어간 변수라고 합니다.
"시간상"이라는 표현을 사용한 이유는 사각지대가 코드의 작성 순서(위치)가 아니라 코드의 실행 순서(시간)에 의해 형성되기 때문입니다. 만약 let으로 선언하고 할당한 변수a를 사용하는 함수b를 a를 선언하기 전에 선언했어도, 함수b 호출을 변수a 선언 다음으로 하면 정상 동작합니다. 함수 선언은 사각지대에 있지만, 함수 호출, 즉 실행순서는 변수 선언 다음이기 때문입니다.
브라우저 렌더링(rendering)은 HTML, CSS, JavaScript 등의 문서가 브라우저에서 출력되는 과정을 의미합니다. 브라우저는 렌더링 엔진을 가지고 다음과 같은 과정으로 렌더링합니다.
cf. 꼬리질문 대비:
리플로우는 브라우저가 렌더링 과정에서 생성한 트리를 다시 생성하는 것을 의미하고, 리페인트는 이 트리를 바탕으로 화면에 렌더링하는 페인트를 다시 수행하는 것을 의미합니다.
좀 더 자세히 설명하자면, 브라우저는 렌더링 과정에서 DOM 트리와 CSSOM 트리를 생성하고, 이를 합쳐 Render트리를 생성합니다. 만약 DOM이 변경되면 이 트리들이 다시 생성되는데 이를 리플로우라고 합니다.
페인트는 브라우저가 이 Render 트리를 화면에 렌더링하는 것을 의미하는데요, 리플로우가 발생하면 이 트리가 다시 생성되므로 이 페인트도 다시 수행해야 합니다. 즉 페인트를 다시 하는 것을 이름그대로 리페인트라고 합니다.
리플로우는 CPU를 많이 차지하고, 리페인트는 GPU를 많이 차지하므로 이 과정이 잦다면 프레임 드랍(Frame Drop)이 발생할 수 있습니다. 이는 사용자 경험에도 좋지 않기 때문에, 리페인트와 리플로우를 방지하려면 불필요한 레이아웃을 줄이고, CSS에서 레이아웃, 페인트를 발생시키는 속성들을 알아두어 가급적 리페인트만 발생하는 속성을 사용하는 것이 좋습니다.
반응형 웹은 디바이스마다 다른 브라우저의 크기에 실시간으로 반응하여, 그 크기에 따라 레이아웃이 변하는 웹을 의미합니다. 하나의 소스 코드로 pc, 태블릿, 모바일 등 모든 스크린에 최적화된 웹 사이트를 구축할 수 있는 방법론입니다.
반응형 웹은 하나의 소스만 사용하기 때문에 효율적인 유지보수가 가능하고, 검색엔진 최적화 유리하다는 장점이 있습니다. 그러나 모바일 전용, 혹은 PC 전용 사이트에 비해 소스가 많아 사이트 속도가 저하될 수 있으며, 여러 브라우저의 스펙에 맞춰야 하기에 웹브라우저 호환성 문제가 생길 수 있다는 단점이 있습니다.
콜 스택은 프로그램 상 현재 위치가 어디인지 기록하며 스택 구조인 만큼 한 번에 한 작업만 가능합니다. JavaScript는 이 콜 스택이 하나인 싱글 스레드 언어입니다.
자바스크립트는 코드를 한 줄씩 처리하다가 함수 실행구문을 만났을 때 해당 함수를 콜 스택의 가장 상단에 차례대로 저장합니다. 그리고 상단의 함수가 실행되면 바로 제거할 수 있습니다.
이 콜 스택에 쌓이는 개별 데이터를 스택 프레임(Stack Frame)라고 하며, 만약 쌓인 스택 프레임의 수가 콜 스택의 용량을 초과할 때는 스택 오버플로우(Stack Overflow) 에러가 발생했다고 합니다.
이름에서 알 수 있듯이 이 콜 스택은 스택구조를 갖고 있기 때문에 처음 들어간 스택이 나중에 처리되고, 나중에 들어간 스택이 먼저 처리되는 특징을 갖고 있습니다. 이를 이용해 스택을 추적할 수도 있습니다.
프론트엔드 개발에서 번들링이란, 웹 애플리케이션을 제공하기 위한 파일 묶음을 만드는 것을 의미합니다. 번들링은 다음과 같은 상황을 해결하기 위해 필요합니다.
만약 여러 js 파일에서 같은 변수를 사용하고 있어 변수 간 충돌이 일어난 경우나,
프레임워크 코드가 무거워서 파일의 사이즈를 줄여야 하는 경우,
배포 코드가 읽기 쉬워 접근이 쉬운 경우에 주로 필요합니다.
이처럼 번들링은 용량을 줄이면서 파일을 통합하기 위해 필요합니다. 이렇게 파일의 용량이 줄어들면 퍼포먼스가 좋아져 사용자에게도 더 나은 UX를 제공할 수 있게 됩니다.
Virtual DOM은 가상 DOM이라고도 하며, 리액트에서 실제 DOM의 사본을 이용해 만든 가상의 DOM 객체를 의미합니다. 가상 DOM은 추상화된 자바스크립트 객체의 형태를 가지고 있습니다.
React는 이 가상 DOM을 활용해 DOM의 바뀐 부분을 확인한 뒤 실제 DOM에 적용하는 방식으로 동작합니다.
이 가상DOM을 사용하면 DOM의 변경이 잦을 때 DOM 전체가 아닌 바뀐 부분만 렌더링하기 때문에 효율적이기 때문입니다. 이 과정을 통해 최소한의 작업으로 실제 DOM을 업데이트하여 더 빠른 렌더링이 가능해지고, 사용자 입장에서는 새로고침 없이 빠른 웹사이트의 동작을 경험할 수 있어 UX에도 좋은 영향을 줄 수 있습니다.
가장 큰 차이로 클래스 컴포넌트에서 사용했던 기능들을 함수 컴포넌트에서도 사용할 수 있도록 함수 컴포넌트에서는 리액트 Hook이라는 메서드를 사용한다는 것입니다.
좀 더 자세히 설명하자면 리액트에서 함수 컴포넌트를 사용하기 이전에는 클래스 컴포넌트를 사용했으며 함수 컴포넌트의 장점으로 인해 현재는 주로 함수 컴포넌트를 사용하게 되었습니다.
클래스 컴포넌트는 복잡할수록 상태 로직을 재사용하기 어려운 반면, 함수형 컴포넌트가 좀 더 직관적이고 보기 쉽다는 장점이 있습니다. 때문에 과거 클래스 컴포넌트에서 함수형 컴포넌트로 넘어가면서 상태를 저장하고 사용하는 등 여러 기능을 보완하고자 리액트 Hook이라는 메서드가 등장하게 되었습니다. 이 Hook은 클래스 컴포넌트에서는 사용할 수 없습니다.
React Hook은 크게 2가지 사용 규칙이 있습니다.
첫째, 리액트 함수의 최상위에서만 호출해야 합니다. 반복문, 조건문, 중첩된 함수 내에서는 사용할 수 없습니다.
두번째, 함수형 컴포넌트와 커스텀 Hook 내에서만 사용해야 합니다. 일반 JavaScript 함수 안에서는 사용할 수 없습니다.
아래의 node.js, 싱글 스레드, event loop는 다음의 자료를 참고했습니다.
https://medium.com/zigbang/nodejs-event-loop%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0-16e9290f2b30
https://www.korecmblog.com/node-js-event-loop/
정확하게 말하면 node는 여러 개의 스레드를 가지고 있어 싱글 스레드가 아닙니다. 그러나 자바스크립트를 실행하는 스레드는 콜스택 단 하나이기에 node를 싱글스레드 라고도 합니다.
노드는 자바스크립트 엔진인 v8 과 비동기를 처리하는 libuv library로 이뤄져 있습니다.
자바스크립트는 하나의 콜 스택을 사용해 코드를 차례대로 실행하기에 비동기 처리를 할 수 없지만, 자바스크립트를 구동하는 환경인 node를 사용하면 libuv가 제공하는 이벤트 루프를 사용해 비동기 작업을 동기처럼 사용할 수 있게 됩니다. 이 이벤트 루프가 싱글스레드이고 실제적으로 자바스크립트를 처리할 수 있는 메인스레드여서 node.js를 싱글스레드 라고 합니다.
자바스크립트 엔진은 콜 스택을 사용해 작업을 처리하기 때문에 싱글 스레드라고도 하지만, 비동기를 처리할 때는 자바스크립트를 구동하는 환경인 브라우저나 node.js 의 태스크 큐, 이벤트 루프를 사용해 처리합니다. 태스크 큐는 비동기 처리 함수의 콜백함수, 이벤트 핸들러 등을 임시 보관합니다. 이벤트 루프는 이 태스크 큐에 대기 중인 함수를 확인하고 콜스택이 비었다면 태스크 큐에서 대기 중인 함수를 콜스택으로 이동시킵니다. 이러한 방법을 통해 Javascript 엔진이 싱글 스레드여도 비동기 호출이 가능하게 됩니다.
이벤트 루프는 자바스크립트에서 비동기 처리를 할 때 태스크 큐에 대기 중인 비동기 함수의 콜백함수, 이벤트 핸들러 등을 콜 스택으로 이동시키는 역할을 합니다.
자바스크립트 엔진은 비동기 처리를 할 때는 자바스크립트를 구동하는 환경인 브라우저나 node.js 의 태스크 큐, 이벤트 루프를 사용해 처리합니다. 태스크 큐는 앞서 언급한 비동기 처리 함수의 콜백함수, 이벤트 핸들러 등을 임시 보관하고 이벤트 루프는 이 태스크 큐에 대기 중인 함수가 있는지, 콜스택에 실행 중인 실행 컨텍스트가 있는지 반복적으로 확인합니다. 만약 콜스택이 비었다면 태스크 큐에서 대기 중인 함수를 FIFO 방식, 즉 순차적으로 태스크 큐에서 콜스택으로 이동시킵니다.
예를 들어 타이머 함수 setTimeout을 실행하면, setTimeout의 콜백함수 평가와 실행은 js엔진이 하지만 타이머 설정, 콜백함수 등은 태스크 큐에 임시로 보관됩니다.
그리고 콜스택에서 작업을 처리하고 나서 이벤트 루프는 콜스택에 실행 컨텍스트 유무를 판별하고, 콜스택이 비었다면 태스크 큐에 대기 중인 함수를 순차적으로 콜스택으로 이동시킵니다. 만약 프로미스의 후속 처리 메서드를 보관하는 마이크로태스크 큐에 대기하고 있는 함수가 있다면 이벤트 루프는 태스크 큐보다 마이크로태스크 큐를 우선하여 콜스택으로 이동시킵니다.
(► 가비지 컬렉션이란?
가비지 컬렉션은 프로그램에서 더 이상 사용하지 않는 메모리를 자동으로 정리하는 것이다.
C 언어 같은 저수준 언어에서는 메모리 관리를 위해 개발자가 스스로 메모리를 할당하고 해제해야 한다.
그러나 JavaScript는 C언어와는 반대로 고수준 언어로 객체가 생성되었을 때 자동으로 메모리를 할당하고 필요하지 않다면 자동으로 해제하는 가비지 컬렉션이 내장되어 있다.
이 가비지 컬렉션이 어떻게 동작하는지, JavaScript가 어떻게 메모리를 관리하는지 알아야 앱의 속도 저하, 예기치 못한 종료, 느린 응답 속도와 같은 문제들이 왜 일어나는지 알 수 있다.
고수준 언어와 저수준 언어
저수준 언어는 기계 친화적인 언어로 레지스터 및 메모리와 직접 상호 작용을 할 수 있다.
컴파일러, 인터프리터가 필요하지 않아 전반적으로 빠르게 실행되는 응용 프로그램을 빌드하는 데에 사용된다.
고수준 언어는 인간이 이해하기 쉬운 언어로 다양한 작업을 수행하는 프로그램을 개발할 수 있습니다. 컴파일러 또는 인터프리터를 사용하여 컴퓨터가 읽을 수 있는 기계어 코드로 변환해야 하며, 하드웨어와 직접 상호 작용하지는 않는다.) => 설명 정리 필요
Stack은 데이터(data)를 순서대로 쌓는 구조로 양동이에 블록을 쌓는 모양새를 생각하면 쉽습니다. 먼저 들어간 데이터는 제일 나중에 나오고, 마지막에 있는 데이터가 먼저 나오는 선입후출, 후입선출의 구조를 가지고 있습니다. 입출력 방향이 같습니다.
이 스택은 조회가 필요하지 않아 데이터를 저장하고 검색하는 프로세스가 매우 빠르며, 최상위 블록인 top에서 데이터를 저장하고 검색하면 된다는 장점이 있습니다.
반면, 큐(Queue)는 대기행렬 이라는 뜻으로 줄을 서서 기다리듯이 데이터를 입력된 순서대로 처리합니다. 먼저 들어간 데이터가 제일 처음에 나오는 선입선출의 구조를 가지고 있습니다. 두 개의 입출력 방향을 가지고 있으며 두 곳으로 접근이 가능합니다. 만약 입출력 방향이 같다면 Queue 자료구조라고 볼 수 없습니다.
Tree는 이름 그대로 나무를 거꾸로 뒤집어 놓은 듯한 모습으로 마치 뿌리가 뻗어나가는 모양을 하고 있습니다. 단방향 그래프이고, 계층적 자료구조입니다.
계층적 구조란 하나의 데이터 바로 아래에 하나 이상의 데이터를 한 번에 한 경로씩 연결되어있는 것을 의미하며 마치 뿌리처럼 위에서 아래 한 방향으로만 뻗어나가는 모양새를 하고 있습니다.
때문에 하나의 데이터 아래에 여러 개의 데이터가 존재할 수 있는 비선형 구조라고도 하고,
아래로만 뻗어나가기 때문에 사이클(cycle)이 없다고도 합니다.
Graph는 여러개의 점들이 서로 복잡하게 연결되어 있는 관계를 표현한 자료구조로 마치 거미줄처럼 여러 개의 점들이 선으로 이어져 있는 복잡한 네트워크망과 같은 모습을 가지고 있습니다.
트리는 이 그래프의 일종으로, 한쪽으로 연결되어 있고 한 방향으로부터 뻗어나가는 단방향 그래프라고 할 수 있습니다.
(설명 작성 예정)
질문 이해
질문을 잘 이해했는가?
질문에 대한 답변이 맞는 내용인가?
개념 설명에 맞는 예시였는가?
답변 명확성
이해하기 쉬운 답변인가?
개념 설명이 간단 명료한가?
불명확하게 설명한 부분이 없었는가?
정확한 CS용어를 사용했는가?
자연스러움
개념 설명, 예시가 인위적이지 않았는가?
모르는 부분은 솔직하게 인정했는가?
자세와 표정이 어색하지 않은가?