A LIST Apart: For People Who Make Websites

최신 디버깅 팁 & 트릭

by Tiffany B. Brown

모바일 장치가 발달하면서 웹 개발과 디버깅은 전에 없이 복잡해졌습니다. 지원해야 할 플랫폼과 브라우저가 더 늘어났습니다. 옛날의 밋밋하고 안내문같은 사이트가 아니라 브라우저에서 동작하는 애플리케이션을 개발하고 있습니다.

With the rise of mobile devices, web development and debugging is more complex than ever. We have more browsers and platforms to support. We have more screen sizes and resolutions. And we’re building in-browser applications instead of the flat, brochure-ware sites of yore.

다행히 도구도 전보다 좋아졌습니다. 주요 브라우저 대부분에서 자바스크립트 콘솔을 지원합니다. 자바스크립트와 HTML DOM 모두 에러 처리 방법을 내장하고 있습니다. 사이트를 원격에서 디버그하는 서비스와 애플리케이션도 있습니다.

Luckily, we also have better tools. The JavaScript console is a standard feature of most major browsers. Both JavaScript and the HTML DOM offer native error handling. We also have services and applications that help us remotely debug our sites.

이 글에서는 에러 처리와 코드 삽입, 모바일 디버깅에 대해 다루겠습니다. 디버깅에 대해 더 보고 싶으면 핼버드 스틴과 크리스 밀스의 글 Advanced Debugging With JavaScript을 읽어보십시오.

In this article I’ll cover error thowing and handling, code injection, and mobile debugging. For more on debugging, see Hallvord R.M. Steen and Chris Mills’ 2009 article, Advanced Debugging With JavaScript.

throw - catch

자바스크립트의 throw - trycatch 문과 error 객체의 조합으로 에러를 처리할 수 있습니다.

JavaScript lets you report and handle errors through a combination of the throw and trycatch statements, and the error object.

throw 문은 함수에 부정확한 매개변수를 넘긴 것 같은 런타임 에러를 잡아내는데 유용합니다. 다음 예제에서 add()는 매개변수를 두 개 받습니다. 넘겨받은 매개변수가 null이거나, 숫자 또는 숫자를 나타내는 문자열이 아니면 에러를 던집니다(throw).

Error throwing is useful for catching runtime errors—say, a function that has incorrect arguments. In the example below, add() accepts two parameters. It will throw an error if the supplied arguments are null, or are neither a number nor a numeric string. (Line wraps marked » —Ed.)

function add(x,y){
     if( isNaN(x) || isNaN(y) ){
          throw new Error("Hey, I need two numbers to add!");
     } else {              
          // 숫자처럼 생긴 문자열을 연결하는게 아니라 + 연산이 되도록 합니다.
          return (x * 1) + (y * 1);
     }
}

add()에 잘못된 매개변수를 넘겨서 호출해 봅시다. 그런 다음 try - catch 블럭으로 에러를 잡아내서(catch) 콘솔에 출력하겠습니다.

Let’s try invoking add() using invalid arguments. We’ll then catch the error thrown by using a trycatch block and output it to the console:

var a;

try{
    a = add(9);
} catch(e) {
    console.error( e.message );
}

그림 1: 드래곤플라이 콘솔 에러

Fig 1: The Dragonfly console error

오페라 드래곤플라이에서 에러 메시지 및 그와 관련된 줄번호를 확인할 수 있습니다. 이 예제에서는 자바스크립트를 HTML 페이지 안에 포함했음을 염두에 두십시오.역주

In Opera Dragonfly (above), we see the error message and its corresponding line number, relative to the script. Keep in mind in these examples we’re embedding JavaScript within our HTML page.

The Firebug error console.

그림 2. 파이어버그 에러 콘솔

Fig. 2: The Firebug error console

파이어버그 역시 에러 메시지와 줄번호를 표시하는데, 줄번호는 문서에 상대적입니다.

Firebug also includes the thrown error message and line number, but relative to the document.

에러 객체에는 세 가지 표준 속성이 있습니다.

All error objects have three standard properties:

이 글을 쓰는 시점에서 파이어폭스의 에러 객체는 비표준 속성인 fileNamelineNumber을 포함합니다. 인터넷 익스플로러의 에러 객체도 비표준 속성 description(message와 비슷하게 동작합니다) 과 number(줄 번호)를 포함합니다.

As of this writing, error objects in Firefox also include two non-standard properties: fileName and lineNumber. Internet Explorer includes two non-standard properties of its own: description (which works similarly to message) and number (which outputs the line number).

stack 속성도 비표준이지만 파이어폭스와 크롬, 오페라 최근 버전은 모두 이 속성을 지원합니다. stack 속성은 함수 호출을 추적해서 대응하는 줄 번호와 매개변수를 반환합니다. 예제를 고쳐서 stackalert()로 확인해 봅시다.

The stack property also isn’t standard, but it is more or less supported by the latest versions of Chrome, Firefox, and Opera. It traces the order of function calls, with corresponding line numbers and arguments. Let’s modify our example to alert the stack instead:

var a;

try{
    a = add(9);
} catch(e) {
    alert( e.stack );
}

그림 3. stack 속성으로 코드 에러를 드러냈습니다.

Fig 3: The stack property revealing the throw error in the code

stack 속성은 코드에서 throw Error가 존재하는 곳(이 예제에서는 7행)과 그 에러를 실제로 발생시킨 곳(이 예제에서는 15행)을 보여줍니다.

The stack property reveals where in the code throw Error exists (in this case, line seven) and on which line the error was triggered (in this case, line 15).

꼭 에러 객체를 던져야만 하는 건 아닙니다. 예를 들어 throw "The value of x or y is NaN." 처럼 메시지를 던질 수도 있습니다. 하지만 에러 객체를 던지는 편이 브라우저 대부분에서 더 풍부한 정보를 얻을 수 있습니다.

You don’t have to throw an error object. You could, for example, throw a message: throw "The value of x or y is NaN." Throwing an error, however, offers richer information in most browsers.

그렇지만 trycatch 문을 쓰면 스크립트 최소화나 실행 성능에 악영향이 있습니다. trycatch 문이 디버그할 때 편리하긴 하지만, 배포할 코드에는 될 수 있으면 쓰지 말아야 합니다.

Using trycatch can, however, have a negative effect on script minification and performance. While handy for debugging, your production-ready code should use trycatch sparingly, if at all.

window.onerror 이벤트로 에러 관리

DOM은 에러 포착 메커니즘도 제공합니다. 바로 window.onerror 이벤트입니다. window.onerror 이벤트는 trycatch와는 달라서, 던지지 않은 에러도 포착하는 이벤트 핸들러를 쓸 수 있습니다. 정의하지 않은 함수를 호출하거나 정의하지 않은 변수에 접근하려 할 때 발생하는 에러는 던질 수 없죠.

The Document Object Model also offers a mechanism for capturing errors: the window.onerror event. Unlike trycatch, you can set an event handler for window.onerror that captures errors you don’t throw. This can happen if you try to invoke an undefined function or access an undefined variable.

window.onerror 이벤트가 발생하면 브라우저는 이벤트 핸들러 함수가 있는지 확인합니다. 이벤트 핸들러 함수가 없다면 사용자에게 에러를 보여줍니다. 이벤트 핸들러 함수가 있다면 그 함수에 매개변수 세 개를 넘겨서 호출합니다.

When the window.onerror event is fired, the browser will check to see whether a handler function is available. If one isn't available, the browser will reveal the error to the user. If one is available, the handler function receives three arguments:

이 매개변수에 접근할 방법은 두 가지입니다.

You can access those arguments in one of two ways:

  1. 모든 함수에 내장되어 있고 지역 변수로 접근할 수 있는 arguments 객체를 쓰거나,

    by using the arguments object that is native to and locally available to all JavaScript functions; or

  2. 명명된 매개변수를 써서 접근할 수 있습니다.

    by using named parameters.

아래 예제에서는 arguments를 썼습니다만, 가독성을 생각해서 명명된 매개변수를 써야 합니다.

In the example below, we will use arguments. For readability, though, you should use named parameters:

window.onerror = function(){
    alert(arguments[0] +'\n'+arguments[1]+'\n'+arguments[2]);
}

init(); //정의되지 않은 함수이며 에러 이벤트를 발생시킵니다.
What our error looks like as an alert in Internet Explorer 9

그림 4. 인터넷 익스플로러 9에서 alert()으로 본 에러

Fig 4: What our error looks like as an alert in Internet Explorer 9

이 예제에서는 init()를 정의하지 않았습니다. 따라서 onerror 이벤트를 지원하는 브라우저에서는 onerror 이벤트가 발생합니다.

Here init() has not yet been defined. As a result, the onerror event will be fired in supporting browsers.

주의할 점이 있습니다. window.onerror를 지원하는 브라우저는 많지 않습니다. 크롬 10+, 파이어폭스(모바일 포함)에서 window.onerror를 지원합니다. 인터넷 익스플로러도 window.onerror를 지원하지만, 도움이 되는 에러 메시지는 버전 9에서부터 지원됩니다. 가장 최근의 WebKit 빌드가 window.onerror를 지원하긴 하지만 사파리는 아직 지원하지 않고, 안드로이드도 극히 최근에서야 지원하기 시작했습니다. 오페라도 지원하지 않습니다. HTML 5 명세가 발전하면서 브라우저 제작사들이 표준을 따르길 기대하십시오.

Now the caveat: support for window.onerror is limited. Chrome 10+ and Firefox (including mobile) support it. Internet Explorer supports it, but truly helpful error messages are only available in version 9+. While the latest builds of WebKit support window.onerror, recent versions of Safari and slightly older versions of Android WebKit don’t. Opera also lacks support. Expect that to change as the HTML5 specification evolves and browser vendors standardize their implementations.

명령행 인터페이스로 자바스크립트를 즉석에서 수정하십시오.

자바스크립트 콘솔은 최근 이용할 수 있는 디버깅 도구 중에서도 상당히 강력한 편입니다. 자바스크립트 콘솔은 자바스크립트를 위한 명령줄이나 마찬가지입니다. 콘솔에 데이터를 찍어볼 수도 있고, 코드가 망가진 원인을 살펴볼 코드를 삽입할 수도 있습니다.

One of the more powerful features available in today’s debugging tools is the JavaScript console. It's almost a command line for JavaScript. With it, you can dump data or inject JavaScript to examine why your code has gone rogue.

자바스크립트 콘솔 불러내기

파이어폭스는 독특합니다. 개발자들은 몇 년 동안 파이어버그를 썼습니다만, 파이어폭스 4부터는 자체 콘솔이 있습니다 (개발자 도구 > 웹 콘솔).

Firefox is a special case. For years, developers have used the Firebug extension. Firefox 4, however, added a native console (Tools > Web Console or Menu > Web Developer > Web Console).

파이어버그는 콘솔 API를 완전히 지원하며 CSS 디버깅 기능도 매우 좋습니다. 기본적인 목적으로는 웹 콘솔도 괜찮지만 파이어버그를 설치하길 추천합니다.

Firebug fully supports the Console API, and has more robust CSS debugging features. I recommend installing it, though the Web Console is a capable tool for basic needs.

아래 예제에는 드래곤플라이를 썼습니다 (네, 오페라에서 일해요). 물론 아래 예제들은 크롬, 사파리, 파이어폭스, 파이어버그, 인터넷 익스플로러에서도 비슷하게 동작합니다.

I’m using Opera’s debugging tool Dragonfly in the examples below (yes, I work for Opera). These examples, however, work similarly in Chrome, Safari, Firefox, Firebug, and Internet Explorer.

앞 예제를 다시 살펴보죠. “result”란 id를 가진 요소가 있을 거라 가정하는 행,
var a = document.querySelector('#result');를 추가합니다.

Let’s take another look at the code from our previous examples. We’re going to add a new line—var a = document.querySelector('#result');—one that assumes an element with an id value of “result.”

querySelector() 메서드를 잠시 살펴보죠. 이 메서드와 querySelectorAll() 메서드는 DOM 선택자 API의 일부분입니다. querySelector() 메서드는 매개변수로 넘긴 CSS 선택자와 일치하는 요소 중 첫 번째를 반환합니다. querySelector()querySelectorAll() 모두 최근 브라우저에서 지원됩니다.
document.getElementById('result')를 써도 되지만 document.querySelector()이 좀 더 효율적입니다.역주

A quick note about the querySelector() method: it and querySelectorAll() are part of the DOM selectors API. querySelector() returns the first element matching the specified CSS selector. Both methods are supported by the latest versions of most browsers. You could also use document.getElementById('result'), but document.querySelector() is more efficient:

function add(x,y){
    if( isNaN(x) || isNaN(y) ){
        throw new Error("Hey, I need two numbers to add!");
    } else {
        return (x * 1) + (y * 1);
    }
}

var a = document.getElementById('result');

try{
    a.innerHTML = add(9);
} catch(e) {
    console.error(e.message);
}
The Dragonfly console

그림 5. 드래곤플라이 콘솔

Fig 5: The Dragonfly console

여전히 에러가 콘솔에 출력됩니다. 정확히 동작하는 자바스크립트 코드를 좀 삽입해보죠. 콘솔에
a.innerHTML = add(21.2, 40);라고 쓰겠습니다.

Our thrown error is still written to the console. But let’s inject some JavaScript that runs correctly. We’ll enter a.innerHTML = add(21.2, 40); in our console:

The Dragonfly console with injected code

그림 6. 드래곤플라이 콘솔에 코드를 삽입한 모습

Fig 6: The Dragonfly console with injected code

보시다시피, a요소의 innerHTML을 덮어 썼습니다.

As you can see, we have overwritten the innerHTML value of a:

A page with injected code

그림 7. 코드가 삽입된 페이지.

Fig 7: A page with injected code

이제 a를 완전히 바꿔 보겠습니다. 콘솔에
a = document.querySelector('h1'); a.innerHTML = add(45,2);라고 입력합니다.

Now let’s change the value of a entirely. Enter a = document.querySelector('h1'); a.innerHTML = add(45,2); in the console:

Changing code in the console

그림 8. 콘솔에서 코드를 바꾸는 모습

Fig 8: Changing code in the console

콘솔에 47이 표시되고, h1 요소의 innerHTML도 47로 바뀌었습니다.

You’ll see that 47 is written to the console, and it is also the new innerHTML of our h1 element:

Modifying the DOM

그림 9. DOM 수정

Fig 9: Modifying the DOM

심지어 콘솔에서 함수를 재정의할 수도 있습니다. add() 함수를 두 매개변수의 곱을 반환하도록 수정한 후 h1 요소의 내용을 수정하겠습니다. 콘솔에 이렇게 입력하십시오.
function add(){ return arguments[0] * arguments[1]; }
a.innerHTML = add(9,9);:

Now, we can even redefine our add() function. Let's make add() return the product of two arguments and then update the h1. Enter function add(){ return arguments[0] * arguments[1]; } in the console, followed by a.innerHTML = add(9,9);:

Overwriting a function using the JavaScript console.

그림 10. 자바스크립트 콘솔을 써서 함수를 덮어썼습니다.

Fig 10: Overwriting a function using the JavaScript console

h1 요소의 새 innerHTML은 재정의한 add 함수의 결과입니다.

The new innerHTML for our h1 element is now 81, the result of our redefined add function:

The results of overwriting a function.

그림 11. 함수를 재정의한 결과

Fig 11: The results of overwriting a function

자바스크립트 콘솔은 코드가 어떻게 동작하는지 이해시키는 강력한 도구입니다. 자바스크립트 콘솔의 힘은 모바일 장치에서 사용했을 때 더 잘 드러납니다.

The JavaScript console offers a powerful tool for understanding how your code works. It’s even more powerful when used with a mobile device.

모바일 장치를 위한 원격 디버깅

모바일 장치에서 코드를 디버깅하는 일은 매우 고통스럽습니다. 하지만 방법이 있습니다. 오페라 드래곤플라이에서 제공하는 원격 디버깅 기능을 이용하면 모바일 사이트를 데스크탑에서 디버그할 수 있습니다. 웹킷도 최근 원격 디버깅을 추가했고 구글 크롬의 개발자 도구에서는 이미 원격 디버깅을 지원합니다.

Debugging code on a mobile device is still one of our biggest pain points. But, again: now we have tools. Opera Dragonfly and its remote debug feature provides developers a way to debug mobile sites from their desktop. WebKit recently added remote debugging to its core and Google Chrome has already folded it into its developer tools.

독립 개발자들이 만든, 비슷한 기능을 하는 타 브라우저용 애플리케이션을 몇 개 소개하겠습니다. Bugaboo는 iOS에서 동작하는 사파리 기반 디버그 도구입니다. JS Console은 웹에서 사용할 수도 있고 iOS 앱으로 쓸 수도 있습니다. Weinre는 웹킷 기반 브라우저용입니다.

Independent developers offer similar products for other browsers. These include Bugaboo, an iOS app for Safari-based debugging; JS Console which is available on the web or as an iOS app; and Weinre for WebKit-based browsers.

이 글에서는 드래곤플라이 원격 디버그JSConsole을 살펴보겠습니다.

Let’s look at two: Dragonfly remote debug and JSConsole.

오페라 드래곤플라이를 이용한 원격 디버그

드래곤플라이의 장점은 자바스크립트 외에도 CSS나 헤더(네트워크 탭을 보세요)를 디버그할 수 있다는 점입니다. 데스크탑에 오페라를 설치하고 모바일 장치에는 Opera Mobile을 설치해야 합니다.

Dragonfly’s strong suit is that you can debug CSS or headers (see the Network tab) in addition to JavaScript. But it does require installing Opera on your desktop and Opera Mobile on your device.

두 장치가 같은 로컬 네트워크에 연결되어 있어야 합니다. 드래곤플라이를 실행한 컴퓨터의 IP 주소도 알고 있어야 합니다. 다음 단계를 따라 하세요.

Both devices should be connected to the same local network. You will also need the IP address of the machine running Dragonfly. Then complete the following steps:

  1. 드래곤플라이를 엽니다.

    open Dragonfly from the Tools > Advanced (Mac OS X) or Page > Developer Tools (Windows, Linux) menus,

  2. 원격 디버그 설정 The Remote Debugger button 버튼을 누릅니다.

    click the Remote Debug button The Remote Debugger button,

  3. 필요하다면 포트 번호를 수정한 후 “적용”을 클릭합니다.

    adjust the port number if you’d like, or use the default and click “Apply, ”

    The remote debugging panel in Dragonfly

    그림 12. 드래곤플라이의 원격 디버그 패널

    Fig 12: The remote debugging panel in Dragonfly

  4. 디버그하려는 장치에서 오페라 모바일을 열고, 주소창에 opera:debug를 입력합니다.

    open Opera Mobile on your target device, and enter opera:debug in the address bar, and

    Opera Mobile debug console

    그림 13. 오페라 모바일 디버그 콘솔

    Fig 13: Opera Mobile debug console

  5. 호스트 컴퓨터의 IP 주소와 포트 번호를 입력한 후 “Connect(연결)”을 누릅니다.

    enter the IP address and port number of the host machine and click “Connec,t” and

    The IP and Port fields of the opera:debug console

    그림 14. opera:debug 콘솔의 IP, 포트 필드

    Fig 14: The IP and Port fields of the opera:debug console

  6. 디버그하려는 페이지로 이동합니다.

    navigate to the URL of the HTML page you wish to debug on your device.

An alert on Opera Mobile

그림 15. 오페라 모바일의 경고창

Fig 15: An alert on Opera Mobile

호스트 컴퓨터의 드래곤플라이에서 원격 페이지를 불러옵니다. 이제 원격 페이지를 데스크탑에 있는 것처럼 조작할 수 있습니다. 결과는 모바일 장치에 나타납니다. 예를 들어 호스트 콘솔에서 alert( add(8,923) )라고 입력하면 경고창은 모바일 장치에 뜹니다.

Dragonfly on the host machine will load the remote page. You can then interact with the page as though it was on your desktop. You will see the results on the device. For example, if you enter alert( add(8,923) ) in the host console, the alert appears on the mobile device screen.


JSConsole을 이용한 원격 디버깅

JSConsole은 브라우저에 무관하게 쓸 수 있는 웹 기반 서비스입니다. JSConsole을 쓸 때는 다른 도구를 쓸 때와는 달리 데스크탑 컴퓨터와 모바일 장치가 같은 네트워크에 있을 필요는 없습니다.

JSConsole is a web-based, browser-independent service. Unlike Bugaboo, Weinre, and Dragonfly, your computer and device don’t have to be connected to the same local network.

JSConsole을 사용하려면 다음 단계를 거칩니다.

To use JSConsole:

원격 콘솔 명령어는 JSConsole 창에 나타납니다 (console.error()이나 console.warn()가 아니라 console.log()를 써야 합니다). JSConsole 창에서 모바일 장치로 코드를 보낼 수도 있습니다. 예를 들어 alert( add(6,3) );라고 입력해 봅니다.

Remote console statements will appear in the JSConsole window (you do need to use console.log() rather than console.error() or console.warn()). You can also send code from the JSConsole window to your device. In this case, alert( add(6,3) );.

Sending a command using JSConsole.com

JSConsole.com을 이용해 명령어 보내기

Fig 16: Sending a command using JSConsole.com

원격 에러 로깅

위의 예제에서는 콘솔에 로그를 표시하거나 경고창을 띄웠습니다. 서버 측 스크립트에 에러를 기록하면 어떨까요?

In the examples above, we’re logging to the console, or launching an alert box. What if you logged your errors to a server-side script instead?

다음 코드에는 XMLHttpRequest()를 이용했습니다.

Consider the following code that uses XMLHttpRequest(). In it, we are :

function sendError(){
     var o, xhr, data, msg = {}, argtype = typeof( arguments[0] );

     // 첫 번째 매개변수가 에러 객체라면 그냥 그걸 씁니다.
     if( argtype === 'object' ){
          msg = arguments[0];
     }

     // 첫 번째 매개변수가 문자열이라면 매개변수가 3개 있는지 확인합니다.
     else if( argtype === 'string') {
     // 매개변수가 3개 있다면 onerror 이벤트라고 간주합니다.
          if( arguments.length == 3 ){
              msg.message    = arguments[0];
              msg.fileName   = arguments[1];
              msg.lineNumber = arguments[2];
          }
        // 아니라면 첫번째 매개변수를 보냅니다.
          else {
              msg.message    = arguments[0];
          }
      }

     // 사용자의 브라우저 이름을 첨부합니다.
     msg.userAgent = navigator.userAgent;

         // JSON 문자열로 변환합니다.
         data = 'error='+JSON.stringify(msg);

     // XHR 요청을 만듭니다.
     xhr = new XMLHttpRequest();
     xhr.open("POST",'./logger/');
     xhr.setRequestHeader("Content-type", "application/x-www- »
     form-urlencoded");
     xhr.send( data );


     // 지원하는 브라우저에서는 에러 메시지를 숨깁니다.
     return true;
}

PHP를 써서 넘겨받은 에러 메시지를 텍스트로 저장합니다.

Here we’re posting our error messages to a script that logs them in a flat file using PHP:

<?php

// JSON 객체를 해석합니다.
$error = json_decode( $_POST['error'], true );
$file = fopen('log.txt','a');
fwrite($file, print_r( $error, true) );
fclose($file);

?>

말해둘 게 있습니다. 당신이 사랑하는 스타벅스(아니면 커피빈이든, 엔제리너스든)에 걸고, 이 스크립트에서 공개된 디렉토리에 파일을 쓰지 않게 만드세요. 조작된 헤더나 변수를 통해 코드를 주입할 가능성을 감수할 만큼의 가치는 없습니다. 이런 형태로 스크립트를 기록하는 건 개발 중에만 해야지, 실 서버에서는 절대 안 됩니다.

Now the disclaimer: please for the love of tequila, don’t let this script write to a world-readable directory. The potential for code injection due to spoofed headers or variables is not worth the risk. Logging scripts like this should only be used during development, and never on production servers.

결론

웹이 진화함에 따라 우리가 쓰는 도구도 진화했습니다. 코드 삽입, 에러 throw-catch, 원격 디버그 서비스를 이용해서 버그가 좀 덜한 앱을 만들 수 있을 겁니다.

As the web has evolved, so have our tools. Code injection, error throwing and catching, and remote debugging services are all helping us ship better, less buggy apps.

1. 줄번호를 유의해서 보라는 뜻입니다.돌아가기

2. getElementById(), getElementsByTagName() 메서드가 반환하는 노드리스트는 호출 당시의 상황을 담는 것이 아니라, 실제 DOM에 대한 "살아 있는" 참조이며 노드리스트를 사용할 때마다 매번 바뀝니다. 이에 반해 querySelector(), querySelectorAll() 메서드는 정적인 배열을 반환합니다. 즉, 이 메서드를 호출한 순간을 캡처한 스크린샷이라고 생각해도 됩니다. querySelector(), querySelectorAll() 메서드가 getElementById(), getElementsByTagName() 메서드에 비해 매우 빠르고 효율적이긴 하지만 사용할 때는 구분할 필요가 있습니다. 이 글을 통해 querySelector(), querySelectorAll() 메서드를 처음 접하셨다면 사용하기 전에 한 번 정도 연습해서 두 메서드의 차이를 확인하시기 바랍니다.돌아가기

댓글 (708)

저자

Tiffany B. Brown Tiffany B. Brown is a member of the Opera Software Developer Relations team, where she advocates for an open, interoperable web. She lives in Los Angeles, loves New Orleans, and mixes a mean Manhattan.