프론트엔드 인터뷰 예상 질문 답해보기

cansweep·2022년 8월 13일
1
post-thumbnail

이 글은 주어진 질문에 대해 주관적으로 답을 적는 기록이기 때문에 틀린 답을 적었을 수도 있습니다. 만약 오류를 발견했다면 언제든지 지적해 주세요.

SPA의 렌더링 기법 중 SSG가 SSR에 비해 성능이 좋은 이유는 무엇인가요?

SSG가 SSR에 비해 성능이 좋은 이유는 빌드 타임에 페이지를 생성하기 때문입니다. SSG는 빌드 타임에 페이지를 생성하며 이를 CDN에 저장합니다. 그리고 페이지에 대한 요청이 들어오면 CDN에서 미리 만들어둔 페이지를 가져와 훨씬 빠르게 유저에게 페이지를 보여줄 수 있습니다.

반면 SSR은 런타임에 페이지가 생성됩니다. 즉, 페이지에 대한 요청이 들어왔을 때마다 페이지를 새로 그리기 때문에 SSG에 비해 느리게 페이지를 제공합니다.

그러면 SSR은 언제 사용하나요?

SSG는 Static Site Generator라는 말 그대로 정적 사이트 생성기입니다. 빌드 타임에는 유저의 요청을 알 수 없고 따라서 유저의 요청에 따라 api의 바디가 달라지거나 url의 파라미터가 달라지는 경우에는 사용할 수 없습니다.

이렇게 유저의 요청에 따라 달라질 가능성을 포함하거나 페이지를 렌더링하는데에 사용되는 데이터가 빈번히 변경되는 경우 SSG보다 SSR을 사용하는 것이 좋습니다.

polling과 SSE, WebSocket에 대해 설명해 주세요.

먼저 polling은 클라이언트가 일정한 주기로 서버에 요청을 보내는 방법입니다. 따라서 지속적인 HTTP 요청이 발생하기 때문에 리소스 낭비가 일어날 수 있습니다.

sse, server sent event는 서버가 일방적으로 클라이언트에게 데이터를 보내는 방법입니다. 클라이언트가 주기적으로 요청을 보내지 않고 첫 요청 이후 서버가 연결을 유지한 채 데이터를 클라이언트에게 전송합니다.

websocket은 양방향 통신이 가능합니다. 서버와 클라이언트가 TCP 연결을 통해 실시간으로 데이터를 주고받을 수 있습니다. polling처럼 주기적으로 요청과 응답을 주고 받는 것이 아니고 sse처럼 연결을 유지하지만 sse와 달리 일방적으로 데이터가 흐르지 않습니다.

Redux의 상태를 변이하고 상태를 구독하는 컴포넌트가 리렌더링되기까지의 과정을 설명해 주세요.

사용자의 상호작용이 발생하면 dispatch를 통해 redux의 store에 관련 내용(상호작용에 대한 미리 정의된 type 같은)을 전달합니다. store는 reducer 함수를 실행시켜 상태값을 새로운 값으로 업데이트합니다. 그리고 이 상태를 구독한 컴포넌트들에게 상태값이 업데이트되었음을 알립니다.
store의 데이터를 사용하고 있는 각 컴포넌트들은 업데이트한 상태를 사용한 부분이 있는지 확인하고 있다면 해당 부분을 리렌더링합니다.

브라우저가 CSS selector를 해석하는 방법과 성능 향상을 위해 어떻게 작성해야 하는지 설명해 주세요.

브라우저는 selector를 오른쪽에서 왼쪽으로 읽습니다. 즉, 제일 오른쪽에 있는 selector를 DOM에서 모두 찾은 후 왼쪽 selector로 넘어가며 해당하는 부모를 가진 요소들을 계속 필터링해 해당하는 요소를 찾습니다.

성능 향상을 위해서는 브라우저가 해당하는 요소를 찾기까지 비교하는 과정을 줄일 수 있도록 selector를 복잡하게 사용하는 것을 피하거나 태그 대신 id나 class selector를 사용하는 것이 있습니다.

브라우저가 화면을 렌더링하는 과정에 대해 설명해 주세요.

브라우저의 렌더링 엔진은 먼저 HTML 문서를 파싱해 DOM 트리를 구축합니다. 그 다음으로 CSS 파일과 함께 포함된 스타일 요소를 파싱합니다.
파싱이 끝나면 결과들을 모아 렌더 트리를 구축하며 렌더 트리의 생성이 끝나면 어떤 요소를 정확히 어디에 배치할 지, 또 어떤 크기로 배치할지 계산하고 계산 결과를 토대로 화면에 그립니다.

script 태그의 async와 defer 속성의 차이를 설명해 주세요.

script 태그의 async 속성은 페이지 파싱과 동시에 스크립트가 다운로드됩니다.
다운로드가 끝나면 진행하던 페이지 파싱을 중단하고 스크립트를 실행합니다.

script 태그의 defer 속성은 페이지 파싱과 동시에 스크립트가 다운로드됩니다.
하지만 async 속성과 다른 점은 페이지 파싱이 끝나면 스크립트를 실행한다는 점입니다.
만약 defer 속성을 사용한 script 태그가 여러 개 존재한다면 각 스크립트는 페이지에 등장한 순서대로 실행됩니다.

렌더링 성능을 향상할 수 있는 방법을 알고있는 대로 설명해 주세요.

화면을 그릴 때 쓰이는 이미지들의 크기를 줄이거나 lazy loading을 적용하여 당장 화면 내에서 쓰이지 않는 이미지들을 늦게 불러오는 식으로 렌더링 성능을 향상할 수 있습니다.

이와 비슷하게 이미지 외에도 폰트, 동영상 등의 용량을 줄이는 것도 렌더링 성능 향상에 도움이 됩니다.

또 자주 쓰이거나 값을 리턴하는데 많은 시간이 소요되는 함수를 메모이제이션하여 좀 더 빠르게 계산 결과를 구할 수 있습니다.

React의 useRef를 어떻게 쓸 수 있는지 설명해 주세요.

useRef는 .current 속성에 변경 가능한 값을 담고 있는 상자처럼 사용할 수 있습니다. 이 상자에는 ref 객체가 들어갈 수 있는데 ref는 DOM 노드나 React element에 접근할 수 있는 방법을 제공합니다.

일반적으로 ref를 사용해야 할 때는 포커스, input 등을 관리할 때, 애니메이션을 직접적으로 실행시킬 때, 서드 파티의 DOM 라이브러리를 React와 같이 사용할 때 입니다.

즉, 이러한 때에 useRef를 사용한다면 React는 노드가 변경될 때마다 변경된 DOM 노드에 .current 속성을 설정합니다.

SessionStorage와 LocalStorage, Cookie에 대해 설명해 주세요.

SessionStorage와 LocalStorage는 웹 스토리지의 한 종류입니다.

SessionStorage는 세션의 Storage 객체에 접근하며 이곳에 저장된 데이터는 세션이 종료될 때 같이 삭제됩니다.
페이지 세션은 브라우저가 열려있는 한 새로고침을 해도 값이 지워지지 않으며 탭 혹은 창마다 각각의 세션 스토리지가 존재하기 때문에 다른 탭/창 간에 값이 공유되지 않습니다.

LocalStorage는 Document의 Storage 객체에 접근합니다.
SessionStorage와 달리 브라우저 세션 간 값이 공유되며 데이터가 만료되지 않습니다.

Cookie는 데이터의 조각으로 이름, 값, 만료일 등의 정보를 가지고 있습니다. 클라이언트에 파일로 저장되며 브라우저는 쿠키를 저장해 두었다가 동일한 서버에 다시 요청을 보내게 될 경우 쿠키를 HTTP 요청 헤더에 담아 함께 전송합니다.

부모 컴포넌트인 A와 그의 자식 컴포넌트 B,C가 있고 둘은 형제 관계일 때,

1-1. B와 C가 컴포넌트 상태를 공유하려면 어떻게 해야하나요?

B와 C가 동일한 상태를 공유하기 위해서는 부모 컴포넌트인 A로 해당 상태를 끌어올려야 합니다.
즉, 부모 컴포넌트인 A에 상태를 선언한 뒤 B와 C에 상태 값, 상태를 바꾸기 위한 함수 등을 props로 넘겨주고 B와 C가 이를 사용할 수 있게끔 합니다.

1-2. C가 형제 노드가 아닌 컴포넌트 트리 구조 상 아주 깊은 곳으로 옮겨졌을 때 여전히 상태를 공유하려면 어떻게 해야하나요?

A와 C의 간격이 많이 멀지 않다면 A와 C 사이에 있는 모든 컴포넌트들에 상태를 props로 넘겨주어 A에 선언된 상태를 C가 사용할 수 있게끔 할 수 있습니다.

하지만 이 경우 C에서 상태 변화가 일어나면 해당 상태를 props로 가지고 있는 모든 컴포넌트에 리렌더링이 일어나게 됩니다.
또한 이러한 경우에는 props를 추적하기 어렵고 따라서 유지보수가 힘들어집니다.

따라서 C가 아주 깊은 곳으로 옮겨졌다면 해당 상태를 Redux나 Recoil 등을 사용해 전역상태로 관리하고 해당 상태가 쓰이는 곳에서 이를 구독해 쓰도록 하는 것이 좋다고 생각합니다.

이벤트 위임에 대해 설명해 주세요.

이벤트 위임이란 자식 요소가 여러 개 있을 때 각각의 자식 요소들에 이벤트 핸들러를 달지 않고 부모에 이벤트 핸들러를 달아 자식 요소들을 제어하는 방식입니다.
이벤트 위임을 사용하면 동적으로 자식 요소들을 추가할 때마다 핸들러를 달아줄 필요가 없으며 window가 추적해야 하는 이벤트 핸들러가 적어지기 때문에 자식 요소에 이벤트 핸들러를 각각 다는 것보다 성능이 좋습니다.

profile
하고 싶은 건 다 해보자! 를 달고 사는 프론트엔드 개발자입니다.

0개의 댓글