Chrome DevTools의 최신 웹 디버깅

소개

오늘날 작성자들은 많은 추상화를 사용하여 웹 애플리케이션을 빌드할 수 있습니다. 많은 작성자가 웹 플랫폼이 제공하는 하위 수준 API와 직접 상호작용하는 대신 프레임워크, 빌드 도구 및 컴파일러를 활용하여 상위 수준의 관점에서 애플리케이션을 작성합니다.

예를 들어, Angular 프레임워크를 기반으로 빌드된 구성 요소는 HTML 템플릿을 사용하여 TypeScript로 작성됩니다. 내부적으로 Angular CLI와 webpack이 모든 것을 JavaScript로 컴파일하고 소위 번들로 컴파일한 다음, 번들로 묶으면 브라우저로 전송됩니다.

현재 DevTools에서 웹 애플리케이션을 디버깅하거나 프로파일링할 때 실제로 작성한 코드 대신 컴파일된 버전의 코드를 확인하고 디버그할 수 있습니다. 하지만 작성자 입장에서는 이러한 상황을 원하지 않습니다.

  • 여러분은 최소화된 JavaScript 코드를 디버깅하지 않고 원래 JavaScript 코드를 디버깅하려고 합니다.
  • TypeScript를 사용할 때는 JavaScript를 디버깅하는 것이 아니라 원래 TypeScript 코드를 디버깅하려고 합니다.
  • Angular, Lit 또는 JSX와 같은 템플릿을 사용할 때 결과 DOM을 항상 디버그하려는 것은 아닙니다. 구성요소 자체를 디버그하는 것이 좋습니다.

전반적으로 작성한 대로 자체 코드를 디버그하는 것이 좋습니다.

소스 맵은 이미 이러한 격차를 어느 정도 해소했지만, Chrome DevTools와 생태계가 이 영역에서 할 수 있는 일이 더 많습니다.

그럼 확인해 볼까요?

작성된 코드와 배포된 코드

현재 Sources(소스) 패널에서 파일 트리를 탐색할 때 컴파일된 번들(종종 축소됨)의 콘텐츠가 표시됩니다. 이는 브라우저가 다운로드하고 실행하는 실제 파일입니다. DevTools에서는 이를 배포된 코드라고 합니다.

배포된 코드를 보여주는 Chrome DevTools의 파일 트리 스크린샷

그리 편리하지 않으며 이해하기 어려운 경우가 많습니다. 작성자는 배포된 코드가 아니라 직접 작성한 코드를 확인하고 디버그하려고 합니다.

이 문제를 해결하기 위해 이제 트리에서 작성된 코드를 표시할 수 있습니다. 이에 따라 트리는 IDE에서 볼 수 있는 소스 파일과 더 유사해지며, 이제 이러한 파일은 배포된 코드와 분리됩니다.

작성 코드를 보여주는 Chrome DevTools의 파일 트리 스크린샷

Chrome DevTools에서 이 옵션을 사용 설정하려면 설정 > 실험으로 이동하여 소스를 작성 및 배포된 트리로 그룹화를 선택합니다.

DevTools의 설정 스크린샷

'코드만 있음'

종속 항목을 사용하거나 프레임워크를 기반으로 빌드하는 경우 서드 파티 파일이 방해가 될 수 있습니다. 대부분의 경우 node_modules 폴더에 숨겨진 일부 서드 파티 라이브러리의 코드가 아닌 내 코드만 표시하려고 합니다.

이를 보완하기 위해 DevTools에는 알려진 서드 파티 스크립트를 무시 목록에 자동 추가라는 추가 설정이 기본적으로 사용 설정되어 있습니다. DevTools > 설정 > 무시 목록에서 찾을 수 있습니다.

DevTools의 설정 스크린샷

이 설정을 사용 설정하면 DevTools가 프레임워크 또는 빌드 도구에서 무시할이라고 표시한 파일이나 폴더를 숨깁니다.

Angular v14.1.0부터 node_moduleswebpack 폴더의 콘텐츠가 다음과 같이 표시되었습니다. 따라서 이러한 폴더와 폴더 안에 있는 파일, 기타 서드 파티 아티팩트는 DevTools의 다양한 위치에 표시되지 않습니다.

작성자는 이 새로운 동작을 사용하기 위해 별도의 조치를 취할 필요가 없습니다. 이 변경사항을 구현하는 것은 프레임워크에 달려 있습니다.

스택 트레이스에서 무시 목록에 포함된 코드

이러한 무시 목록에 추가된 파일이 더 이상 표시되지 않는 한 위치는 스택 트레이스에 있습니다. 개발자는 이제 더 관련성 높은 스택 트레이스를 확인할 수 있습니다.

DevTools의 스택 트레이스 스크린샷

스택 트레이스의 모든 호출 프레임을 보려면 언제든지 Show more frame 링크를 클릭하면 됩니다.

코드를 디버깅하고 단계별로 실행하는 동안 표시되는 호출 스택도 마찬가지입니다. 프레임워크나 번들러가 DevTools에 서드 파티 스크립트에 관한 정보를 제공하면 DevTools는 단계 디버깅 중에 관련 없는 모든 호출 프레임을 자동으로 숨기고 무시 목록에 포함된 코드를 건너뜁니다.

디버깅 중 DevTools 소스 디버거 스크린샷

파일 트리에서 무시 목록에 포함된 코드

Sources 패널의 Authored Code 파일 트리에서 무시 목록에 있는 파일 및 폴더를 숨기려면 DevTools의 Settings > Experiments에서 Hide ignore-listed code in sources 트리 view를 선택합니다.

DevTools의 설정 스크린샷

이제 샘플 Angular 프로젝트에서 node_moduleswebpack 폴더가 숨겨집니다.

작성 코드는 표시되지만 node_modules는 표시되지 않는 Chrome DevTools의 파일 트리 스크린샷

'빠른 열기' 메뉴의 무시 목록에 포함된 코드

무시된 코드는 파일 트리뿐만 아니라 'Quick Open' 메뉴 (Control+P (Linux/Windows) 또는 Command+P (Mac))에도 숨겨집니다.

'Quick Open' 메뉴가 있는 DevTools의 스크린샷

스택 트레이스의 추가 개선사항

관련 스택 트레이스를 이미 다루었으므로 Chrome DevTools가 스택 트레이스에 관한 더 많은 개선사항을 도입합니다.

연결된 스택 트레이스

일부 작업이 비동기식으로 발생하도록 예약된 경우 DevTools의 스택 트레이스는 현재 스토리의 일부만 알려줍니다.

예를 들어 다음은 가상의 framework.js 파일에 있는 매우 간단한 스케줄러입니다.

function makeScheduler() {
  const tasks = [];

  return {
    schedule(f) {
      tasks.push({ f });
    },

    work() {
      while (tasks.length) {
        const { f } = tasks.shift();
        f();
      }
    },
  };
}

const scheduler = makeScheduler();

function loop() {
  scheduler.work();
  requestAnimationFrame(loop);
};

loop();

개발자가 example.js 파일의 자체 코드에서 이를 사용하는 방법은 다음과 같습니다.

function someTask() {
  console.trace("done!");
}

function businessLogic() {
  scheduler.schedule(someTask);
}

businessLogic();

someTask 메서드 내부에 중단점을 추가할 때 또는 콘솔에 출력된 트레이스를 검사할 때 이 작업의 '근본 원인'인 businessLogic() 호출의 언급이 표시되지 않습니다.

대신, 이 작업으로 이어지는 이벤트 간의 인과적 링크를 파악하는 데 도움이 되도록 작업 실행으로 이어진 프레임워크 예약 로직만 보고 스택 트레이스에 탐색경로가 없습니다.

예약된 시기에 관한 정보가 없는 일부 비동기 실행 코드의 스택 트레이스입니다.

'비동기 스택 태그 지정'이라는 새로운 기능 덕분에 비동기 코드의 두 부분을 함께 연결하여 전체 스토리를 전달할 수 있습니다.

Async Stack Tagging API에 console.createTask()이라는 새로운 console 메서드가 도입되었습니다. API 서명은 다음과 같습니다.

interface Console {
  createTask(name: string): Task;
}

interface Task {
  run<T>(f: () => T): T;
}

console.createTask() 호출은 나중에 작업의 콘텐츠 f를 실행하는 데 사용할 수 있는 Task 인스턴스를 반환합니다.

// Task Creation
const task = console.createTask(name);

// Task Execution
task.run(f);

작업은 생성된 컨텍스트와 실행 중인 비동기 함수의 컨텍스트 사이에 링크를 형성합니다.

위의 makeScheduler 함수에 적용하면 코드는 다음과 같습니다.

function makeScheduler() {
  const tasks = [];

  return {
    schedule(f) {
      const task = console.createTask(f.name);
      tasks.push({ task, f });
    },

    work() {
      while (tasks.length) {
        const { task, f } = tasks.shift();
        task.run(f); // instead of f();
      }
    },
  };
}

덕분에 Chrome DevTools는 이제 더 나은 스택 추적을 표시할 수 있습니다.

예약된 시점에 관한 정보가 포함된 비동기 실행 코드의 스택 트레이스

이제 businessLogic()가 스택 트레이스에 어떻게 포함되는지 확인할 수 있습니다. 그뿐 아니라 이전과 같이 일반적인 requestAnimationFrame가 아니라 작업의 이름으로 친숙한 someTask입니다.

친숙한 통화 프레임

프레임워크는 프로젝트를 빌드할 때 모든 종류의 템플릿 언어에서 코드를 생성하는 경우가 많습니다(예: HTML처럼 보이는 코드를 브라우저에서 실행되는 일반 자바스크립트로 바꿔주는 Angular 또는 JSX 템플릿). 이렇게 생성된 함수 유형에는 그다지 친숙하지 않은 이름이 주어질 때가 있습니다. 축소된 뒤에 한 글자의 이름을 사용하거나, 불분명하거나 익숙하지 않은 이름을 사용할 수도 있습니다.

샘플 프로젝트에서 이와 관련된 예시는 스택 트레이스에 표시되는 AppComponent_Template_app_button_handleClick_1_listener입니다.

자동 생성된 함수 이름이 있는 스택 트레이스 스크린샷

이 문제를 해결하기 위해 Chrome DevTools는 이제 소스 맵을 통해 이러한 함수의 이름을 변경할 수 있도록 지원합니다. 소스 맵에 함수 범위 시작 부분에 해당하는 이름 항목이 있는 경우 호출 프레임은 스택 트레이스에 이 이름을 표시해야 합니다.

작성자는 이 새로운 동작을 사용하기 위해 별도의 조치를 취할 필요가 없습니다. 이 변경사항을 구현하는 것은 프레임워크에 달려 있습니다.

향후 계획

이 게시물에 요약된 추가 기능 덕분에 Chrome DevTools가 더 나은 디버깅 환경을 제공할 수 있습니다. 팀에서 탐색하고 싶은 영역이 더 있습니다. 특히 DevTools에서 프로파일링 환경을 개선하는 방법을 알아야 합니다.

Chrome DevTools 팀은 프레임워크 작성자에게 이러한 새로운 기능을 채택하도록 권장합니다. 우수사례: DevTools를 사용하여 Angular 디버깅 개선에서 이를 구현하는 방법을 안내합니다.