console.log만 알고 끝내기엔 아깝다
console.log는 대부분의 개발자가 가장 먼저 배우는 자바스크립트 디버깅 도구이자, 그대로 눌러앉아 다른 건 거의 안 쓰게 되는 도구이기도 하다. 물론 잘 동작한다. 하지만 console 객체에는 디버깅을 훨씬 빠르고 명확하게 해주는 메서드가 10개도 넘게 숨어 있다. 게다가 크롬 DevTools의 breakpoint, 호출 스택, watch expression 같은 기능에 익숙해지고 나면 log를 찍는 빈도는 자연스럽게 줄어든다.
우선 자바스크립트 콘솔 메서드를 한 번 훑어보자:
네 가지 메서드 모두 같은 콘솔에 출력되지만, 브라우저마다 스타일이 다릅니다. 경고는 노란색 배경, 에러는 빨간색에 아이콘까지 붙고 둘 다 스택 트레이스가 함께 찍히죠. DevTools의 필터를 이용하면 레벨별로 숨기거나 특정 레벨만 골라 볼 수 있는데, 앱이 커져서 메시지가 수백 개씩 쏟아지는 순간부터 이 기능의 진가가 드러납니다.
여러 값을 한 번에 로그 찍는 게으른 방법
변수 여러 개를 한꺼번에 확인하고 싶을 때, 문자열로 이어 붙이지 마세요. 각각 인자로 따로 넘기거나, 더 나아가 객체로 감싸서 이름표를 붙여주는 게 훨씬 낫습니다:
{ user, count } 패턴은 객체 축약 문법을 활용한 것으로, 변수 이름이 그대로 키가 됩니다. 콘솔에는 { user: {...}, count: 3 } 형태로 찍히고, user를 펼쳐서 내부 구조까지 확인할 수 있어요. 객체를 문자열로 변환하지 않으니 원래 구조가 그대로 살아 있습니다.
객체 배열은 console.table로 한눈에
객체가 잔뜩 들어 있는 배열을 console.log로 찍으면 접힌 상태로 나와서 알아보기 힘들죠. 이럴 때 console.table을 쓰면 진짜 표 형태로 깔끔하게 보여줍니다:
브라우저 콘솔에서 첫 번째 호출은 세 행을 모두 출력하고, 각 컬럼은 정렬까지 가능합니다. 두 번째 호출은 name과 role 컬럼만 골라서 보여주죠. API 응답이든 쿼리 결과든 파싱한 CSV든, 표 형태로 다룰 데이터라면 이 한 줄이 체감 편의성을 확 끌어올려 줍니다.
console.dir vs console.log 차이
언뜻 비슷해 보이지만, DOM 요소를 찍어 보면 동작이 확연히 다릅니다:
const el = document.querySelector("button");
console.log(el); // HTML을 출력: <button>Click me</button>
console.dir(el); // 모든 속성을 포함한 JS 객체 뷰를 출력
log은 요소를 HTML 형태로 보여주지만, dir은 객체 그 자체를 펼쳐 줍니다. 모든 프로퍼티, 이벤트 핸들러, 계산된 스타일 참조까지 전부 다요. 어떤 요소가 어떤 메서드와 속성을 가지고 있는지 파헤치고 싶다면 dir만한 게 없습니다.
연관된 출력 묶어서 보기
디버깅이 길어지면 콘솔이 금세 지저분해집니다. 이럴 때 console.group과 console.groupEnd로 관련 메시지를 감싸면, 접었다 폈다 할 수 있는 블록으로 깔끔하게 정리됩니다:
호출할 때마다 접을 수 있는 이름 붙은 그룹이 만들어집니다. 기본적으로 그룹을 접힌 상태로 시작하고 싶다면 console.groupCollapsed를 사용하세요. 의심스러워 보이는 것만 펼쳐서 확인하고 싶을 때 특히 유용합니다.
console.time으로 코드 실행 시간 측정하기
간단한 성능 체크라면 console.time과 console.timeEnd만한 게 없습니다.
time과 timeEnd에 넘기는 라벨은 반드시 똑같아야 합니다. 라벨만 다르게 주면 여러 타이머를 동시에 돌릴 수도 있고요. 다만 "이 반복문이 느린가?" 수준을 넘어서는 제대로 된 성능 분석이 필요하다면, DevTools의 Performance 패널로 넘어가세요. 전체 타임라인과 플레임 차트까지 기록해 줍니다.
assert: 문제가 있을 때만 로그 찍기
console.assert는 조건이 거짓일 때만 출력됩니다. 평소엔 콘솔을 어지럽히지 않으면서, 코드 곳곳에 조용히 점검 장치를 심어두고 싶을 때 딱 좋죠:
항상 참이어야 하는 불변 조건(invariant)을 확인할 때 좋습니다. 반면 정상적으로 실패할 수도 있는 상황이라면 console.assert보다는 에러를 던지는 편이 낫습니다.
필요할 때 스택 트레이스 찍기
console.trace는 예외를 던지지 않고도 현재의 호출 스택(call stack)을 출력해 줍니다. 어떤 함수를 누가 호출했는지 추적하고 싶을 때 아주 유용하죠:
출력 결과는 inner → outer → (top level) 순서로 나옵니다. 실제 앱에서는 지금 디버깅 중인 클릭 핸들러가 세 군데에서 호출되고 있다는 사실을 이런 식으로 발견하게 됩니다.
debugger 문으로 실행 멈추기
자바스크립트 실행을 가장 빠르게 일시정지시키는 방법은 단어 하나면 충분합니다:
function computeTotal(items) {
const subtotal = items.reduce((s, i) => s + i.price, 0);
debugger;
return subtotal * 1.08;
}
DevTools가 열려 있는 상태라면 debugger; 문은 breakpoint처럼 동작합니다. 해당 줄에서 실행이 멈추고, 스코프 안의 변수들, 호출 스택, step-over·step-into 같은 컨트롤, 현재 상태에서 표현식을 평가하는 기능까지 완전한 디버거 환경이 그대로 열리죠. DevTools가 닫혀 있으면 debugger;는 아무 일도 하지 않습니다.
console.log 대신 진짜 디버거를 처음 써보면 거의 초능력을 얻은 기분이 듭니다. 무엇을 찍을지 미리 정하지 않아도 스코프 안의 모든 변수를 한눈에 볼 수 있고, 조건문을 한 줄씩 따라가며 어느 분기가 실행되는지 지켜볼 수도 있습니다. 까다로운 버그를 잡는 시간이 몇 분에서 몇 초로 줄어듭니다.
커밋하기 전에 debugger 줄은 꼭 지우세요. 아니면 아예 Sources 패널에서 줄 번호를 클릭해 DevTools에 직접 breakpoint를 거는 편이 더 낫습니다.
알아두면 좋은 크롬 DevTools 사용법
몇 년을 쓰고도 모르고 지나치는 기능들이 있습니다.
- Conditional breakpoints(조건부 중단점): Sources 패널에서 줄 번호를 우클릭해
user.id === 42같은 조건을 걸 수 있습니다. 조건이 참일 때만 breakpoint가 걸립니다. - Logpoints: 같은 메뉴의 "Add logpoint." 코드를 건드리지 않고도, 실행을 멈추지 않으면서 로그만 찍어줍니다.
- 콘솔의
$_: 마지막으로 평가된 표현식을 가리킵니다. 뭔가 실행한 뒤$_로 그 결과를 그대로 집어올 수 있습니다. $0: Elements 패널에서 현재 선택된 요소입니다.$0.textContent로 방금 클릭한 요소를 바로 들여다볼 수 있죠.- 객체로 복사하기: 콘솔에 찍힌 값을 우클릭해 "Store as global variable"을 고르면
temp1,temp2같은 변수가 생겨 자유롭게 만져볼 수 있습니다. - Network 패널 → Copy as fetch: 아무 요청이나
fetch()호출로 바꿔주는데, 이걸 콘솔에 붙여넣고 입맛대로 고쳐 다시 실행할 수 있습니다.
이 중에 꼭 필요한 기능은 하나도 없습니다. 하지만 손에 익으면 하나같이 시간을 아껴줍니다.
배포 전 정리하기
개발 중에는 남아 있는 console.log가 별 문제 안 되지만, 프로덕션에서는 시끄러운 소음이 됩니다. 도움이 되는 습관 몇 가지를 소개합니다.
- ESLint의
no-console같은 린트 규칙으로 빠뜨린 로그를 잡아내세요.warn과error는 예외로 두면 됩니다. - 디테일한 로그는 조건문으로 감싸세요:
if (process.env.NODE_ENV !== "production") console.log(...). - 트레이스 수준의 출력에는
console.debug를 쓰세요. 대부분의 번들러나 로그 수집기는 이걸 걸러낼 수 있습니다. - 더 나은 방법: 작은 로거 모듈(또는
debug같은 라이브러리)을 써서, 코드를 고치지 않고도 카테고리별로 로그를 켜고 끌 수 있게 만드세요.
로깅은 공짜가 아닙니다. 호출할 때마다 인자를 직렬화해서 버퍼에 써야 하죠. 뜨거운 루프 안에 깜빡하고 둔 로그 하나가 눈에 띄게 성능을 갉아먹을 수 있습니다.
다음 주제: 정규 표현식
문자열 처리 코드를 디버깅할 일이 많을 텐데, 그중 상당수는 정규표현식과 엮여 있습니다. 자바스크립트에서 가장 압축적이면서 동시에 가장 암호 같은 기능이죠. 다음 장에서는 자바스크립트 정규표현식과 그걸 활용하는 메서드들을 천천히 살펴봅니다.
자주 묻는 질문
console.log와 console.dir은 어떻게 다른가요?
console.log는 브라우저 기본 포맷으로 값을 출력합니다. DOM 요소라면 HTML 형태로 렌더링해서 보여주죠. 반면 console.dir는 항상 자바스크립트 객체 뷰로 속성들을 펼쳐서 보여줍니다. 요소의 마크업이 아니라 프로퍼티를 들여다봐야 할 때는 console.dir이 정답입니다.
console.log 없이 크롬 DevTools에서 자바스크립트를 디버깅하려면?
Sources 패널을 열고 해당 파일을 찾은 다음, 줄 번호를 클릭해서 breakpoint를 걸면 됩니다. 실행이 그 줄에 닿는 순간 멈추고, 변수 상태를 살펴보거나 한 줄씩 스텝 실행하고, 콘솔에서 식을 평가해볼 수도 있어요. 코드 안에 debugger; 문을 심어두면 소스에서 직접 breakpoint를 트리거할 수도 있습니다.
자바스크립트 코드 실행 시간을 측정하려면 어떻게 하나요?
측정하고 싶은 코드를 console.time('label')과 console.timeEnd('label')로 감싸주세요. 라벨만 똑같이 맞춰주면 콘솔에 경과 시간이 밀리초 단위로 찍힙니다. 더 세밀한 프로파일링이 필요하다면 DevTools의 Performance 패널로 플레임 차트를 기록해서 실행 흐름 전체를 볼 수 있습니다.
console.table은 언제 쓰면 좋나요?
console.table은 배열이나 객체를 정렬 가능한 표 형태로 콘솔에 출력해줍니다. 중첩된 객체 덤프를 눈으로 훑는 것보다 훨씬 편하죠. 특히 객체로 이뤄진 배열에 최적인데, 각 객체가 하나의 행, 키들이 열이 됩니다. 두 번째 인자로 표시할 컬럼만 골라서 넘길 수도 있습니다.