보통 우린 뭔가 자바스크립트 실행 상황을 알고싶을때, console.log
메소드를 실행하고 있다. 어자피 브라우저에서 어떤 객체를 넣든 객체 상황에 맞게 예쁘게 출력해주기 때문에 별 탈은 없다.
하지만 콘솔에 찍는 아주 유용한 메소드들이 존재하지만, 이를 모르는 이가 많다.
지금 내가 하고 있는 이 프로젝트에서도 그런 모습을 엿볼 수 있었는데, console.log
함수를 빈 함수로 치환하여 사용을 막은 코드가 있는데... 그것만 막았더라... 에휴... 할많하않.
어쨌든, 오늘은 MDN에서 일일이 찾는것보다 더 편하게 내가 알려주도록 하겠다.
프론트엔드 개발자들, 이거 필독 알제?
console[level]()
왠만한 언어에 로깅 개념이나 프로젝트를 써봤다면 알 것이다. JS에서 제공하는 로그 레벨은 아래와 같다.
debug
info
warn
error
따라서 위 문구를 console.
에서 입력해서 갖다 쓰면 된다. 예를 들면 console.debug()
.
사용법은 console.log
와 다를 게 하나도 없으며, 로그 레벨을 나눌 수 있다는 장점이 있다.
개발자 도구의 콘솔에서, 기본 수준(Default Level)이라는 선택박스가 있을 것이다. 그걸 클릭하면 디버그, 정보, 경고, 오류 순으로 체크박스가 있으며 원하는 레벨에 체크하면 된다.
참고로 console.log
는 info
레벨에 해당한다.
안타깝게도 node.js 에서 로그 수준을 조절하는 방법이 없다. 대신 기본적으로 console.debug
호출한 출력은 안 뜨는데, 이건 node.js 를 디버그 모드로 실행(실행 시 DEBUG
환경변수 부여)해야 보인다.
그래서 여러모로 체계적이면서 유용한 로깅을 위해 winston 같은 외부 로깅 라이브러리를 쓰기도 한다.
console.log(객체)
MDN 에서는 객체 내역을 남길 때, console.log(obj)
처럼 객체를 그대로 쓰기 보다 console.log(JSON.parse(JSON.stringify(obj)))
처럼 직렬화 처리 후 남기기를 권하는데, 이유는 간단하다. 단순 객체를 남기고 값을 바꾸면, 그 전에 로그 남겼던 값도 변경되기 때문이다. 객체의 성질을 잘 알면 이해가기 쉬울 것이다.
console.table()
MDN에서 자세한 사용법 참조.
이 메소드는 객체를 테이블 형태, 즉, 우리가 DB 테이블과 유사한 형태의 내용을 출력해주는 아주 재밌는 메소드다.
백문이 불여일견, 예시를 보여주겠다.
출처: Use console.table() to display objects
어자피 보통 백엔드에서 JSON 뱉을 때, 이런 구조로 칼럼명을 객체로 담은 배열로 보낼 거기 때문에, console.table()
메소드를 쓰면 테이블로 어떻게 표시할 건지 한눈에 볼 수 있어 매우 유용하다.
또한가지 좋은 점은, 객체가 바뀌어도 테이블 결과물은 바뀌지 않는 것이다!
안타깝게도 이 메소드는 여기서 소개하는 메소드 중 유일하게 IE에서 지원하지 않는다.
console.dir()
MDN에서 자세한 사용법 참조.
사실 이 메소드에 객체 넣고 호출해봐야 console.log
에서 호출한 결과물과 큰 차이점이 없다.
하지만, 이녀석의 용도는, 객체의 속성을 깔끔하게 보기 쉽게 출력해주는 용도가 되겠다.
특히 node.js 에서는 이녀석을 호출해야 객체 구조를 한 눈에 볼 수 있다. 물론 한 눈이라고 해서 많은 속성을 한 눈에 한 콘솔 라인에 출력해주지 못할 수는 있다.
즉, console.log
에 비해 console.dir
이 갖는 차이점은 아래와 같다.
DOM
객체를 출력할 때, log
메소드는 태그 내용을 보여주는 반면, dir
메소드는 해당 객체의 순수 구조와 값을 보여준다.__proto__
등의 확장 속성이나 원시 속성, 열거하지 않은 속성을 볼 필요가 없다.따라서, DOM 객체를 뿌리거나 원시 객체, 즉, JSON에 출력될 내용을 구조적으로 보고싶을 때, 이 dir
메소드를 쓰도록 하자.
console.trace()
MDN에서 자세한 사용법 참조.
이녀석은 인자를 주지 않아도 되며, 호출하면 현재 호출한 기준의 스택 구조를 출력해준다. 따라서 지금 이 구문이 어디서 실행되고 있는지, 예를 들어 어떤 함수를 통해서, 어떤 흐름으로 호출하는지 알고자 할 때 호출하면 된다.
출처: Console.trace() - Javascript Debugging Tips
넷스케이프 시절부터 JS를 해오던 시니어 개발자들에게 신선한 충격일 수 있다. 왜냐면 그때당시 이런 스택 구조를 분석할 방법 자체가 없었으니까. 물론 Error 객체 던져버리면 알 수는 있었지만... 여전히 불편한 건 매한가지다.
자, 정리하자면, 내가 어디서 어떻게 무슨 내용을 원해서 이 스크립트를 실행하는가? trace
메소드 한방으로 해결하자.
console.group()
MDN에서 자세한 사용법 참조.
이녀석은 콘솔 출력 내용을 그룹핑해주는 재밌는 메소드다. 예를 들어, A 함수 호출 -> 안에 B 함수 호출 -> B 함수 호출 후 다시 안에 C 함수 호출 -> 종료 후 A 함수 나머지 실행 이런 실행 흐름 과정을 구조적으로 파악하고자 할 때, 이 함수를 쓰면 되는데, 사용법은 아래와 같다.
function grouping() {
console.group('그룹핑 함수 실행 결과')
console.log('이걸 해보고')
console.info('이걸 해보니 이렇게 나왔네?')
console.warn('이건 좀 아닌 것 같다.')
console.groupEnd()
}
또한 그룹은 중첩도 가능한데, MDN에서 아래와 같이 실행하면,
console.log("This is the outer level");
console.group();
console.log("Level 2");
console.group();
console.log("Level 3");
console.warn("More of level 3");
console.groupEnd();
console.log("Back to level 2");
console.groupEnd();
console.log("Back to the outer level");
이렇게 나온다고 한다.
자매격인 console.groupCollapsed()
메소드가 있는데 group()
메소드와 사용법은 똑같다. 대신, 접혀 있는 상태로 시작하는 차이점만 있다.
console.time()
MDN에서 자세한 사용법 참조.
아직도 Date
객체로 실행 시간을 재고 있는가? 불쌍하다.
그런 불쌍한 중생을 위해 여기 준비한 벤치마킹 메소드를 제공하니, 이걸 쓰도록 하여라.
사용법은 아래와 같다.
console.time("얼마나 걸리냐");
alert("얼마나 빨리 클릭하는지 보자.");
console.timeLog("얼마나 걸리냐");
alert("그런데 짜잔! 절대라는 건 없네.");
console.timeEnd("얼마나 걸리냐");
이렇게 하면, 경고창이 뜬 뒤 몇 밀리초만에 눌렀냐에 대한 시간이 아래처럼 출력될 것이다.
얼마나 걸리냐: 2542ms [실행 위치]
얼마나 걸리냐: 4161ms - timer ended
여기서 time
, timeLog
, timeEnd
메소드 쓰는 걸 보면 알겠지만, 일종의 벤치마크를 할 식별자를 지정할 수 있다. 물론 지정하지 않아도 상관은 없지만, 다른 벤치마크와의 충돌을 피하고 싶다면, 식별자를 인자로 제공하면 된다.
time
메소드는 타이머가 시작됨을 알리는 메소드,
timeLog
메소드는 중간에 걸린 시간을 알리는 메소드,
timeEnd
메소드는 타이머 종료 후 걸린 시간을 알리는 메소드가 되겠다.
으아니 이렇게 유용한 메소드를 몰랐다니! 그냥 우리가 몰랐던 것들이다. 알았으면 적극 활용하도록 하자
다행히도 비동기 대응도 잘 지원되니, 비동기 작업에도 적극적으로 활용하도록 하자.
async function asyncTimer() {
console.time('asyncTimer')
await new Promise(ok => setTimeout(ok, 1000))
console.timeEnd('asyncTimer')
}
단, 주의사항이 있는데, 비동기 실행 흐름에서 끝맺음을 잘 파악해야 한다. 아래처럼.
function asyncGroup() {
console.group('asyncTimer')
new Promise(ok => setTimeout(ok, 1000))
.then(() => (console.log('asyncTimer'), console.groupEnd('asyncTimer')))
}
만약 이렇게 짜면,
function asyncGroup() {
console.group('asyncTimer')
new Promise(ok => setTimeout(ok, 1000))
.then(() => console.log('asyncTimer'))
console.groupEnd('asyncTimer')
}
비동기 실행 시점에 이미 그룹핑은 끝난 상태기 때문에 그룹에서 벗어난 메시지가 출력될 것이다.
그럼 즐거운 자스 디버깅 라이프를 즐기도록!
끗.
감사합니다