43. 겸손한 자바스크립트의 원리

소개

앞선 글 들에서 우리는 HTML과 CSS에 대해 많은 이야기를 했고, 그것들을 성공적으로 실행에 옮기는 방법과 함께 자바스크립트의 기초들 – 자바스크립트는 무엇이고, 당신에게 어떤 도움이 되며, 왜 그것에 대해 알아야 하는지 역시 이야기했다. 실질적인 자바스크립트 사용에 대해서 더 깊이 다루기에 앞서, 잠시 멈춰서 스크립트 때문에 당신의 사이트를 외면하는 사용자가 생기지 않게끔 주의깊게 사용하는 법에 대해서 생각해 보는 것이 좋겠다. 이것이 “겸손한unobstrusive” 자바스크립트의 핵심 사항이다. 그것이 무엇이고, 왜 우리가 그것을 필요로 하는지 더 잘 이해하기 위해, 자바스크립트 프로그래밍과 관계된 여러가지 불확실성들을 고려해보도록 하자.

  • 일부 브라우저는 자바스크립트를 지원하지 않거나, 혹은 너무 오래되었기 때문에 당신의 스크립트를 완전히 무시할 수 있다.
  • 브라우저에서 스크립트를 지원한다 하더라도, 사용자들이 보안상의 이유로 스크립트를 꺼 두었을 수 있고, 혹은 그들이 근무하는 회사의 방화벽이 모든 <script> 태그를 없애고 있을 수도 있다.
  • 브라우저에서 스크립트를 지원한다 하더라도, DOM 명세의 일부분을 독자적으로 해석/지원하여 결과적으로는 당신의 스크립트 중 일부분만을 이해할지도 모른다(IE가 종종 이런 종류의 잘못을 저지른다).
  • 스크립트가 완전히 해석되었다고 하더라도, 굉장히 복잡한 HTML에 기반해 있으며 HTML은 (스크립트 제작자가) 예측하지 못한 방법으로 바뀔 수 있다.
  • 당신의 프로그래밍 문맥이 완벽한 HTML에 의해 축복받았다고 하더라도, 당신은 사용자들이 어떤 입력장치를 가지고 페이지를 브라우징할 지 확신할 수 없다. 상당수의 스크립트들이 마우스를 사용할 수 있을 때에만 동작하며, 마우스 대신 키보드를 쓰는 사용자들에 대해서는 잊고 있다(장애를 가진 사람들 중 상당수는 마우스를 사용할 수 없으며, 어떤 사람들은 키보드를 더 선호한다).
  • 당신의 스크립트가 위에서 언급한 모든 문제들을 전부 해결했고 또한 완벽하게 동작한다 하더라도, 다른 프로그래머들이 그것을 이해하지 못할 수도 있다.

문제들의 목록이 꽤나 길어보인다. 이중 대부분은 기술적인 문제라기 보다는 컨셉의 문제, 혹은, 당신이 원한다면, 철학적인 문제이다. 이에 더해서, 마지막 두가지 문제점은 다른 프로그래밍 언어에서도 고려되어야 할 문제이지만, 앞의 네가지는 자바스크립트 프로그래밍 환경에 고유한 문제이다 – 따라서 프로그래밍 경험이 많더라도 별로 도움이 되지 않는다.

짧게 말하자면, “겸손한unobtrusive” 자바스크립트는 당신의 사이트를 방문한 사람들이 위에 열거한 이유 때문에 발을 돌리게 되는 상황을 막을 수 있게끔 프로그래밍하는 것이다 – 설사 당신의 자바스크립트가 정확히 동작하지 않는다 하더라도, 방문자들은 여전히 당신의 사이트를 이용할 수 있어야 한다. 조금 더 기본적인 수준에서라도. 이 글은 겸손한 자바스크립트의 원칙과 실제 사용에 대해 다루며, 이후의 과정에 대비해서 당신을 멋지게 준비시킬 것이다.

이 글의 구조는 다음과 같다:

  • 겸손한 자바스크립트의 정의
  • 구조와 동작의 분리
  • 사용성을 위한 레이어 추가
    • 예제 – 입력양식 유효성검사
    • 원칙들
    • 예제 – 팝업
    • 예제 – Ajax
  • 깔끔하며, 의미 있는 HTML
  • 브라우저 호환성
  • 요약

겸손한 자바스크립트의 정의

위에 열거한 문제들을 다루기 위해서, 가장 중요한 것은 당신이 무엇을 하고 있는지, 그리고 왜 그것을 하고 있는지 이해하는 것이다. 우리가 필요로 하는 것은, 적합한 자바스크립트 개발의 이론이다.

그러한 이론은 겸손한 자바스크립트에 의해 제공된다. 그것은 테크닉이 아니다; 겸손한 자바스크립트는 하나의 새로운 겸손해지시오() 함수를 당신의 스크립트에 추가하고는 그를 통해 열반의 경지에 들어가는 차원의 문제가 아니다 – 그것은 생각의 방식이다. 당신의 스크립트로 인해 불편해지는 사람이 아무도 없게끔 하기 위해, 당신의 스크립트에 어떠한 근거없는 추측도 존재하지 않도록 주의해야 한다.

자, “근거없는 추측 없애기” 이것 역시 다소 긴 주제이다. 다행히도, 우리는 겸손함을 3가지 범주로 분류할 수 있다: 당신의 스크립트는 사용자와, 브라우저들과, 동료 프로그래머들에 대해 겸손해져야 한다.

  • 억측 1: 모든 브라우저가 자바스크립트를 지원한다 – 사실이 아니다: 사용자들에 대해 겸손해지기 위해, 당신의 사이트에서 스크립트를 제거하더라도 사용자들이 여전히 당신의 사이트를 이용할 수 있어야 한다. 비록 사용자들의 상호작용이 자바스크립트를 지원하는 경우에 비해 훨씬 부족하다고 하더라도 말이다.
  • 억측 2: 모든 브라우저들은 똑같이 동작한다 – 사실이 아니다: 브라우저들에 대해 겸손해지기 위해, 당신의 스크립트는 에러들과 호환성 문제들을 이끌어 나가야 하며, 리더기나 모바일 같은 특수한 장비들 역시 고려해야 한다.
  • 억측 3: 다른 모든 이들이 내 코드를 이해할 것이다 – 사실이 아니다: 동료 프로그래머들에 대해 겸손해지기 위해, 코드를 깔끔하게 만들고 당신의 코드가 무엇을 하는지(무엇을 하게 하려 하는지) 설명하는 주석들을 많이 달도록 하라.

이 글은 처음의 두가지 억측에 대해 좀 더 자세히 다룰 것이다. 세번째 억측은 별도의 글에서 다루어질 것이다.

이러한 억측을 피하는 것에 더해, 겸손한 자바스크립트는 당신의 자바스크립트 코드를 HTML으로부터 분리해 낼 것을 요구한다. 이것이 이러한 프로그래밍 철학 중에서 가장 기술적인 부분이므로, 이것을 먼저 다룬 후에 우리의 억측들로 돌아올 것이다.

구조와 행동의 분리

우리가 모든 CSS 들을 별도의 파일에 놓고 스타일 속성이나 기타 다른 표현적 마크업들을 삼가함으로써 구조와 표현을 분리하는 것과 마찬가지로, HTML 구조와 자바스크립트 행동들을 분리해야 한다. 이유는 동일하다: 당신의 관심영역을 분리하고, 당신의 코드를 깔끔하게 해주며, HTML 이나 CSS에 손 댈 필요 없이 자바스크립트 작업을 할 수 있게 해준다.

기본적인 규칙은 간단하다: HTML 파일은 자바스크립트 코드를 포함하면 안된다 – CSS를 포함하지 않아야 하는 것과 마찬가지로 말이다. 자바스크립트 개발자들이 HTML 파일에 넣을 수 있는 것은 두가지이다: 내장embeded 된 스크립트와 이벤트 핸들러가 그것이다. 스크립트 코드들을 없애는 것이, 구조와 행동을 분리하는 가장 간단한 방법이다.

마지막 글에서 배웠듯이, 내장된 스크립트들은 HTML 페이지 내부에, <script> 태그로 둘러싸여져 있는 자바스크립트 코드 들이다. 이것들은 쉽게 외부 스크립트 파일로 옮겨질 수 있으므로, 아무런 문제도 일으키지 않는다.

<a href=“somewhere.html” onmouseover=“hideAll()”> 와 같은 인라인 이벤트 핸들러들은 없애기가 약간 더 힘들다. 이것은 특정 이벤트가 일어났을때 어떤 이벤트 핸들러(자바스크립트 함수)가 실행되는지 정의하는 것이다. 이벤트 핸들러를 겸손하게 만들기 위해 우리가 할 일은 그것들을 별도의 스크립트 파일로 보내는 일이다. 이것은 외부 스크립트 파일이 적절한 요소를 찾아내고, 거기에 이벤트 핸들러를 연결하는 것을 의미한다.

이벤트 핸들러에 대해 더 많이 배우고 싶다면, 우리의 글 중 Handling events with JavaScript 를 참고하기 바란다.

특정한 요소를 찾아내기 위해 가장 쉬운 방법은, 그것에 ID를 주는 것이다. 예를 들어:

<!-- HTML: -->
<a href="somewhere.html" id="somewhereLink">
<!-- JavaScript: -->
var x = document.getElementById('somewhereLink');
if (x) {
  x.onmouseover = hideAll;
}

hideAll() 함수는 사용자가 링크 위로 마우스를 가져갈때마다 실행되고, 이 코드는 <a href=“somewhere.html” onmouseover=“hideAll()”> 와 동일하다.

더 좋은것은, 이 두 줄의 코드는 “somewhereLink”라는 아이디를 가진 요소를 포함하는 모든 페이지들에서 동작한다는 것이며, 따라서 당신은 시간을 들여 이것을 반복할 필요가 없다. 그리고 이러한 요소를 포함하지 않는 페이지들에 대해서는, if(x) 구문이 에러 메세지가 나지 않을 것을 보장하고 있다: 요소 x가 실제로 존재할때에만 이벤트 핸들러를 할당하기 때문이다.

그리고 브라우저가 자바스크립트를 지원하지 않는다면? 당연히, 마우스오버는 동작하지 않는다. 하지만 링크는 여전히 링크이고, 여전히 따라갈 수 있다.

이제 우리의 코드는, 깔끔해진것에 더해, 좀더 관리하기 편해졌다.

예를 들자면, 마우스오버와 포커스 이벤트를 결합하는것은 종종 좋은 결과를 가져온다. 마우스오버는 사용자가 마우스를 쓸 때에만 동작한다. 마우스를 사용하지 않는 사람들은 키보드를 사용해서 클릭하고자 하는 링크에 포커스를 줄 것이며, 이것은 포커스 이벤트를 동작시킨다. 만약 우리가 이 이벤트에도 마찬가지로 함수를 등록해준다면(즉, 함수에게 이 이벤트에 대해서도 동작하라고 말해둔다면), 우리의 프로그램이 키보드에 대해서도 동작할 것임을 확신할 수 있게 된다.

스크립트를 HTML에서 분리해 뒀다면 이것은 아주 쉽게 할 수 있다:

var x = document.getElementById('somewhereLink');
if (x) {
  x.onmouseover = x.onfocus = hideAll;
}

2글자를 추가함으로써 우리의 프로그램이 키보드로도 동작하게끔 만들었다. 쉽지 않은가?

인라인 이벤트 핸들러를 사용했었다면 어떻게 했어야 됬을지 한번 생각해보자. 우리는 사이트 전체를 헤집고 다니면서, 마우스오버 이벤트를 가진 모든 링크에 onfocus=“hideAll()” 이라는 구문을 일일이 손으로 추가해 주어야 했을 것이다. 뭔가 다른 유용한 일에 투자할 수 있었을 시간을 아주 많이 낭비할 뿐만 아니라, 에러를 보증하는 방법이기도 하다 – 아주 특정한 상황에서만 사용되는, 조금 따로 떨어져 있는 템플릿 속에 들어있는 링크는 잊어버리고 바꾸지 않기 쉬우며, 또한 많은 onfocus= 중 어느 하나에 오타를 낼 수도 있다.

따라서, HTML과 CSS를 분리하는 것이 현명한 것 처럼, HTML에서 자바스크립트를 분리해내는 것 역시 마찬가지로 좋은 방법이다. 내장된 스크립트와 인라인 이벤트 핸들러들을 없애는 것은 아주 쉬우며, 그 즉시 당신의 코드의 유용성과 유지보수성을 향상시킨다.

사용성 레이어 추가하기

겸손한 자바스크립트의 가장 기술적인 부분을 다루었으므로, 우리가 앞서 논의했던 억측들로 돌아갈 시간인 듯 하다. 이중 가장 중요한 것은, 모든 사람들이 자바스크립트를 쓸 것이라는 착각에서 벗어나는 것이며, 이러한 발상의 전환은 웹 사이트에 스크립트를 결합시키는 전반적인 목적에 직접적으로 결부된다.

자바스크립트의 목적은, 당신의 사이트에 사용성을 배려하는 도구layer를 하나 추가하는 것이다. 여기서 “추가” 라는 표현에 조금 주목해보도록 하자: 만약 스크립트가 사용성 전체라면(바꿔 말해서, 자바스크립트 없이는 사이트를 사용할 수 없다면), 당신은 정말 심각한 실수를 저지르고 있는 것이며 당신의 스크립트는 전혀 겸손하지 않은 것이다.

예제 – 입력양식의 유효성 검증

하나의 예를 들어보면 이것을 분명히 할 수 있으므로, 입력양식의 유효성 검증 부분에 대해 이야기를 해 보자. 입력양식에 사용자들이 입력한 내용은 데이터베이스에 추가되기 전에 항상 체크해야 하는데, 왜냐하면 이런 불특정 다수의 – 악의적일수도 있는 – 사용자들이 채워 넣는 데이터를 묵시적으로 신뢰한다는 것은, 당신의 사이트가 해킹당할 수 있는 가장 빠르고 확실한 길이기 때문이다. 우리는 데이터를 수용하기 전에 항상, 그리고 반드시 그것을 체크해야 한다.

그럼에도 불구하고, 이러한 유효성 검증을 서버에서 하는 것은 시간을 좀 소모하게 된다는 단점을 갖고 있다. 사용자가 입력양식을 서버에 전송하고, 서버는 사용자가 제출한 양식이 규칙에 맞는지, 또는 에러가 있는지 알려주는 응답 페이지를 만들어낸다. 서버가 아무리 빠르게 반응한다고 하더라도, 제출과 응답 사이에는 항상 약간의 딜레이가 있기 마련이다 – 이 지연시간을 0.5초라고 생각해보자.

상황을 좀 더 악화시켜서, 사용자가 실수-예를 들어, 주소를 적지 않았다거나-를 저질렀다면, 사용자는 문제를 해결하고 입력양식을 다시 한 번 전송해야 하며, 다시 0.5초를 기다려야 한다. 물론 이것은 아주 긴 시간은 아니지만, 사용자의 마음 한 구석에는 계속 누적되고 있다. 특히, 사용자가 이러한 반복을 몇번 해야 한다면 말이다.

자바스크립트가 개입해야 할 곳이 바로 여기이다. 입력양식을 서버에 전송해버리기 전에 검토하는 스크립트를 추가한다면, 사용자들이 빈번히 저지르는 실수들을 서버와 설왕설래 하는 일 없이 잡아줄 수 있을 것이며, 이러한 인터페이스는 훨씬 빠르고 부드럽게 돌아가는 것 처럼 느껴질 것이다.

즉, 입력양식의 유효성 검증에 자바스크립트를 사용하는 것은 좋은 아이디어이다. 그러나-이것은 아주 중요하다-, 스크립트는 서버사이드 유효성 검증에 더해서 사용해야 한다. 전자(스크립트)는 부드러운 인터페이스를 제공하겠지만, 당신에게 확실한 보안을 제공하는 것은 후자(서버사이드)이며(에러를 발생시키기로 마음먹었다면, 스크립트로 만들어진 유효성 검증을 우회하는 것은 아주 쉽다 – 스크립트를 끄기만 하면 된다), 사용자의 브라우저가 자바스크립트를 지원하지 않을 때에 에러처리방법을 제공하는 것 역시 서버이다.

2009년 초반(이것은 가까운 시일 안에 바뀔수도 있다), 오페라 브라우저는 다른 브라우저들보다 빨리 HTML 5의 Web Forms 2.0 명세를 지원하고 있다. 웹 입력양식 2.0은 간단히 말해서 HTML 입력양식의 발전된 형태이며, 클라이언트에서 자바스크립트 없이 입력양식의 유효성을 점검하는 기능이 몇가지 내장되어 있고, 따라서 자바스크립트를 끄는것으로는 이 유효성검증을 우회할 수 없게 되어있다. 웹 입력양식 2.0에 대해서 더 많이 알고 싶다면 Improve your forms using HTML 5 을 체크해보기 바란다.

원칙들

이 예는 몇가지 중요한 원칙들을 강조하고 있다:

  1. 사이트는 자바스크립트 없이 동작할 수 있어야 한다.
  2. 자바스크립트가 사용 가능하다면, 당신은 사용자들에게 추가적인 사용성을 선사할 수 있다; 사용자들이 자신이 원하는 일을 좀 더 빨리 처리할 수 있게끔 하고, 성가신 페이지 리로드를 가급적 줄이는 사용성 말이다.
  3. 자바스크립트는 안전하지 않다. 이 이야기는, 입력양식에 사용자가 입력한 것을 체크하는 것과 같은 아주 중요한 작업에 있어서, 자바스크립트만으로 이루어진 루틴을 신뢰해서는 *절대로* 안된다는 말이다. 무엇보다도, 악의적인 사용자는 단순히 자바스크립트를 꺼버리는 것 만으로 당신이 마련한 방어벽을 우회할 수 있다.

자, “사이트는 자바스크립트 없이도 동작할 수 있어야 한다” 는 말이 정확히 무엇을 의미하는가? 이 말은, 어떤 사용자든, 사용하는 브라우징 장치가 무엇이든, 소프트웨어가 무엇이든 간에, 사이트의 내용을 읽을 수 있고 그 안에서 이동할 수 있어야 하며 다른 중요한 기능들을 사용할 수 있다는 의미이다. 그 이상도 아니고, 그 이하도 아니다(그 이하도 아니다, 라는 것이 더 중요하다).

중요한 것은 이것이다 – 스크립트를 꺼 둔 사용자에게, 스크립트를 켜 둔 사용자와 동일한 기능성을 제공할 필요는 없다. 입력양식의 유효성을 검증하는 예제 에서는, 스크립트를 꺼 둔 사용자는 자신이 제출한 입력에 대한 결과를 보기 위해 0.5초를 기다려야 하며 따라서 스크립트를 켜 둔 사용자에 비해 약간 불편함을 느낄 수 있다.

사실, 이것은 일반적인 법칙이다. 자바스크립트를 끄면, 사용성이 감소하며, 웹 개발자로서 당신의 주요 업무는 사용자들이 사이트의 기본적인 것들: 내용과 내비게이션을 사용할 수 있음을 확실히 하는 것이다. 다른 모든 기능들은 부차적인 것이다.

예제 – 팝업

또 다른 예제로서, 팝업 창을 생각해보자. 팝업창은 때때로 유용하며, 브라우저가 자바스크립트를 지원한다면 만드는 것도 아주 쉽다. 그러나, 브라우저가 자바스크립트를 지원하지 않는다며, 사용자들은 팝업을 볼 수 없을 것이다. 자바스크립트를 지원하지 않는 브라우저로도 여전히 사이트를 사용할 수 있으면서도, 자바스크립트를 지원하는 브라우저에게는 좀 더 부드러운 인터페이스를 제공하려면 어떻게 할 것인가?

In HTML:

<a href="somewhere.html" class="popup">Go somewhere</a>

In JavaScript:

var x = document.getElementsByClassName('popup'); // a custom function
for (var i=0;i<x.length;i+=1) {
    x[i].onclick = function () {
        window.open(this.href,'popup','arguments');
        return false;
    }
}

여기에서 가장 중요한 것은 링크의 href 속성이다. (href속성이)팝업창에 나타나야 할 페이지를 정의하고 있지만, 또한 자바스크립트가 비활성화되었다 하더라도 사용자들은 확실히 링크를 따라 갈 수 있게끔 하고 있다. 따라서 이 예제는 자바스크립트 없이도 완벽하게 동작한다 – 아주 조금 덜 좋을 뿐이다.

자바스크립트가 활성화되면, 추가적인 사용성:팝업을 제공할 수 있다. 모든 링크들은 “popup” 클래스를 가지며, 또한 팝업창을 여는 onclick 이벤트 핸들러를 갖고 있음을 알 수 있을 것이다. 팝업창에 어떤 페이지가 나타날 것인가? 링크의 href 속성에 정의된 페이지(this.href)이다.

다른 예제이지만, 원칙은 동일하다. 첫째, 모든 사용자가 정보에 접근할 수 있게끔 하고, 그 위에 자바스크립트를 사용해서 부드러운 인터페이스를 추가하도록 하라.

예제 – Ajax

이러한 이론은 이따금씩 현실에 적용하기 어려울 수도 있다. 특히 당신이 웹 개발에 비교적 신참자인 상태에서, 예를 들어, Ajax 사이트를 개발하려고 할 때 더욱 그렇다. 이러한 테크닉을 적용하기 위한 좋은 방법은, 계층적으로 생각하는 것이다. 사이트의 기본적인 기능은 무엇인가? 이 기본적인 기능이 가장 하단의 계층에 위치해야 하며, 이것은 스크립트 여부에 관계없이 동작해야 한다. 그 위에, 사이트를 좀 더 사용하기 쉽게 만드는, 자바스크립트로 동작하는 추가적인 사용성을 제공할 수 있다. 이러한 계층은 사이트의 기본적인 기능과 충돌하지 않아야 한다; 그저 몇가지 추가적인 장점들을 제공할 뿐이다.

이런 일반적인 규칙을 예제로서 분명히 해 보자. 당신의 사이트에서 핸드폰을 비교하고 있다고 가정하자. 사이트의 기본적인 기능은 아래에 있다:

  1. 특정 핸드폰에 대해 검색한다 – 타입으로 검색하거나, 좀더 일반적인 기준 – 예를 들어 “WIFI 지원” 이라거나, “내 데스크탑 컴퓨터와 동기화될 수 있는 것” 등.
  2. 검색 조건에 맞는 핸드폰의 목록을 가져온다.
  3. 이 목록을 가격, 이름/타입, 혹은 기타 기준에 의해 정렬한다.

이러한 모든 기능들은 한줄의 자바스크립트도 쓰지 않고 만들어 낼 수 있으며, 당신의 첫 과제는 바로 그것을 하는 것이다. 따라서:

  • 검색 페이지
  • 당신이 검색한 결과에 따라서 서버가 만들어 준, 목록 페이지.
  • 목록 페이지에 있는, 서버에서 다른 방법으로 정렬해서 보내준 페이지에 대한 링크.

스크립트가 전혀 없는 이러한 페이지를 만들어 냄으로써, 당신은 브라우저나 장비를 가리지 않고 동작하는 가장 기본적인 계층을 만들어내었다.

먼저 이것을 한 이후, 자바스크립트에 기반한 기능을 이러한 기본적인 페이지에 추가할 수 있다. 가장 분명한 예제를 들자면 정렬하는 스크립트이다. 무엇보다도, 정렬을 위해 필요한 데이터 – 가격이나 기능 – 은 이미 페이지의 테이블 안에 들어있으며, 이것을 가져오기 위해 다시 서버와 통신할 필요는 전혀 없다. 당신이 만들어야 하는 것은, 테이블에서 데이터를 읽은 후 <tr>들을 정렬할 스크립트이다.

스크립트를 만들었으면, 사용자가 실제로 그것을 이용할 수 있게끔 확실히 해야 한다. 이것을 할 수 있는 링크를 제공하는 것이 가장 확실한 해결책이다.

여기에서 중요한 것은, 테이블에 이미 링크들이 있다는 것이다: 이미 있는 링크들은, 다른 방법으로 정렬된 페이지를 서버에서 가져오는 링크들이다. 따라서, 가장 좋은 해결책은, 이 링크들의 기본적인 동작보다 우선해서 동작하게끔 하는 스크립트를 제공하는 것이다 – 우리가 팝업 예제에서 했던 바로 그것 말이다.

자 이제 새로운 함수를 만들고, 이 함수를 링크의 onclick 이벤트 핸들러에 할당해서, 이것을 눌렀을 때 서버에 연결하는 것이 아니라 당신의 스크립트를 호출하도록 하자.

따라서, 모든 사용자가 같은 ‘정렬’ 링크를 보겠지만, 이 링크들의 정확한 동작방법은 사용자들의 브라우저가 추가적인 사용성 계층 – 자바스크립트가 지원하는 – 을 다룰 수 있는지의 여부에 따라 다르다. 이것이 가능하다면, 스크립트가 정렬을 해 줄 것이고, 불가능하다면, 새로운 페이지를 서버에서 받아 올 것이다.

HTML 요소의 기본적인 동작 방식 위에 얹혀 사는 것이 겸손한 자바스크립트의 가장 핵심이다. 브라우저가 스크립트를 지원한다면, 매우 좋다, 스크립트를 실행한다. 브라우저가 스크립트를 지원하지 않는다면, HTML 요소의 기본적인 동작 방식으로 돌아간다. 당신이 이 원칙을 고수하는 한, 당신의 스크립트는 겸손해질 것이다.

깔끔하며, 의미 있는 HTML

스크립트는 웹 페이지의 문맥 위에서 동작한다. 어떤 웹 페이지? 이론적으로는, 어떤 페이지든 상관없다 – 당신이 조작할 수 있는 HTML 요소들이 있는 한 말이다. 하지만, 현실적으로는, 의미있게 마크업되고 구조화된 HTML로 이루어졌으며, HTML과 CSS를 잘 분리해 둔, 표준에 부합하는 페이지 위에서 작업하는것이, WYSIWYG 저작도구로 만들어 낸, 테이블로 레이아웃을 잡고 있는 괴물같은 페이지 위에서 작업하는 것보다 훨씬 쉽다는 것을, 빠르게 깨닫게 될 것이다.

당신이 뉴스 사이트에서 작업중이고, 모든 페이지에 목차를 포함시키고, 목차를 클릭했을때 뉴스 기사의 제목으로 링크되게끔 하고 싶다고 가정해보자. 이것을 하기 위해 가장 간단한 방법은, 페이지의 모든 헤더 태그(<h1>, <h2> 등)을 검색해서 이의 목록을 만들고, 목록을 클릭하면 적합한 헤더로 사용자를 이동시키게끔 하는 것이다. 스크립트가 완성되었으니 다음 작업에 착수하자. (덧붙여 말하자면, 이 스크립트 역시 겸손한 스크립트이다. 헤더로 점프하는 기능은 있으면 좋은 부가기능이며, 이것이 없다 하더라도 사용자들은 여전히 페이지를 읽고 내비게이션을 이용할 수 있다.)

자 이제, 불행히도, 당신이 작업하고 있는 웹사이트가 의미있는 HTML과 CSS로 구성되지 않았다고 가정해보자. 사이트의 모양이 이렇다고 해 보자:

<div class="contentcontainer">
  <p class="maincontent"><b class="headline">McCain suspends campaign to spend more time with his economy</b><br>
  In a move that shocked political observers ... [etc etc]</p>
</div>

이렇게 엉망진창으로 마크업된 페이지에도 목차를 만들어주는 스크립트를 작성할 수 있겠는가? 물론, 할 수 있다. 모든 <b> 태그를 체크하고, 그 태그가 class=“headline” 라는 문구를 갖고 있는지 확인해보면 된다 – 이것이 헤드라인이고, 당신의 스크립트는 아마도 동작할 것이다.

그럼에도 불구하고(스크립트가 동작함에도 불구하고), 이제 당신은 제목 레벨에서 명시적으로 구조화된 중첩을 놓치고 있다. 깔끔하고, 의미에 맞게 마크업된 페이지는, <h3> 제목들이 앞에 있는 <h2> 들에 종속된다는 사실을 즉시 파악할 수 있도록 해주며, 당신의 스크립트는 그 사실을 이용할 수 있다.

위의 예 처럼 의미있게 마크업되지 않은 페이지에서는, 매 <b class=“headline”> 마다 그것이 메인 제목인지, 부제목인지, 부제목의 부제목, 아니면 또 다른 어떤것인지 판단할 방법을 찾아야만 할 것이다.

비록 문제가 해결되기는 했지만, 그것은 중요한 것이 아니다. 중요한 것은, HTML 저자들이 제목을 마크업하기 위해 적합한 헤더 태그를 사용했다면, 당신의 스크립트가 언제, 어디서 동작하든 관계없이 정확한 정보를 찾아낼 수 있을 것이라고 완전히 확신할 수 있다는 것이다. 뒤집어 말하면, HTML 저자들이 <b class=“headline”> 같은 것을 사용한다면, 그는 자신이 지금 무슨 행동을 하고 있는지 정확히 모르고 있는 것인데, HTML에 수정을 가하면서 그것을 <strong> 또는 <span> 태그로 쉽게 바꿔버릴수도 있다는 것이다. 그리고, HTML이 수정될 때 마다, 당신의 스크립트 역시 매번 바뀌어야 한다.

따라서, 간결하고 의미있게 작성된 페이지에서 스크립트 작업을 하는 것은, 태그의 짬뽕 속에서 허우적대고 있는 스크립트에 비해, 일반적으로 만들기 쉽고, 관리하기는 항상 훨씬 쉽다.

브라우저 호환성

겸손한 자바스크립트는 또한 브라우저들 사이에서 겸손하게 행동하는 스크립트이다. 이것은 스크립트가 가능한 한 많은 브라우저에서 동작해야 하며, 지원되지 않는다고 해서 에러메세지를 보여서는 안된다는 뜻이다; 대신에 스크립트는 우아하게 뒤로 물러나서, 사이트를 방문한 사람들에게 여전히 모든 기능이 동작하는 페이지를 넘겨주어야 한다. 이것은 아주 멋지게 들리지만, 자바스크립트 개발자들의 입장에서는 가장 마스터하기 어려운 부분이기도 하다.

자바스크립트 세계의 위대한 스승인 Douglas Crockford가 브라우저를 가리켜 이르길, “세상에서 가장 공격적인 프로그래밍 환경” 이라 말한 바 있다. 브라우저는 (아직) 완전한 응용프로그램 플랫폼이 아닐 뿐만 아니라, 디버거처럼 여러가지 것들을 증명하는 면에 있어서 불충분하고 좋지 않은 기록만을 남기고(물론, 상황은 계속해서 좋아지고는 있지만), 게다가 브라우저들 사이의 불일치성의 그 심각한 숫자는 자바스크립트 프로그래머들이 미쳐가도록 신속하게 몰아간다.

불행히도, 브라우저 간의 비호환성은 생활의 일부분과도 같다. 당신이 뭔가 비범한 자바스크립트를 작성하려고 하는 즉시, 다양한 브라우저들의 행동 방식이 너무나도 다른 것을 발견하게 될 것이다. 가장 일반적으로는, 당신의 스크립트가 IE를 제외한 모든 브라우저에서 동작하는 것을 발견하게 될 것이다. 물론, 다른 브라우저들도 이러한 문제점들을 갖고 있기는 하지만 말이다.

이러한 비호환성의 가장 근본적인 이유는 대부분의 유명한 브라우저들이 그들만의 독자적인 자바스크립트 처리 엔진을 갖고 있기 때문이다. 이러한 엔진이 당신의 스크립트를 처리하고, 해석하고, 또한 실행하게 되는데, 이 엔진들은 서로 다르다.

이러한 문제들의 가장 일반적인 소스는 인터넷 익스플로러이다; 다른 브라우저들 사이에서는, 서로 다르게 동작하는 부분이 극히 적으며, 또는 단순히 지원되지 않는 정도이다. MSIE 팀은 자신들의 브라우저가 표준에 부합하도록 작업하고 있지만, 이 작업은 아직 끝나지 않았다. 따라서 여러가지 문제들이 발생할거라고 예상할 수 있다.

설령, 이러한 문제들이 마치 마법처럼 해결되었다고 하더라도, 수많은 비호환성들이 여전히 계속 존재할 것인데, 특정 자바스크립트 엔진이 특정 메서드를 아직 지원하지 못하기 때문일 수 있고, 혹은 엔진의 프로그래머가 실수를 저질렀기 때문일수도 있다.

따라서, 문제가 있고, 이 문제는 조만간에는 해결되지 않을 전망이다. 우리는 어떻게 대처해야 할 것인가?

가장 좋은 전략은 이것을 받아들이고, 이 시리즈의 후반에서 다뤄질 핵심적인 기술 상세에 집중하는 것이다. 모든 브라우저들 사이의 비호환성을 완전히 습득하는 것은 불행히도 불가능하지만, 자바스크립트 프로그래밍을 시작하는 사람들이 도움을 받을 수 있는 것들이 몇가지 있다. QuirksMode.org 사이트에서는 각각의 브라우저들이 지원하는 메서드와 속성들을 알기쉽게 보여주며, 풍부한 버그 노트를 제공한다.

이에 더해, 많은 사람들이 이 길을 이미 걸어갔다. 그들 중 일부는 가장 심각한 문제들로부터 당신을 구원해 줄 자바스크립트 라이브러리를 만들어내기로 결심했다. 따라서, 브라우저간의 비호환성을 해결하기 위해 라이브러리를 사용하는 것은 실용적인 전략이다.

그럼에도 불구하고, 주의하라는 당부를 하나 하겠다. 자바스크립트 프로그래밍에 경험이 없다면, 당신이 처음으로 작성하는 큰 프로젝트는 라이브러리의 도움 없이 해보는 것을 심각하게 고려해야 한다. 이유는, 능수능란한 자바스크립트 프로그래머가 되려면, 표면의 뒤에서 어떤 일들이 벌어지고 있는지 깊이있게 이해하기 위해 충분한 훈련을 해야만 한다는 것이다. 이렇게 함으로써, 당신은 브라우저들이 당신의 스크립트를 어떻게 망가뜨리는지에 대해 날카로운 느낌을 갖게 될 것이고, 이러한 느낌은 당신이 자바스크립트 프로그래머로써 발전해 나가는데 도움이 될 것이다.

즉, 문제를 해결하기 위해 라이브러리를 사용하는것은 좋다, 하지만 시작부터 그것을 바로 사용하고 싶은 유혹에 견뎌내길 바란다. 당신이 무엇을 극복하기 위해 노력하는지 알기 위해, 라이브러리 없이 해보기를 바란다.

요약

겸손한 자바스크립트는 테크닉이라기 보다는 프로그래밍 철학에 가깝다. 이것의 가장 중요한 요소는 어떤 계층에 어떤 사용성을 부여할 것인지 분명하게 파악하는 것이다. 사이트의 필수불가결한 기능들은 전부 평범한 HTML 안에 들어있어야 하며, 일단 이러한 기초를 만들어 낸 후 그 기초 위에 자바스크립트 계층을 추가하여, 지원되는 브라우저에서 더 멋지고, 깔끔하고, 빨라 보이는 인터페이스를 만들어내도록 하라.

여기에 더해, 겸손한 자바스크립트는:

  1. 구조와 표현을 분리한다: 당신의 코드를 깔끔하게 하고 유지보수를 쉽게 해준다.
  2. 브라우저간 비호환성에 응급처치를 제공한다.
  3. 간결하고, 의미에 맞는 HTML 계층과 함께한다.

겸손한 자바스크립트는 그다지 어렵지 않다. 이것은 기본적으로 마음가짐을 바꾸는 것이다; 일단 당신이 몇시간 정도를 투자해서 겸손한 자바스크립트에 대해 계획해본다면, 올바른 결정을 내리는 것이 점점 더 쉬워지는 것을 깨달을 것이다.

일단 당신이 겸손한 자바스크립트에 익숙해지면, 이전의 오만하던 시절로 돌아가고 싶지 않게 될 것이다.

저자에 대해

 

Peter-Paul Koch 는 네덜란드, 암스테르담에서 활동하는 프리랜서 웹 개발자이다. 그는 현재 인터넷에서 가장 우수한 자바스크립트 사이트 중 하나인 quirksmode.org를 운영하고 있다. 그중에서도 그의 W3C DOM 호환성 테이블은, 추측하건대 전세계의 웹 개발자들로부터 그들이 쥐어뜯은 머리카락을 다시 심고 헤어케어 제품을 사는데 소모했을 5백만 파운드를 절약해주었다. 마이크로소프트, 오페라, 애플 과 같은 브라우저 제작사들이 그의 테이블을 참고하여 자신들의 브라우저에서 버그를 해결하고 있다.

이 글을 다 읽어주셨다면, 댓글을 남겨주세요. 좋았다라는 격려도 좋고, 잘못된 부분을 지적해 주시는 것도 좋습니다. 마음에 드셨다면 아래 Like 버튼을 눌러서 페이스북과 트위터로 소개해 주시면 더욱 좋겠습니다.