Chrome 자주 사용하는 디버깅 방법 및 기타 기능

✍🏼 작성일 2022년 08월 07일    💡 수정일 2022년 08월 12일
❗️ 참고: 이 글이 작성된 지 이미 일이 지났습니다. 시의성에 유의하세요
🖥  설명:Chrome의 디버깅 기능은 매우 강력합니다. 여기서는 제 업무에서 가장 자주 사용하는 몇 가지 기능을 소개하겠습니다.
📚  Craft에도 게시: https://www.craft.do/s/20CjMjTupEMXFc

Chrome은 하나의 브라우저일 뿐만 아니라 프론트엔드 엔지니어에게는 강력한 디버깅 도구이기도 합니다. 아래는 제가 업무에서 가장 자주 사용하는 몇 가지 기능들입니다. 하나씩 소개하겠습니다.

브레이크포인트(Breakpoint)

이는 가장 기본적이면서도 많이 사용되는 기능이지만, 제가 면접본 많은 외주 개발자 분들은 Chrome의 브레이크포인트 디버깅을 어떻게 사용하는지 모르거나, 들어만 봤지만 실제 사용법을 모르는 경우가 많았습니다. 기본적인 사용법을 간단히 소개하겠습니다.

브레이크포인트를 추가하는 방법은 코드에 직접 debugger 표현식을 한 줄 추가하는 것입니다. 코드가 이 부분에 도달하면 실행이 중단됩니다:

Image

VSCode에서 노란색 밑줄은 경고를 나타냅니다. 일반적으로 이 방법은 사용하지 않습니다. 왜냐하면 이 방법은 console.log와 비교해 뚜렷한 장점이 없을 뿐만 아니라, 오히려 더 복잡하기 때문입니다. 사용한 후에는 삭제해야 하며, 그렇지 않으면 코드가 실행되지 않습니다.

또 다른 방법은 devtools의 source 탭에서 직접 소스 코드를 찾는 것입니다. 일반적으로 console.log로 출력한 후, 콘솔 오른쪽의 파일 이름을 클릭하면 Sources 탭에서 소스 코드를 확인할 수 있습니다. 왼쪽 하단의 포맷 버튼을 클릭한 후, 코드 왼쪽의 줄 번호 옆에 중단점을 설정하면 디버깅을 할 수 있습니다. 아래 그림과 같습니다:

Image

중단점 이후, 그림에서 빨간색 부분의 버튼들은 왼쪽에서 오른쪽으로 순서대로 다음과 같은 의미를 가집니다:

  • 继续执行 (계속 실행): 클릭하면 중단점이 다음 중단점까지 바로 실행됩니다.

  • setp over: 현재 중단점 위치가 함수가 아닌 경우 step과 동일하게 다음 줄로 실행됩니다. 함수인 경우 해당 함수를 건너뛰고 다음 줄로 계속 실행됩니다.

  • setp into: 비동기 코드가 없는 경우 setp과 동일하게 다음 줄로 실행됩니다. 비동기 코드가 있는 경우 비동기 코드 내부의 첫 번째 줄로 들어갑니다.

  • step out: 클릭하면 현재 함수에서 빠져나옵니다.

  • setp: 다음 동기 코드 줄을 실행합니다. step into와 달리 비동기 코드 실행을 건너뜁니다. 현재 중단점이 함수 위치에 있는 경우 함수 호출 내부의 첫 번째 줄로 들어갑니다.

  • 暂时停用/激活断点 (일시적으로 중단점 비활성화/활성화): 처음 클릭하면 중단점 기능이 일시적으로 비활성화되어 중단점을 설정하지 않은 것처럼 코드가 멈추지 않고 실행됩니다. 아래의 Breakpoints에 있는 중단점들이 전체적으로 회색으로 표시됩니다:

Image

Image

  • 에러 발생 지점에서 중단을 클릭하여 강조 표시 후 활성화하면, 코드는 catch 여부나 HTTP 오류 등 모든 throw error 지점에서 자동으로 중단됩니다. 아래의 Pause on caught exceptions을 반드시 체크해야 하며, 체크하지 않으면 효과가 없습니다:

Image

이 기능은 코드 실행이 완료되고 페이지 로딩이 끝난 후, 상호작용이 시작될 때 활성화하는 것이 가장 좋습니다. 그렇지 않으면 페이지에 진입하자마자 오류가 발생할 수 있으며, React의 정상적인 오류까지 포함되어 페이지가 제대로 로드되지 않을 수 있습니다.

공식 중단점(breakpoint)에 대한 이미지를 바로 첨부합니다:

Image

공식 이미지 👆🏻

위 이미지에서 버튼 아래에는 클릭할 수 있는 일련의 토글 삼각 기호가 있으며, 순서대로 다음과 같습니다:

  • Watch는 중단점에서 접근 가능한 모든 컨텍스트 변수를 모니터링하여 표시할 수 있습니다. 변수가 존재하지 않거나 접근할 수 없는 경우(예: a.b.c를 접근할 때 a가 존재하지 않는 경우) 사용할 수 없음이 표시됩니다. 중단점에서 실행이 멈출 때, 해당 위치에 입력된 변수는 자동으로 표시되며, 마우스를 올리지 않아도(위의 공식 이미지처럼) 변수를 확인할 수 있어 매우 편리합니다.

  • Breakpoints는 이미 설정된 중단점을 나타냅니다. 체크박스에 체크된 것은 사용 가능한 중단점이며, 체크되지 않은 것은 일시적으로 무시되는 중단점입니다(임시로 체크하거나 해제할 수 있음).

Image

현재 실행 중인 중단점의 배경은 노란색으로 표시됩니다.

  • Threads는 현재 호출 중인 파일 스레드를 나타내며, 현재 페이지의 JavaScript 스레드는 Main으로 표시됩니다. 이 부분은 일반적으로 사용되지 않으며, Web Worker를 디버깅할 때 유용하거나 현재 페이지에서 Chrome 브라우저 확장 프로그램을 디버깅하는 데 사용할 수 있습니다.

  • Scope는 현재 중단점에서 접근 가능한 변수 값을 표시합니다. JavaScript의 클로저와 호출 스택 특성으로 인해 많은 클로저 내부의 변수가 표시될 수 있습니다:

Image

  • Call Stack은 함수의 호출 스택을 의미하며, 가장 상위에 있는 것이 가장 최근의 호출입니다. 서로 다른 함수를 클릭하여 그 사이를 이동할 수 있습니다. 주의할 점은 이동할 때 실제로 해당 위치가 다시 실행되는 것은 아니며, 해당 위치의 클로저 변수를 확인하기 편리하도록 하는 기능입니다.

UI 브레이크포인트

어떤 경우에는 UI 문제가 왜 그렇게 변화하는지 알 수 없거나 위치를 파악할 수 없는 상황이 발생합니다. 예를 들어, 동료가 버튼에 hover 시 버튼 색상이 변하는 코드를 작성했는데, 여러분은 이 로직에 새로운 기능을 추가해야 하지만 그 코드가 어느 파일에 작성되어 있는지 모르는 경우(동료가 업무 인수인계 없이 휴가를 떠났다면, 정말 짜증 나는 상황입니다!).

버튼에 hover 시 버튼에 class 이름이 추가되는 것을 발견했다면, DOM 브레이크포인트를 사용하여 디버깅할 수 있습니다. Elements 탭에서 해당 요소를 우클릭하면 됩니다:

Image

UI 중단점은 지정한 UI 이벤트가 실행되는 코드 바로 직전에 코드 실행을 중단할 수 있습니다. UI 이벤트에는 다음이 포함됩니다:

  • 서브트리 수정: 서브트리에 추가, 속성 변경 등 어떤 수정이 발생하면 해당 로직이 실행되기 직전에 코드 실행이 중단됩니다.

  • 속성 수정: 현재 우클릭한 요소에 어떤 수정이 발생하면 해당 로직이 실행되기 직전에 코드 실행이 중단됩니다.

  • 노드 제거: 현재 우클릭한 요소가 제거되면 해당 로직이 실행되기 직전에 코드 실행이 중단됩니다.

예를 들어, Feishu 문서에서 블록이 포커스되면 해당 노드에 focus 클래스 이름이 추가됩니다:

Image

Image

이때 attribute modifications를 사용하여 중단점을 설정할 수 있습니다:

Image

물론, 기본적으로 온라인 코드는 압축된 상태로 제공됩니다. 왼쪽 하단의 {}를 클릭하면 포맷팅됩니다:

Image

포맷팅 후 Chrome은 새 탭을 열고 파일명 뒤에 :formatted를 추가합니다:

Image

주의할 점은, 마우스 오른쪽 버튼으로 클릭한 요소가 변경될 때 부모 노드가 변경되는 경우(예: 부모 노드 전체가 제거되는 경우) UI 중단점이 실행되지 않는다는 것입니다.

오버라이드(Overwrite)

Charles에는 비슷한 기능으로 Map js(기억이 맞다면)가 있고, ProxyMan에는 Map Local이라는 유사한 기능이 있습니다. 모두 같은 의미입니다.

때로는 배포/테스트 프로세스가 길 때(특히 에디터와 같은 기본 도구 컴포넌트의 경우 패키지를 배포해야 함), 특정 케이스를 빠르게 검증하려면 번거로울 수 있습니다. 이때 Chrome의 오버라이드 기능을 사용할 수 있습니다.

이 기능은 Charles의 Map js 기능과 유사하며, 로컬 파일을 페이지의 요청에 대한 응답으로 사용할 수 있습니다. 먼저 Sources에서 이 기능을 활성화해야 합니다. 물론, 로컬 파일 저장 위치를 지정하지 않은 경우 먼저 위치를 지정해야 합니다:

Image

이때 Chrome은 해당 경로에 대한 완전한 접근 권한이 필요하다고 알려줄 것입니다. 동의하면 됩니다:

Image

로컬 폴더를 선택한 후(여기서는 ~/Developer/Overwrite 폴더를 선택했습니다), Overwrite 기능을 활성화할 수 있습니다:

Image

그런 다음 Network 탭으로 이동하여 css/js와 같은 리소스를 선택합니다. 여기서는 js를 선택했습니다:

Image

주의: Sources에서 Overwrite를 활성화하지 않았다면, 여기에는 Save for overrides가 표시되지 않습니다.

이후 해당 파일을 자유롭게 수정하고, 페이지를 새로고침하여 변경된 효과를 확인할 수 있습니다.

주의할 점은, js 파일 요청에 타임스탬프가 포함된 경우 Overwrite가 적용되지 않는다는 것입니다. Chrome은 파일을 매핑할 때 엄격한 경로 매칭을 사용하기 때문입니다.

스니펫

정확히 말하면 이것은 "디버깅 방법"은 아니지만, 평소에 코드 검증을 위한 스니펫을 여기에 저장해두면 Sublime(입력한 변수를 자동 완성할 수 있음)처럼 유용하게 사용할 수 있습니다:

Image

파일 시스템

이 기능은 위에서 설명한 몇 가지 기능과 같은 위치에 있으며, 브라우저에서의 수정 사항을 실시간으로 로컬 파일 시스템에 동기화하는 데 사용됩니다. 이 기능은 Express와 같은 서버에서 js/css/html 등을 반환하는 간단한 HTML 웹 서비스의 로컬 디버깅 시에 적합합니다.

하지만 이 기능은 공식적으로 React App에는 적합하지 않다고 명시되어 있습니다. 현재 대부분의 프로젝트가 React, Vue 등의 현대적인 프레임워크로 구축되어 있기 때문에 이 기능은 거의 사용되지 않으며, 여기서는 공식 스크린샷만 첨부하겠습니다:

Image

기타

MacVim

위에서 언급한 Overwrite로 가져온 js 파일은 일반적으로 압축된 온라인 코드이며, 일부는 상당히 클 수 있습니다. 그래서 저는 보통 Vim으로 열어 포맷팅을 합니다. Vim을 설정하는 것은 너무 번거로워서 MacVim을 사용하는데, 바로 사용할 수 있는 경험을 제공하며 약간의 수정만으로 더 나은 환경을 만들 수 있습니다. MacVim을 사용하는 이유는 성능이 매우 뛰어나기 때문입니다. 수십 Mb 크기의 파일도 몇 초 안에 포맷팅할 수 있습니다. 저는 일반적으로 js-beautify를 설정하여 포맷팅하는데, 이름은 js-beautify이지만 js, css, html을 모두 포맷팅할 수 있습니다.

js-beautify를 사용하려면 먼저 vim-plug를 설치해야 합니다. 이것은 vim 플러그인 관리자입니다: https://github.com/junegunn/vim-plug, 사용 방법은 여기를 참조하세요: https://github.com/junegunn/vim-plug/wiki/tutorial.

참고: 설치 시 마법이 필요합니다.

js-beautify는 이것을 사용하세요: https://github.com/beautify-web/js-beautify.

이것은 제 vim 설정입니다. 저는 [] 단축키를 js-beautify 호출 방식으로 사용하여 매번 명령어를 입력할 필요가 없게 했습니다:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
set number
set relativenumber
set smartindent
set autoindent
set hlsearch
set display=lastline
set scrolloff=3
set laststatus=2
set showmatch
set ruler
set guifont=Monaco:h12
syntax on
autocmd FileType *.js setlocal equalprg=js-beautify\ --stdin
nmap [] :%!js-beautify<CR>
colorscheme evening
call plug#begin(has('nvim') ? stdpath('data') . '/plugged' : '~/.vim/plugged')
Plug 'jelera/vim-javascript-syntax'
call plug#end()
if !has('gui')
set term=$TERM
endif

VSCode

VSCode도 중단점 디버깅 기능을 지원합니다(Chrome 커널 덕분에). 하지만 Node 애플리케이션만 디버깅할 수 있습니다(브라우저 확장 프로그램과 함께 사용해 웹 애플리케이션을 디버깅할 수 있지만, 이미 Chrome이 있으므로 필요 없습니다). 기본 사용 방법은 Chrome과 유사하므로 여기서는 설명하지 않겠습니다. 이미지를 첨부합니다:

Image

- EOF -
이 글의 최초 게시: Chrome 자주 사용하는 디버깅 방법 및 기타 기능 - Xheldon Blog