기술면접 front 4

Imnottired·2023년 3월 5일
0

이벤트 루프와 태스크 큐에 대해 설명해주세요

자바스크립트는 기본적으로 싱글 스레드로 한번에 하나의 작업만 할 수 있습니다.

이와 같은 코드가 있으면 스택에 순서대로

main() -> printSquare() -> square() -> multiply()로 push가 되고,
pop은 함수의 실행이 종료되었을 때 그 함수를 꺼내는 것이니까

multiply() -> square() -> console.log() -> printSquare() -> main()과 같은 과정으로 pop이 됩니다.

  • console.log도 함수입니다.

이런 식으로 콜 스택에 재귀적인 호출이 일어나 함수가 계속 쌓이게 되면 Maximum call stack size exceeded라는 에러메세지를 발생시킵니다.

비동기 콜백
또한 간단한 프로그램이라면 상관 없지만, 복잡한 프로그램을 구동한다고 하고 시간이 매우 오래걸리는 작업이 스택에 쌓이고 실행될 경우, 그 다음 작업은 무한정 대기하게 되는데, 이 경우를 블로킹(blocking)이라고 합니다.

이것이 문제가 되는 이유는, 블록킹이 발생할 경우 브라우저가 다른 일을 할 수가 없기 때문에 조작이 불가능해지기 때문입니다.

이러한 문제를 해결하기 위한 해결 방안이 비동기 콜백(Asynchronous Callbacks)입니다.

자바스크립트가 싱글 스레드임에도 불구하고 웹사이트에서 여러 작업을 할 수 있도록 지원해주는 것이 브라우저가 Web APIs 같은 것들을 제공해 비동기 작업을 가능하게 해주기 때문입니다!

자바스크립트 내부에는 callstack이 있는데, ajax나 setTimeout, dom event 함수와 같은 비동기 함수를 pop 과정을 거쳐 실행하게 되면, 자바스크립트 엔진은 call stack에서 web APIs(브라우저)로 함수를 보내고 정해진 시간 혹은 이벤트가 발생한 순간에 순차적으로 Callback Queue라는 곳에 적재합니다.

Callback queue에 적재된 함수들은 js의 call stack에 쌓여있던 것들이 모두 제거되었을 때 차례대로 스택에 쌓여서 실행되게 됩니다. 이것을 이벤트 루프라고 합니다.

->이후 콜백 큐는 태스크 큐라고 정정합니다. HTML 표준 스택에서 task queue로 표기하기 때문입니다.

태스크 큐와 마이크로태스크 큐
일반적인 동작과정은 위에서 설명한 것과 같은데, 세부적으로는 태스크 큐와 마이크로 태스크 큐, 2개의 큐로 나누게 되고 이는 Promise 동작 방식과 연관이 있습니다.

또한 자세한 내용으로 태스크큐와 마이크로태스크 큐 모두 제일 오래된 태스크에 우선순위를 주어 태스크를 꺼내는 우선순위 큐(priority Queue)로 동작합니다.

태스크큐에 들어가는 콜백함수들(후자)
setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI 렌더링
마이크로태스크큐에 들어가는 콜백함수들

마이크로 태스크 큐(우선)
Process.nextTick, promise, object.observe, MutationObserver
이벤트 루프는 이와 같은 2개의 큐에서 콜백함수를 꺼내야하는데, 순서는 마이크로태스크 큐가 태스크 큐보다 우선순위를 가지고 있습니다!

따라서 비동기 로직을 다룰 때 콜백 함수를 사용하게 될 경우, 이러한 우선순위를 예측하여 코드를 작성해야 합니다.

이벤트 루프는 다음을 반복합니다.
호출스택이 비었는지 지속적으로 확인합니다.
호출 스택이 비게 되면 제일 먼저 마이크로 태스크 큐를 확인하고 가장 오래된 태스크부터 꺼내서 호출스택으로 전달해 주는데, 이걸 마이크로태스크 큐가 텅 비어있을때까지 수행합니다.
모든 마이크로태스크가 처리된 직후, 렌더링 작업이 필요하면 렌더링을 수행합니다.
매크로 태스크 큐를 확인합니다.
매크로 태스크 큐에서 가장 오래된 태스크 하나를 꺼내 호출 스택에 전달해 줍니다.
다시 1번 으로 돌아갑니다.

자바스크립트는 싱글 스레드 기반의 언어지만, 자바스크립트가 구동되는 환경(Node.js, 브라우저)은 여러 스레드가 사용되는데 여러 스레드가 사용되는 구동 환경이 자바스크립트 엔진과 연동하기 위해 사용되는 장치가 '이벤트 루프' 입니다. 웹 사이트나 애플리케이션의 코드는 메인 스레드에서 실행되며, 같은 이벤트 루프를 공유합니다.

키워드 :

Callstack, queue, 스레드, 브라우저

https://narup.tistory.com/261
https://whales.tistory.com/130

Bundle 사이즈를 줄이려면 어떻게 해야하나요?

자바스크립트와 React의 성능을 최적화 하는 방법 중 하나는 Webpack을 통해서 번들 된 자바스크립트 파일의 크기를 최대한 줄이는 것이다.

Webpack 활용

JS, CSS 압축하여 번들사이즈를 줄인다.

코드 스플릿팅 (Code Splitting)

모듈 간 의존성을 자동으로 분석해 하나의 번들로 만들어주는 번들러를 통해 이 과정을 자동화 할 수 있다. 하지만 코드의 양이 너무 많아지는 경우, 하나의 번들 파일이 너무 커져, 그 파일을 불러오고 실행하는데 많은 시간이 소요될 수 있다. 코드 스플릿팅의 장점은 반드시 필요한 코드만 불러오고 요청을 병렬적으로 처리해서 로딩 속도를 개선할 수 있다는 점이다.

코드 스플릿팅에는 두 가지 차원이 있다. 하나는 webpack의 설정을 활용하는 것이고 두 번째는 React에서 lazy를 활용해서 앱의 일부를 별도의 번들로 나눌 것을 명시하는 것이다. 전자의 방법으로는 사용하는 외부 패키지 등 여러 청크에서 반복적으로 사용되는 코드를 별도의 번들로 분리하는 것이 용이하고 후자로는 앱에서 특정 페이지에서 필요한 코드만 불러올 수 있도록 번들을 분리하는 것에 용이하다.

https://medium.com/@uk960214/%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-1-%EB%B2%88%EB%93%A4-%ED%81%AC%EA%B8%B0-%EC%A4%84%EC%9D%B4%EA%B8%B0-react-webpack-minify-code-splitting-e2391e7e5f1b

default import 사용

default import와 member style import(global import) 했을 때 가져오는 파일 사이즈가 다르다.
(2021.07 업데이트 - 추가 설명: lodash는 CJS 모듈을 사용하고 default exports를 한다. ESM에서 named import하면 다른 export에 대해 tree shaking이 안되기 때문에 default import와 named import의 파일 사이즈가 다르게 된다.)
// member style imports(global import):
import { Row, Grid as MyGrid } from 'react-bootstrap';
import { merge } from 'lodash';

// default style imports:
import Row from 'react-bootstrap/lib/Row';
import MyGrid from 'react-bootstrap/lib/Grid';
import merge from 'lodash/merge';

import { time } from 'lodash' // 69.4kb (gzipped: 24.5kb)
import times from 'lodash/times' // 2.8kb (gzipped: 1.2kb)

@next/bundle-analyzer 를 사용해서 번들 사이즈를 분석했다. devDependencies로 설치하고, 실행 시 ANALYZE=true npm run build 를 실행하면 build하면서 번들 사이즈를 분석한다.

키워드 :

코드 스플리팅, 웹팩, 번들사이즈

타입스크립트를 사용하는 이유는 무엇인가요?

컴파일 언어, 정적 타입 언어
자바스크립트는 동적 타입의 인터프리터 언어로 런타임에서 오류를 발견할 수 있습니다. 이에 반해 타입스크립트는 정적 타입의 컴파일 언어이며 타입스크립트 컴파일러 또는 바벨(Babel)을 통해 자바스크립트 코드로 변환됩니다. 코드 작성 단계에서 타입을 체크해 오류를 확인할 수 있고 미리 타입을 결정하기 때문에 실행 속도가 매우 빠르다는 장점이 있습니다. 하지만 코드 작성 시 매번 타입을 결정해야 하기 때문에 번거롭고 코드량이 증가하며 컴파일 시간이 오래 걸린다는 단점이 있습니다.

높은 수준의 코드 탐색과 디버깅
타입스크립트는 코드에 목적을 명시하고 목적에 맞지 않는 타입의 변수나 함수들에서 에러를 발생시켜 버그를 사전에 제거합니다. 또한 코드 자동완성이나 실행 전 피드백을 제공하여 작업과 동시에 디버깅이 가능해 생산성을 높일 수 있습니다. 실제로 한 연구에 따르면 모든 자바스크립트 버그의 15%가 사전에 타입스크립트로 감지할 수 있다고 합니다.

강력한 생태계
타입스크립트는 그리 오래되지 않은 언어임에도 불구하고 강력한 생태계를 가지고 있습니다. 대부분의 라이브러리들이 타입스크립트를 지원하며 마이크로소프트의 비주얼 스튜디오 코드(VSCode)를 비롯해 각종 에디터가 타입스크립트 관련 기능과 플러그인을 지원합니다.

키워드 :

동적언어, 정적언어, 버그(오류), 타입

쿠키, 세션, 웹스토리지의 차이에 대해 설명해주세요

쿠키(Cookie)

클라이언트(브라우저)에 저장되는 키와 같이 들어있는 작은 파일이다.
클라이언트의 상태 정보를 로컬에 저장했다가 참조한다.
클라이언트에 300개까지 쿠키저장 가능, 하나의 도메인당 20개의 값만 가질 수 있으며, 하나의 쿠키값은 4KB까지 저장이 가능하다.
Response Header에 Set-Cookie 속성을 사용하면 클라이언트에 쿠키를 만들 수 있다.
쿠키는 사용자가 따로 요청하지 않아도 브라우저가 Request 시에 Request Header를 넣어서 자동으로 서버에 전송한다.

키워드 :

클라이언트, 파일, 도메인, 4kb

세션(Session)

사용자 정보를 파일 브라우저에 저장하는 쿠키와 달리 세션은 서버 측에서 관리한다.
서버에서 클라이언트를 구분하기 위해 세션 ID를 부여하며, 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증상태를 유지한다.
접속 시간에 제한을 두어 일정 시간 응답이 없다면 정보가 유지되지 않게 설정 가능하다.
데이터를 서버에 두기 때문에 쿠키보다 보안에 좋지만, 사용자가 많아질수록 서버 메모리를 많이 차지하게 된다.

키워드 :

서버, id, 인증

쿠키와 세션 간단 비교

데이터 저장위치: 쿠키는 클라이언트, 세션은 서버
보안: 저장위치 때문에 쿠키는 스니핑에 당할 우려가 있지만, 세션은 쿠키를 이용해 세션 아이디만 저장하고 서버에서 처리하기때문에 보안성은 쿠키<세션
라이프 사이클: 쿠키는 브라우저를 종료해도 만료기간이 남아있으면 존재, 세션은 브라우저 종료 시 만료기간에 상관없이 종료
속도: 쿠키>세션

키워드 :

보안, 저장위치, 속도, 라이프 사이클

웹 스토리지(Web Storage)

클라이언트에 데이터를 저장할 수 있도록 HTML5부터 추가된 저장소
간단한 Key-Value 스토리지 형태
쿠키와 달리 자동 전송의 위험성이 없음
오리진(Origin)(도메인,프로토콜,포트) 단위로 접근이 제한되는 특성 덕분에 CSRF로 부터 안전
쿠키보다 큰 저쟝 용량 지원(모바일 2.5MB, 데스크탑 5~10MB)
서버가 HTTP 헤더를 통해 스토리지 객체를 조작할 수 없음(웹 스토리지 객체 조작은 JavaScript 내에서만 수행)
오직 문자형(string) 데이터 타입만 지원
로컬 스토리지(Local Storage)와 세션 스토리지(Session Storage)가 있으며, 같은 Storage 객체를 상속하기 때문에 메서드가 동일

키워드 :

HTML5, KEY-VALUE, 5MB, 문자형

로컬 스토리지(localStorage)

사용자가 데이터를 지우지 않는 이상, 브라우저나 OS를 종료해도 계속 브라우저에 남아있음 (영구성)
단, 동일한 브라우저를 사용할 때만 해당
지속적으로 필요한 데이터 저장(자동 로그인 등)

세션 스토리지(sessionStorage)

데이터가 오리진 뿐만 아니라 브라우저 탭에도 종속되기 때문에, 윈도우나 브라우저 탭을 닫을 경우 제거
일시적으로 필요한 데이터 저장(일회성 로그인 정보, 입력폼 저장 등)

키워드 :

영구성, 휘발성, 브라우저

크로스 브라우징 경험이 있으신가요?

오늘날 전세계의 영향을 끼치는 정보의 바다🌊 웹 브라우저는 초기 브라우저 시장점유 전쟁 동안 서로간의 배타적인 기술을 도입하면서 똑같은 웹 페이지도 브라우저에 따라 다르게 보이고 서로 다른 기술로 인해 많은 혼란을 겪어 왔습니다. 따라서 상호 호환 브라우징(cross browsing)의 미성숙으로 웹 기술이 혼란 상태에 빠지게 됩니다.

웹 사이트 또는 웹 응용 프로그램이 서로 다른 브라우저에서 작동하고 브라우저 기능이 없거나 부족할 때 제한된 기능을 최대한 유지하도록 하는 것.
즉, 표준에 따라 브라우저와 관계없이 웹 페이지 기능을 만듦으로써 모든 웹 브라우저 사용자가 방문했을 때 정보로써의 소외감을 느끼지 않도록 하는 것입니다.

이에 대처하기 위해서는 개발할 기능들을 정의하고, 지원하는 브라우저를 파악한다.
주 타겟층을 예측하는 것도 중요하다.
어르신들은 인터넷이라고 생각하는 것은 IE라고 생각하기 때문에, 이런 점들을 고려해야한다.

라이브러리를 사용하는 것도 중요하다. underscore.js,HTML5 polyfill 라이브러리
(cost 발생)

해당 함수가 있는지 확인하여 지원하는 브라우저인지 확인한다.

반응형웹 브라우저, 이미지

키워드 :

브라우저, IE, 표준

https://onlydev.tistory.com/1
https://asfirstalways.tistory.com/237

웹 소켓을 사용해보셨나요?

약속을 영어로 표현하면, 프로토콜이라고 합니다.

HTTP가 등장하기 이전 세대에서 통신한다 함은, 터미널 창에서 딱딱한 텍스트를 주고 받는 것이었어요.

웹소켓-정리
그런데 HTTP가 등장하니, 시각적으로나 정보량 차원에서 엄청나게 멋진 문서를 주고 받을 수 있게 되었습니다.

그런데 HTTP에는 무서운 대전제가 붙습니다.

사용자가 URL을 요청할 때에만! 서버에서 해당 페이지를 꺼내주는 식이라는 겁니다.

거꾸로 말하자면, 사용자는 서버로부터 새로운 정보를 받아보기 위해서, 반드시 새로운 URL을 요청해야 한다는 말과 같습니다.

웹소켓

웹소켓은 HTML5 표준 기술로, 사용자의 브라우저와 서버 사이의 동적인 양방향 연결 채널을 구성합니다.

Websocket API를 통해 서버로 메세지를 보내고, 요청 없이 응답을 받아오는 것이 가능합니다.

웹소켓은 매우 단순한 API로 구성되어 있습니다.

웹소켓을 이용하면 하나의 HTTP 접속으로 양방향 메시지를 자유롭게 주고받을 수 있습니다.

웹소켓 통신과 비교하면 xmlhttprequest에서는 통신할 때마다 꼭 요청 헤더가 부여되기 때문에 불과 1바이트의 정보를 송신하고 싶어도 수 킬로바이트에 달하는 쓸데없는 정보를 보내야 합니다.

예를 들어, 채팅 입력을 한 문자마다 서버에 송신하고 싶은 경우처럼, 실시간을 추구한 애플리케이션에서는 이 점이 성능 차이로 이어질 가능성이 크다고 할 수 있습니다.

HTTP vs 웹 소켓 차이점

지금까지 존재했던 통신방법과 WebSocket의 결정적인 차이는 프로토콜에 있습니다.

WebSocket 프로토콜은 접속 확립에 HTTP를 사용하지만, 그 후의 통신은 WebSocket 독자의 프로토콜로 이루어집니다. 또한, header가 상당히 작아 overhead가 적은 특징 이 있습니다.

장시간 접속을 전제로 하기 때문에, 접속한 상태라면 클라이언트나 서버로부터 데이터 송신이 가능합니다.

더불어 데이터의 송신과 수신에 각각 커넥션을 맺을 필요가 없어, 하나의 커넥션으로 데이터를 송수신 할 수 있습니다.

그리고 통신시에 지정되는 URL은 http://www.sample.com/ 과 같은 형식이 아니라 ws://www.sample.com/ 과 같은 형식이 됩니다.

시간 양방향 데이터 통신이 필요한 경우.
많은 수의 동시 접속자를 수용해야 하는 경우.
브라우저에서 TCP 기반의 통신으로 확장해야 하는 경우.
개발자에게 사용하기 쉬운 API가 필요할 경우.
클라우드 환경이나 웹을 넘어 SOA(Service Oriented Architecture) 로 확장해야 하는 경우

키워드 :

양 방향 통신, 커넥션, 요청

https://inpa.tistory.com/312
https://inpa.tistory.com/entry/SOCKET-%F0%9F%93%9A-WS-%EC%9B%B9%EC%86%8C%EC%BC%93-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0

웹사이트 성능 최적화에는 어떤 방법이 있나요?

모든 프로젝트에 프레임워크와 SPA 라이브러리가 필요로 되는 건 아니고 한번 선택되면 바꾸기 어렵기 때문에 선택을 신중히 해야한다. 접근성, 안정성, 프로젝트 적합도, 러닝커브, Document, 관련 생태계 등 많은 고려 할 점이 있다.

프레임워크 라이브러리 선택

SPA 라이브러리 같은 경우에는 SSR 이나 Pre-rendering 지원되는지 알아보면 좋다. SEO나 FCP, TTI 향상을 위해서 다양한 렌더 방법이 고려 될 수 있는데 내가 선택한 라이브러리가 이를 지원 하지 않는다면 애초에 성능 개선을 위한 렌더 방법 선택을 못할 수도 있다. (참고 : Web Rendering)

graphQL 도입

바닥부터 시작하는 프로젝트라면 한번의 호출로 원하는 데이터를 쏙쏙 빼올 수 있는 GraphQL 도 매력적인 선택이다. GraphQL은 최소한의 요청으로 최적의 최소 데이터를 가져오기 때문에 성능 개선을 위한 강력한 무기가 될 수 있다. (참고 : GraphQL과 REST의 차이점)

JS

로드시 블로킹 방지
script 로드를 위한 script 태그는 DOM 생성 블로킹을 일으킬 수 있기 때문에 HTML 최하단에 배치 되어야 하며 비동기적인 로드를 위해서 async defer 속성 사용도 고려 할 수 있다. ( 참고 : defer, async 스크립트)

로드 사이즈 줄이기
Bundling 대부분 Webpack, Parcel 같은 번들러가 제공하는 기능을 이용해서 파일 사이즈를 줄일수 있다. 번들러를 이용해서 하나의 번들로 만들면 되면 한번의 호출로 여러 자바스크립트 파일을 사용 할 수 있다. minify 기능을 이용하면 자바스크립트를 공백을 최소한 해서 코드 라인수를 줄이게 되서 파일 크기가 줄어 들게 된다. 트리 쉐이킹 기능을 이용하면 쓰지 않는 코드는 번들에 추가하지 않는다 (참고 : 트리 쉐이킹으로 자바스크립트 페이로드 줄이기). 라이브러리를 사용할 때 트리 쉐이킹 사용의 이점을 극대화 할수 있다.

CSS

기본적으로 CSS는 렌더링 차단 리소스 이다.
DOM은 CSSOM이 있어야 렌더 트리가 구상되기 때문에 CSS는 항상 html 최상단 head 태그에 배치하도록 한다.

특정 조건에서만 필요한 CSS가 있을 때 미디어 쿼리를 사용하면 불필요한 블로킹을 방지 가능하다.
차단이든 비차단이든 일단 다 받아온다

이미지

WebP 사용

레이지 로드 이용

키워드 :

JS, CSS, 이미지

https://www.stevy.dev/frontend-web-performance-guide-1/

profile
많이 배우려고 하고 합니다. 아쉬운 점이 있으면 말씀해주시면 감사하겠습니다.

0개의 댓글