브라우저에 url을 입력하면 진행되는 과정
1. handling inputs: user가 url 창에 txt를 입력하면
브라우저의 주소창(주소 표시줄)은 사용자가 URL을 입력하거나 검색어를 입력할 때 매우 중요한 역할을 합니다. 현대 브라우저들은 사용자가 엔터를 누르기 전에 입력된 텍스트가 URL인지 검색어인지 미리 판단하여 적절한 동작을 준비합니다. 이 과정은 다음과 같이 이루어집니다:
URL과 검색어 구분 방법
- 도메인 구조 분석: 브라우저는 입력된 텍스트에 '.com', '.net', '.org' 등의 최상위 도메인(TLD)이 포함되어 있는지 확인합니다.
- 프로토콜 확인: 'http://', 'https://', 'ftp://' 등의 프로토콜이 텍스트 앞에 있으면 URL로 간주합니다.
- 공백 확인: 일반적으로 URL에는 공백이 포함되지 않으므로, 공백이 있으면 검색어로 판단할 가능성이 높습니다.
- 특수 문자 분석: '@', '/', ':', 등의 특수 문자가 특정 패턴으로 사용되면 URL일 가능성이 높습니다.
- 이전 방문 기록 참조: 사용자가 이전에 방문한 웹사이트 주소와 일치하는지 확인합니다.
브라우저의 준비 과정
- URL로 판단된 경우:
- DNS 조회를 미리 시작하여 IP 주소를 확인합니다.
- HTTPS 연결을 위한 SSL/TLS 핸드셰이크를 준비합니다.
- 웹 서버에 연결을 시도합니다.
- 검색어로 판단된 경우:
- 기본 검색 엔진 URL을 준비합니다.
- 검색어를 URL 인코딩하여 쿼리 파라미터로 추가할 준비를 합니다.
- 자동 완성 기능:
- 입력 중인 텍스트를 바탕으로 방문 기록, 북마크, 인기 검색어 등을 참조하여 자동 완성 목록을 표시합니다.
- 보안 검사:
- 입력된 URL이 알려진 피싱 사이트나 악성 웹사이트인지 확인합니다.
2. enter를 입력하면
1. UI thread가 network thread에게 url 전달
2. loading spinner( UI thread가 메니징)
3. network thread가 protocol 활용 dns에 연결, TLS(transfort layer security) connection
a. 만약 network thread로 http 301 response 오면 u thread로 redirect 전달
b. UI thread가 another network call iniates
- DNS: Domain Name System, 도메인 이름을 IP 주소로 변환하는 시스템
- TLS: Transport Layer Security, 인터넷 통신의 보안을 위한 암호화 프로토콜
- https의 s http over tls
- HTTP 301: 영구적인 URL 리다이렉션을 나타내는 HTTP 상태 코드
3. read response
1. Network thread 가 필요하면 response 의 few bytes of stream 을 읽음
2. response header의 content-type 으로 type 확인,3. type 정확하게 확인하려 MIME(Multi-purpose Internet Mail extensions) type sniffing
4. content-type 이
a. HTML 형식: Renderer process 에게 파일 전달 준비
b. HTML 아닌, zip 형식이나 다른 형식 : Download manager 에게 파일 전달 준비
5. SafeBrowsing: domain & data 가 known malicious site -> warning page 보여줌
6. CORB(Cross Origin Read Blocking): 민감한 cross-site data 는 renderer process 에게 전달
응답 처리 과정
- 초기 응답 읽기
- 네트워크 스레드가 응답의 처음 몇 바이트를 읽습니다.
- 이는 응답의 유형을 빠르게 파악하기 위함입니다.
- 콘텐츠 타입 확인
- 응답 헤더의 'Content-Type' 필드를 확인합니다.
- 이 필드는 서버가 보내는 데이터의 형식을 나타냅니다.
- MIME 타입 스니핑( MIME(Multi-purpose Internet Mail extensions) type sniffing)
- 콘텐츠 처리 결정
- HTML 형식인 경우: Renderer 프로세스에 전달할 준비를 합니다.
- 다운로드 가능한 형식(예: ZIP)인 경우: 다운로드 매니저에 전달할 준비를 합니다.
- 안전 검사 (SafeBrowsing)
- 도메인과 데이터가 알려진 악성 사이트인지 확인합니다.
- 악성 사이트로 판단되면 경고 페이지를 표시합니다.
- CORB (Cross Origin Read Blocking)
- 다른 출처의 민감한 데이터가 Renderer 프로세스에 전달되는 것을 방지합니다.
- 이는 보안을 강화하고 정보 유출을 막는 역할을 합니다.
- MIME 타입: 파일의 형식을 나타내는 표준화된 방식
- SafeBrowsing: 악성 웹사이트로부터 사용자를 보호하는 기능
- CORB: 크로스 오리진 데이터 읽기를 차단하는 보안 메커니즘
- Renderer 프로세스: 웹 페이지를 렌더링하는 프로세스
4. Find renderer process: Network thread 가 확인이 끝난 후, 브라우저가 사이트 이동해야하면
1. Network thread 가 data is ready 라고 UI thread 에게 전달
2. UI thread 미리 찾아놓은(혹은 시작한) Renderer process 에게 data(html file)를 전달
a. Network request 가 수백 ms 걸리기 때문에 2단계에서 UI thread 가 Network thread
에게 URL 전달 후 미리 Renderer process 찾음
1. 2, 3단계 진행되어 data is ready 되면, 미리 찾은 Renderer process 도 준비완료
ii. 2, 3단계 진행 중 cross site로 redirect 되면 Renderer process 아닌 다른
process 필요
용어 정리
- UI 스레드: 사용자 인터페이스를 관리하는 스레드
- 네트워크 스레드: 네트워크 통신을 담당하는 스레드
- 렌더러 프로세스: 웹 페이지의 콘텐츠를 렌더링하는 프로세스
- 크로스 사이트: 현재 도메인과 다른 도메인으로의 이동
과정 설명
- 데이터 준비 완료 알림
- 네트워크 스레드가 필요한 데이터를 모두 받으면 UI 스레드에 "데이터 준비 완료" 메시지를 보냅니다.
- 렌더러 프로세스에 데이터 전달
- UI 스레드는 미리 준비해 둔 렌더러 프로세스에 HTML 파일 등의 데이터를 전달합니다.
- 렌더러 프로세스 사전 준비
- UI 스레드는 네트워크 요청이 진행되는 동안 (수백 밀리초 소요) 미리 렌더러 프로세스를 찾거나 시작합니다.
- 이는 페이지 로딩 시간을 단축하기 위한 최적화 기법입니다.
- 렌더러 프로세스 사전 준비의 목적
로딩 시간 단축: 페이지 로딩 속도를 향상시킵니다.
리소스 효율성: 시스템 리소스를 효율적으로 사용합니다.
- 시나리오별 처리
a. 정상적인 경우:- 네트워크 요청(2, 3단계)이 완료되고 "데이터 준비 완료" 상태가 되면, 미리 준비된 렌더러 프로세스가 즉시 사용 가능합니다.
- 네트워크 요청 중 다른 사이트로 리다이렉션되면, 미리 준비한 렌더러 프로세스를 사용할 수 없습니다.
- 이 경우, 새로운 사이트에 적합한 다른 렌더러 프로세스를 찾거나 시작해야 합니다.
이 과정을 통해 브라우저는 효율적으로 페이지를 로드하고 렌더링할 준비를 합니다. 사전에 렌더러 프로세스를 준비함으로써 로딩 시간을 단축하고, 필요한 경우 보안을 위해 다른 프로세스를 사용할 수 있는 유연성을 갖습니다.
5. commit navigation: data, render process가 준비되면
1. Browser process(안에 UI thread)가 Renderer process 에게 IPC 보낸다 commit navigation 을 위해
2. data streah 도 보낸다 Renderer process 가 HTML data를 계속 받을 수 있도록
3. Browser process 가 Renderer process 로부터 commit navigation 되었다는 confimation 을 들으면
4. Navigation 은 끝나고 document loading phase 가 시작된다
a. 주소창 업데이트
b. security indicator & site settings Ul reflect new page information
c. session history for the tab updated
i. forward/back button 에 방금 방문한 사이트 추가
ii. 탭/윈도우 닫을 때 복구 기능을 위해 session history is stored on disk
용어 정리
- IPC: Inter-Process Communication, 프로세스 간 통신
- commit navigation: 새 페이지로의 이동을 확정하는 과정
- Browser process: 브라우저의 주요 프로세스, UI 스레드를 포함
- Renderer process: 웹 페이지를 렌더링하는 프로세스
네비게이션 커밋 과정
- IPC 전송
- Browser process의 UI 스레드가 Renderer process에 IPC를 보내 네비게이션 커밋을 요청합니다.
IPC 전송의 목적
브라우저 프로세스와 렌더러 프로세스 간의 안전하고 효율적인 통신을 위해 사용됩니다.
IPC 메시지 내용
네비게이션 커밋 요청: 새 페이지로의 이동을 확정하라는 지시
페이지 정보: URL, 보안 상태, HTTP 헤더 등
렌더링 지시사항: 렌더링 모드, 자바스크립트 실행 여부 등
- Browser process의 UI 스레드가 Renderer process에 IPC를 보내 네비게이션 커밋을 요청합니다.
- 데이터 스트림 전송
- HTML 데이터 스트림을 Renderer process에 지속적으로 전송합니다.
- 커밋 확인
- Renderer process가 네비게이션 커밋이 완료되었다는 확인을 Browser process에 보냅니다.
- 문서 로딩 단계 시작
- 네비게이션이 종료되고 실제 문서 로딩 단계가 시작됩니다.
브라우저 UI 업데이트
a. 주소창 업데이트: 새 페이지의 URL로 주소창이 갱신됩니다.b. 보안 정보 표시:
- 보안 표시기(예: 자물쇠 아이콘)가 업데이트됩니다.
- 사이트 설정 UI가 새 페이지 정보를 반영합니다.
c. 세션 히스토리 업데이트:
i. 방금 방문한 사이트가 앞으로/뒤로 가기 버튼에 추가됩니다.
ii. 세션 히스토리가 디스크에 저장되어 탭이나 창을 닫았다 다시 열 때 복구할 수 있게 합니다.
+. initial load complete: navigation is committed
1. Renderer process 는 계속 loading resource, render page -> start rendering process
2. Renderer process 가 rendering 끝내면 browser process 에게 IPC back
a. 모든 frame(render process) 에서 onload evnet 발생 후 모든 resource 다 실행된 다음 IPC back
3. UI thread 는 loading spinner tab에서 지움
* client side 의 JavaScript 가 추가적인 resource load 하거나 render new view 할 수 있음
렌더링 프로세스 진행
- 리소스 로딩 및 페이지 렌더링
- Renderer 프로세스는 HTML, CSS, JavaScript 등의 리소스를 계속 로드합니다.
- 동시에 페이지 렌더링을 시작합니다.
- 이 과정에는 DOM 트리 구축, 스타일 계산, 레이아웃 생성 등이 포함됩니다.
- 렌더링 완료 알림
- 렌더링이 완료되면 Renderer 프로세스는 Browser 프로세스에 IPC를 통해 알립니다.
- 이 알림은 다음 조건이 모두 충족된 후에 발생합니다:
a. 모든 프레임(iframe 포함)에서 'onload' 이벤트가 발생
b. 페이지의 모든 리소스가 로드되고 실행됨
- UI 업데이트
- Browser 프로세스의 UI 스레드는 로딩 스피너를 탭에서 제거합니다.
- 이는 사용자에게 페이지 로딩이 완료되었음을 시각적으로 알립니다.
추가적인 동적 로딩
- 클라이언트 측 JavaScript는 초기 로드 완료 후에도 추가적인 작업을 수행할 수 있습니다:
- AJAX를 통한 새로운 리소스 로드
- DOM 조작을 통한 새로운 뷰 렌더링
- 웹소켓을 통한 실시간 데이터 업데이트
- 이러한 동적 업데이트는 페이지의 초기 로드가 완료된 후에도 계속될 수 있습니다.
dom의 개념
html이나 xml 같은 마크업 언어로 작성된 문서를 javascript같은 언어가 조작할 수 있도록 하는 인터페이스를 의미합니다.
dom은 계층적 구조를 가진 노드 트리로 구성됩니다.
dom이 필요한 이유
동적인 웹 페이지를 구현하려면 자바스크립트와 같은 프로그래밍 언어가 문서에 접근하고, 제어할 수 있는 수단이 있어야 하지만, 마크업 언어로 작성된 문서에는 이러한 수단이 없습니다. 따라서 문서에 접근하고 제어할 수 있는 dom이 필요합니다.
dom을 통해 어떤 동작을 할 수 있는지 예를 들어주세요
button element가 클릭되었을 때, 특정 함수를 호출하도록 event handler를 추가할 수 있고 웹 페이지 내에 새로운 요소를 추가하거나, 삭제, 수정할 수 있습니다.
dom은 왜 계층적 구조로 표현하는지 설명해주세요
계층적 구조에서는 노드들 간의 관계가 부모, 자식, 형제 등으로 명확하게 정의됩니다. 이는 노드의 추가, 제거, 이동 작업을 쉽게 할 수 있도록 도와줍니다.
Virtual Dom의 개념
웹 성능을 최적화하기 위해 사용되는 dom 관리 방법으로 웹 어플리케이션의 상태 변경 시, 객체 형태의 가상 dom을 통해 변경된 부분만 찾아내어 이를 실제 dom에 적용하는 기능을 합니다
virtual dom의 동작 순서는 diffing(비교)과 Reconciliation(재조정) 크게 두 가지로 구분할 수 있는데, diffing이란 virtual dom에서 변경점을 찾아내는 과정을 의미하며 Reconciliation(재조정)이란 찾아낸 변경점을 실제 dom에 적용하는 과정을 의미합니다.
virtual dom이 동작하는 예시를 간략히 설명해주세요
먼저 어플리케이션이 제일 처음 rendering 될 때 어플리케이션의 초기 상태를 담은 virtual dom을 메모리 상에 하나 생성합니다. 이후 어플리케이션이 실행되면서 state나 props가 변경된 부분이 있는 경우 새로운 버전의 virtual dom을 메모리 상에 하나 더 생성합니다. 새로운 버전의 virtual dom이 생성 된 수 이전 버전의 virtual dom과 비교하는 과정인 diffing에 돌입하고, 변경점을 찾아냅니다. 이 과정에서 두 virtual dom 트리의 각 노드를 비교하여 어떤 부분이 변경되었는지 확인합니다.
변경점을 찾아낸 이후에는 실제 적용 과정인 Reconciliation(재조정)에 돌입합니다. 이 과정에서 변경된 부분만 실제 dom에 업데이트 하기 때문에, 브라우저 성능이 향상될 수 있는 것입니다.Reconciliation이 완료된 이후 또 다른 변경점이 생기면, 구버전의 virtual dom이 폐기되고 새로운 변경사항을 virtual dom이 다시 생성됩니다.
state나 props가 변경될 때마다 비교와 재조정이 수행되는건가요?
react를 비롯하여 virtual dom을 사용하는 대부분의 프레임워크에서는 batch 업데이트를 지원하고 있습니다. 따라서 여러 개의 state와 props가 동시에 변경되면 이를 각각 처리하는 것이 아니라 한꺼번에 몰아서 처리합니다.
virtual dom을 사용하는 것이 그렇지 않은 것보다 좋은가요?
항상 그런 것은 아닙니다 간단한 어플리케이션의 경우 virtual dom을 사용하는 것이 오히려 오버헤드를 초래할 수 있습니다. virtual dom도 메모리 공간을 차지하고 비교하는 과정 역시, cpu를 활용하기 때문입니다.
다만 dom 트리가 복잡하고 상태변경이 빈번하게 일어나는 대규모 어플리케이션에서 사람의 인지능력으로는 어떤 dom을 업데이트해야 하는지 식별하기 어렵기 때문에 virtual dom을 사용하는 것입니다.
Reflow란 무엇인지 설명해주세요
reflow란 웹 페이지 내에서 요소의 위치 또는 크기의 변화가 있을 때 변화된 레이아웃을 다시 계산하여 렌더트리에 적용하는 과정을 의미합니다. width, height, padding, margin 그리고 border-width와 같은 크기 관련 속성 position, top, left와 같은 위치 관련 속성, display, flex 속성과 같은 레이아웃 관련 속성 font-size, font-weight와 같은 폰트 크기 관련 속성이 리플로우를 유발하는 속성입니다.
repaint란 무엇인지 설명해주세요
repaint란 변화된 시각적 표현을 다시 계산하여 렌더 트리에 적용하는 과정을 말합니다. color, background-color 같은 색상 관련 속성, border-color- border-radius와 같은 테두리 관련 속성이 리페인트를 유발하는 속성입니다.
reflow와 repaint의 성능상 차이점을 설명해주세요
부모 노드의 레이아웃 변화는 자식 노드의 레이아웃까지 영향을 미치기 때문에 리페인트와는 달리, 리플로우가 발생하면 하위 렌더 트리를 다시 계산하고 재구성하는 과정이 필요합니다. 따라서 리플로우는 그 자체만으로도 부하가 큰 작업입니다. 또한 리플로우가 발생하면 일반적으로 리페인트도 다시 발생하기 때문에 성능에 큰 영향을 끼친다고 할 수 있으며, 렌더링 성능을 최적화하기 위해선 리플로우를 최소화해야 합니다. 또한, 리플로우는 주로 cpu를 활용하여 연산하는 반면, 리페인트는 gpu를 활용한다는 차이도 있습니다.
reflow를 최소화하기 위한 방법은 무엇이 있을까요?
dom 업데이트를 하나로 묶어 Batch update를 하는 방법을 생각해 볼 수 있습니다. 또한 offsetHeight, offsetWidth와 같은 자바스크립트 레이아웃 속성에 여러번 접근하면 리플로우가 발생할 수 있기 때문에(브라우저는 이 값을 반환하기 전에 현재 dom의 레이아웃 상태를 확인하고, 필요하다면 레이아웃을 다시 계산합니다 이를 강제 reflow라고 합니다) 이러한 속성들은 변수에 저장해 두고 재사용해야합니다. 마지막으로 가급적 레이아웃 변경이 적은 요소를 사용해야합니다. position 속성을 예로 들면 fixed나 absolute 같은 값들을 사용할 수 있습니다(다른 요소들의 layout에 영향을 미치지 않음)
브라우저 렌더링의 순서를 설명해주세요
먼저 서버로부터 HTML 문서를 전달받으면, 브라우저 엔진은 위에서 아래로 순차적으로 파싱하며 태그와 속성을 발견합니다. 이 태그와 속성들은 트리 형태로 변환되어 메모리에 저장되는데 이를 dom 트리라고 합니다. html 파싱 중 css 링크 또는 스타일 태그를 만나면 이를 파싱하여 cssom 트리로 변환합니다. 문서의 파싱이 완료되면 dom과 cssom 트리를 결합하여 렌더 트리를 생성합니다. 렌더 트리는 브라우저 상에서 요소의 위치와 크기를 결정하는 리플로우 과정을 거치며, 마지막으로 요소의 색상 경계선 등 시각적 요소를 그리는 페인팅 과정이 진행됩니다.
html 파싱 중간에 script 태그를 만나면 어떻게 되나요?
파싱 중간에 script 태그를 만나면 브라우저는 해당 스크립트를 로드하고, 실행하기 위해 파싱을 일시 중단합니다. 외부 스크립트의 경우 스크립트를 로드하고 실행한 후 파싱을 재개하며 내부 스크립트의 경우 실행이 완료될 때까지 파싱이 중단됩니다. 이로 인해 파싱 속도가 저하되고, dom 트리가 완성되기 전에 스크립트가 dom을 조작할 가능성이 있어 예기치 못한 상황이 발생할 수 있습니다. 이러한 문제를 방지하기 위해 async나 defer 속성을 사용하여 파싱에 미치는 영향을 최소화할 수 있습니다.
async와 defer 속성에 대해 설명해주세요
async와 defer는 스크립트를 비동기적으로 로드하는 속성입니다. 이들은 html 파싱이 중단되는 현상과 dom 트리가 완성되기 전에 스크립트가 실행되는 것을 방지하기 위해 사용됩니다. async 속성은 스크립트가 로드되는 직시 실행하는 반면, defer 속성은 스크립트를 비동기적으로 로드하되, html 파싱이 완료된 후 스크립트를 실행합니다. 따라서 async는 스크립트 로드 순서 상관 없이 실행되는 경우에 적합하고 defer는 스크립트의 실행 순서가 중요할 때 적합합니다.
호이스팅이란 무엇인지 설명해주세요
호이스팅이란, 변수와 함수의 선언문이 해당 스코프의 최상단으로 끌어올려지는 현상을 의미합니다. 이러한 현상으로 변수와 함수가 초기화되기 전에 접근할 수 있는 현상이 발생합니다. 단 es6에서 등장한 방식인 let과 const로 선언한 변수들은 호이스팅은 되지만, 초기화 전에 접근할 수는 없습니다.
변수와 함수 모두 호이스팅이 동일하게 동작하나요?
아닙니다 변수는 선언만 호이스팅 되지만 함수는 선언과 초기화 모두 호이스팅 됩니다. 이러한 특성으로 인해 변수는 초기화 전에 참조할 경우, undefined가 나오지만, 함수는 초기화 전에 호출해도 정상적으로 호출이 가능합니다.
왜 변수와 달리 함수만 초기화 과정까지 호이스팅이 되나요?
function 키워드로 선언한 함수는 선언과 초기화, 할당 단계가 내부적으로 동시에 진행되기 때문입니다. 반면 변수는 선언과 초기화를 한 구문으로 코딩했어도, 내부적으로는 두 단계에 걸쳐서 실행됩니다.
왜 let과 const으로 선언한 변수는 초기화 전에 접근할 수 없도록 막아 놓았나요?
호이스팅 현상으로 인해 초기화되지 않은 변수를 개발자가 참조할 수 없도록 하기 위해서입니다. 즉, 코드의 예측 가능성을 높이기 위해 TDZ라는 개념을 도입한 것입니다. 또한 자바스크립트의 창시자인 브랜든 아이크에 따르면, 호이스팅 현상은 자바스크립트 개발 과정에서 실수로 생긴 일종의 버그이기 때문에 이를 es6 버전에서 해결한 것으로 보입니다.
자바스크립트는 인터프리터 언어인데 어떻게 호이스팅 현상이 일어날 수 있는건가요?
일반적으로 알고 있는 인터프리터의 개념과는 달리 자바스크립트 엔진은 코드 실행을 위해 파싱과 실행이라는 두 단계를 거치게 됩니다. 파싱 단계에서 구문 트리를 생성합니다 이 단계에서 변수와 함수 선언이 메모리에 등록됩니다 이를 통해 실행 컨텍스트가 생성됩니다.
실행 컨택스트를 생성할 때 변수 환경과 렉시컬 환경을 설정하게 됩니다
렉시컬 환경: 코드의 스코프 구조를 기반으로 변수와 함수의 접근 가능성을 의미합니다
스코프란 무엇이며 자바스크립트의 스코프는 어떻게 동작하나요?
스코프란 변수나 함수의 유효 범위를 의미합니다. 즉, 특정 변수나 함수를 어느 위치에서 참조할 수 잇는 지를 나타내며 만약 스코프를 벗어난 위치에서 참조할 경우 Reference Error가 발생합니다. 자바스크립트의 스코프는 크게 전역 스코프와 로컬 스코프로 나눌 수 있으며 이들 모두 렉시컬 스코프 규칙(변수가 선언된 위치에 따라 접근 가능 범위가 결정됨)에 따라 결정됩니다. 로컬 스코프는 다시 함수 스코프와 코드블록 스코프로 나눌 수 있는데 let과 const로 저으이한 변수만 블록 스코프를 가질 수 있습니다
렉시컬 스코프란 무엇일까요??
렉시컬 스코프란 변수가 어디에 정의되어 있는지에 따라 스코프가 결정되는 메커니즘을 의미하며 정적 스코프라고 부르기도 합니다 이는 코드가 작성된 위치에 따라 변수의 유효 범위가 결정된다는 뜻입니다. 이러한 이유로 서로 독립적인 로컬 스코프 a, b가 있을 때 b내부에서 선언된 변수를 a 위치에서 a 내부에서 선언된 변수를 b 위치에서 참조할 수 없습니다. 또한 함수가 중첩될 경우 내부 함수는 외부 함수의 변수를 참조할 수 있지만 외부함수는 내부 함수의 변수를 참조할 수 없습니다.
자바스크립트에서 변수를 참조하는과정을 설명해주세요
자바스크립트는 함수가 실행될 때마다 메모리 상에 실행 컨텍스트를 생성(파싱은 최초 1회 런타임 중에 호출 시마다 새로운 컨텍스트 환경을 생성함)합니다. 이 실행 컨텍스트 안에는 렉시컬 환경이 존재 하는데 여기에 현재 스코프에 선언한 모든 변수와 함수들이 저장되어 있는 환경 레코드가 존재합니다. 또한 현재 환경에서 찾지 못한 변수를 상위 스코프에서 찾기 위해 상위 스코프를 가리키는 외부 렉시컬 환경 참조도 갖고 있습니다. 이를 통해 코드 상에서 변수나 함수를 참조하면, 먼저 현재의 환경 레코드에서 찾아보고 없을 경우 외부의 렉시컬 환경 참조를 통해 상위 스코프를 참조하게 됩니다. 이런 식으로 모든 상위 스코프를 탐색했는데도 찾지 못할 경우, 전역 스코프까지 올라가며 여기서도 찾지 못하면 Reference Error를 발생시킵니다.
화살표 함수와 function 키워드의 차이점을 설명 해주세요
먼저 화살표 함수는 코드 블럭을 사용하지 않을 경우, return문을 명시할 필요가 없습니다 또한 function 키워드는 arguments 객체를 통해 함수 인자에 접근할 수 있지만 화살표 함수는 arguments 객체를 갖고 있지 않기 때문에 나머지 매개 변수를 통해 함수 인자에 접근할 수 있습니다. 마지막으로 함수 호출 방식에 따라 this의 참조가 다르게 동작하는 function 키워드와는 달리 화살표 함수는 항상 상위 스코프의 this를 참조합니다.
왜 화살표 함수에서는 this가 항상 상위 스코프를 참조하도록 하였을까요?
function 키워드로 정의한 함수는 호출 방식에 따라 this 바인딩이 다르게 동작하기 때문에 this 값을 예측하기 어렵다는 문제가 있습니다. 따라서 화살표 함수에서는 this가 항상 상위 스코프를 참조하도록 개선하여 this 바인딩의 일관된 동작을 보장하고, 코드 흐름에 따라 this의 참조값을 예측하기 쉽도록 만든 것입니다.
function 키워드 함수의 this 바인딩은 어떤 식으로 동작하나요?
일반적인 함수 호출의 경우는 this가 전역 객체를 가리키며, 객체의 메서드로 호출되는 경우는 해당 객체를 가리키게 됩니다. 또한 함수가 이벤트 핸들러로서 호출되는 경우에는 이벤트가 발생한 요소를 가리킵니다. 이처럼 function 키워드로 정의한 함수는 this 바인딩의 일관성이 부족하기 때문에 es6 이전에는 apply나 call bind와 같은 함수를 통해 명시적으로 this 바인딩을 수행했습니다
클로저에 대해 설명해 주세요
클로저는 내부 함수가 외부 함수의 실행 컨텍스트를 '기억'하는 상태입니다. 외부 함수가 실행을 마쳐도, 내부 함수가 반환되거나 호출되면 외부 변수에 접근할 수 있습니다. 이런 상태를 유지하면서도 독립적으로 동작하는 형태는 데이터 캡슐화나 상태 유지에 이용됩니다. 일상적으로 사용되는 예로는 useState같은 리액트의 훅들이 있습니다.
이벤트 루프와 콜백에 대해 설명해주세요
자바스크립트는 싱글 스레드 언어입니다. 그 말인 즉슨, 두 개 이상의 연산이나 함수를 동시에 실행할 수 없다는 뜻이죠 하나의 연산이 실행 중이면, 쓰레드가 block되는 것입니다. 다행이 libuv라는 C++ 라이브러리를 통해, 브라우저의 경우 Fetch와 같은 웹 API를 통해 백그라운드에서 처리하죠. 이렇게 백그라운드에서 처리하는 작업을 비동기 작업이라고 합니다.
메인 쓰레드에서 실행되는 모든 함수들은 call stack 이라는 공간에 lifo 형태로 차곡차곡 쌓이게 됩니다. 함수가 호출되면 call stack에 push 되고 return 문을 만나면 pop 되는 단순한 구조이죠 만약 call stack에 비동기 함수가 들어오면 즉시 pop 하여 백그라운드로 전달합니다. 비동기 함수가 백그라운드에서 처리되는 한편 동시에 call stack에서는 다음 함수가 계속해서 실행되고 있기 때문에 single thread blocking 문제를 해결할 수 있습니다. 이후 web api에서 비동기 처리가 완료되면 호출 시점에 전달한 callback함수가 event queue 라는 공간에 fifo 구조로 쌓이게 됩니다. 여기서 event loof가 등장하는데 간단히 말하자면 evnet queue에서 call stack으로 callback 함수를 이동시켜주는 역할을 합니다. 이벤트 루프는 call stack이 완전히 비어있는지 수시로 확인하며, 비어있는 경우 event queue에서 callback 함수를 shift한 다음 call stack에 push 해주는 역할을 수행합니다.
프로미스의 개념에 대해 설명해주세요
promise는 비동기 연산의 상태를 나타내는 객체입니다. 비동기 처리가 진행중이면 pending, 성공이면 fulfilled, 실패면 reject라는 상태값을 가집니다. Promise는 비동기 프록래밍을 then과 catch 체이닝을 통해 보다 간결하게 표현할 수 있도록, es6에서 새로 도입되었습니다.
프로미스 등장 이전에는 어떤 방식으로 비동기 처리를 했는지 설명해주세요
프로미스 등장 이전에는 비동기 작업을 처리하는 함수에 성공 콜백과 실패 콜백을 각각 넘겨서 완료 상태에 따른 처리를 했습니다 이런 방식이다 보니, 두 개 이상의 비동기 작업이 순서를 갖고 실행되어야 할 때 콜백 함수 안에 또다른 콜백 함수가 점점 중첩되는 callback hell 현상이 발생하여 코드 가독성 및 유지보수성 저하의 요인이 되곤 했습니다.
async-await에 대해 설명해주세요
promise의 완료를 기다리기 위한 문법으로, async 키워드로 정의한 함수 내에서 호출되는 promise 앞에 await 키워드를 쓰면 해당 promise가 완료될 때까지 코드의 실행을 일시 중단할 수 있습니다. 이를 통해 비동기 코드를 마치 동기 코드처럼 쉽게 작성할 수 있습니다.
async-await를 사용할 때 주의해야할 점을 알려주세요
await의 에러 핸들링은 반드시 try-catch 블록에서 해야합니다. 또한 await는 promise가 완료될 때까지 함수의 실행을 중단하기 때문에 실행 흐름을 잘 고려하여 적재적소에 써야합니다. 예를 들어 여러 비동기 작업이 순차적으로 진행될 필요가 없는 경우는 await 대신 promise.all 함수를 사용하는 것이 바람직합니다.
react에서 key는 무엇인지 설명해주세요
키는 리스트를 매핑하여 동일 한 컴포넌트를 여러 개 렌더링 할 때 각 컴포넌트에 전달되는 고유한 값입니다. 재조정 단게에서 각 노드의 key 값들을 비교하여 리스트의 추가, 삭제, 혹은 순서가 변경된 노드를 식별하고, 이를 통해 필요한 리랜더링만 수행하기 우해 사용합니다.
배열의 index를 키값으로 하면 안되는 이유가 무엇인가요?
배열의 인덱스를 key 값으로 사용하면 안 되는 이유는 순서가 변경되어도 동일한 key 값이 유지되기 때문입니다. key 값이 동일하면 재조정 단계에서 리랜더링 대상으로 식별하지 않을 가능성이 생깁니다. 따라서 배열 내에서 순서가 변경되어도 각 컴포넌트의 key 값이 변경되지 않는 고유한 값으로 설정해야 합니다.
고유한 key값이 없는 경우 대체 방법은?
컴포넌트에 전달되는 각 props를 적절히 조합하여 서로 겹치지 않는 id를 만드는 것이 효과적입니다. 이런 방식으로도 고유한 id를 할당하기 어려운 경우에는, 랜덤한 uuid를 생성하여 key값으로 전달할 수 있습니다. uuid는 128비트로 이루져 있기 때문에, 서로 겹칠 가능성이 극히 적기 때문입니다.
Cors란 무엇인지 설명해주세요
cors는 cross origin resource sharing의 약자로 교차 출처 리소스 공유라고도 불립니다. 2009년에 html5 표준으로 채택된 프로토콜이며, sop에 의해 제한된 교차 출처 간 리소스 공유를 허용하기 위한 방법입니다. 애플리케이션의 요구 사항이 복잡해지면서, 다른 도메인의 리소스를 활용하는 경우가 많아졌기 때문에 등장한 프로토콜로 서버에서 cors 관련 헤더를 설정하여 다른 도메인에서의 리소스 요청을 허용할 수 있습니다. cors 에러는 cors 헤더를 적절히 설정하지 않은 상태에서 교차 출처 리소스를 요청하는 경우 발생할 수 있습니다.
sop란 무엇인지 설명해주세요
same origin policy의 약자로 동일 출처 정책을 의미합니다. 1990년대 후반에 등장한 보안 정책으로, 현재 출처와 동일한 출처의 리소스만 접근할 수 있도록 하는 정책입니다. 여기서 동일 출처란 도메인과, 프로토콜, 포트 번호가 모드 같은 경우를 의미하며 하나라도 다를 경우 동일 출처 정책에 의해 리소스 접근이 제한됩니다.
sop가 없을 경우 가능한 보안 취약점은 무엇인가요?
사용자 인증 정보에 해당하는 세션 id 같은 정보들이 쿠키에 포하되어 있을 수 있기 때문에 이 세션 정보를 탈취하여 xss(악성 스크립트가 사용자 브라우저에서 실행되도록 하는 공격) 또는 csrf(의도하지 않은 요청을 서버에 보내도록 유도하는 공격)와 같은 해킹 공격에 이용할 수 있습니다.sop 정책을 통해 리소스를 다른 도메인에서 접근하지 못하도록 제한한다면 이러한 해킹 공격을 어느정도 완화할 수 있습니다.
cors 프로토콜이 동작하는 원리를 설명하세요
서버는 응답 처리 코드에서 cors 관련 헤더를 설정할 수 있습니다. 이 헤더를 통해 요청을 허용할 도메인과 http 메서드, 그리고 요청 헤더의 종류를 정의할 수 있습니다. 이후 브라우저에서 서버로 리소스를 요청할 때, 이 헤더에 설정한 정보와 일치하지 않는다면 브라우저에서 cors 에러가 발생하는 것입니다. cors 프로토콜 스펙에서 정의한 비교적 보안적으로 민감하지 않다고 판단되는 요청들이 있는데 이를 단순 요청이라고 칭하며 이 요청을 제외한 모든 cors 요청에는 실제 요청을 전송하기 전 요청 허가를 위한 preflight 요청이 발생할 수 있습니다
preflight 요청이 무엇인지 설명해주세요
preflight 요청은 보안적으로 민감한 cors 요청에 대해 요청이 가능한지를 먼저 확인하는 과정입니다. 브라우저에서 자동으로 실행되는 요청으로 options 메서드를 사용하며 서버에서 설정한 cors 관련 설정들을 header 값으로 확인할 수 있습니다. 이 과정을 통해 허용되지 않는 요청에 대한 처리 부하를 낮출 수 있습니다.
단순 요청이 무엇인지 설명해주세요
요청의 메서드가 get, head, post 중 하나이며, header와 content typeㅇ cors 프로토콜에서 지정한 값이 경우가 단순 요청에 해당합니다. 이 경우는 preflight 과정을 통한 권한 조회 과정 없이 cors 요청이 가능합니다.
쿠키의 특징에 대해 설명해주세요
쿠키는 웹 클라이언트에서 사용하는 데이터 저장 수단으로 key value 쌍으로 데이터가 저장됩니다. 쿠키는 http 요청 시 자동으로 헤더에 포함되어 전송되기 때문에 주로 인증 정보와 같이 서버와의 통신에 필요한 데이터를 저장하며 많은 용량의 쿠키가 저장되어 있을 경우 통신 과정에서 오버헤드가 발생할 수 있기 때문에 일반적으로 쿠키 한 개의 용량을 4kb 정도로 제한합니다. 또한 쿠키는 expries 혹은 max-age 속성을 통해 데이터 저장 시 만료 날짜를 지정할 수 있고, path 속성을 통해 같은 도메인 내에서도 쿠키가 전송될 url 범위를 설정할 수 잇다는 특징이 있습니다
localstorage와 sessionstorage의 공통점에 대해 설명해주세요
localstorage와 세션스토리지는 html5에서 새롭괴 도입된 web storage로 domument 객체로도 접근할 수 있는 쿠키와는 달리 자바스크립트를 통해서만 데이터 저장과 접근이 가능합니다 key value 형태로 약 5mb 까지 저장이 가능하며 http 요청 시 자동으로 데이터를 전송하지 않기 때문에 비교적 대용량의 데이터를 클라이언트 측에서 관리하고 싶을 때 사용합니다. 쿠키와는 달리 명시적으로 만료 날짜를 지정할 수 없습니다.
localstorage와 sessionstorage의 차이점에 대해 설명해 주세요
로컬스토리지는 탭이나 브라우저를 닫아도 데이터가 제거되지 않으며 도메인만 동일하다면 2개 이상의 탭이 열려있어도 이들간의 데이터가 공유되는 특징이 있습니다. 반면 sessionStorage는 탭이나 브라우저가 닫히면 데이터가 자동으로 제거되며 동일한 탭 내에서만 데이터가 공유된다는 특징이 있습니다.
트랜스파일러란 무엇인가요?
트랜스파일러는 프로그래밍 언어로 작성된 코드를 다른 언어 또는 다른 문법으로 변환하는 도구입니다. babel, swc, esbuild 같은 도구들이 이에 해당하며 이를 통해 개발 과정에서 react의 jsx 문법이나 타입스크립트를 사용할 수 있습니다.
컴파일러와 트랜스파일러의 차이점은 무엇인가요
컴파일러는 프로그래밍 언어로 작성된 코드를 기계어, 또는 바이트 코드로 변환하지만 트랜스파일러는 프로그래밍 언어를 또 다른 언어로 변환합니다. 또는 프로그래밍 언어로 작성된 코드에서 최신 문법을 구형 문법으로 변환하는 역할도 수행하죠 브라우저의 제품 혹은 버전에 따라 문법의 지원 범위가 다르기 때문에 애플리케이션이 다양한 브라우저에서 구동되려면 이 과정이 필요합니다.
트랜스파일러와 폴리필은 어떤 차이가 있나요?
두 도구 모두 구형 브라우저 지원을 위해 사용하지만, 트랜스파일러는 빌드 타임에 실행되는 반면, 폴리필은 런타임에 실행된다는 차이점이 있습니다 또한 트랜스파일러는 문법만 변경하기 때문에 api 자체가 브라우저에서 지원하지 않는 경우는 폴리필을 사용해야 합니다. 예를 들어 es6에서 도입된 api인 promise는 기본적으로 구형 브라우저에서 사용이 불가능합니다. 트랜스파일러 또한 api 호환성 작업은 수행하지 않죠 이 때 폴리필을 적용하면 웹 어플리케이션에서 promise 함수가 호출되었을 때 이를 감지한 뒤, 내부적으로 다른 함수를 호출하여 사용자가 보기에는 동일한 동작으로 보이게끔 우회할 수 있습니다. 대표적으로는 core-js라는 폴리필 라이브러리가 있습니다.
React 프로젝트에서 트랜스파일러를 사용하는 이유는 무엇인가요?
브라우저는 자바스크립트 엔진이 내장되어 있기 때문에 기본적으로 표준 자바스크립트 코드만 실행이 가능합니다. 한편 리액트에서 컴포넌트 가독성을 높이기 위해 사용하는 jsx 문법은 표준 자바스크립트라고 볼 수 없죠 따라서 빌드 타임에서 jsx 문법으로 작성된 코드를 표준 자바스크립트 코드로 변환하는 작업을 거쳐야 합니다. 동일한 원리로 개발 과정에서 정적 타입 지원을 위해 사용하는 타입스크립트 역시 빌드 타입에 트랜스파일러 작업을 거칩니다.
http 상태 코드의 개념을 설명하세요
http 상태 코드는 서버와 클라이언트 간의 http 통신 결과를 세자리 숫자로 표현한 응답 코드입니다. 통신 결과가 성공적이었는지 요청 과정에 문제가 있었는지 또는 서버 내부에서 오류가 발생했는지를 명확하게 표현하기 위해 사용되며 100번대부터 500번대까지의 숫자를 사용합니다.
200번대 상태 코드에 대해 설명하세요
200번대 상태 코드는 클라이언트 요청이 서버에서 성공적으로 처리되었음을 나타냅니다. 뿐만 아니라 요청 처리의 결과가 응답 본문에 포함되어 있는지, 그리고 클라이언트의 요청에 의해 서버에서 특정 동작이 수행되었는지도 알 수 있습니다. 대표적으로 201 코드는 클라이언트의 post 요청에 의해 서버에 리소스가 성공적으로 생성되었음을 의미합니다. 또한 204 코드는 통신 결과는 성공했으나 응답 본문은 별도로 제공하지 않는다는 의미입니다.
300번대 상태 코드에 대해 설명하세요
300번대 상태 코드는 클아이언트의 요청을 다른 리소스 혹은 url로 유도하는 역할을 합니다. 예를 들어 304 상태 코드는 현재 요청하는 리소스가 변경되지 않았음을 의미합니다. 그렇기 때문에 현재 클라이언트 측에 캐싱되어 잇는 리소스를 그대로 재사용하면 된다고 지시하는 것이죠
400번대 상태 코드에 대해 설명하세요
400번대 상태 코드는 클라이언트 요청이 잘못되었음을 의미합니다. 뿐만 아니라 요청이 구체적으로 어떻게 잘못되었는지도 알 수 있습니다. 예를 들어 401 코드는 잘못된 인증 정보를 갖고 요청했음을 의미하며 404 코드는 요청한 리소스가 서버에 존재하지 않는다는 것을 의미합니다.
400번대 상태 코드와 500번대 상태 코드의 차이점을 설명하세요
400번대 상태 코드는 클라이언트의 요청이 잘못되었음을 의미하지만 500번대 상태 코드는 요청은 서버에 정상적으로 도달 했으나 요청을 처리하는 과정에서 문제가 발생했음을 의미합니다.
상태 코드 꼭 지켜야 하는가?
명확한 상태 코드를 전달하면 클라이언트측에서 어떤 종류의 에러가 발생했는지 빠르게 파악할 수 있으며 이에 따른 적절한 처리를 할 수 있습니다. 또한 axios와 같은 promise 기반 라이브러리는 200번대 상태 코드인 경우만 resolve로 처리하고, 나머지는 reject로 처리합니다. 즉 실패한 처리를 200번대 코드로 응답하면 reject가 아닌 resolve로 처리되기 때문에 디버깅이 다소 힘들어 질 수 있습니다.
'개발 > 기록' 카테고리의 다른 글
| nextjs 쿠키 설정 의문 (0) | 2025.02.24 |
|---|---|
| null undefined 차이 (0) | 2025.02.19 |
| NIST 패스워드 가이드라인 2024 업데이트 (0) | 2025.01.09 |
| Netlify로 배포할 때 편한 점 (1) | 2024.12.04 |
| slow 4g 환경에서 FCP, LCP 측정 비교 (1) | 2024.12.03 |