프로젝트에서 파일 업로드와 다운로드를 구현하면서 사용한 코드들의 의미를 알아보기 위해 정리한 글입니다.

파일 업로드

flow :
file input -> 파일 선택 -> formdata 객체 만들기 -> multipart로 전송

Input type=file

<input type="file"
       id="avatar" name="avatar"
       accept="image/png, image/jpeg">

file type은 input 요소의 공용 특성 외에도 추가적인 특성을 지원한다.

accept는 선택할 수 있는 파일 유형을 지정할 수 있다. 확장자(.jpg,.pdf,.doc)나 MIME 유형의 문자열을 값으로 입력하면 해당 유형의 파일만 선택할 수 있다.

아래처럼 입력하면 엑셀파일만 선택할 수 있다.
accept='application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'

capture는 이미지 또는 비디오 데이터를 캡처할 때 사용할 방법이고, files는 선택한 파일을 나열하는 FileList다. multipletrue로 지정하면 여러 개의 파일을 선택할 수 있다.

선택한 파일에는 아래와 같이 접근할 수 있고,

const selectedFile = document.getElementById('input').files[0];

onChange event를 이용해 e.target.files[0]로도 접근할 수 있다.

Formdata

FormData 인터페이스는 form 필드와 그 값을 나타내는 일련의 key/value 쌍을 쉽게 생성할 수 있는 방법을 제공한다. 또한 XMLHttpRequest.send() 메서드를 사용해 쉽게 전송할 수 있다.

리액트에서 formData로 파일을 보내는 코드를 아래처럼 짰다.

  const [targetFile, setTargetFile] = useState<RcFile[]>([]);

const handleFileChange = (e)=>{
    const file = e.target.files[0]
    setTargetFile(file)
}

const onSubmit = ()=>{
    const formData = new FormData();

      formData.append('fileKey',targetFile[0])

      axios.post("api/uploadfile", formData)
              .then(res => {
                console.log(res);
              })
              .catch(err => {
                console.log(err);
              });
}


...
<input type="file" name="file" onChange={e => this.handleFileChange(e)}/>

Multipart

Multipart란 웹 클라이언트가 요청을 보낼 때 http 프로토콜의 바디 부분에 데이터를 여러 부분으로 나눠서 보내는 것을 의미한다. 여러 부분을 하나의 복합 메세지로 보낸다.

form을 통해서 파일을 등록하고 전송할 때 웹 브라우저가 보내는 HTTP 메시지는 Content-Type 속성이 multipart/form-data로 지정되며, 정해진 형식에 따라 메시지를 인코딩하여 전송한다. 이를 처리하기 위해 서버는 멀티파트 메시지에 대해서 각 파트별로 분리하여 개별 파일의 정보를 얻게 된다.

HTTP는 위 이미지와 같이 4개의 파트로 나뉘고
Header의 Content-Type 필드로 message body에 들어가는 데이터 타입을 명시한다.

multipart 메시지는

  • 서로 붙어있는 여러개의 메시지를 포함하여 하나의 복합 메시지로 보내진다.
  • MIME multipart 메세지는 Content-type 헤더에 boundary 파라미터를 포함한다
  • boundary는 메시지 파트를 구분하는 역할을 하며, 메세지의 시작과 끝 부분도 나타낸다
  • boundary를 선택하는 것은 클라이언트의 몫이다. 보통 무작위의 문자(UUID등)을 선택해 메세지의 본문과 충돌을 피한다
  • HTTP form을 채워서 제출하면, 가변 길이 텍스트 필드와 업로드 될 객체는 각각 멀티파트 본문을 구성하는 하나의 파트가 되어 보내진다. 멀티 파트 본문은 여러 다른 종류의 길이의 값으로 채워진 form을 허용한다.
  • multipart/form-data : 사용자가 양식을 작성한 결과 값의 집합을 번들로 만드는데 사용한다.

대용량 업로드에서 난 에러처리

파일 업로드를 진행하던 중

504 Gateway Time-out

에러가 발생했다. 파일 용량이 커서 nginx의 기본 timeout을 넘어갔기 때문에 발생하는 에러였다. 서버와 클라이언트간 connection을 유지하는 시간이 길기 때문이고 nginx의 기본 timout 시간을 바꿔주면 에러는 해결된다.

우리는 서버에서 bull library를 이용해 queue를 만들어 파일부터 전송하고, 업로드 과정은 클라이언트와의 connection과는 상관없이 처리하는 방식으로 구현했다.

파일 다운로드

flow :
api 요청 -> response를 blob으로 받아옴 -> 브라우저에서 다운로드

Blob

Blob객체는 파일류의 불변하는 미가공 데이터를 나타낸다. 텍스트와 이진 데이터의 형태로 읽을 수 있으며, ReadableStream 으로 변환한 후 그 메서드를 사용해 데이터를 처리할 수도 있다.

Javascript에서 File 인터페이스는 사용자 시스템의 파일을 지원하기 위해 Blob 인터페이스를 확장한 것이므로, 모든 Blob 기능을 상속한다.

생성

const blob = new Blob(array,options)

const blob = new Blob([response.data], { type: response.headers['content-type'] });
  • array : ArrayBuffer, ArayBufferView,Blob(file),DOMString 객체 또는 이러한 객체가 혼합된 Array를 사용할 수 있다.

  • option

    • type : 데이터의 MIME 타입, 기본값은 ""
      • endings : \n을 포함하는 문자열 처리를 'transparent'와 'native'로 지정. 기본값은 transparent

Property는 size type를 가지고, slice(start,end,type)를 사용해 지정된 바이트 범위의 데이터를 포함하는 새로운 Blob 객체를 만들 수 있다. 이를 Chunks 객체라고 한다.

Blob URL

  • Blob 객체를 가리키는 URL 생성
  • createObjectURL : Blob 객체를 나타내는 URL을 포함한 다음과 같은 DOMString을 생성. 이 Blob URL은 생성된 window의 document(브라우저)에서만 유요하다
  • revokeObjectURL() : URL.createObjectURL()을 통해 생성한 기존 URL을 폐기한다. revokeObjectURL을 통해 해제하지 않으면 자바스크립트 엔진에서 GC되지 않는다. 메모리 누수를 방지하기 위해 생성된 URL을 DOM과 바인딩한 후에는 해제하는 것이 좋다.
  • revokeObjectURL
export const downloadFile = (response: AxiosResponse<Blob>) => {
  const blob = new Blob([response.data], { type: response.headers['content-type'] });
  const url = window.URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;

  const filename = response.headers['content-disposition']
    .split('filename=')[1]
    .split(';')[0];

  link.setAttribute('download', filename);
  document.body.appendChild(link);
  link.click();
  link.remove();
  window.URL.revokeObjectURL(url);
};

reference

'Javascript' 카테고리의 다른 글

this  (0) 2021.11.28
실행 컨텍스트  (0) 2021.11.28
자바스크립트 런타임환경  (0) 2021.09.11
이벤트  (0) 2021.08.28
CRP(Critical render path, 브라우저 렌더링 순서)  (0) 2021.08.21

당근 게임을 만들면서 아래의 코드를 실행했을 때 undefined가 출력되었다.

this.field.addEventListener('click',this.onClick)

this.onClick은 할당이 되어있는 상태였는데 왜..?
이유는 click의 콜백으로 전달할 때 클래스의 정보는 안 넘어가기 때문이었다.

그래서 this를 공부하고 정리했다.

this는 함수가 호출될 때 결정된다.

전역공간에서 this는 전역 객체를 가리킨다

함수 호출시 : 전역객체

  • 함수를 호출하는 순간 함수를 실행하는 주체는 전역객체이기 때문

    function a(){
          console.log(this); //window
    }
    
      a()
    

function b(){
function c(){
console.log(this)
}

c()
}

b();// window

### 메서드 호출시 : 호출한 대상 객체가 바인딩 됨

``` javascript
var d = {
    e:function(){
        function f(){
            console.log(this);
        }
      f(); // window
    }
}

d.e() // d

callback 호출시 기본적으로는 함수내부에서와 동일하다.

  • 기본적으로 함수의 this과 같다.
  • 제어권을 가진 함수가 콜백의 this를 지정해둔 경우도 있다.(call, apply,bind)

call,apply,bind

function a(x,y,z){
    console.log(this,x,y,z);
}

var b = {
    bb:'bbb'
};

a.call(b,1,2,3) // {bb:"bbb"} 1 2 3

a.apply(b,[1,2,3]); // // {bb:"bbb"} 1 2 3

var c= a.bind(b);
c(1,2,3); // {bb:"bbb"} 1 2 3

var d = a.bind(b,1,2);
d(3) //{bb:"bbb"} 1 2 3

생성자함수 호출시

function Person(n,a){
    this.name = n;
      this.age = a;
}

var gisele1 = Person('나다',30);
console.log(window.name, window.age); // 나다, 30

var gisele2 = new Person('나다',30);
console.log(gisele); //Person{age:30,name:'나다'}

ES6의 Arrow function은 this를 바인딩하지 않고, 스코프 체인상의 this에 바로 접근할 수 있다.

다시 맨 처음 문제로 돌아와서 콜백 함수에 class를 바인딩하기 위해서는 세 가지 방법이 있다.

// 1. bind 함수로 this바인딩 해주기
this.onClick = this.onClick.bind(this);

// 2. 콜백함수 내부에서 화살표 함수로 event 넘겨주기
this.field.addEventListener('click', (event) => this.onClick(event));

// 3. onClick 함수를 화살표 함수로 선언하기

this.field.addEventListener('click', this.onClick);
...
onClick = (event) => {
    // arrow function은 자동으로 this바인딩
    const target = event.target;
    if (target.matches('.carrot')) {
      target.remove();
      playCarrot();
      this.onItemClick && this.onItemClick('carrot');
    } else if (target.matches('.bug')) {
      this.onItemClick && this.onItemClick('bug');
      playBug();
    }
  };

'Javascript' 카테고리의 다른 글

파일 업로드 / 다운로드  (0) 2021.11.30
실행 컨텍스트  (0) 2021.11.28
자바스크립트 런타임환경  (0) 2021.09.11
이벤트  (0) 2021.08.28
CRP(Critical render path, 브라우저 렌더링 순서)  (0) 2021.08.21

실행컨텍스트란?

  • context : 이 자리에서 어떤 역할을 수행하는지 알기 위해서는 그 코드에 영향을 주는 주변 코드나 변수들을 파악해야 한다. 그렇게 영향을 주는 환경을 일컬어 context라고 한다. 해당 코드의 배경이 되는 조건/환경
  • 실행 컨텍스트 : 어떤 조건/환경을 지니는 코드 뭉치를 실행할 때 필요한 조건/환경정보
  • 자바스크립트에서 동일한 조건을 지닐 수 있는 조건 : 전역공간, 함수, eval, module
  • 자바스크립트는 함수에 의해서만 context를 구분할 수 있다. 즉, 함수를 실행할 때 필요한 조건, 환경정보를 담은 객체

실행 컨텍스트의 내부의 환경정보

  • 현재 환경과 관련된 식별자 정보들
  • VariableEnvironment : 식별자 정보 수집, 변화 반영x
  • LexicalEnvironment(Environment Record, outer Environment Reference)
    • 각 식별자의 데이터 추적, 변화 반영ㅇ
    • 어떤 실행 컨텍스트의 환경정보가 담긴 사전이라고 생각하면 됨
    • 실행컨텍스트를 구성하는 환경정보들을 모아 사전처럼 구성한 객체를 의미한다
    • Environment Record: 현재 문맥의 식별자 정보, 실행 컨텍스트가 최초 실행될 때 하는 일,
      • hoising : 현재 컨텍스트의 식별자 정보들을 수집해서 environmentRecord에 담는 과정, 실제 일어나는 현상이 아니고 environment Record 과정을 좀 더 쉽게 이해하기 위해서 만든 허구의 개념
    • outer Environment Reference : 외부 환경에 대한 참조, scope chain 현상, 실행 컨텍스트가 수집해 놓은 정보만 접근을 할 수가 있음 -> 변수의 유효범위(스코프)

reference

  • 정재남 - 코어자바스크립트

'Javascript' 카테고리의 다른 글

파일 업로드 / 다운로드  (0) 2021.11.30
this  (0) 2021.11.28
자바스크립트 런타임환경  (0) 2021.09.11
이벤트  (0) 2021.08.28
CRP(Critical render path, 브라우저 렌더링 순서)  (0) 2021.08.21

자바스크립트 런타임 환경


출처 https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf

자바스크립트가 구동되는 환경을 이해하기 위해 공부하며 정리한 포스트입니다.

자바스크립트는 기본적으로 싱글 쓰레드 기반 언어이기 때문에 호출 스택이 하나입니다. 따라서 한 번에 한 작업만 처리할 수 있습니다. 만약 호출 스택에 처리 시간이 오래 걸리는 함수가 있으면 그 작업을 처리하는 동안 브라우저는 멈추게 됩니다. 하지만 자바스크립트는 런타임 환경인 브라우저가 제공하는 멀티쓰레딩을 이용해 다양한 작업을 동시에 할 수 있습니다. 자바스크립트는 V8 엔진(Memory Heap + Call stack) + 브라우저가 제공하는 Web API + 이벤트루프 + 콜백 큐로 구성된 환경에서 동작합니다.

자바스크립트 엔진 (V8)

크롬브라우저가 javascript 코드나 스크립트를 받으면 V8 엔진이 코드를 파싱합니다. 먼저 문법 오류를 먼저 검사합니다. 위에서부터 아래로 코드를 읽으며 JS 코드를 컴퓨터가 이해할 수 있는 기계어로 번역합니다.

V8 엔진은 메모리힙과 콜스택을 가지고 있습니다.

Memory Heap(메모리 힙)

변수나 함수 선언은 메모리 힙에 올라갑니다.

Call stack(호출 스택)

호출 스택에는 실행되는 코드가 쌓입니다. 스택에 함수가 추가되면 엔진은 그 코드를 파싱하고, 변수들을 힙에 올립니다. 현재 실행되고 있는 함수가 호출 스택의 가장 상단에 위치하는데, 함수가 값을 return하거나 web api를 호출하면 스택에서 제거(pop)되고, 그 다음 함수를 실행합니다. 호출 스택이 완전히 빌 때까지 이 과정을 반복합니다. 스택이 하나이기 때문에(싱글 스레드) 이 동기적이고, 한 번에 한 동작만 수행합니다.

Web APIs

Web API는 event listner, HTTP/AJAX request, timing function(setTimeout) 등의 기능을 제공합니다. call stack에서 함수가 Web API를 실행하면 스택에서 제거되며, Web API의 콜백 함수는 큐에 저장됩니다.

Callback Queue

콜백큐에는 콜백함수가 저장됩니다. Queue이기 때문에 먼저 들어온 것이 먼저 실행됩니다.(FIFO) 콜백큐에도 두 가지가 있습니다.

Microtask Queue

Promise나 Mutation Observer의 콜백이 들어옵니다. Task Queue보다 우선순위가 높고, Event Loop는 빌 때까지 call stack에 콜백함수를 넣습니다.

Task Queue

일반적인 콜백함수가 들어옵니다. Microtask Queue보다 우선 순위가 낮고, 가장 앞에 있는 콜백 함수만 Call Stack에 들어갑니다.

Microtask Queue Task Queue
Promise, Mutation Observer의 콜백 함수 이외의 콜백함수
우선 순위 높음 우선 순위 낮음
큐가 빌 때까지 event loop가 실행 제일 앞의 task만 실행

Render Seqeunce

변형한 코드를 화면에 업데이트하 위해 주기적으로 호출합니다. Request Animation Frame의 콜백이 전부 실행되면 Render Tree를 그리고 Layout, Paint 과정이 일어납니다.
예를 들어 아래와 같은 코드를 실행했을 때, 배경 색상이 노란색 되는 이유는 각각의 콜백을 모두 실행한 결과를 화면에 그리기 때문입니다.

body.style.backgroundColor = 'red'
body.style.backgroundColor = 'blue'
body.style.backgroundColor = 'yellow'

Event Loop

이벤트루프는 Call Stack이 비면 Task Queue의 콜백함수를 Call stack에 넣는 역할을 합니다. 이벤트루프가 아래의 그림처럼 순회합니다. Call stack의 function이 실행하는데 오래걸릴 때 화면에서 아무 변화가 없는 이유는 event loop가 Call stack에 머물러있어 다음 과정인 Render Sequene를 실행하지 못하기 때문입니다.


출처 드림코딩 - 프론트엔드 필수 브라우저101


📑 referece

'Javascript' 카테고리의 다른 글

this  (0) 2021.11.28
실행 컨텍스트  (0) 2021.11.28
이벤트  (0) 2021.08.28
CRP(Critical render path, 브라우저 렌더링 순서)  (0) 2021.08.21
Web API  (0) 2021.08.12

 

이벤트 핸들링

DOM의 모든 element는 event target을 상속한 node다. Event target은 DOM 인터페이스로, 이벤트를 받을 수 있고, 이벤트에 대한 리스너를 가질 수 있다. 이벤트가 발생하면 event object를 만들어서 등록한 콜백함수에 전달한다.

 

method action
addEventListner 특정한 이벤트에 event handler를 등록. 여러번 호출하면 핸드러를 여러개 붙일 수 있다.
removeEventListner Event target에 등록된 이벤트 리스너를 제거
dispatchEvent Event target에 이벤트를 발생시킴

Event object(이벤트 객체)

이벤트에 관한 상세한 정보를 가지고 있는 객체

이벤트가 발생하면 브라우저는 이벤트 객체라는 것을 만들어 핸들러 함수에 인수 형태로 전달한다.

 

property  
event.type 발생한 이벤트의 종류
event.currentTarget 이벤트를 처리하는 요소. 화살표 함수를 사용했거나 함수를 다른 곳에 바인딩한 경우에 이벤트가 처리되는 요소 정보를 얻을 수 있다.
event.target 이벤트가 발생한 가장 안쪽의 요소

버블링과 캡처링

DOM 이벤트에서 정의한 이벤트 흐름 3단계

  1. 캡처링 - 이벤트가 하위 요소로 전파
  2. 타깃 - 이벤트가 실제 타깃 요소에 전달되는 단계
  3. 버블링 단계 - 이벤트가 상위 요소로 전파되는 단계

캡처링 Capturing

최상위 조상에서 이벤트가 시작해 아래로 전파되는 단계이다. 캡처링 단계를 이용해야 하는 경우는 흔치 않다.

버블링 Bubbling

자식 요소에서 이벤트가 발생하면 부모 요소까지 이벤트가 전파되는 것을 말한다. 즉 한 요소에 이벤트가 발생하면, 부모 요소의 등록된 핸들러가 동작한다. 가장 최상단의 조상 요소까지 이 과정을 반복하면서 요소 각각에 할당된 핸들러가 동작한다. 거의 모든 이벤트는 버블링되지만 focus 이벤트와 같이 버블링 되지 않는 이벤트도 있다.

  • event.target : 실제 이벤트가 시작된 요소. 버블링이 진행되어도 변하지 않는다.
  • event.currentTarget : '현재' 요소. 현재 실행 중인 핸들러가 할당된 요소(=this)

버블링을 중단하기 위해서 event.stopPropagation()을 사용할 수 있지만 꼭 필요한 경우가 아니면 사용하지 않는게 좋다. 클릭 이벤트를 분석하기 위해 이벤트 리스너를 등록해둔 경우, stopPropagation을 사용하면 분석 로직이 동작하지 않을 수 있다.
이벤트 핸들러가 원하는 상황에서만 동작하도록 코드를 작성하는 것이 더 좋다.

const addButton = document.querySelector('.add-button')
const buttonParent = document.querySelector('.parent-div')

buttonParent.addEventListner('click',(e)=>{
    if(e.currentTarget !== e.target){
        return;
    }

      console.log('div 이벤트')
})

addButton.addEventListner('click',(e)={
    console.log('버튼 클릭')
})

이벤트 위임

비슷한 방식으로 여러 요소를 다뤄야 할 때, 각각의 자식요소에 이벤트를 할당하지 않고, 공통 조상에 이벤트 핸들러를 할당해 여러 요소를 다룰 수 있다. 성능면에서도 이 방법이 더 좋다.

각 요소에 이벤트 할당

<ul>
    <li>우유</li>
      <li>두유</li>
      <li>커피</li>
</ul>
const items = document.querySelectAll('li')

items.forEach(item=>{
    item.addEventListner('click',onClickItem)
})

const onClickItem = (e)=>{
    console.log(e.innerText)
}

이벤트 위임

const list = document.querySelector('ul')

list.addEventListner('click',onClickItem)

const onClickItem = (e)=>{
    if(e.target.tagName === 'li'){
        console.log(e.target.innerText)
    }
}

이벤트의 기본 동작

많이 이벤트가 발생 즉시 브라우저에 의해 특정 동작을 자동으로 수행한다.

  • a 태그 : 링크를 클릭하면 해당 URL로 이동
  • submit : 서버에 form 데이터가 전송

자바스크립트를 사용해 직접 동작을 구현해야하는 경우 기본적인 동작을 막는 방법은 두 가지다.

  • event.preventDefault() 메서드를 사용
  • addEventListner가 아닌 on 방식으로 할당되었다면 false를 반환
       <a href='/' onclick="return false">하이</a>    

addEventLister의 passive:true 옵션은 브라우저에게 preventDefault()를 호출하지 않겠다고 알리는 역할을 한다. 예를 들어 모바일 기기에서 touchmove와 같은 이벤트는 스크롤링을 발생시키는데 preventDefault()를 사용하면 스크롤링을 막을 수 있다. 브라우저는 스크롤링을 발생시키는 이벤트를 감지했을 때 모든 핸들러를 처리하는데, preventDefault가 어디에서도 호출되지 않은 것을 확인하고 스크롤링을 진행한다. 이 과정에서 지연과 버벅임이 발생하는데 passive:true 옵션을 주면 핸들러가 스크롤링을 취소하지 않을 것이라는 정보를 브라우저에게 알려줘서, 브라우저는 화면을 최대한 자연스럽게 스크롤링을 처리할 수 있다. passive 옵션은 기본적으로 정해져있기 때문에 임의로 조작하지 않는 편이 좋다.

기타

  • keypress 이벤트는 deprecated
  • keydown 이벤트는 브라우저가 입력을 처리하기 전에 발생, keyup 이벤트는 브라우저가 입력을 처리한 후에 발생
  • form을 이용하면 여러 input의 value를 한번에 받아올 수 있다

📑 referece

'Javascript' 카테고리의 다른 글

실행 컨텍스트  (0) 2021.11.28
자바스크립트 런타임환경  (0) 2021.09.11
CRP(Critical render path, 브라우저 렌더링 순서)  (0) 2021.08.21
Web API  (0) 2021.08.12
DOM  (0) 2021.08.10

Critical rendering path

브라우저가 HTML, CSS, Javascdript를 화면에 픽셀로 변환하는 일련의 단계

CRP는 DOM, CSSOM, Render tree, Layout, Paint를 포함한다. CRP를 이해하고 최적화하는 것은 뛰어난 사용자 상호작용을 보장하며 버벅거림을 피할 수 있도록 하고, 1초당 60프레임에 리플로우와 리페인트가 발생할 수 있도록 하는데 중요하다.

브라우저는 요청 후에 서버로부터 HTML을 응답받는다. 응답받은 HTML을 분석하고, 수신된 바이트를 DOM트리로 변환한다. 브라우저는 스타일시트, 스크립트 또는 외부 자원(이미지 참조 등)에 대한 링크를 찾을때마다 요청을 한다.(불러온 에셋을 다룰 때까지 나머지 HTML을 분석 작업은 중단됨) CSSOM이 완료되면 브라우저는 렌더 트리를 생성하고 보여지는 컨텐츠를 위해 스타일을 계산한다. 렌더트리가 완료된 후 모든 렌더 트리 요소들에 대한 위치와 크기가 정의된 레이아웃이 만들어진다.

 

Construction Construction
DOM->CSSOM -> Render Tree Layout -> Paint -> Composition

 

1. DOM

  • DOM Tree는 완전하게 파싱된 HTML 페이지의 Object 표현이다.
  • html로부터 시작해 각 element, text에 대한 node가 만들어진다.
  • DOM Tree 생성은 점진적으로 진행된다. 페이지에 내용을 표시하기 위해 문서 전체를 로드할 필요가 없다.
  • CSS와 javascript 로드시에 페이지의 렌더링을 차단할 수 있다.
  • 불필요한 tag나 wrapper는 사용하지 않고, div를 남용하는 대신 sementic 태그를 이용하는 것이 성능에 좋다.

2. CSSOM

  • DOM을 스타일링 하기 위한 페이지의 모든 스타일 정보
  • CSS는 상속과 덮어쓰기가 가능하기 때문에 CSS 전체가 파싱되기 전에 사용하면 잘못된 스타일이 적용될 수 있다.
  • 따라서 브라우저는 모든 CSS를 수신하고 처리할 때까지 페이지 렌더링을 막는다.
  • 구체적인 선택자보다 덜 구체적인 선택자가 더 빠르지만 성능차이가 크지는 않다.

3. Render Tree 만들기

  • DOM과 CSSOM이 합쳐진 것으로 페이지에서 최종적으로 렌더링할 내용을 나타내는 Tree
  • Render Tree는 오직 보여지는 node만 캡쳐한다.
    • 예] display:none 속성은 렌더트리에 포함되지 않는다.(visible:hidden은 포함됨)

4. Layout

  • 요소들이 페이지에서 배치되는 위치와 방법, 각 요소의 너비높이 그리고 서로 관련된 위치를 결정한다.
  • 뷰포트 메타 태그는 레이아웃의 너비를 정의한다.

<meta name="viewport" content="width=device-width, initial-scale=1">
  • 레이아웃은 디바이스가 회전하거나 브라우저의 사이즈가 조정될 때마다 발생한다.
  • 레아아웃의 성능은 DOM의 영향을 받는다. 노드의 수가 많을수록 레이아웃은 더 길어지며, 스크롤링 또는 다른 애니메이션이 있으면 레이아웃에 jank를 일으키는 병목현상이 발생할 수 있다.
  • 레아아웃 이벤트의 반복과 형성시간을 줄이기 위해서 일괄 업데이트를 해야하고, 박스 모델 속성을 애니메이션화 하지 말아야 한다.
  • 박스모델 : HTML 요소를 padding, border, margin, content 으로 구분하는 것.

5. Paint

  • 화면에 픽셀을 그리는 단계.
  • 렌더 트리가 생성되고 레이아웃이 나타나기 시작하면 화면에 픽셀을 그릴 수 있다.
  • load시에 전체 화면을 그리고, 이후에는 브라우저가 필요한 최소 영역만 다시 그리도록 최적화 되어있다
  • Layer 단위로 준비(z-index 등). 변화가 있을 때 해당 레이어만 수정하도록 최적화되어 있다.

6. Composition

  • 준비한 레이어를 화면에 놓는 과정

CRP 최적화 방법

  • 자원 로드 순서 관리
  • 파일 사이즈 줄이기
  • 자원 다운로드를 연기함으로써 중요 자원들의 수를 최소화
  • Operation 과정에서 layout, paint는 되도록 적게 발생해야 함
  • ex] element를 이동할 때 top, left 속성을 변경하면 layout+paint+composition이 다 발생하지만 translate를 이용할 경우 composition만 발생한다.

https://csstriggers.com/ 참고


📑 referece

'Javascript' 카테고리의 다른 글

실행 컨텍스트  (0) 2021.11.28
자바스크립트 런타임환경  (0) 2021.09.11
이벤트  (0) 2021.08.28
Web API  (0) 2021.08.12
DOM  (0) 2021.08.10

Web APIs

MDN - Web APIs

종류

  • DOM APIs
  • Network APIs
  • Graphics APIs
  • Audio/Video APIs
  • Device APIs
  • File APIs
  • Storage APIs
    등등등

브라우저 구조분석

  • 문서 객체 모델(Document Object Model, DOM) : 웹 페이지 내의 모든 콘텐츠를 객체로 나타내준다. document 객체는 페이지의 기존 진입점 역할을 한다.
  • 브라우저 객체 모델(Browser Object Model, BOM) : 문서 이외의 모든 것을 제어하기 위해 브라우저(호스트 환경)이 제공하는 추가 객체를 나타낸다.
    • navigator : 브라우저와 운영체제에 대한 정보를 제공한다.
    • location : 현재 URL을 읽을 수 있게 해주고 새로운 URL로 변경할 수 있다.

Document

브라우저의 좌표

getBoundingClientRect

  • element.getBoundigClientRect() 메서드는 elem을 감싸는 가장 작은 네모의 창 기준 좌표를 DOMRect 클래스의 객체 형태로 반환한다.
  • x와 y : 요소를 감싸는 네모창 기준 x,y
  • width와 height : 요소를 감싸는 네모의 너비, 높이
  • 창 기준 : clientX clientY
  • 문서 기준 : pageX pageY
  • top bottom : 요소를 감싸는 네모의위쪽 모서리, 아래쪽 모서리의 Y좌표
  • left right : 요소를 감싸는 네모의 왼쪽 모서리, 오른쪽 모서리의 X좌표
  • left = x
  • top = y
  • right = x + width
  • bottom = y + height

client, offset, page, screen의 차이

client : 스크롤을 무시하고 브라우저 페이지에서의 좌표
offset : 스크롤을 포함한 전체 문서를 기준으로 이벤트 대상 객체의 상대적 마우스 좌표
page : 스크롤 화면을 포함해 전체 문서 기준
screen: 모니터 화면에서의 좌표


reference

'Javascript' 카테고리의 다른 글

실행 컨텍스트  (0) 2021.11.28
자바스크립트 런타임환경  (0) 2021.09.11
이벤트  (0) 2021.08.28
CRP(Critical render path, 브라우저 렌더링 순서)  (0) 2021.08.21
DOM  (0) 2021.08.10

DOM(Document Object Model)

HTML이나 XML 문서의 프로그래밍 interface이다.

  • 문서의 구조화된 표현 제공
  • 프로그래밍 언어가 DOM 구조에 접근할 수 있는 방법을 제공해 문서를 표현하고, 저장하고, 조작하는 방법을 제공한다.

HTML이나 XML Document 구조를 바탕으로 요소들이 화면에 나타나고, 이벤트에 반응하고 값을 입력받는 등의 기능을 수행할 객체들로 실체화 된 형태를 의미한다. 구조화된 nodes와 property와 method를 갖고 있는 objets로 문서를 표현한다. 이들은 웹 페이지를 스크립트 또는 프로그래밍 언어들에서 사용될 수 있게 연결시켜주는 역할을 담당한다. DOM은 javascript를 이용해 명령을 받을 수 있지만 javascript 객체는 아니며, 언어에 종속되지 않고 DOM을 조작할 수 있다. (javascript, 파이썬 beautifulsoup 등) DOM은 웹 페이지의 객체 지향 표현이며, 자바스크립트와 같은 스크립팅 언어를 이용해 DOM을 수정할 수 있다.

Node


[https://velog.io/@mollog/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC%EC%99%80-%EC%A4%91%EC%9A%94%ED%95%9C-%EC%9B%90%EC%B9%99]
이미지 출처

  • DOM의 요소들은 node를 상속받기 때문에 textContent, childNodes, firstChild, lastChild, parentNode, cloeNode, appendChild 등 node의 기능을 전부 갖고 있다.
  • node는 eventTarget 을 상속받기 때문에 이벤트 관련된 메소드를 사용할 수 있다.
  • Event Target method : addEventListner, removeEventListner, dispatchEvent
  • 각 요소마다 고유의 기능도 있다. ex) a - href,target, img - src
  • CSS는 CSS Object Model을 가짐. 트리형식. 브라우저는 DOM+CSSOM을 이용해 화면을 그림
  • BOM : Browser Object Model - 브라우저 자체를 다루는 api. ex)alert, setTimeout, ..

DOM tree


[https://ko.wikipedia.org/wiki/%EB%AC%B8%EC%84%9C\_%EA%B0%9D%EC%B2%B4\_%EB%AA%A8%EB%8D%B8]
이미지 출처

node들의 트리 구조로 이루어져있다.

Virtual DOM

Virtual DOM (VDOM)은 UI의 이상적인 또는 “가상”적인 표현을 메모리에 저장하고 ReactDOM과 같은 라이브러리에 의해 “실제” DOM과 동기화하는 프로그래밍 개념

  • Virtual DOM은 SPA에서 사용하면 DOM의 구조만 간결히 흉내낸 자바스크립트 객체
  • 실제 DOM을 조작하는 것은 무겁기 때문에 가벼운 가상DOM을 만들어, 실ㅈ ㅔDOM과 비교해 바뀐 부분만 실제 DOM을 조작해 반영.
  • 런타임에서 작동함. 브라우저가 js 파일(라이브러리)을 받아서 DOM을 그리고 최소한의 변경으로 구현하는 방법을 찾는 방식

Svelte

  • 가상 DOM 없이 조작을 하기 때문에 리액트, 뷰보다는 빠름
  • Svelte은 컴파일러이기 때문에 런타임 환경이 아닌 배포되기 전에 위의 과정이 일어남

📑 reference

'Javascript' 카테고리의 다른 글

실행 컨텍스트  (0) 2021.11.28
자바스크립트 런타임환경  (0) 2021.09.11
이벤트  (0) 2021.08.28
CRP(Critical render path, 브라우저 렌더링 순서)  (0) 2021.08.21
Web API  (0) 2021.08.12

+ Recent posts