메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

겸손한 Javascript 및 Ajax 코드 작성 안내서

좋은 프로그래밍 습관으로 웹 애플리케이션 작성하기

Joe Lennon, Software developer, Core International
Joe Lennon photo
Joe Lennon은 아일랜드 코크 출신의 모바일 및 웹 애플리케이션 개발자로 현재 25살이다. Joe는 Core International에 재직 중이며, Core의 모바일 HR 셀프 서비스 솔루션 개발을 이끌고 있다. Joe는 또한 DB2 pureXML, Flex, JavaScript, Adobe AIR, .NET, PHP, Python 및 기타 등등의 주제로 IBM developerWorks에 기사와 튜토리얼을 많이 기고한 열성적인 기술 저자이다. Joe의 첫 번째 저서인 Beginning CouchDB는 2009년 말에 Apress에서 출간되었다. Joe는 여유 시간에 여행, 독서 및 비디오 게임을 즐긴다.
(An IBM developerWorks Contributing Author)

요약:  겸손한 Javascript란 웹 애플리케이션에서 Javascript, CSS 및 HTML 요소를 분리하는 습관을 말합니다. 웹 애플리케이션을 이런 식으로 구성하면 애플리케이션을 유지보수하기가 더욱 쉬워지며 애플리케이션이 다양한 플랫폼과 웹 브라우저에서 일관되게 작동하도록 할 수 있습니다. 이 기사에서는 다양한 기술을 사용하여 겸손한 방식으로 웹 애플리케이션을 개발하는 데 따른 이점을 활용하는 방법을 배웁니다.

원문 게재일:  2010 년 11 월 02 일 번역 게재일:   2011 년 3 월 15 일
난이도:  중급 원문:  보기 PDF:  A4 and Letter (64KB | 15 pages)Get Adobe® Reader®
페이지뷰:  5737 회
의견:  


소개

Javascript와 Ajax(Asynchronous JavaScript + XML) 애플리케이션을 작성하는 경우에는 애플리케이션에서 제공해야 하는 대화식 기능에 집중한 나머지 웹 애플리케이션 개발과 관련된 기본적인 사항을 잊기 쉽다. Javascript와 Ajax 애플리케이션을 겸손한 방식으로 작성하는 것이 여러 면에서 중요하다. 이렇게 하면 우선, 애플리케이션 로직을 내용과 분리할 수 있어서 나중에 애플리케이션을 유지보수하기가 더욱 수월해진다. 또한 다양한 플랫폼과 웹 브라우저에서 가장 기본적인 양식으로 애플리케이션이 일관되게 작동하게 할 수 있기 때문에 개발자는 Javascript와 Ajax 기능을 추가할 때만 이러한 문제를 신경 쓰면 된다. 아마도 가장 중요한 점은 이러한 방식으로 웹 애플리케이션을 개발하게 되면 개발자가 점진적 향상의 개념을 따르게 되며 이는 애플리케이션이 Javascript나 특정 Javascript 기능(Ajax 포함)을 지원하지 않는 브라우저를 사용하는 사용자를 지원하게 된다는 사실을 의미한다. 지금까지 겸손한 방식으로 Javascript 애플리케이션을 작성해왔다면 이 기사를 통해 모든 사용자가 사용자를 지원하는 웹 애플리케이션을 작성할 수 있고 이러한 애플리케이션을 사용하는 사용자에게 부가적인 기능을 제공하는 우수 사례를 발견할 수 있을 것이다.

겸손한 Javascript라는 용어는 비교적 모호한 정의이지만 일반적으로는 좋은 프로그래밍 습관으로 구성된 콜렉션을 사용하여 웹 페이지와 애플리케이션을 작성하는 프로세스라고 할 수 있다. 이러한 프로세스에는 다음과 같은 것들이 포함된다.

  • 애플리케이션에서 Javascript, CSS 및 HTML 요소를 분리해서 유지
  • Javascript를 사용하여 애플리케이션의 기능을 점진적으로 개선하되, 코어 함수에는 Javascript 사용하지 않음
  • 반복을 줄이고 구성을 최적화하여 읽고 유지보수하기 쉽도록 코드의 구조를 유지보수
  • 웹 및 접근성 표준 고수

이러한 방식은 좋은 프로그래밍 습관이며 이러한 방식으로 개발을 하면 제한된 기능을 사용하는 사용자는 물론이고 다양한 웹 브라우저와 장치를 사용하는 여러 사용자를 웹 애플리케이션에서 지원할 수 있다. 또한 이러한 방식으로 빌드한 애플리케이션은 일반적으로 더 잘 구성되고 구조화되며 더 빨리 수행되고 버그가 덜 생긴다.

이 기사에서는 인라인 CSS나 Javascript 이벤트 핸들링을 사용하지 않으면서 애플리케이션의 프리젠테이션, 스타일 및 작동 계층을 분리해서 유지하는 방법을 살펴본다. 또한 겸손하지 않은 몇 가지 Javascript 코드 예제를 살펴보고 이를 통해 좋지 못한 프로그래밍 습관으로 여겨지는 속성을 확인한다. 그런 다음 이러한 개발 스타일과 관련된 몇 가지 우수 사례에 대한 지침과 더불어 이러한 문제를 정정하고 같은 코드를 겸손한 방식으로 작성하는 방법을 배운다. 겸손한 코드와 관련해서는 특히, Ajax 애플리케이션이 문제가 된다. 애플리케이션에 리치 Ajax 인터페이스가 있다고 해서 개발자가 이 코드를 점진적으로 향상된 방식으로 추가할 수 없는 것은 아니기 때문이다. Ajax 기능에서 제공해야 하는 유동성을 이용할 수 없는 사용자에게 폴백(fallback)을 제공하는 방식으로 Ajax 함수에 접근하는 방법을 배우게 된다. 마지막 부분에서는 Javascript를 끈 상태에서도 계속해서 작동하는 동적 Ajax 로딩을 제공하는 애플리케이션에 대한 예제를 상세하게 살펴본다.


작동을 내용과 분리하기

Ajax와 Web 2.0이 개발되기 전에는 클라이언트측 양식 유효성 검증, 롤오버 이미지 및 내용 보기/숨기기와 같은 기본적인 기능을 구현하기 위해 Javascript를 주로 사용했다. 간단한 Javascript 코드를 이용하면 이러한 기능을 사용할 수 있었기 때문에 해당 HTML 문서에 있는 <head> 섹션의 <script> 블록에서 두세 개의 함수를 작성한 다음, onclick과 같은 HTML 요소 속성을 사용하여 이 함수를 이벤트에 첨부하는 것이 일반적이었다(예: <input type="button" value="Click Me!" onclick="buttonPressed();">).

코드를 여러 부분으로 분리하는 데 있어서는 Javascript만 문제가 되는 것은 아니다. CSS 스타일도 인라인으로 삽입된다. 다음과 같은 예제, <input type="button" value="Click Me!" onclick="buttonPressed();" style="background-color: #999" />를 생각해 보자.

이러한 코딩 스타일은 일반적으로 요소의 작동이나 모양을 변경하는 단순한 작업으로 시작한다. 문제는 이런 식으로 작성되는 코드가 증가할수록 코드를 관리하고 겸손한 방식으로 코드를 개발하기가 더욱 어려워진다는 점이다. 규모가 큰 애플리케이션에서는 여러 위치에서 코드를 변경해야 하고 그 결과 코드를 변경하는 과정에서 무엇인가를 누락하기 쉽기 때문에 인라인으로 작성한 Javascript와 CSS 코드를 변경하기가 매우 어렵다.

인라인으로 코드를 작성하는 대신 모든 Javascript와 CSS 코드를 HTML 마크업 외부에 두어야 한다. idclass와 같은 참조 속성을 사용하여 Javascript와 CSS가 DOM에서 이러한 요소를 쉽게 찾고 식별하도록 해야 한다. 단추의 경우에는 목록 1과 같이 코드를 다시 작성할 수 있다. 이 기사에 있는 모든 예제에서는 Prototype Javascript 라이브러리를 사용하지만 이 라이브러리 대신 원하는 라이브러리나 원시 Javascript를 사용할 수 있다. 여러 가지 Javascript 프레임워크를 비교하는 기사에 대한 링크는 참고자료를 참조한다.


목록 1. Javascript와 CSS 코드를 HTML 마크업 외부에 유지해두기기

// HTML code 

<input type="button" value="Click Me!" id="my_button" />

// JavaScript code

$("my_button").observe("click", buttonPressed);

// CSS code

#my_button { background-color: #999; }

HTML 마크업에서 Javascript와 CSS 코드를 혼합해서 사용하지 말아야 하듯이 CSS 코드를 Javascript에 뒤섞지 말아야 한다. 예를 들면, 목록 1에서는 buttonPressed 함수를 통해 요소의 스타일을 변경한다. 목록 2에 있는 예제를 살펴보도록 하자.


목록 2. buttonPressed 함수를 통해 순간적으로 요소의 스타일을 변경하는 방법을 확인할 수 있는 예제

function buttonPressed() {
    $("my_div").setStyle({
        backgroundColor: "#FF6600",
        fontSize: "12px"
    })
}

아는 바와 같이 이 코드는 스타일을 직접 처리하며 이러한 방식은 스타일 변경 작업을 CSS를 통해 처리하기 때문에 좋지 않다. 그 대신, CSS를 사용하여 특정 클래스 이름에 스타일 특성을 정의한 다음, Javascript를 사용하여 이 클래스를 관련 오브젝트에 적용해야 한다. 따라서 목록 2에 있는 코드를 목록 3에 있는 코드와 같이 개선해야 한다.


목록 3. 개선된 코드

// JavaScript code

function buttonPressed() {
    var my_div = $("my_div");
    if(!my_div.hasClassName("highlight")) 
        my_div.addClassName("highlight");
}

// CSS code:

.highlight { background-color: #FF6600; font-size: 12px; }

이러한 방식으로 코드를 분리하면 코드의 구조를 효과적으로 체계화할 수 있어서 발생할 수 있는 모든 문제점을 진단하고 수정하기가 훨씬 더 수월해진다. 또한 Javascript와 CSS 코드가 단지 <head> 섹션에만 있는 경우에도 이 코드를 HTML 코드 안에 삽입하기보다는 외부 파일에 저장하는 것이 바람직하다. 대부분의 경우에는 이렇게 하는 것이 애플리케이션의 속도를 높이는 데 도움이 된다. 외부 파일은 처음 액세스될 때 캐시되고 따라서 다음 페이지에서는 다시 이 파일을 다운로드할 필요가 없기 때문이다.

여전히 인라인 코드를 사용해서 점진적 향상 개념을 사용하는 Javascript 애플리케이션을 기술적으로 빌드할 수 있다고 하더라도 이렇게 하면 유지보수하기 어려운 지저분한 코드가 작성된다. 자신을 위해서라도 가능한 언제나 Javascript, CSS 및 HTML을 분리해야 한다.


작동 중인 겸손하지 않은 Javascript

겸손하지 않은 Javascript를 확인할 수 있는 가장 좋은 방법은 예제를 살펴보는 것이다. 다음과 같은 방식으로 작성된 링크를 많이 보게 된다. <a href="#" id="my_link">Click me</a>.

그다음으로는 Javascript 코드에서 다음과 같은 이벤트 핸들러를 찾을 수 있다. $("my_link").observe("click", validateAndSubmit);.

validateAndSubmit 함수에는 유효성을 검증하는 몇 가지 규칙이 있을 수 있으며 이러한 규칙을 통과하면 양식이 제출되거나 다른 조치가 일부 수행된다. 이것이 아무런 문제가 없는 것처럼 보일 수도 있지만 Javascript를 사용하지 않는 브라우저에서는 이 링크가 전혀 작동하지 않는다. 물론 브라우저가 현재 사용자가 있는 페이지를 가리키는 앵커인 # URL을 찾으려고 하지만 곧 중지된다.

참고: Javascript는 실행되지 않거나 건너뛰기 쉽고 이렇게 되면 보안에 매우 취약해지며 양식과 입력의 유효성을 검증할 수 있는 신뢰할 수 있는 수단이 되지 못하기 때문에 규칙에 따라 클라이언트측 유효성 검증을 Javascript에 의존해서는 안 된다. 그 대신 클라이언트측 유효성 검증을 사용자 경험을 개선하고 서버에 전송되는 올바르지 않은 양식의 수를 줄이는 수단으로만 사용해야 한다. 개발자는 언제나 서버측에서 유효성을 검증하여 잘못된 문자가 입력되지 않도록 해야 한다.

이 경우에 클라이언트측 유효성 검증은 Javascript를 사용하는 경우에만 작동하게 해야 한다. 이 링크를 수정하면 다음과 같이 된다. <a href="page2.html" id="my_link">Click me</a>.

그러면 해당 Javascript 코드에서 링크를 수행해야 하는지 판별할 수 있다(목록 4 참조).


목록 4. 링크를 수행해야 하는지 판별하기

function validateAndSubmit() {
    //validation logic here
    if(valid) {
        return true;
    } else {
        alert("Error!");
        return false;
    }
}

목록 4에서 valid가 false로 리턴되면 경보 상자가 열리고 링크가 수행되지 않는다. 이벤트 핸들러가 false 값을 리턴했기 때문이다.

일반적으로 빠른 이동 드롭 다운 목록에서도 겸손한 Javascript를 사용한다. 목록 5에 있는 예제를 참고한다.


목록 5. 빠른 이동 드롭 다운 목록

// HTML code

<select id="my_select">
    <option value="">Select...</option>
    <option value="http://www.google.com">Google</option>
    <option value="http://www.yahoo.com">Yahoo!</option>
    <option value="http://www.bing.com">Bing</option>
</select>

// JavaScript code

function goToSearch(e) {
    var el = Event.element(e);
    if($F(el).length > 0)
        window.location = $F(el);
}

document.observe("dom:loaded", function() {
    $("my_select").observe("change", goToSearch);
});

또한, Javascript가 사용 안함으로 설정되어 있으면 드롭 다운 목록에서 항목을 선택해도 이 예제는 아무런 조치도 수행하지 않는다. 여기서 문제는 사용 가능한 페이지 중 하나를 탐색하는 데 필요한 표준 HTML 폴백이 없다는 점이다. 이 예제를 다시 작성해 보자. 이번에는 점진적 향상 개념을 사용하여 Javascript 함수를 삽입한다(목록 6 참조).


목록 6. 점진적 향상

// HTML code:

<form name="redirect" method="get" action="redirect.php">
<select name="my_select" id="my_select">
    <option value="">Select...</option>
    <option value="http://www.google.com">Google</option>
    <option value="http://www.yahoo.com">Yahoo!</option>
    <option value="http://www.bing.com">Bing</option>
</select>
<input type="submit" value="Go!" />
</form>

이 예제에서는 리디렉션을 처리할 서버측 스크립트를 정의할 수 있는 HTML <form> 요소를 사용하며 Javascript는 사용 불가능해야 한다. Javascript를 사용 안함으로 설정했을 때 사용자가 Go! 단추를 클릭하면 redirect.php로 양식이 제출되고 쿼리 문자열로 해당 URL이 전달된다. 그러고 나면 올바른 옵션이 선택되었는지 그리고 수신된 입력을 기반으로 출력을 리디렉트하는지 서버에서 유효성을 검증할 수 있다.

이 예제에서는 Javascript를 사용하여 다음과 같은 두 가지 방법으로 이러한 기능을 점진적으로 개선할 수 있다.

  • 사용자가 검색 엔진을 선택했는지에 대한 유효성 검증
  • 추가로 HTTP 요청을 전송하지 않고 리디렉션을 수행

그러면 이제 Javascript를 사용하여 이러한 개선사항을 구현해 보도록 하자(목록 7 참고).


목록 7. Javascript를 사용하여 개선사항 구현하기

// JavaScript code

function goToSearch(e) {
    Event.stop(e);
	
    var my_select = $F("my_select");
    if(my_select.length > 0)
        window.location = my_select;
    else
        alert("You must select a search engine!");
}

document.observe("dom:loaded", function() {
    document.redirect.observe("submit", goToSearch);
});

목록 7에 있는 코드는 기본 조치가 시행되지 않도록 하여 양식이 서버로 제출되지 않도록 한다. 그런 다음에는 검색 엔진이 선택되었는지 유효성을 확인한다. 검색 엔진이 선택된 경우에는 사용자를 선택된 URL로 리디렉트한다. 검색 엔진이 선택되지 않은 경우에는 오류 메시지가 있는 경보 상자를 표시한다.

원래의 예제는 <select> 요소 자체의 onchange 이벤트에서 작동했지만 목록 6에 있는 예제에는 Go! 단추가 추가되었다. 여기에서 문제는 제출 단추나 Javascript를 사용해야 이 요소만으로 구성된 양식을 제출할 수 있다는 점이다. Go! 단추가 필요 없는 경우에는 Javascript가 활성화된 브라우저에서는 이 단추가 숨겨지도록 Javascript를 사용하여 단추의 스타일을 동적으로 설정할 수 있다. 이렇게 하면 Javascript가 활성화되지 않은 브라우저에서는 이 단추가 계속 존재하지만, 그렇지 않은 브라우저에서는 이 단추가 숨겨지게 된다. 그런 다음에는 <select> 요소의 onchange 이벤트에 이벤트 핸들러를 추가하여 두 가지 방식의 장점을 모두 취할 수 있다.


겸손한 코드 작성하기

겸손한 방식으로 코드를 작성하려면 먼저, 가장 일반적으로 사용하는 브라우저(Javascript를 지원하지 않는 브라우저)에서 작동하는 솔루션을 개발해야 한다. 최신 웹 브라우저에는 Javascript를 사용 안함으로 설정하거나 플러그인을 사용 가능하게 하는 내장 옵션이 있다. Javascript를 사용할 수 있는 사치를 누리지 못하는 사용자의 관점에서 사이트를 보려면 이러한 옵션을 사용한다.

먼저, Javascript를 사용하지 않고 HTML 코드를 작성하며 웹 페이지에서 제공해야 하는 모든 기본적인 기능을 수행하도록 HTML 코드를 작성한다. 입력 데이터를 제출해야 하는 경우에는 <form> 태그를 실제 action 속성과 함께 사용한다. <img><div>와 같은 부적당한 요소에 이벤트를 첨부하는 기능은 없을 것이므로 다른 항목에 링크해야 하는 경우에는 이전부터 사용해 온 유용한 하이퍼링크를 사용한다. 이런 식으로 작동 애플리케이션을 빌드한다. 이 애플리케이션이 이전보다 멋진 사용자 경험을 제공하거나 모양이 세련될 필요는 없지만 작동은 해야 한다.

애플리케이션이나 웹 페이지가 Javascript가 없어도 제대로 작동하고 개발자가 Javascript를 통해 수행하려고 하는 기본적인 요구사항이 만족되면, Javascript를 사용하여 페이지를 점진적으로 향상시키는 과정으로 넘어갈 수 있다. 이런 식으로 애플리케이션을 개발하면, HTML 요소를 이 요소의 목적에 맞게 사용할 가능성이 높아지기 때문에 웹 페이지가 더 많은 의미론적 의미를 갖게 된다. 또한, 이런 식으로 개발하게 되면 이렇게 하지 않았을 경우에는 쓸모없어질 수 있는 기능을 계속해서 사용할 수 있다는 이점을 누릴 수 있게 된다.

이와 관련된 좋은 예는 양식 필드를 <form> 태그를 사용하지 않고 사용하는 경우로 특히, Ajax 애플리케이션에서 자주 사용된다. 이제는 애플리케이션에 <form> 요소를 삽입하는 대신 document.getElementById와 같은 DOM 요소를 사용하여 제출해야 하는 값을 가져오고 이 값을 XMLHttpRequest를 사용하여 서버에 제출하기가 너무 쉬워졌다. 이러한 방식으로 애플리케이션을 빌드하게 되면 기본 이벤트가 고려되지 않아 결과적으로 애플리케이션의 유용성이 떨어진다는 문제점이 있다. 예를 들어, 검색 텍스트 상자와 단추에서 이 섹션에 기술된 XMLHttpRequest를 사용하여 사이트 검색을 수행하지만 이 프로세스에서는 <form> 요소를 사용하지 않는다고 하자. 텍스트 상자에 쿼리를 입력함과 동시에 Return 키를 누르면 양식이 제출되어 검색이 수행될 것으로 예상할 수 있다. 그러나 불행히도, 이렇게 되지만은 않으며 따라서 개발자는 키보드 이벤트를 캡처하는 방법을 알아내어 이러한 기능을 따라 해야 한다. 역설적이지만 처음에 <form> 요소를 사용했으면 Return 키를 눌렀을 때 실제로 작동했을 것이다. 이는 개발자들이 일상적으로 계속해서 남용하고 오용하며 자주 간과하기도 하는 HTML 요소의 기본 작동과 관련된 하나의 예일 뿐이다.

겸손한 코드를 작성하는 간단한 예제를 살펴보도록 하자. 썸네일 이미지가 있으며 사용자가 썸네일 이미지를 클릭하면 lightbox(마스크 오버레이 효과를 사용하여 페이지가 배경으로 페이드되도록 표시된 일종의 모달 팝업 창)에 확대된 이미지가 표시된다고 가정하자. 단지 <img> 태그를 작성하는 대신 이미지에 onclick 이벤트를 첨부하고 lightbox를 호출하여 확대 이미지가 표시되도록 한다. 이러한 기능이 어떻게 수행되어 Javascript 지원을 받지 못하는 사용자에게도 서비스가 제공되는지 살펴보도록 하자.

먼저 해야 할 일은 구현하고자 하는 기능이 무엇인지 면밀히 계획하는 것이다. 이미지를 클릭하면 현재 있는 페이지에서 확대 이미지가 표시되도록 하고 싶다. 또한, 화려한 lightbox 효과를 추가하되, 다른 기능은 제거하고 기본적인 기능만 남기고 싶다. 이것이 본질적으로 수행해야 하는 기능이다. HTML만 사용한 솔루션은 매우 간단하다(목록 8 참조).


목록 8. HTML만 사용한 솔루션

<a href="large.jpg" id="my_thumb" target="_blank"><img src="thumb.jpg" 
width="50" height="50" alt="My Picture" /></a>

목록 8은 기존에 사용해온 일반적인 HTML만을 사용한다는 기본적인 요구사항을 충족시키고 있다. 이 코드는 쓸만하지만 그 이상은 아니다. Javascript를 사용하는 페이지에서는 새 창 대신 현재 창의 lightbox 오버레이에 확대 이미지가 표시되도록 하고 싶다. 목록 9와 같이 하면 이러한 기능을 수행할 수 있다. (확대 이미지의 URL을 인수로 받는 openLightbox 함수가 lightbox를 실행한다고 가정한다.)


목록 9. shownLargImage() 함수

function showLargeImage(e) {
    Event.stop(e);
    var link = Event.element(e).up("a");
    openLightbox(link.href);
}

document.observe("dom:loaded", function(e) {
    $("my_thumb").observe("click", showLargeImage);
});

한 단계 더 발전시키기 위해서는 썸네일 갤러리가 필요하며 lightbox를 열어서 각 썸네일 이미지와 관련된 확대 이미지를 표시할 수도 있다. 이 또한 단순하다. ID를 사용하기보다는 클래스 이름을 사용하거나 lightbox 스크립트에서 일반적으로 사용한 바와 같이 rel 속성을 사용한다(목록 10 참조).


목록 10. Thumbnail 갤러리 작성

// HTML code

<a href="large1.jpg" rel="lightbox" target="_blank"><img src="thumb1.jpg" 
width="50" height="50" alt="Picture 1" /></a>

<a href="large2.jpg" rel="lightbox" target="_blank"><img src="thumb2.jpg" 
width="50" height="50" alt="Picture 2" /></a>

<a href="large3.jpg" rel="lightbox" target="_blank"><img src="thumb3.jpg" 
width="50" height="50" alt="Picture 3" /></a>

// JavaScript code

function showLargeImage(e) {
    Event.stop(e);
    var link = Event.element(e).up("a");
    alert(link.href);
}

document.observe("dom:loaded", function(e) {
    $$("a[rel=lightbox]").each(function(thumb) {        
        thumb.observe("click", showLargeImage);
    });
});

아는 바와 같이 최종 결과는 매우 깔끔하며 읽기 쉽고 코드를 유지 보수하기도 쉽다. 불필요한 id 속성을 사용하거나 인라인 형식으로 핸들러를 첨부하지 않고도 다수의 항목에 이벤트를 첨부할 수 있다. 코드를 겸손하지 않게 작성했을 때 이것이 어떻게 처리될지 생각하면 매우 끔찍하다. Javascript를 지원하지 않는 브라우저에서는 <a> 태그가 없으면 코드가 전혀 작동하지 않게 된다. 인라인 onclick 핸들러는 <img> 요소에서 확인할 수 있으며 확대 이미지의 URL은 마크업 자체에서 직접 인수로 전달된다. 잠시 물러나서 하고자 했던 것이 무엇인지 면밀히 살펴봄으로써 필자는 액세스가 가능하고 표준을 고수하며 의미론적 의미가 있고 점진적 방식으로 간결한 lightbox 기능을 제공하는 솔루션을 제공할 수 있었다.


겸손한 Ajax

Web 2.0과 Ajax 애플리케이션이 출현하면서 웹 개발자에게는 대화식 웹 애플리케이션 작성과 관련된 새로운 과제가 대두되었다. 비동기 HTTP 요청을 사용한 데이터 검색이 장점이 있는 것은 분명하다. 다시 말해서 Ajax를 활용하는 애플리케이션은 응답 속도가 빠르고 사용하기 쉬우며 유용성 면에서도 기존의 데스크탑 애플리케이션 못지않다. (어떤 사람들은 잘 설계된 웹 애플리케이션이 기존의 애플리케이션보다 훨씬 더 유용하고 액세스하기 쉽다고 주장한다.)

Ajax 요청을 사용하는 데 따른 문제점은 멋진 Ajax로 인해 Javascript 애플리케이션이 필요 없는 사용자에게도 서비스를 제공해야 한다는 사실을 쉽게 잊을 수 있다는 점이다. 예를 들어, 일반적인 등록 양식을 살펴보자. 이러한 양식을 Ajax 형식으로 변경할 수 있는 방법은 여러 가지가 있다. 사용자의 이름이나 이메일 주소가 이미 사용 중인지 자동으로 확인할 수 있으며 페이지를 다시 고치지 않고도 양식의 유효성을 확인할 수 있고 심지어 양식을 제출하고 그 결과를 동적으로 표시할 수도 있다.

사용자 이름과 암호를 요청하는 간단한 양식을 살펴보자. 이 양식은 비동기 HTTP 요청을 서버측 스크립트로 전송한 다음, 프로세스가 성공적이면 응답으로 'ok'를 리턴하고 유효성에 문제가 있으면 오류 메시지를 리턴한다. 이 양식의 HTML 형식 코드는 목록 11과 같다.


목록 11. 간단한 양식

<form id="register">
	<label for="username">Username</label>
	<input type="text" name="username" id="username" />
	<label for="password">Password</label>
	<input type="password" name="password" id="password" />
	<input type="submit" value="Register" id="reg_button" />
</form>

첫 번째 문제는 매우 분명하다. 목록 11에 있는 양식에는 메소드나 action 속성이 없으며 따라서 Register 단추를 눌러도 아무런 조치도 수행되지 않는다. 왜냐하면 Javascript를 사용하여 id 속성으로 쉽게 양식을 가져오고 이 양식을 Ajax를 사용하여 제출할 수 있다고 해서 양식을 제출하는 표준 메소드를 사용하지 않아도 되는 것은 아니기 때문이다. 그대신 서버측 스크립트를 작성하여 해당 양식에서 추가 필드를 찾을 수도 있다. 아는 바와 같이 이것이 불가능하면 보통의 양식 포스트(post)를 통해 요청을 수행한 후, 전체 페이지를 다시 제공해야 한다. 이것을 1로 설정하면 요청은 비동기 Ajax 호출을 사용하여 수행되며 개발자는 OK나 오류 메시지만 다시 전송하면 된다. 그런 다음에는 Ajax 요청에서 필드 값을 1로 설정한다. 물론 이렇게 하면 브라우저에서 Javascript를 지원하지 않으면 Ajax 요청이 실행되지 않는다.

개정된 양식은 목록 12와 같다.


목록 12. 개정된 양식

<form id="register" method="post" action="register.php">
    <label for="username">Username</label>
    <input type="text" name="username" id="username" />
    <label for="password">Password</label>
    <input type="password" name="password" id="password" />
    <input type="submit" value="Register" id="reg_button" />
</form>

이제는 이 양식을 가져오고 해당 Ajax 요청을 동일한 서버측 스크립트에 제출할 수 있다. 서버측 스크립트는 응답을 어떻게 전송해야 하는지 쉽게 구별할 수 있으며 Ajax 필드가 존재하지 않으면 오류 메시지를 표시하면서 등록 페이지로 다시 리디렉트하거나 값이 1이면 단지 간단한 메시지를 출력한다. 이러한 조치를 수행하는 Javascript 코드는 다음과 같이 목록 13에 있으며 여기에서는 Prototype 라이브러리를 사용했다.


목록 13. 양식을 사용하여 Ajax 요청을 서버측 스크립트에 제출하기

<script type="text/javascript">
    function registerSuccess(transport) {
        if(transport.responseText == "ok")
            alert("Success!");
        else
            alert(transport.responseText);
    }

    function registerFailure(transport) {
        alert(transport.status+' '+transport.statusText);
    }

    function submitUsingAjax(e) {
        Event.stop(e);
        var options = {
            parameters: { 
                ajax: "1"
            },
            onSuccess: registerSuccess,
            onFailure: registerFailure
        }
        $("register").request(options);
    }

    document.observe("dom:loaded", function() {
        $("register").observe("submit", submitUsingAjax);
    });
</script>

목록 13에서는 양식의 submit 이벤트에 이벤트 핸들러를 추가한다. 이 핸들러는 기본 이벤트가 실행되지 않도록 하며 추가 ajax 인수 값을 1로 설정하고 원래의 URL 및 데이터 양식을 사용하여 ajax 요청을 수행한다. HTTP 응답 코드가 성공적으로 수신되면 registerSuccess 함수가 호출되며 그렇지 않고 오류가 발생하는 경우에는 registerFailure 함수가 호출된다.


겸손한 Ajax와 관련된 또 다른 예제

대용량 데이터 세트를 페이지로 그룹화하는 경우(일반적으로 페이지 매김 기능이라고 함)에는 Ajax가 특히 유용하다. 예를 들어, 검색 결과 세트가 있는 경우에는 한 번에 수백 개가 넘는 검색 결과를 표시하기보다는 이 데이터를 더 작은 서브세트, 즉 10개의 레코드로 나누어 표시하고 페이지 사이를 앞, 뒤로 이동할 수 있는 옵션을 제공하는 경우가 더 많다. 이러한 경우로는 Google의 검색 결과를 예로 들 수 있다. 이 페이지 맨 밑에는 검색 결과 페이지 사이를 이동할 수 있는 옵션이 있다.

일반적으로 페이지 이동과 관련된 표준 방식은 데이터를 로드하는 서버측 스크립트에 매개변수를 전달하여 어떤 결과 세트 페이지를 출력해야 하는지 서버측 스크립트에 명령하는 것이다. 문제는 사용자가 다른 페이지로 이동해야 할 때마다 서버로 요청을 다시 전송해야 하고 따라서 새로운 데이터 세트로 페이지를 다시 로드해야 한다는 데 있다.

Ajax를 사용하면 새로운 데이터 페이지가 페치되는 경우에도 사용자는 전체 페이지가 다시 로드되는 상황을 지켜볼 필요가 없으며 개발자는 단지, 페이지의 일부를 새로운 데이터 세트로 바꾸기만 하면 된다. 이러한 과정이 어떻게 작동하는지 예제를 통해 살펴보도록 하자.

언제나 그렇듯이 가장 먼저 해야 할 일은 Javascript가 지원되지 않는 브라우저를 사용하는 사용자에게 서비스가 제공되는지 확인하는 일이다. 이렇게 하려면 기존의 방식, 즉 새로운 데이터 세트로 페이지를 다시 고치는 방식에서 애플리케이션이 작동하는지 확인해야 한다(목록 14 참조). 또한, ajax 플래그를 서버측 스크립트에 전달하는 개념을 사용하여 보통의 GET 요청이나 Ajax 호출을 통해 서버측 스크립트가 호출될 것인지 이 스크립트가 알 수 있도록 한다.


목록 14. 애플리케이션이 Javascript가 지원되지 않는 브라우저를 사용하는 사용자를 지원하는지 확인하기

//HTML code

<div id="results">
    <ol>
        <li>Result 1</li>
        <li>Result 2</li>
        ...
        <li>Result 10</li>
    </ol>

    <a class="paging" href="results.php?page=2">Next Page</a>
    <a class="paging" href="results.php?page=10">Last Page</a>
</div>

results.php 서버측 스크립트는 1 페이지에 목록 14에 있는 것과 같은 페이지를 생성하며 링크를 클릭하면 두번 째 페이지나 마지막 페이지가 표시된다. 사용자가 1 페이지에 있지 않은 경우에는 Previous Page와 First Page 링크가 표시되며 마지막 페이지가 있는 경우에는 Next Page나 Last Page 링크는 표시되지 않는다. 또한 페이지 목록을 표시하여 특정 페이지로 쉽게 이동할 수 있도록 할 수도 있다. 그러면 Javascript가 지원되지 않는 브라우저에서도 이러한 페이징 섹션이 중단되지 않도록 이 기능을 Ajax 형식으로 변경하려면 어떻게 해야 할까? 이렇게 하는 것은 정말로 간단하다. 단지 모든 페이지 링크에 대한 참조를 가져와서 페이지 링크를 클릭했을 때 기본적인 조치가 실행되지 않도록 하면 된다. (브라우저는 현재 페이지를 링크의 href 속성에 있는 페이지로 바꾼다.) 그 후에는 href 속성을 가져와서 이 속성을 해당 Ajax 요청을 수행하는 데 필요한 URL로 사용한다. 끝으로 해당 ajax 매개변수를 추가한다. 그러면 서버측 스크립트가 Ajax 요청을 인식할 수 있게 된다(목록 15 참조).

서버는 호출 방법(Ajax 호출 또는 보통의 GET 요청)에 따라 전체 페이지를 리턴하거나 요청된 데이터 세트로 바꾸고자 하는 섹션만을 리턴한다. 그 후에는 해당 함수가 results div의 내용을 <ol> 결과 목록과 페이지 표시 링크가 포함된 HTML(서버에서 리턴한)로 바꾼다. 페이지 표시 링크는 페이지를 이동할 때마다 변경된다.


목록 15. 페이징 섹션을 Ajax 형태로 변경하기

<script type="text/javascript">
    function movePageSuccess(transport) {
        $("results").innerHTML = transport.responseText;
    }

    function movePage(e) {
        Event.stop(e);
        var el = Event.element(e);
        var url = el.href;
        var options = {
            method: "get",
            parameters: {
                ajax: "1"
            },
            onSuccess: movePageSuccess
        }
    }

    document.observe("dom:loaded", function() {
        $$(".paging").each(function(link) {
            link.observe("click", movePage);
        });
    });
</script>

Ajax와 관련된 또 다른 간단한 예제를 살펴보도록 하자. 아는 바와 같이 Javascript를 의무적으로 요구하기보다는 애플리케이션을 점진적으로 향상시키는 방법으로 Ajax를 다루는 것이 비교적 간단하다. 또한, 더 나은 코딩 습관을 사용하게 되면 Javascript를 많이 사용하여 잘못된 방식으로 동일한 작업을 수행하기보다는 겸손한 방식으로 Ajax를 다루는 것이 사실상 훨씬 더 쉽고 효과적이라는 사실을 발견하게 된다.


결론

이 기사에서는 겸손한 Javascript와 점진적 향상의 개념과 처음에는 Javascript를 사용하지 않고 애플리케이션을 설계한 후, 나중에 Javascript를 추가하여 Javascript를 통해 혜택을 누릴 수 있는 사용자에게 맞게 사용자 경험을 개선하는 개념을 소개했다. 이 기사는 겸손한 방법으로 애플리케이션을 개발하는 방법과 관련된 완전한 자료는 아니다. 그러나 필자와 마찬가지로 Javascript와 Ajax를 반드시 겸손하게 다루지 않아도 되는 웹 애플리케이션을 개발하는 데 많은 시간을 보낸 개발자라면 이러한 웹 애플리케이션 개발 철학을 받아들이는 것이 얼마나 이로운지 놀라게 될 것이다.


참고자료

교육

제품 및 기술 얻기

  • Prototype은 동적 웹 애플리케이션을 쉽게 개발할 수 있게 도와주는 Javascript 프레임워크이다. 최신 버전은 1.6이다.

  • DVD로 제공되거나 다운로드할 수 있는 IBM 시험판 소프트웨어를 사용하여 차기 개발 프로젝트를 혁신하자.

토론

필자소개

Joe Lennon photo developerWorks Contributing author level

Joe Lennon은 아일랜드 코크 출신의 모바일 및 웹 애플리케이션 개발자로 현재 25살이다. Joe는 Core International에 재직 중이며, Core의 모바일 HR 셀프 서비스 솔루션 개발을 이끌고 있다. Joe는 또한 DB2 pureXML, Flex, JavaScript, Adobe AIR, .NET, PHP, Python 및 기타 등등의 주제로 IBM developerWorks에 기사와 튜토리얼을 많이 기고한 열성적인 기술 저자이다. Joe의 첫 번째 저서인 Beginning CouchDB는 2009년 말에 Apress에서 출간되었다. Joe는 여유 시간에 여행, 독서 및 비디오 게임을 즐긴다.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=웹 개발
ArticleID=632027
ArticleTitle=겸손한 Javascript 및 Ajax 코드 작성 안내서
publish-date=11022010
author1-email=joe@joelennon.com
author1-email-cc=

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.