Single Thread 환경
브라우저의 가장 큰 특징은 Single thread방식이라는 점! 요즘 운영체제들은 대부분 Multi thread를 기본으로 지원하고 더 나아가서 interrupt 방식을 제공하면서 단일이지만 멀티처럼 느껴지는 환경을 제공한다.
그렇다면 여기서 single thread와 multi thread란 뭘까?
single thread
한 번에 한 가지 일을 처리할 수 있음. 실행순서를 thread queue에 담아두는데 FIFO(Firt-In-First-Out) 정책을 가지고 있음.
가장 대표적인 게 바로 setTimeout 함수임.
multi thread
한 번에 여러 가지 일을 처리할 수 있음
setTimeout
과 setInterval
을 통해서 single thread의 작동 원리를 알아보자.
우리가 보통 두 함수를 실행할 때 첫 번째 인자로는 함수를, 두 번째 인자로는 초(milliseconds)를 넣는데
두 번째 인자로 0을 넣으면 곧바로 실행되는 것을 의미할까?
정답은 NO!
지정된 시간 이후에 실행을 시키는 것을 의미하는 게 맞긴 맞는데, 정확히 짚고 넘어가면 그 시간 이후 thread queue에 등록하는 걸 의미한다. 그렇기 때문에 내가 지정한 초가 지나고 바로 함수가 실행되지 않을 수도 있다.
requestAnimationFrame()함수
최근 개발자들이 js로 브라우저 기반의 게임이나 캔버스 기반의 영상 등에 주목하면서 setInterval함수를 많이들 사용하면서
최신 브라우저에서는 이러한 기능을 기본으로 제공해주는 requestAnimationFrame
라는 새로운 함수를 포함하기 시작했다. requestAnimationFrame이름 너무 기니까 줄여서 RAF로 부를 예정쓰.
이 함수는 setInterval함수에서 언제 호출할지 초를 설정하는 것과는 달리 브라우저에서 다음 repaint가 일어날 때 콜백이 호출되도록 설정한다.
여기서 나오는 repaint에 대한 개념은 스크롤을 조금 더 내리면 나올 예정이다 :)
setInteval함수는 브라우저의 repaint가 일어나는 프레임과는 무관하게 불필요한 호출이나 지연되는 호출이 일어날 수 있는데 RAF는 다음 프레임이 repaint 될때 호출되서 애니메이션 등을 표현할 때 최적화해서 사용할 수 있다. 일반적으로 초당 60프레임에 해당하는 주기로 호출되는데, 대부분 브라우저에선 W3C 권장대로 현재 모니터 출력 주기와 같게 호출되고 있어서 애니메이션을 출력하는데 최적화 되어있다고 한다! 어휴 길다 길어
setInterval함수는 추가작업을 통해 현재 시간을 반환해야 하는데 RAF는 기본적으로 현재 시각을 timestamp로 변환해서 정수값 인자로 넘겨준다.
개발자의 관점에서 setInterval과 RAF는 기능적인 측면에서 별 차이가 없을수도 있지만 웹페이지를 방문하는 사용자들은 그 차이를 느낄 수 있고, 그 작은 차이가 재방문을 유도하는 것으로 이어질 수 있다는 점!
아쉬운 점은 IE와 Edge17 버전 이하는 페인트 리사이클 이전에 RAF 실행을 보장하지 않는다는 점.. 이쯤되면 IE는 없어져야 한다…
DOM과 자바스크립트
DOM 너무 싫고 아직도 안 친해졌는데.. 익숙해져야지.. 후 js가 다른 프로그래밍 언어와 다른 특징을 하나 뽑아보자면 그건 바로 DOM과 유기적으로 동작하며 상호작용 한다는 점이다.
DOM이란 Document Object Model의 줄임말로 플랫폼과 언어에 독립적으로 문서에 접근해 구조나 내용을 바꾸고 디자인을 바꿀 수 있는 인터페이스를 말한다.
js가 DOM을 쉽게 변경할 수 있어서 부담없이 사용하고 있는데, 조금이라도 더 빠른 js를 개발하려면 좀 더 고민해봐야 하는 문제가 있다. 그건 바로 js가 DOM을 변경하고 검색할 때 컴퓨팅 자원 소모가 심하다는 것! DOM은 js와 다르게 HTML로 표현되며, 문서가 트리구조라서 js 자체에서 처리하는 것과 다르게 기본으로 트리구조 전체를 검색해야 한다.
또한 js를 통해 DOM이 수정되면 브라우저가 화면에 웹페이지를 다시 출력해야 하는 상황이 발생하곤 하는데, 이러한 현상을 “DOM repaint 혹은 reflow가 이루어진다”고 말한다.
그렇다면 repaint와 reflow가 무엇인지도 함께 살펴보자.
DOM repaint
DOM repaint는 특정 element의 visibility를 수정하거나 배경색 혹은 글자색 등을 바꿀 때 일어나는 것을 말한다. 화면에 각 HTML element들의 위치는 변경되지 않고, 화면에 표시되는 것들이 바뀔때 일어난다. 특정 DOM element의 visibility를 수정하면 해당 DOM의 자식 DOM까지 하위 트리구조 전체를 탐색해야 해서 CPU자원이 소모된다.
쉽게 말해 DOM 요소들의 위치가 변경되지 않고 표현되는 스타일만 변경되는 경우를 repaint라고 한다.
DOM reflow
Dom reflow는 repaint와 다르게 DOM이 화면에 표시되는 구조가 바뀔때 혹은 CSS클래스가 바뀔 때 일어난다. 다시 말해, DOM 트리가 배치되는 위치를 전체적으로 다시 계산해서 화면에 출력하는 것을 의미한다.
특정 element의 위치가 변경되면 그에 영향을 받는 자식 element들과 해당 element 이후에 나타나는 element들에 대해서 전체적으로 위치를 다시 계산해야 해서 DOM repaint보다 자원 소모가 크다.
이러한 repaint와 reflow 때문에 우리는 React를 쓴다고 한다. 사실 React를 쓰는 이유가 그냥 컴포넌트 단위로 쪼개서 코드를 단순화하는데 의의가 있다고 생각했는데 그게 아니었다. 일반적인 DOM tree는 CSS 값이 하나만 바뀌어도 전체가 다시 랜더링 되는 반면, React에서의 Virtual DOM은 바뀐 부분에 대해서만 랜더링이 되기 때문에 훨씬 효율적인 것!
Reference
- 속깊은 자바스크립트 6장(양성익 저)
- https://velopert.com/3236