프론트엔드 엔지니어 면접에서 자주 나오는 질문 1편

(추후에도 정리할 수 있음 더 정리하기…)

해당 영상에서 나온 것들을 위주로 정리

1. Virtual-DOM이란?

Virtual DOM은 무엇인가요?
Virtual DOM (VDOM)은 UI의 이상적인 또는 “가상”적인 표현을 메모리에 저장하고 ReactDOM과 같은 라이브러리에 의해 “실제” DOM과 동기화하는 프로그래밍 개념입니다. 이 과정을 재조정이라고 합니다.
(React 공식 문서 참조)

(1) 브라우저는 HTML을 전달 받으면 이를 파싱하여 DOM 노드로 이루어진DOM 트리를 생성한다
(2) CSS파일과 각 엘리먼트의 inline 스타일을 파싱, 스타일 정보를 사용해서 Render 트리를 생성한다
(3) 이 노드 스타일을 동기적으로 attachment하고 렌더 트리가 다 만들어지면 레이아웃(reflow) 과정을 통해 노드들에 스크린의 좌표가 주어지며 위치가 정해진다
(4) 렌더링이 끝나면 paint() 메소드를 통해 렌더링된 요소들에 색을 입힘

그렇다면 왜 Virtual DOM은 효율적인걸까?

  • DOM을 직접 조작한다면 그 때마다 레이아웃의 재계산과 리렌더링이 일어날 것
  • 이 변화가 일어날 때 Virtual DOM에서 계산한다면 이 DOM은 가상 DOM이기 때문에 렌더링되지 않고, 그렇기 때문에 연산 비용의 절감 효과가 있다
  • Virtual DOM은 DOM fragment를 관리하는 과정을 자동화 및 추상화하고 어떤 부분이 바뀌었는지를 파악해준다

velopert님 블로그를 참조함

2. useMemo와 useCallback

(1) useMemo

1
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

메모이제이션된 값을 반환합니다 (React 공식 문서)

  • 복잡한 함수의 return값을 기억해야 할 때 사용
  • 렌더링 중에 실행되므로 사이드 이펙트가 일어나는 것을 useMemo로 처리해선 안된다 → useEffect()를 사용할 것!

(2) useCallback

1
2
3
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);

메모이제이션된 콜백을 반환합니다 (React 공식 문서)

  • 불필요한 렌더링을 방지하기 위해 설계된 함수
  • 의존성을 갖는 reference(여기서는 [a, b])가 변경되었을 때 실행됨

→ 사실 useMemo()나 useCallback()은 (렌더링 최적화를 위해 사용 가능하지만) 이제 useState()와 useEffect()로 거의 다 처리할 수 있다

참고자료: React.memo() 현명하게 사용하기

3. 리렌더링의 조건

  • React에서 렌더 순서는 App → 부모 → 자식 순
  • React에서 마운트 순서는 자식 → 부모 → App 순
  • React는 컴포넌트의 상태가 변하면 컴포넌트의 리렌더링을 발생시킨다
    • 자신의 상태가 변경될 때
    • 부모 컴포넌트가 리렌더링 될 때
    • 자신이 전달받은 props가 변경될 때
    • forceUpdate()가 실행될 때

4. 자바스크립트의 실행 컨텍스트

참고 페이지

  • 실행 컨텍스트란 실행 가능한 코드를 형상화하고 구분하는 추상적 개념으로 코드가 실행되기 위해 필요한 환경
  • 실행 가능한 코드는 전역 코드, Eval 코드, 함수 코드로 나뉜다

(1) 실행 컨텍스트의 실행 과정

  • 컨트롤이 실행 가능한 코드로 이동하면 새 실행 컨텍스트가 생성된다
  • 전역 코드로 컨트롤이 진입하면 전역 실행 컨텍스트가 생성되고 실행 컨텍스트 스택에 쌓인다(이 전역 실행 컨텍스트는 웹페이지를 나가거나 브라우저를 닫을 때 까지 유지됨)
  • 함수를 실행하면 해당 함수의 실행 컨텍스트가 생성되고 직전에 실행된 코드 블록의 실행 컨텍스트 위에 쌓인다
  • 함수 실행이 끝나면 실행 컨텍스트를 파기하고 직전의 실행 컨텍스트에 컨트롤을 반환

(2) 실행 컨텍스트의 구조

  • 실행 컨텍스트는 변수 객체(Variable Object), 스코프 체인, this로 이루어져 있다
  • 변수 객체는 변수, 매개변수, 인수정보, 함수 선언 등을 담고 있다
  • 전역 컨텍스트는 전역 함수와 전역 변수를 가지고, 함수 컨텍스트는 매개변수 객체와 내부 함수, 지역 변수를 갖는다
  • 스코프 체인은 해당 전역/함수 컨텍스트가 참조할 수 있는 변수, 함수 선언 등의 정보를 담고 있는 전역 객체, 활성 객체의 리스트를 가리킨다
  • 실행 컨텍스트 스택 내 활성 객체를 선두로 리스트의 마지막은 당연히 전역 객체를 가리킨다
  • 자바스크립트 엔진은 스코프 체인을 통해 렉시컬 스코프(함수가 중첩될 때 상위 스코프를 따라 올라가는 것)를 파악한다
  • 자바스크립트의 함수는 호출 될 때 매개변수 인자 이외에 arguments 객체와 this를 전달 받는다
  • this는 어떤 스코프에 위치해 있느냐에 따라 다른데 전역 객체에 있다면 this는 window(브라우저), global(Node.js) 객체를 의미한다
  • 메소드의 내부함수나 콜백의 경우에도 this는 전역 객체에 바인딩 된다
  • 함수가 객체의 프로퍼티 값이라면 메서드로 호출되는데, 이 메서드 내부의 this는 해당 메서드를 호출한 객체에 바인딩된다
  • new 연산자로 생성자를 호출할 경우 자바스크립트는 빈 객체를 먼저 생성하여 this를 바인딩하고 바인딩된 this를 통해 프로퍼티를 생성하여 객체를 리턴한다

5. 클로저

  • 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서라면 클로저가 사용된다
  • 클로저는 반환된 내부함수가 자신이 선언되었을 때의 환경인 스코프를 기억하고 자신이 선언됐을 때의 스코프 밖에서 호출되어도 그 스코프에 접근할 수 있는 함수를 말한다
  • 말이 어려운데 클로저는 함수 안에 함수가 있게 되면 기본적으로 생성된다
  • 그렇게 되면 자연스레 스코프 체인이 형성될 텐데 이 스코프 체인이 형성될 때 변수 값들을 보존하고 기억하게 된다 (이는 메모리에서 해당 함수가 없어질 때까지 존재함)

6. 이벤트 루프와 이벤트 버블링, 이벤트 위임

참고 페이지: 이벤트 버블링, 이벤트 캡처 그리고 이벤트 위임까지

  • 이벤트 버블링은 특정 화면 요소에 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되는 특성 → 이는 HTML요소가 트리 구조를 가지기 때문
  • 이런 버블링은 stopPropagation()을 통해 막을 수 있다
  • 이벤트 캡쳐는 이와 반대 방향으로 진행되는 전파 방식
  • 하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트를 제어하기 위한 것이 이벤트 위임

7. promise, async, await

자바스크립트에서 비동기 처리란?

  • 특정 로직의 실행이 끝날때 까지 기다리지 않고 나머지 코드를 먼저 실행하는 것
  • 이를 해결하기 위해 콜백 함수를 사용했었음
  • promise는 이 비동기 처리에 사용되는 객체로 Pending(대기), Fulfilled(이행), Rejected(실패)의 3가지 상태를 가진다
  • new promise()가 호출되면 대기 상태가 되며 첫번째 매개변수로 콜백 함수를 선언할 수 있으며 이 콜백 함수는 resolve와 reject 인자를 가진다
  • resolve가 실행되었을 때에 이행 상태가 되고 reject가 실행되었을 때 실패 상태가 된다
  • 이행 상태가 된다면 then()을 사용하여 처리 결과 값을 받을 수 있고 실패 상태가 된다면 catch()로 처리 결과 값을 받을 수 있다

비동기 처리 패턴에 사용되는 async와 await

  • 코드의 순서를 보장하기 위해 사용하는 예약어(async)와 연산자(await)
  • await의 처리 코드는 promise를 반환해야 한다
  • async와 await의 예외를 처리하려면 try catch문을 사용해야 한다

8. 자바스크립트의 가비지 컬렉션

  • 자바스크립트는 도달 가능성(reachability)이라는 개념을 사용해 메모리를 관리한다
  • 가비지 컬렉터는 루트 정보를 수집하고 이를 기억한다
  • 루트가 참조하고 있는 모든 객체를 방문하고 이것들을 기억한다
  • 기억한 모든 객체에 방문하여 그 객체가 참조하는 객체까지 기억한다 (한 번 방문하면 다시 방문하지 않음)
  • 루트에서 도달 가능한 모든 객체를 방문할 때까지 반복한다
  • 이 때 기억되지 않은 모든 객체를 메모리에서 삭제
  • 최적화 기법으로 세대별 수집(새로운 객체/오래된 객체로 나누어 감시), 점진적 수집(가비지 컬렉션을 나누어 수행), 유휴 시간 수집(CPU가 유휴 상태일 때만 실행) 기법을 사용함

9. www.google.com을 입력 했을 때 일어나는 일

잘 정리된 문서가 있으므로 링크만 남김

10. 브라우저가 display: none;을 처리하는 법

참고 페이지 : 렌더링 트리 생성, 레이아웃 및 페인트

  • DOM과 CSSOM 트리는 결합해 렌더링 트리를 형성
  • 페이지를 렌더링하는 데 필요한 노드만 포함시킴
  • 레이아웃을 통해 위치와 크기 계산
  • 페인트 및 픽셀 렌더링

이 때 display: none;은 요소가 보이지 않고 레이아웃에도 포함되지 않도록 렌더링 트리에서 요소가 완전히 제거됨 (visibility: hidden은 레이아웃에서 공간을 차지함)