돌아가기

[번역] 브라우저에서 실행되는 코드인가, 브라우저가 실행하는 코드인가

#Web#Performance#translate

제어권을 놓으면 성능이 잡힙니다

이 글은 Jim Nielsen의 “Write Code That Runs in the Browser, or Write Code the Browser Runs”를 원저자의 허락을 받아 번역한 글입니다.

Alex Russell이 남긴 메모를 곱씹어 보고 있습니다. 그는 이렇게 말합니다.

메인 스레드에서 JS를 실행하는 순간, 발전에 뒤처질 위험이 있습니다.

웹 개발의 선(禪)은 자기 코드에는 시간을 조금만 쓰고, 대신 거대한 C++/Rust 하위 시스템을 서로 연결한 다음, 빌어먹을 길에서 비켜나는 데 있습니다.

Bluesky 스레드에서 Alex는 말을 이어갑니다.

어떻게 하면 될까요? 거대한 C++/Rust 덩어리와 연결된 선언형 시스템을 사용하면 됩니다. 컴포지터에는 CSS를 사용하고(스크롤과 애니메이션 포함), DOM을 만들 때는 HTML 파서를 사용합니다. 각종 미디어 처리는 JS를 다시 호출하지 않도록 상위 수준 시스템에 맡깁니다.

저는 다음 두 문장의 차이를 계속 생각하게 됩니다.

  • X를 하는 코드를 작성해야 한다.
  • X를 하도록 브라우저 API를 호출하는 코드를 작성해야 한다.

A) 브라우저에 제안하는 것과 B) 브라우저의 마이크로매니저가 되는 것 사이에는 큰 차이가 있습니다.

제목도 여기서 나왔습니다. 브라우저 안에서 실행되는 코드를 작성할 수도 있고, 브라우저에게 실행을 맡기는 코드를 작성할 수도 있습니다.

몇 가지 예시

그렇다면 제가 서로 연결할 수 있는 브라우저의 ‘하위 시스템’은 무엇일까요? 직접 처리하는 대신 브라우저에 맡길 수 있는 작업에는 어떤 것이 있을까요?

몇 가지 예가 떠오릅니다.

  • View Transitions API를 사용합니다(JS로 DOM을 디핑하고 애니메이션을 직접 구현하는 대신).
  • CSS 트랜지션이나 @keyframes를 사용합니다(GPU 가속). setInterval로 직접 업데이트하는 JS 방식과 대비됩니다.
  • JS로 스크롤 로직을 작성하는 대신 CSS의 scroll-behavior: smooth를 사용합니다.
  • JS 레이아웃 엔진(예: Masonry 복제품) 대신 CSS Grid나 Flexbox를 사용합니다.
  • JS 미디어 플레이어 대신 네이티브 디코딩과 하드웨어 가속을 지원하는 <video><audio> 요소를 사용합니다.
  • JS로 이미지를 직접 교체하는 대신 반응형 이미지에 srcset을 지정한 <picture><img>를 사용합니다.
  • JS로 상태를 두고 추적 및 검증 로직을 작성하는 대신 내장 폼 상태(formData)와 유효성 검사(required, pattern 등)를 사용합니다.
  • ARIA를 잔뜩 사용한 커스텀 컴포넌트 대신 키보드 및 접근성 동작을 기본으로 제공하는 <details>, <dialog>, <select> 같은 네이티브 요소를 사용합니다.

은하급 두뇌로 생각하기

위에서부터 setTimeout → requestAnimationFrame → document.startViewTransition → @view-transition 순서로 나열된 은하급 두뇌 밈

요령은 제어하려는 욕구를 내려놓는 것입니다. 스스로 이렇게 말해 보세요. “이 작업에서 브라우저를 일일이 통제하지 않고 제어권을 내려놓으면, 브라우저는 내가 작성할 수 있는 어떤 코드보다 성능이 뛰어난 저수준 API를 이용해 스스로 처리 방법을 선택할 것이다.”

예를 들어 웹에서 전환 애니메이션을 구현하는 몇 가지 방법을 살펴보겠습니다. 한 단계씩 내려갈수록 메인 스레드의 자바스크립트 코드가 맡던 책임을 브라우저 렌더링 엔진으로 더 많이 넘깁니다.

  • setTimeout
    • JS 타이머와 DOM 조작을 사용합니다. 브라우저는 가능할 때 다시 그리며, 프레임 드롭이 생깁니다.
  • requestAnimationFrame
    • 브라우저의 다시 그리기 주기에 맞춥니다. 부드럽지만 디핑, 정리 등 많은 일을 직접 처리해야 합니다.
  • JS의 View Transitions
    • JS가 시작하고 브라우저가 스냅샷을 만들어 애니메이션을 적용합니다. 네이티브 성능을 활용하지만, 구체적인 연출은 직접 해야 합니다.
  • CSS의 View Transitions
    • 기대하는 바를 큰 틀에서 선언한 다음 브라우저에 맡깁니다.

한쪽 끝에는 다음과 같은 생각이 있습니다.

제어권을 최대한 많이 갖고 싶다. 그 대가로 성능은 내가 신경 쓰겠다.

반대쪽 끝에는 이런 생각이 있습니다.

제어권은 필요 없다. 그 대가로 성능은 브라우저가 신경 써라.

여러분은 어떨지 모르겠지만, 저는 성능과 접근성, 현지화를 비롯한 수많은 문제를 브라우저를 만드는 전문가들에게 훨씬 더 맡기고 싶습니다.

결국 끝없는 트레이드오프입니다

웹에서 무언가를 만드는 일은 선택의 연속입니다.

  • 직접 한다.
  • 브라우저에 맡긴다.
  • 그 중간을 택한다.

무언가를 직접 하기로 할 때마다 트레이드오프도 함께 선택하는 셈입니다. 제어권을 더 많이 가질수록 성능이 저하되는 경우가 많습니다.

왜 직접 할까요? 흔히 자신이 만드는 경험을 원하는 수준으로 제어하고 싶기 때문입니다. 그래도 전혀 문제없을 수 있습니다! 다만 브라우저가 대안을 제공한다는 점을 고려하지 않았거나 몰랐기 때문이 아니라, 의식적으로 내린 선택이어야 합니다. 어쩌면 브라우저에 대안이 있을지도 모릅니다!

그러니 “내가 원하는 일을 하는 코드를 어떻게 작성할까?”라고 묻는 대신, 이렇게 질문해 보세요. “브라우저가 이미 하는 일들을 연결하는 코드를 작성해 내가 원하는 것, 혹은 그에 충분히 가까운 결과를 얻을 수 있을까?”

이런 방식으로 개발하면 성능이 크게 좋아질 가능성이 높습니다. 유지보수 부담도 크게 줄어드는 것은 말할 것도 없습니다!


원저자 소개

Jim Nielsen은 웹을 만들며 마주하는 여러 주제를 자신의 블로그에 기록하는 저자입니다. 원문과 다른 글은 Jim Nielsen의 블로그에서 확인할 수 있습니다.

PREVIOUS ARTICLE

이전 글이 없습니다

NEXT ARTICLE

[번역] 취향과 판단력을 얻는 법