prototype & scriptaculous 인 액션

120

Post on 22-Jul-2016

259 views

Category:

Documents


0 download

DESCRIPTION

데이브 크레인, 베어 바이볼트, 톰 로크 지음 | 박천구 옮김 | 오픈소스 & 웹 시리즈 _ 006 | ISBN: 9788992939126 | 28,000원 | 2008년 02월 28일 발행 | 624쪽

TRANSCRIPT

Page 1: Prototype & Scriptaculous 인 액션
Page 2: Prototype & Scriptaculous 인 액션

Prototype & Scriptaculous

인 액션

Page 3: Prototype & Scriptaculous 인 액션

Prototype & Scriptaculous

인 액션

Page 4: Prototype & Scriptaculous 인 액션

iv

목 차

1부 시작하기

1장 Prototype과 Scriptaculous 소개

1.1 간단하게 살펴보는 Ajax의 역사 ..................................4

1.1.1 Ajax 등장 이전의 시대 .........................................5

1.1.2 개척자의 단계 ................................................6

1.1.3 이주자들의 도착 ..............................................7

1.1.4 문명화 ......................................................8

1.2 Prototype이란? ..............................................8

1.2.1 자바스크립트 언어의 특징 ......................................9

자바스크립트 객체 클래스 ......................................9

자바스크립트의 함수 ..........................................10

자바스크립트의 배열 ..........................................10

자바스크립트의 문자열과 숫자 ..................................11

1.2.2 웹 브라우저의 특징들 ..........................................11

Document Object Model .......................................12

HTML 폼 ....................................................12

자바스크립트의 이벤트 ........................................12

Ajax 유틸리티 ................................................13

1.3 Scriptaculous란? .............................................13

1.3.1 시각적인 효과 ................................................13

1.3.2 드래그 앤 드롭 ...............................................14

1.3.3 컴포넌트 ....................................................15

1.3.4 유틸리티와 테스팅 프레임워크 ..................................15

1.4 Prototype과 Scriptaculous의 적용 ...............................16

옮 긴 이 글 ................................................xvi

머 릿 말 ...................................................xviii

서 문 ......................................................xx

Page 5: Prototype & Scriptaculous 인 액션

v

1.4.1 평점 예제 소개 ...............................................16

컴포넌트 사용하기 ............................................17

사용자 인터페이스의 초기화 ....................................18

이벤트 핸들러 추가 ...........................................20

비동기 방식으로 HTTP 호출하기 .................................20

1.4.2 Prototype과 Scriptaculous 추가하기 .............................24

DOM 헬퍼 메소드 .............................................24

이벤트 핸들러 ................................................24

더 쉬워진 Ajax 요청 ...........................................26

사용자 인터페이스에 세련미를 추가하기 ..........................28

1.5 요약 ........................................................31

2장 QuickGallery 소개

2.1 설계와 구현 ..................................................34

2.1.1 애플리케이션에 대한 요구사항 ..................................35

2.1.2 파일시스템 네비게이션 ........................................36

폴더 내의 컨텐트 검사 .........................................37

현재 위치 메뉴 생성 ...........................................39

2.1.3 썸네일 이미지 생성 ...........................................40

2.1.4 조각들을 합치기 ..............................................42

2.1.5 HTML 생성 ..................................................46

2.2 전통적인 웹 애플리케이션 모델에 대한 평가 .......................50

2.2.1 링크, 폼 그리고 전체 페이지 갱신 ...............................51

2.2.2 전통적인 웹 애플리케이션과 QuickGallery .........................52

디렉터리 변경 ................................................52

클로즈업 모드로 이미지 보기 ...................................53

2.3 요약 ........................................................54

3장 Prototype으로 Ajax를 단순화하기

3.1 Ajax 적용을 위한 재설계 .......................................56

3.1.1 비동기적인 요청의 설계 ........................................57

컨텐트 중심적인 Ajax 활용 .....................................58

스크립트 중심적인 Ajax ........................................59

데이터 중심적인 Ajax ..........................................60

Page 6: Prototype & Scriptaculous 인 액션

vi

3.1.2 Prototype의 Ajax 관련 클래스...................................61

Ajax.Base ....................................................61

Ajax.Request .................................................62

Prototype.js의 코딩 스타일 .....................................63

Ajax.Request의 선택사항 옵션들 .................................65

3.2 XML과 Ajax 함께 사용하기 .....................................68

3.2.1 XML 응답 설계하기 ...........................................68

3.2.2 서버 측 코드의 수정 ...........................................69

3.2.3 클라이언트 측 코드의 작성 .....................................71

서버에 데이터를 요청하기 ......................................73

응답을 풀어놓기 ..............................................73

새로운 데이터를 디스플레이 하기 ................................76

현재 위치 메뉴 렌더링 .........................................77

하위폴더 목록의 렌더링 ........................................78

썸네일 이미지의 렌더링 ........................................79

모두를 조합하기 ..............................................80

3.3 JSON과 Ajax 함께 사용하기.....................................81

3.3.1 서버 측 코드의 수정 ...........................................82

3.3.2 클라이언트 코드의 수정 ........................................83

3.4 요약 ........................................................85

4장 Prototype의 고급 Ajax 기능 사용하기

4.1 Prototype의 고급 Ajax 클래스들 ................................88

4.1.1 Ajax.Updater .................................................89

4.1.2 Ajax.PeriodicalUpdater.........................................90

4.1.3 Ajax.Responders ..............................................90

4.2 HTML과 Ajax 함께 사용하기 ....................................91

4.2.1 HTML 조각 생성하기 ..........................................91

4.2.2 클라이언트 측 코드의 수정 .....................................92

4.2.3 복수의 DOM 엘리먼트 업데이트하기 .............................93

문제를 요약하기 ..............................................94

응답에 스크립트 추가하기 ......................................95

사용자 정의(custom) 헤더로 응답하기 ............................99

4.2.4 자동으로 컨텐트 업데이트 하기 .................................101

Page 7: Prototype & Scriptaculous 인 액션

vii

4.3 데이터 중심적인 Ajax와 컨텐트 중심적인 Ajax의 비교 ...............103

4.3.1 개발 편의성에 대한 고려 .......................................104

4.3.2 개발툴들에 적합한가 ..........................................106

4.3.3 퍼포먼스의 비교 ..............................................106

4.3.4 미래에도 경쟁력이 있는 솔루션 찾기 .............................112

4.4 요약 ........................................................114

2부 Scriptaculous 빨리 익히기

5장 Scriptaculous 효과

5.1 단기성공과제(Quick Win) : 단 한 줄의 코드로 효과 추가하기 .........119

5.2 Scriptaculous와 예제들의 설정 ..................................121

5.2.1 Scriptaculous 구하기 ..........................................122

5.2.2 Scriptaculous 라이브러리 로딩하기 ..............................123

5.3 Scriptaculous가 제공하는 효과의 유형 ............................124

5.4 효과에 대한 이해 .............................................125

5.4.1 effects laboratory .............................................125

5.4.2 공통적인 효과 옵션 ...........................................128

효과의 지속기간 설정 ..........................................129

시작점과 종료점 제어하기 ......................................129

프레임 그리기에 영향을 주기 ...................................129

효과의 변화를 제어하기 ........................................130

병렬 효과 동기화하기 ..........................................130

효과들을 순차적으로 실행하기 ..................................130

5.4.3 코어 효과 둘러보기 ...........................................130

불투명(opacity) 효과 ..........................................130

Highlight 효과 ...............................................132

Scale 효과 ...................................................132

MoveBy 효과 ................................................135

5.4.4 콤비네이션 효과에 알아보기 ....................................136

Fade와 Appear 효과...........................................136

BlindUP과 BlindDown 효과 .....................................137

SlideUp과 SlideDown 효과 .....................................138

Shrink와 Grow 효과 ...........................................138

Puff 효과 ....................................................139

Page 8: Prototype & Scriptaculous 인 액션

viii

DropOut 효과 ................................................139

SwitchOff 효과 ...............................................139

Squish 효과 ..................................................139

Fold 효과 ....................................................140

Shake 효과 ..................................................140

Pulsate 효과 .................................................140

5.5 Show와 Hide 효과를 쉽게 제어하기 ..............................140

5.5.1 Effect.toggle() 유틸리티 함수 ...................................141

5.5.2 Toggle Pane 위젯 .............................................142

5.6 transition으로 작업하기 ........................................149

5.6.1 내장 transition 사용하기 .......................................149

5.6.2 Transition Mapper 소개 ........................................150

5.6.3 여러분의 transition을 작성하기 ..................................153

5.7 효과가 진행되는 동안에 제어권 확보하기 .........................155

5.8 효과의 취소 ..................................................156

5.9 복수 효과의 제어 .............................................158

5.9.1 동시에 효과를 실행하기 ........................................158

5.9.2 순차적으로 효과를 실행하기 ....................................159

글로벌 queue의 사용 ..........................................160

우리가 이름 붙인 queue를 사용하기 .............................161

Queues Lab 페이지 살펴보기 ...................................162

5.10 요약 ........................................................164

6장 Scriptaculous 컨트롤

6.1 이번 장을 위한 예제 프로그램의 사용 ............................166

6.2 in-place text editor ............................................168

6.2.1 in-place text editor 생성하기 ....................................168

InPlaceEditor의 스크립트 제어 ...............................171

6.2.2 InPlaceEditor의 옵션 ..........................................172

InPlaceEditor Lab 페이지 .......................................174

에디터의 외양을 제어하기 ......................................175

CSS와 DOM ID 옵션을 명시하기 .................................176

콜백 옵션 사용하기 ...........................................178

서버로부터 텍스트를 전송 받아 로딩하기 .........................180

Page 9: Prototype & Scriptaculous 인 액션

ix

6.2.3 몇몇 사용예제 ................................................181

예제를 위한 서버 측 설정 ......................................181

InPlaceEditor로 서버 측 검증작업 하기 ...........................182

InPlaceEditor와 서버 측 재포맷팅 수행하기 ........................187

6.3 InPlaceCollectionEditor ........................................190

6.3.1 InPlaceCollectionEditor 생성 ....................................190

6.3.2 InPlaceCollectionEditor 옵션 ....................................193

6.4 Ajax autocompleter 컨트롤 .....................................195

6.4.1 Ajax autocompleter 생성하기 ...................................196

6.4.2 Ajax.Autocompleter의 옵션 .....................................199

서버 측 파라미터를 명시하기 ...................................200

autocompleter의 실행을 제어하기 ...............................201

사용자가 정보를 받도록 유지하기 ................................201

여러분의 코드가 정보를 받도록 유지하기 .........................202

텍스트 필드에 복수의 자동 완성 아이템을 허용하기 .................202

6.4.3 SF 영화 autocompleter 서블릿 ..................................203

MoviesAutocompleterServlet 클래스 .............................204

정렬되지 않은 목록을 구성하는 JSP 페이지 ........................207

6.4.4 선택 메뉴에 스타일 적용하기 ...................................208

6.5 Scriptaculous local autocompleter 컨트롤 .........................211

6.5.1 로컬 autocompleter의 생성 .....................................211

6.5.2 Autocompleter.Local의 옵션 ....................................214

얼마나 많은 선택항목이 보여질지 제어하기 ........................215

문자열의 시작부분부터 매칭하는 것 이상의 방법 ...................216

대소문자를 구분하여 매칭 제어하기 ..............................217

6.6 Slider 컨트롤 .................................................218

6.6.1 slider 컨트롤 생성하기 .........................................219

6.6.2 slider와 이미지를 함께 사용하기 .................................222

6.6.3 Control.Slider 옵션 ............................................225

컨트롤의 방향 설정 ...........................................226

값의 범위 설정하기 ...........................................227

컨트롤을 활성화/비활성화 하기 .................................228

값이 변경될 때 통지 받기 ......................................229

6.6.4 보다 흥미진진한 예제 ..........................................230

HTML 엘리먼트의 생성과 스타일 적용 ............................232

Page 10: Prototype & Scriptaculous 인 액션

x

슬라이더의 범위를 설정하기 ....................................233

슬라이더의 값을 디스플레이하기 ................................234

6.7 요약 ........................................................235

7장 Scriptaculous 드래그 앤 드롭

7.1 이번 장을 위한 예제코드 .......................................240

7.2 드래그 하기 ..................................................241

7.2.1 엘리먼트를 draggable로 만들기 .................................241

7.2.2 Draggable 옵션 ..............................................244

엘리먼트를 원래의 위치로 되돌리기 ..............................245

그리드 내에서만 이동이 가능하도록 제한하기 ......................246

축을 기준으로 이동을 제한하기 .................................248

엘리먼트의 중첩순서에 영향 주기 ................................248

ghosting 기능 활성화시키기 ....................................249

드래그 핸들을 사용하기 ........................................250

움직임에 대해 통지를 받기 .....................................251

효과의 변경 ..................................................252

7.3 드래그한 아이템을 드롭하기 ....................................253

7.3.1 드롭 타겟을 정의하기 ..........................................253

7.3.2 Drop 타겟 옵션 ...............................................254

시각적인 단서를 제공하기 ......................................255

draggable이 drop 타겟에 의해 인지되는 것을 제한하기 .............256

임박한 드롭에 대해 통지 받기 ...................................258

드롭에 대해 통지 받기 .........................................259

7.3.3 드래그 앤 드롭 예제 ...........................................260

7.4 드래그 앤 드롭으로 정렬하기 ...................................265

7.4.1 sortable 엘리먼트의 생성 ......................................266

7.4.2 Sortable 엘리먼트의 옵션 ......................................269

정렬될 것을 명시하기 ..........................................270

드래그의 동작을 제어하기 ......................................273

정렬될 엘리먼트를 제한하기 ....................................274

정렬 가능한 엘리먼트들 사이에서 아이템을 이동하기 ................275

수직방향이 아닌 정렬 가능 엘리먼트 생성하기 .....................277

정렬 가능한 엘리먼트들을 중첩시키기 ............................280

Page 11: Prototype & Scriptaculous 인 액션

xi

스크롤 제어하기 ..............................................281

통지를 받기 ..................................................283

7.4.3 정렬 가능한 엘리먼트를 직렬화하기 ..............................284

ID 매칭 패턴을 커스터마이징 하기 ...............................288

7.5 요약 ........................................................290

3부 Prototype에 대해 상세히 알아보기

8장 객체에 대한 모든 것

8.1 스크래치패드 애플리케이션 소개 ................................294

8.2 Object 타입 ..................................................296

8.2.1 Object 생성 ..................................................297

복잡한 Object 선언 ...........................................298

JSON을 사용한 간결한 객체 선언 ................................299

8.2.2 prototype 속성을 사용하여 객체 정의하기 ........................301

8.2.3 객체에 대한 리플렉팅 ..........................................304

8.3 Object와 Prototype ...........................................308

8.3.1 Class.create()를 사용하여 생성자를 간단하게 .......................308

8.3.2 Object.extend() 메소드로 객체 계층구조 선언 ......................310

8.3.3 간단한 객체 합치기 ...........................................310

8.3.4 Object 계층을 모델링하기 ......................................314

단일 상속 ...................................................315

믹스인(mixin)을 이용하는 다중 상속 ..............................319

8.4 요약 ........................................................324

9장 함수를 가지고 놀아보기

9.1 자바스크립트 함수 ............................................326

9.1.1 함수의 선언 ..................................................327

9.1.2 함수의 호출 ..................................................329

9.1.3 Function 컨텍스트 ............................................331

9.1.4 Function 클로저 ..............................................333

9.1.5 언제 컨텍스트와 클로저를 사용하는가 ............................336

9.2 Prototype.js로 함수를 확장하기 .................................339

9.2.1 bind() 메소드 ................................................339

9.2.2 bindAsEventListener() 메소드 ...................................340

Page 12: Prototype & Scriptaculous 인 액션

xii

9.3 요약 ........................................................342

10장 배열(Array)로 보다 쉽게

10.1 Array에 대한 소개.............................................344

10.2 내장 자바스크립트 Array .......................................345

10.2.1 Array의 length를 사용하여 반복연산하기 .........................345

10.2.2 Array를 스택처럼 다루기: pop(), push(), shift(), unshift() .............346

10.2.3 slice(), splice(), concat()를 사용하여 자르고 변경하기 ................348

10.2.4 reverse()와 sort()를 사용하여 순서변경하기 ........................350

10.2.5 Array와 String: join()과 split() ...................................352

10.2.6 다른 Array 유사 객체 ..........................................352

10.3 Prototype.js와 Array ...........................................353

10.3.1 first(), last(), indexOf()를 사용하여 엘리먼트의 위치에 접근하기 .......354

10.3.2 clear(), compact(), without(), flatten()을 사용하여 Array 수정하기 ......354

10.4 Enumerable 객체의 메소드들 ...................................356

10.4.1 all(), any(), include()를 사용하여 배열을 검색하기 ...................358

10.4.2 detect(), findAll(), reject(), grep(), partition()을 사용하여 배열 필터링 ...360

10.4.3 pluck(), invoke() 그리고 collect()로 복잡한 배열 엘리먼트 다루기 ......364

10.4.4 inject()와 zip()을 사용하여 복잡한 배열 생성하기 ...................369

10.4.5 max(), min() 그리고 sortBy()를 사용하여 숫자기준으로 정렬하기 .......372

10.4.6 DOM 컬렉션 다루기 ...........................................375

10.5 Hash와 ObjectRange로 작업하기 ................................376

10.5.1 Hash 객체 사용하기 ...........................................376

$H를 사용하여 Hash 생성하기 ..................................377

keys()와 values()를 사용하여 Hash에 대해 반복연산하기 .............379

toQueryString()으로 Hash를 조작하기 ............................380

10.5.2 ObjectRange 사용하기 .........................................381

10.6 요약 ........................................................382

11장 브라우저로 돌아가서

11.1 DOM 메소드들에 대한 집중 강좌 ................................384

11.1.1 트리구조 탐색하기 ............................................386

11.1.2 트리 구조 수정하기 ...........................................390

11.2 Prototype과 DOM ............................................393

11.2.1 간단한 헬퍼 함수들 ...........................................394

Page 13: Prototype & Scriptaculous 인 액션

xiii

11.2.2 Element 객체 ................................................396

11.2.3 Insertion 객체 ................................................403

11.2.4 Position 객체 ................................................405

11.3 Event 객체의 확장 ............................................411

11.4 HTML 폼 조작하기 ............................................413

11.5 요약 ........................................................419

4부 고급수준의 주제들

12장 실전에서의 Prototype과 Scriptaculous

12.1 QuickGallery 애플리케이션에 대한 요구사항 .......................424

12.2 슬라이드쇼 에디터 개발하기 ....................................425

12.2.1 페이지 레이아웃의 수정 ........................................426

12.2.2 드래그 앤 드롭 전략의 정의 ....................................432

12.2.3 드래그 앤 드롭의 구현 .........................................433

12.2.4 에디팅 가능한 캡션을 제공하기 .................................437

12.3 Ajax 기반의 저장기능 추가하기 ..................................440

12.3.1 저장 포맷 정의하기 ...........................................440

12.3.2 슬라이드쇼 저장하기 ..........................................441

12.3.3 서버에서 컨텐트를 로딩하기 ....................................444

12.4 툴바 생성하기 ................................................447

12.5 슬라이드쇼 플레이어 구현하기 ..................................450

12.5.1 사용자 인터페이스 명시하기 ....................................451

12.5.2 슬라이드쇼 플레이어의 구현 ....................................453

12.5.3 플레이어 실행하기 ............................................456

12.6 모든 부분을 서로 합치기 .......................................460

12.7 요약 ........................................................478

13장 Prototype, Scriptaculous 그리고 레일스

13.1 자바스크립트 생성하기 ........................................482

13.1.1 Prototype과 레일스 스타일로 쓴 Hello World .....................483

13.1.2 레일스 헬퍼 소개 .............................................485

13.2 Ajax 헬퍼들 .................................................487

13.2.1 표준 옵션 설정 ..............................................488

URL 지정하기 ...............................................488

Page 14: Prototype & Scriptaculous 인 액션

xiv

페이지 업데이트 제어하기 .....................................488

자바스크립트 콜백 지정하기 ....................................489

13.2.2 Ajax 헬퍼 둘러보기 ...........................................490

link_to_remote ..............................................491

form_remote_tag ............................................491

observe_field ................................................493

observe_form ................................................494

periodically_call_remote .......................................495

remote_function .............................................496

13.3 Scriptaculous 헬퍼 ...........................................497

13.3.1 비주얼 효과 만들기 ...........................................498

13.3.2 인 플레이스 에디터(in-place editor) 구현하기 .....................499

13.3.3 자동완성 기능 추가하기 .......................................501

13.3.4 드래그 앤 드롭 구현하기 ......................................503

드래그 가능한 객체와 드롭 가능한 객체 만들기 ....................504

드래그 앤 드롭 설정하기 .......................................506

리스트 엘리먼트를 정렬 가능하게 하게 ...........................506

13.4 자바스크립트 써? 말어? ......................................509

13.5 다음 단계: RJS ..............................................510

13.5.1 다중 업데이트 문제 ...........................................510

13.5.2 Hello from RJS ................................................512

13.5.3 다중 업데이트와 RJS ..........................................514

13.5.4 RJS 살펴보기 ................................................515

엘리먼트 프록시 사용하기 ......................................516

클래스 프록시 사용하기 ........................................517

컬렉션 사용하기 .............................................517

임의의 자바스크립트 추가하기 ..................................518

13.5.5 RJS를 인라인으로 렌더링하기 ..................................519

13.6 요약 .......................................................520

부록 A HTTP 입문

A.1 왜 HTTP에 관심을 가져야 하는가? ..............................522

A.2 HTTP란 무엇인가? ...........................................523

A.2.1 리소스와 URL ...............................................523

Page 15: Prototype & Scriptaculous 인 액션

xv

A.2.2 무상태 .....................................................525

A.3 요청의 형태에는 어떤 것이 있나? ...............................525

A.4 HTTP 메시지 포맷 ............................................526

A.4.1 요청 메시지 포맷 .............................................527

A.4.2 응답 메시지 포맷 .............................................529

A.5 Ajax 접속이란? ..............................................530

A.5.1 Ajax에서 요청 생성하기 .......................................531

A.5.2 Ajax를 통해 응답 받기 ........................................532

A.5.3 요청 메시지 실습 페이지 ......................................533

부록 B HTTP 트래픽 측정

B.1 HTTP 트래픽 데이터 잡아내기 ..................................539

B.1.1 모질라 LiveHTTPHeaders ......................................541

B.1.2 마이크로소프트 Fiddler .......................................542

B.2 HTTP 트래픽 데이터 파싱하기 ..................................544

부록 C 톰캣 5.5 설치와 실행

C.1 배포본 가져와서 압축 풀기 ....................................551

C.2 JAVA_HOME 설정하기 ........................................552

C.3 애플리케이션 컨텍스트 설정하기 ................................553

C.4 톰캣 시작하기 ...............................................554

C.5 톰캣 컨텍스트 관리하기 .......................................555

부록 D PHP 설치와 실행

D.1 시스템 요구사항 .............................................560

D.1.1 PHP 버전 ...................................................560

D.1.2 웹 서버 .....................................................560

D.1.3 운영체제 ...................................................561

D.1.4 라이브러리 ..................................................561

D.2 설치 .......................................................561

D.2.1 리눅스에 PHP 설치하기 .......................................562

D.2.2 Mac OS X에 PHP 설치하기 .....................................564

D.2.3 윈도우에 PHP 설치하기 .......................................566

D.3 QuickGallery 설정하기 .........................................569

Page 16: Prototype & Scriptaculous 인 액션

xvi

부록 E 서버 측 기술 포팅

E.1 요청 헤더 읽기 ..............................................573

E.1.1 PHP .......................................................574

E.1.2 자바 서블릿 API .............................................574

E.1.3 .NET .......................................................575

E.1.4 루비온레일스 ................................................575

E.2 응답 헤더 더하기 .............................................576

E.2.1 PHP ........................................................576

E.2.2 자바 서블릿 API ..............................................576

E.2.3 Java Server Pages ............................................577

E.2.4 .NET .......................................................577

E.2.5 루비온레일스 ................................................578

E.3 POST 요청 바디 읽기 .........................................578

E.3.1 PHP .......................................................579

E.3.2 자바 서블릿 API .............................................579

E.3.3 .NET .......................................................579

E.3.4 루비온레일스 ................................................580

E.4 요약 .......................................................580

Page 17: Prototype & Scriptaculous 인 액션

xvii

모든 개발자의 좋은 친구이자

지루한 가사일을 돌봐주는 여인

베스타에게

Page 18: Prototype & Scriptaculous 인 액션

xviii

옮 긴 이 글

2002년에 처음 책과 인연을 맺은 지 6년이 지나서야 다시 책과 인연을 맺게 되었습니다.

그동안 인터넷 생태계는 참 많이 변해서 오픈소스, 웹 2.0, Ajax, MVC 프레임워크, 자

바스크립트 프레임워크 등이 탄생하였습니다. 물론 주목할 만한 변화들이 이보다는 많

겠지만 이 책은 이러한 패러다임들 중에서 자바스크립트 프레임워크와 Ajax에 대한 내

용을 다루고 있습니다.

아마 대부분의 개발자들은 누군가가 작성한 코드를 유지보수하거나 읽어본 적이 있

으실 겁니다. 제 경우에는 가장 괴로운 부분이 바로 ‘자바스크립트’였습니다. 읽기 어

려웠을 뿐 아니라 이곳 저곳에 중복된 기능이 산재해 있고 심지어 모듈화되어 있지도

않아서 한 군데를 수정해도 모두 적용이 되지 않아 일일이 다 찾아서 수정을 해줘야 했

습니다. 또한 특정 브라우저에서만 정상적으로 수행되는 코드들로 인해 타 브라우저에

대한 서비스는 아예 초기부터 포기하는 경우도 많았습니다.

하지만 이제 우리는 이러한 고민들을 하지 않아도 됩니다. 걸출한 개발자 샘 스티븐

슨이 개발한 Prototype을 사용하면 브라우저 간의 호환성을 보장하는 것은 물론이고

획기적으로 코딩량을 줄일 수 있으며 OOP와 유사한 개념을 적용하여 클래스 형태로

개발할 수 있고 상속의 개념을 적용하여 계층구조로 설계할 수도 있습니다.

또한 요즘의 모든 애플리케이션들이 Ajax 기능을 적극적으로 채택하고 있다는 것을

고려하면 Prototype이 지원하는 Ajax 관련 기능은 너무나 매력적입니다. 단 몇 줄의 코

딩만으로 이전에는 상당한 양의 코딩이 필요했던 작업을 수행할 수 있으니 말입니다.

Ajax에 대한 지원을 위해 Prototype은 여러가지 형태의 Ajax 관련 클래스를 제공하고

있습니다.

Prototype이 자바스크립트 전반에 걸친 라이브러리라면 토마스 푹스의 Scriptaculous

는 웹 페이지 내에서 사용자의 UX(User Experience)를 향상시킬 수 있는 기능을 제공하는

시각효과에 특화된 라이브러리입니다. Scriptaculous는 크게 효과와 컨트롤로 구분이

Page 19: Prototype & Scriptaculous 인 액션

xix

되며 10여 개에 달하는 효과를 제공하므로 웹 페이지에 다양한 효과를 구현할 수 있고

이들의 조합 또한 쉬워서 상당히 많은 효과를 사용할 수 있습니다. 또한 컨트롤의 경우

는 Prototype이 제공하는 Ajax 기능을 사용하여 서버 측과 자연스럽게 연동이 되므로

간단한 설정만으로 구글의 검색어 추천 기능과 같은 컨트롤을 사용할 수 있게 됩니다.

Scriptaculous를 사용하면 페이지 내의 엘리먼트들을 움직이게 하거나 사라지게 하

거나 또는 크기를 변경하는 작업 역시 쉽게 구현할 수 있습니다. 플래쉬나 실버라이트

와 같은 툴을 사용해야 할 수 있던 일을 아주 간단하게 수행할 수 있다는 말이지요. 가

장 강력한 것은 데스크탑 애플리케이션의 경우와 같은 드래그 앤 드롭 기능을 너무도

쉽게 사용할 수 있다는 것입니다. 여러분은 이 기능을 사용하여 사용자들이 좀 더 친숙

한 환경인, 데스크탑과 같이 사용하도록 유도할 수도 있습니다.

저는 요즘 왜 개발자가 3D 업종이 되었을까? 하는 고민을 하고 있습니다. 끊이지 않

는 야근, 밤샘작업, 주말근무, 불안한 미래 등등 헤아릴 수 없이 많습니다만 가장 힘이

드는 건 고되고 긴 근무시간입니다. 하지만 이제 적어도 자바스크립트에 관련된 개발

을 진행할 때는 Prorotype과 Scriptaculous를 적절히 사용한다면 좀 더 일찍 퇴근해서

책도 읽고 오픈소스의 커미터로 활동하는 여가를 즐길 수도 있을 겁니다. Prototype과

Scriptaculous를 사용해서 환상적인 애플리케이션을 많이 개발하시기 바랍니다.

이렇게 훌륭한 라이브러리를 개발해준 두 개발자 샘 스티븐슨과 토마스 푹스에게 감

사 드리고, 루비온레일스와 부록 부분의 번역과 검토에 도움을 주신 손권남님, 꼼꼼한

베타리딩과 편집으로 저를 도와주신 위키북스의 관계자분들, 직장 상사 및 동료들 그

리고 넉 달의 시간 동안 매진할 수 있도록 도와준 아내 지영, 딸 민서, 그리고 곧 태어

날 아이 바다에게 고마움을 전합니다.

박 천구

2008년 봄

Page 20: Prototype & Scriptaculous 인 액션

xx

편리함이 핵심이다.

웹 애플리케이션 개발은 보통 이론적으로 매우 수월해 보이는 것을 구현할 때마저도

문제를 회피하는 방법을 찾아내는 것에 집중되어 있다. 아마도 가장 어려운 것처럼 보

이는 부분은 웹 브라우저일 것이다. 모든 주요 브라우저들이 다양한 버그를 가지고 있

고 또 스펙에 명시된 사항들을 완전하게 지원하지도 않는 것은 제외하더라도, 사용자

인터페이스를 구성하는 컨트롤의 결여와 불필요할 만큼 복잡한 자바스크립트 코딩 그

리고 당연한 것이겠지만 끔찍한 브라우저들 간의 비호환성 같은 기본적인 한계에 금새

부딪히게 된다.

자, 이런 모든 것은 잊도록 하자. 이 책은 정말로 중요한 것-여러분의 생각을 구현하

는 것-에 집중하기 위해 어떻게 Prototype과 Scriptaculous를 사용하는지 보여줄 것이

다. 어떻게 이 목표를 달성할 것인가에 대한 간단한 전제는 편리함이다. 편리함이라는

개념은 두 라이브러리 내의 모든 단계에 걸쳐 녹아 있다. 우선 라이브러리라는 것은 개

발자인 여러분에게 편리한 것이다. 대개의 경우 여러분은 짧은 라인의 코드만을 작성

하면 되고 그 코드는 잘 동작할 것이다. 또 라이브러리들은 전반적으로 일정한 스타일

을 따르므로 여러분이 처음 사용할지라도 아주 많은 것들을 배워야 할 필요도 없다. 소

스코드는 아주 읽기 편하게 최적화되어 있다(단지 조금만 시간을 투자하면 된다!) 이

덕분에 짧은 시간에 풍부한 사용자 인터페이스를 생성하여 이러한 편리함을 사용자에

게 전해줄 수 있다. 실제로 밑단의 기술을 어떻게 작동시킬까를 고민하는 대신에 약간

의 변경만을 통해 사용자 인터페이스를 개선할 수 있다. 이런 방법을 통해 초기부터

디자이너들과 사용자들을 프로세스에 참여하게 할 수 있는 생산적인 “반복적인 개발

rinse and repeat” 사이클을 확보할 수 있다(그렇다. 실질적인 “베타” 1 단계를 수행할

수 있게 된다.)

1 보통 개발시간에 쫓겨 실질적인 ‘베타’ 단계를 거치지 못하게 되지만 생산적인 개발 사이클을 확보하게 되면 베타다운 베타 단계를 진행할 수 있

게 된다.

머 릿 말

Page 21: Prototype & Scriptaculous 인 액션

xxi

Prototype과 Scriptaculous가 이런 접근방법을 고안하진 않았다. 두 라이브러리 모

두 루비온레일스라는 웹 개발 프레임워크로부터 태어났고 이런 접근방법도 차용하게

되었다. 만약 레일스를 사용해 보았다면 많은 것들이 아주 친숙할 것이다. 만약 사용해

보지 않았다면 한번 사용해보라!

편리함(편리한 기능)은 아주 쓸모가 많다. 웹사이트 개발 시에 기반이 되는 백엔드부

터 사용자 화면에 걸쳐 모든 면에서 편리함이 적용되고 있다. Scriptaculous 사용자는

“puff 이펙트가 절 눈물 흘리게 만들었어요. 그것은 기쁨의 눈물이었습니다”라고 이야

기하기도 한다. 여러분이 이처럼 반응하지는 않을지 몰라도 여러 가지 방법으로 이 라

이브러리들을 즐길 수 있다. 아마 가장 좋은 것은 여러분이 일찍 개발을 끝냈기 때문에

제 시간에 집에 퇴근하는 것이다

웹에 훌륭한 것을 만들어 내는 재미를 즐겨보라. 그리고 여러분이 좋다면 IRC 채

널 2 과 메일링 리스트에 가입해서 배운 것을 커뮤니티에 환원해라. 더 나아가 패치를

작성하고 버그를 수정하거나 Prototype과 Scriptaculous를 위한 여러분만의 오픈소스

확장모듈을 개발하라!

토마스 푹스

CTO, wollzelle

Scriptaculous 창시자

2 1988년에 핀란드의 자코 오이카리넨(Jarkko Oikarinen)이 개발한 실시간 채팅프로그램으로 (Internet Relay Chat)의 약자이다.

Page 22: Prototype & Scriptaculous 인 액션

xxii

몇 년 전까지, 일반적으로 자바스크립트는 적절한 프로그래밍을 할 수 없는 언어로 무

시되어 왔다. Ajax의 출현은 자바스크립트에게 새로운 도구를 선사했고 개인들이 자신

을 자바스크립트 프로그래머라고 소개하는 것이 가장 존경받는 일이 되었다. 나 또한

자바스크립트로 개발해야 했기 때문에 여기 저기서 자바스크립트 프로그래밍을 하면

서 다른 방법으로는 해결할 수 없는 꽤 깔끔한 트릭들을 찾아냈고 이런 변화를 따르게

되었다.

심지어 자바스크립트 언어 자체에 대해서 연구하기 시작했고 자바스크립트가 전혀

자바와 같지는 않지만 그 자체의 로직과 스타일을 가지고 있다는 점을 발견하고는 꽤

놀랐다. 나는 prototype 프로퍼티를 이용해 객체를 상속구조화 하는 것을 이해했고 자

바스크립트 객체를 생성하기 시작했다. 자바스크립트의 클로저가 어떻게 동작하는지

를 깨닫던 날 굉장히 기뻤고 어느 정도 자바스크립트를 마스터했다는 사실을 스스로

축하했다. 자만은 실패를 부르는 법이다.

나는 어디선가 알게 된 샘 스티븐슨(Sam Stephenson)이 개발한 Prototype 라이브러리를

선택하였고, 다른 사람이 Prototype 라이브러리를 사용하여 작성한 몇 줄의 코드를 복사

해서 넣어보았다. 그리고 나는 그것이 코드 양을 현저히 줄여줄 수 있다는 것을 깨닫게

되었다. 곧 참을 수 없는 호기심이 생긴 나는 Prototype이 어떻게 동작하는지 알고 싶어

졌다. 내가 처음 Prototype의 소스코드를 읽게 되었을 때, 나는 내가 발견한 것이 오래된

Perl의 사용형태라고 생각했다. 그 소스코드는 내가 익숙하게 사용하는 자바스크립트처

럼 보이지 않았고 나는 다른 능숙한 프로그래머들처럼 Prototype을 잊었다.

하지만 오랫동안 그 생각을 지울 수가 없었고 Prototype 소스를 볼 때마다 코딩 스

타일에 점점 수긍하게 되었다. 나는 그 당시에 루비라는 새로운 스크립팅 언어에 흥미

를 느끼고 있었는데 그 두 가지를 연관지어 생각해보기 시작했다. 마침내 어떤 패턴을

발견했다. 이 과정에서 나는 내가 처음 자바스크립트를 배웠을 때보다 자바스크립트

서 문

Page 23: Prototype & Scriptaculous 인 액션

xxiii

를 아주 재미있게 만들어주는 요소들인 클로저(closure)나 prototype chains 1 그리고 다

른 것들을 샘이 빠뜨렸다는 것을 알게 되었다. 많이 고민하여 개발된 라이브러리였기

때문에 초반부의 잘 정리된 많은 라인의 코드가 라이브러리의 다른 부분에서 계속해서

재사용될 수 있었다.

토마스 푹스(Thomas Fuchs)의 Scriptaculous 라이브러리 역시 동일한 접근 방식을 취하

고 있는데, 잘 설계된 부분 코드들로부터 좀 더 커다란 부분을 생성하고 초보자들이 라

이브러리의 모든 기능을 단 몇 줄의 코딩만으로 사용할 수 있도록 화려하게 래핑하였다.

내가 Ajax 코스를 가르칠 때, Scriptaculous를 분석하고 노래하고 춤추고 드래그 앤 드

롭을 지원하는(맞다, 노래하고 춤춘다는 얘기는 거짓말이다) 사용자 인터페이스를 만

드는 날은 종종 크리스마스 같은 느낌이 들었는데, 내 학생들은 몇 시간 내에 단 몇 줄

의 코드만으로 그들이 일주일은 걸릴 것이라고 생각했던 깔끔하고 훌륭한 작업들을 성

취해냈다.

여러분은 이 책에서 몇 라인만의 코딩으로 빠르게 이 라이브러리들을 사용하는 방법

을 얻을 수 있다. Prototype과 Scriptaculous는 쉬운 일은 쉽게 처리할 수 있도록 해주

어 개발 시에 비즈니스 로직을 원만하게 처리하게 하고, 크로스 브라우저에 대한 걱정

과 여러분 자신의 라이브러리를 지원하는 부담으로부터 해방시켜준다. 또한 이 책을

통해 이 라이브러리들이 어떻게 작동되는지 좀 더 깊이 있게 이해할 수 있고, 결과적으

로 자바스크립트가 어떻게 동작하는지 알게 될 것이다.

나는 Prototype과 Scriptaculous를 사용하면서 자바스크립트 코딩이 한층 재미있음

을 느꼈다. 이런 즐거움이 여러분에게도 매력적이었으면 한다.

데이브 크레인

1 자바스크립트에서 각 Object는 다른 객체의 prototype이라는 프로퍼티를 상속받는다. 프로퍼티를 레퍼런스하기 위해서 표현식을 실행할 때, 자

바스크립트는 먼저 해당 프로퍼티가 현재의 객체에 정의되어 있는지를 확인하고 만약 그렇지 않다면 부모 객체에 정의되어 있는지를 찾아가게

된다. 이러한 과정은 루트 prototype에 도달할 때까지 계속된다. 이렇게 prototype이 상속관계에 의해 연결되어 있는 것을 prototype chain이라

고 한다.

Page 24: Prototype & Scriptaculous 인 액션

xxiv

이 프로젝트가 실현되고 우리의 생각들이 여러분이 읽고 있는 책으로 담길 수 있도록

공헌해준 많은 사람들에게 감사를 표하고 싶다.

책이 집필되는 여러 단계에 있어 원고에 대한 피드백을 주고, 보다 나은 책이 될 수

있도록 도와준 리뷰어들에게도 감사를 표한다. 그들은 Philip Hallstrom, Christopher

Haupt, Derek Lakin, Jon Tirsen, Deepak Vohra, Jeff Cunningham, Christopher

Bailey, Scott Shaw, Mark Eagle 그리고 Benjamin Gorlick이다. 출판 전에 면밀하게

기술적인 부분에 대한 검토를 해준 Deepak Vohra에 특히 감사의 말을 전한다.

마지막에 발견된 에러들과 초기 원고들 사이의 불일치들을 찾아내준 매닝출판사 베

타리더 프로그램의 독자들에게도 감사의 말을 전한다.

제작팀인 Andy Carroll, Dottie Marisco, Gordan Salinovic, Elizabeth Martin, Mary

Piergies뿐만 아니라 매닝출판사의 모든 분들께 감사의 말을 전하며 특히 발행자인

Marjan Bace와 편집장인 Mike Stephens, Cynthia Kane에게 감사의 말을 전한다.

머리말을 써준 토마스 푹스와 레일스 관련 장을 집필해준 톰 로크에게 그들의 이름

을 빌려주고 우리의 시도를 도와준 노력에 대한 진심 어린 감사를 전한다.

데이브 크레인

무엇보다도 이런 훌륭한 라이브러리들을 개발해 준 샘 스티븐슨, 토마스 푹스에게 감

사를 표하며 프로젝트가 궤도를 이탈하지 않고 눈부신 속도로 지속되도록 노력해

준 Prototype의 핵심 개발팀인-Justin Palmer, Andrew Dupont, Dan Webb, Scott

Raymond, Mislav Marohnic, Christophe Porteneuve, Tobie Langel 그리고 Seth

Dillingham 에게 감사를 표한다.

나의 동료들인 Simon Warrick, Tim Wilson, Susannah Ellis, Simon Crossley, Rob

감 사 의 글

Page 25: Prototype & Scriptaculous 인 액션

xxv

Levine, 그리고 Historic Futures의 Miles Wilson에게 이 프로젝트를 도와준 것에 대

해 감사를 표하며 Wendy, Nic, Graeme 그리고 재능 있는 나의 학생들인 Skillsmatter.

com 팀에게 이 책이 어떻게 써져야 하는지에 대한 나의 생각을 구체화할 수 있도록 도

와준 것에 대해 감사를 표한다.

그리고 베어와 톰에게 이 책이 구체화될 수 있도록 도와준 그들의 값으로 매길 수 없

는 도움과 통찰력에 대해 감사한다.

마지막으로 내가 책을 쓰는 동안 참아준 우리 가족의 나머지 사람들 Chia, Bean, 그

리고 Sophie와 나의 어머니, 아버지께 감사 드리고 제때에 먹이를 주지 않았음에도 참

아준 나의 고양이들에게도 감사의 말을 전한다.

베어 바이볼트

내게 키보드보다는 종이와 펜을 들도록 격려해주고 내가 집필에 관심을 보였을 때 “당

장 책을 써!” 라고 용기를 준 Javaranch.com의 내 친구들인 Ernest Friedman-Hill, Eric

Pascarello, Ben Souther, Max Habibi, Mark Herschberg 그리고 Kathy Sierra에게 감

사의 말을 전하며 이 외에도 많은 사람들에게 감사한다.

Javaranch.com의 소유주인 Paul Wheaton에게 머물고, 배우고 또 남을 도울 수 있는

그런 훌륭한 곳을 만들어 준 것에 대해 감사한다.

데이브 크레인과 마이클 스티븐스에게 나를 믿어 주고 이 일에 공헌할 기회를 준 것

에 대해 감사한다.

또한 이 책의 페이지 중 어딘가에 그들의 동의 없이 스크린 캡처로 모습이 실려 있는

나의 개 Gizmo와 Little Bear에게도 감사한다. 이들은 내가 타이프를 치는 동안 나의

발치에 누워서 함께 해주었다.

또한 긴 밤 동안 단어를 선택하느라 야단법석을 떨고, 브라우저 특징에 대해 불평하

는 나를 참아주고 몇 년 전 Mac을 소개해주었던 내 파트너인 Jay에게도 감사한다.

Page 26: Prototype & Scriptaculous 인 액션

xxvi

Prototype과 Scriptaculous는 모두 여타 소프트웨어 라이브러리와 마찬가지로 생산성

에 관련된 툴이다. 웹 브라우저 기반에 코딩을 하는 것은 기이한 경험이다–기본적인

기능면에서 부족한 점이 있긴 하지만 어떤 데스크탑 GUI 툴킷보다도 자유롭고 표현력

이 풍부하다. 나는 제품의 한 부분으로 사용되는 자신만의 드래그 앤 드롭 라이브러리

나 드롭 다운 리스트 위젯을 유지보수하는 DHTML/Ajax 개발자는 몇몇 알고 있지만

데스크탑 개발자의 경우는 본적이 없다. 이런 기능들은 소프트웨어 프로젝트의 존재에

대한 것이 아니라 단지 프로젝트를 완료하는 수단이다. 이러한 기능을 구현하기 위해

저수준의 코드를 만지작거리고 있는 것은 잘해야 주위를 산만하게 하고 최악의 경우에

는 프로젝트를 실패하게 만드는 짐이 된다.

대상 독자

이 책은 비즈니스 아이디어와 컨셉을 우아하게 표현하기 위해 사용자의 작업흐름과 만

족감을 향상시키는 데 시간을 투자해야 할 필요가 있거나 또는 뛰어난 새로운 기능을

개발하려는 명확한 목적을 지닌 자바스크립트 코더를 대상으로 쓰여졌다. Prototype과

Scriptaculous는 여러분의 코드를 유연하고 우아하게 표현해주며 여러분이 프로그래밍

외의 일상에서 보상을 받게 해준다. 만약 자신만의 좌표계를 개발하느라 빈둥거리거나

트리 위젯, 정렬 알고리즘, 이벤트 리스너 등과 같이 현대 컴퓨팅에서는 흔한 것들을

처음부터 새로 만든다면 여러분은 여기서 얻을 것이 없을 것이다. 하지만 다시 생각해

보면 Prototype과 Scriptaculous는 확실히 여러분이 그 일들을 빠르고 더 잘할 수 있게

도와줄 것이다.

우리의 두 번째 대상 독자층은 이 라이브러리들이 동작하는 방식에 대한 이해를 높

이려는 경험 많은 Ajax 프로그래머들이다. 우리는 이들 라이브러리에 대한 대부분의

특징들을 어느 누구라도 사용할 수 있는 직접적인 예제를 통해 제시할 것이며 주요한

컴포넌트와 기능들의 내부적인 작동에 대해 살펴볼 시간 또한 갖게 될 것이다. 우리는

보다 크고 중요한 패턴에 주의를 기울였으며 다양한 조각들이 모여 비교적 조화롭게

전체를 이루도록 노력하였다.

이 책 에 대 해

Page 27: Prototype & Scriptaculous 인 액션

xxvii

여러분이 단순히 일을 효과적으로 마무리 지을 방법을 찾거나 또는 자바스크립트 스

킬을 다음 레벨까지 연마하기를 원한다면, 이 책이 많은 도움이 되기를 바란다.

로드맵

우리는 체계적으로 토론을 이끌어 나가기 위해 이 책을 네 개의 부로 나누었다. 1부

는 웹 기반 클라이언트에 있어 최근 관심이 급증하는 비동기 방식의 요청에 집중한다.

Ajax는 작지만 애플리케이션 디자인의 많은 관점에 있어 거대한 영향력을 발휘하는 기

능이며 Prototype은 우리가 이러한 작업을 수행하는 데 많은 도움을 준다.

1장은 Prototype과 Scriptaculous에 대한 일반적인 소개와 현대 Ajax 환경에서 이

들 라이브러리의 위상에 대해서 다룬다. 2장은 우리의 주요한 예제 애플리케이션인

QuickGallery라는 웹 기반 이미지 뷰어를 소개한다. 3장과 4장에서는 Ajax 형태의 요

청을 생성하는 데 필요한 기본적인 컴포넌트부터 애플리케이션이 HTTP 트래픽을 처

리하는 방식에서 야기된 아키텍쳐상의 이슈들을 해결한 Prototype의 최근 버전이 제공

하는 보다 정교한 헬퍼에 이르기까지, Prototype이 지원하는 여러 가지 형태의 Ajax 기

능들을 QuickGallery를 사용하여 알아본다.

2부는 Scriptaculous 라이브러리를 다루며 각 주요 컴포넌트마다 한 장씩을 할당했다.

5장은 이펙트(Effect) 하위시스템에 대해서 알아보고 한 라인만을 추가하여 바로 만족스

럽게 구동시킬 수 있는 첫 번째 특별 effect를 실행하는 것에서 시작하여 커스터마이징

과 효과(effect)들을 조합하여 우리들만의 효과를 작성하는 법까지 알아본다.

6장은 추가 작업 없이 웹 페이지에서 사용 가능한 Ajax 기반의 컴포넌트들을 제공하

는 컨트롤(Control) 하위 시스템에 대해 검토한다. 또한 온라인 배치부터 커스터마이징에

대한 이해와 이런 컴포넌트들의 조합에 대한 충분한 이해까지 전반적으로 알아볼 것이

며 양방향 형태의(interactive) 업무흐름을 제공하기 위해 이런 컴포넌트들을 어떻게 연결

하여 서버 측에서 처리하는지도 보여줄 것이다.

7장에서는 Scriptaculous의 드래그 앤 드롭 하위 시스템에 대해서 알아볼 것이다.

Scriptaculous는 기본적인 기능을 제공하는 상대적으로 간단한 객체들과 이러한 객체

들 상위에 구축된 정교한 드래그 앤 드롭 UI 컴포넌트 레이어로 드래그 앤 드롭을 구성

하고 있다. 우리는 이러한 시스템들이 어떻게 동작하고 여러분의 프로젝트에서 어떻게

이러한 시스템들을 사용할 것이지 설명할 것이다.

Page 28: Prototype & Scriptaculous 인 액션

xxviii

3부는 언어 자체에 관심이 있는 사람들을 위한 파트이다. 자바스크립트는 유연한 언

어이며 Prototype은 이러한 자바스크립트를 아주 흥미롭고 유용한 체계로 구성해 준다.

Prototype이 핵심적인 객체에 제공해주는 새로운 특성들을 훑어보고 각 특성들을 설명

하는 작고 실용적인 예제들을 다룰 것이다. 새로운 특성들에 대해 최대한 많은 부분을

다루기 위해 3부에서는 전체가 아닌 부분코드를 가지고 설명하는 방식을 취하며 이 부

분코드들을 여러분이 실행시켜 볼 수 있도록 편리한 인터프리터를 제공한다.

8장은 모든 다른 자바스크립트의 객체들이 생성되는 기반 클래스인 Object 클래스에

대해서 알아볼 것이다. 재사용이 가능한 형태의 새로운 객체를 생성하는 방법을 보여

주고 어떻게 자바스크립트의 prototype 속성를 사용하여 상속 시스템을 활용하는지 보

여줄 것이다. 그 후에 Prototype 라이브러리가 이러한 기술을 어떻게 단순화시켜주는

지 설명하고 Prototype을 사용하여 어떻게 여러분의 객체들을 계층적으로 생성하는지

보여줄 것이다.

9장은 자바스크립트의 함수들과 클로저(closure)에 관련된 개념에 대해서 살펴볼 것이

다. 이번 장은 분량은 짧지만 자바스크립트 언어의 유용한 특성들 중 하나임에도 가장

잘못 이해되고 있는 것에 대해서 다루는 아주 유용한 장이다. 클로저는 다루기 어려울

수 있지만 Prototype은 이것에 간단하게 접근할 수 있게 도와준다.

10장은 자바스크립트의 배열에 대해서 다룬다. Prototype은 우리가 Array 객체를 다

루는 방법을 완전히 바꾸어 놓았다고 해도 과언이 아니며, 30가지가 넘는 새로운 방법

을 제공한다. 우리는 이 각각의 방법들을 세밀하게 다룰 것이고 어떻게 DOM 엘리먼트

의 집합이나 기존의 자바스크립트 객체들로 이루어진 배열 객체가 아닌 다른 객체들에

게까지 신기하고 새로운 편의성이 확장될 수 있는지 알아볼 것이다.

11장에서는 웹브라우저의 환경, 즉 DOM 엘리먼트와 HTML 폼에 대한 Prototype의

지원기능에 대해서 알아본다. 이 장에서 다루게 되는 기능은 브라우저 간의 비호환성

문제를 해결한 사용자 인터페이스를 쉽게 만들 수 있도록 도와주고 우리가 파트2에서

설명한 Scriptaculous 라이브러리의 화려한 기능에 견줄 만한 저수준의 기능들을 제공

한다.

4부는 두 개의 고급 토픽을 다루고 이들 라이브러리에 대한 이야기를 마무리한다.

12장은 우리가 1부에서 설명했던 QuickGallery 애플리케이션에, 이 책의 2부와 3부에

서 배운 내용을 적용하여 빠르게 새로운 기능을 추가해 본다. 이러한 과정은 실제 환경

Page 29: Prototype & Scriptaculous 인 액션

xxix

에서 이들 라이브러리를 적용하는 프로세스에 대해서 설명한다.

13장은 Scriptaculous와 Prototype 그리고 루비온레일스 프레임워크를 통합하는 방

법에 대해서 알아보고 보다 우아하고 쉬운 사용성을 제공하기 위해 어떻게 레일스가

이들 라이브러리에 기초하여 개발되었는지 보여준다.

우리가 웹에서 하는 모든 일의 기초는 HTTP이다. 그리고 우리가 Ajax를 사용하면

좀 더 세밀하게 HTTP를 제어할 수 있게 된다. 위대한 힘에는 커다란 책임이 따른다는

말이 있다. 부록 A에서는 기본적인 프로토콜에 대한 내용을 다루고, 부록 B에서는 애

플리케이션의 HTTP 트래픽을 프로파일링하기 위해 이 책에서 사용한 기술을 좀 더 상

세하게 다룬다.

이 책의 주요 예제는 주로 서버 측에서 실행되는 PHP와 자바 코드로 구성되어 있다.

우리의 모든 독자들이 이 기술들을 알고 있지 못하므로 부록 C와 D는 가장 많이 사용

되는 운영체제에 자바의 톰캣서버, PHP의 아파치 서버를 차근차근 설치하는 가이드를

제공한다.

이 책은 자바스크립트 코드에 초점을 맞추고 있으므로 우리가 예제에서 제시한 서버

측 코드는 전체적으로 아주 단순하다. 그러나 우리는 서버 측 코드에 Ajax와 함께 사

용되는 경우에만 발견될 만한 트릭들을 사용했다. 부록 E에서는 이런 트릭들을 어떻게

마스터하여 예제에서 상세하게 다루지 않은 여타 다른 서버 측 언어로 컨버팅할 수 있

는지 가이드를 제시하였다.

코드 컨벤션

이 책에서 제공하는 예제코드들은 자바스크립트, 자바, JSP, 루비 그리고 PHP를 포함

한 여러 가지 프로그래밍 언어로 작성되어 있다. 이러한 언어로 작성된 조금 긴 라인의

코드를 ‘예제’란 헤더를 표기하여 제공하고 좀 더 짧은 라인의 코드는 그냥 간단하게 텍

스트와 함께 즉시 한 라인으로 표기하였다. 모든 경우에 있어 코드를 보기 쉽도록 모노

스페이스 폰트를 사용하여 본문 텍스트와 구별하였다. 많은 장문의 예제들은 숫자로

주석을 달아 본문에서 참조토록 하였으며 코드를 조금씩 추가해가며 살펴보게 되는 몇

몇 경우에는 수정되는 부분을 볼드체로 표기하였다.

8장부터 11장까지는 Prototype 라이브러리의 저수준 언어적 특성을 다루므로 거의

모두 짧은 라인의 코드를 다루었다. 모든 예제 코드를 한 번에 제시하기보다는 예제들

Page 30: Prototype & Scriptaculous 인 액션

xxx

의 부분만을 제시한다. 이러한 부분코드들은 예제와 유사하지만 8장에서 제시하여 11

장까지 계속 사용되는 양방향의 인터프리터(Scratchpad 애플리케이션) 위에서 실행되

는 점에서 차이가 있다. 이 인터프리터는 우리가 검토하는 코드 중에 눈으로 식별할 수

없는 효과를 제공하는 코드들을 시각화시켜 볼 수 있도록 해주며 각 부분 코드는 인터

프리터상에서 보여지는 스크린샷과 함께 제공된다.

코드 다운로드

이 책을 위한 전체 예제 코드는 이 책을 위해 마련된 매닝출판사 웹사이트 내의 페이지

http://www.manning.com/crane3과 위키북스 홈페이지 wikibook.co.kr에서 다운받

을 수 있다. 예제코드는 부분코드의 실행에 필요한 인터프리터를 포함하고 있으며 다

른 장들을 위한 보다 긴 예제들 역시 포함하고 있다. 이들 중 어떤 것은 자바가 구동되

는 웹 서버나 PHP가 구동될 아파치 서버를 필요로 한다. 부록 C와 D에서 이러한 설치

와 실행에 관련된 내용을 다루었다.

온라인 포럼에서 만나요

이 책은 Prototype과 Scriptaculous에 대한 완전한 기초지식을 제공했지만 책을 읽

는 동안 발생할 수 있는 모든 의문점에 대해 다룰 수는 없다. 매닝출판사는 발행하는

모든 책들의 저자와 대화할 수 있는 온라인 포럼을 제공하므로 여러분은 데이브, 베

어, 톰과 이 책을 위한 온라인 포럼인 http://www.manning-sandbox.com/forum.

jspa?forumID=276 에서 만날 수 있다.

Prototype과 Scriptaculous는 이 책에서 제공하는 것보다 훨씬 왕성한 활동을 온라인

에서 하고 있다. Prototype의 공식문서는 http://www.prototypejs.org에서 찾을 수 있

으며 Scriptaculous는 주로 위키사이트인 http://wiki.script.aculo.us에서 문서화 작업

이 진행된다. 또한 이 두 라이브러리에 대한 일반적인 질문들은 Ruby on Rails Spinoffs

그룹의 사이트인 http://groups.google.com/group/rubyonrails-spinoffs?hl=en에 해

도 된다. 그룹의 이름과는 상관없이 루비 코더들만이 배타적으로 사용하는 곳이 아니

라 보다 넒은 층의 Prototype과 Scriptaculous를 지지하는 사용자들을 위한 그룹이다.

여러분의 질문을 기다리고 있다!

Page 31: Prototype & Scriptaculous 인 액션

xxxi

저자와의 온라인 대화

『Prototype & Scriptaculous 인 액션』을 구매하면 매닝 출판사가 운영하는 비공개 웹포

럼을 무료로 접속할 수 있으며 여러분은 책에 대한 논평을 남기거나 기술적인 질문을

하거나 저자나 다른 사용자로부터 도움을 받을 수 있다. 포럼에 접속하거나 또는 포럼

에서 소식지를 받아보려면 http://www.manning.com/crane3에 웹 브라우저로 접속

하면 된다. 일단 여러분이 등록을 하면 이 페이지는 어떻게 포럼에 도움을 요청하는지

어떤 종류의 도움이 가능한지 그리고 포럼 내에서 행동은 어떻게 해야 하는지에 대한

정보를 알려준다.

매닝의 독자들에 대한 책임은 개인 독자들 간에 그리고 독자들과 저자들 사이의 의

미 있는 대화가 발생할 수 있는 장소를 제공하는 것이다. 저자들이 일정한 부분만큼 참

여를 해야 하는 책임은 없으며 그들은 자발적으로 이 포럼에 공헌하고 있다(돈을 지불

받지 않는다). 저자들의 흥미를 유발할 수 있는 질문을 하여 그들의 관심이 떠나지 않

도록 노력하라!

저자들의 온라인 포럼과 이전 저장된 이전의 토론 내용들은 출판사의 웹사이트에서

이 책이 출간되는 한 계속 제공될 것이다.

Page 32: Prototype & Scriptaculous 인 액션

xxxii

『Prototype & Scriptaculous 인 액션』표지의 그림은 ‘이클로간(Ichlogan)’이라고 하

는 터키 어느 지방의 고유 의상을 입은 부족의 모습이다. 이 그림은 런던 올드 본드의

윌리엄 밀러(William Miller)가 1802년 1월 1일에 출간한 오스만 제국(Ottoman Empire)의 의

상 컬렉션에서 인용한 것이다.

이 컬렉션 표지가 손실되어 지금까지 발견되고 있지 않다. 이 책의 목차는 영어와 불

어로 쓰여 있으며, 모든 그림을 작업한 두 명의 아티스트들의 이름이 기술되어 있고,

표 지 그 림 에 대 해

‘인 액션’ 시리즈의 책들은 소개, 개요, 그리고 실용적인 예제를 결합하여 학습과 기억

이 쉽도록 디자인되었다. 인지과학 분야의 연구에 따르면 사람들이 기억하는 것은 스

스로 탐험하는 동안 발견한 것들이다.

비록 매닝의 어느 누구도 인지과학자가 아니지만 배움이 영원한 것이 되려면 탐험의

단계, 놀이의 단계, 그리고 재미있게 배운 것을 다시 말하는 단계를 거쳐야 한다고 확

신한다. 사람들은 활동적으로 탐험한 후에 그들이 완벽히 마스터했다고 말할 수 있는

새로운 것들만을 이해하고 기억한다. 인간은 실행을 통해서 배운다. ‘인 액션’ 시리즈의

책들에 있어 본질적인 부분은 그것이 예제중심이라는 것이다. 이 책은 독자들이 책의

내용을 시험해보고, 새로운 코드를 가지고 놀아보고, 새로운 생각들을 탐구하도록 격

려한다.

이 책의 제목에는 보다 실제적인 다른 이유가 있다: 우리의 독자들이 바쁘다는 것이

다. 독자들은 이 책을 그들의 업무를 처리하거나 문제를 해결하는 데 사용한다. 독자

들은 그들이 쉽게 원하는 부분만을 찾아볼 수 있고 그들이 원할 때에 원하는 것을 배울

수 있는 책을 필요로 한다. 이 시리즈의 책들은 그러한 독자들을 위해 기획되었다.

인 액 션 시 리 즈 에 대 해

Page 33: Prototype & Scriptaculous 인 액션

xxxiii

두 명 모두 컴퓨터 프로그래밍 책의 표지를 장식했다는 데 놀랄 것이다… 2백 년이 지

난 후에.

이 컬렉션은 Manning 출판사의 한 편집자가 맨하탄 웨스트 26번가 게러지(Garage)에

있는 골동품 벼룩시장에서 구매한 것이다. 판매한 사람은 터키 앙카라 출신 미국인이

었으며 거래는 그날 당일 이루어졌다. Manning의 편집자는 개인적으로 그 책을 구매

하기에 충분한 현금을 가지고 있지 못했으며 신용카드나 수표는 사용할 수 없었다.

판매자가 앙카라로 돌아가려 하는 상황이었고, 저녁 때 상황은 더욱 안 좋아졌다.

해결책이 뭐였을까? 구두로 약속하고 악수로 도장 찍는 낡은 방식이 최선의 방책이

었다. 판매자는 나중에 돈을 송금해줄 것을 제안했고, 편집자는 계좌 번호를 적고, 컬

렉션을 들고 나왔다. 물론 다음날 돈을 부쳤다. 우리는 기뻤고, 낯선 사람에게 신뢰를

보여준 이름 모를 사람에게 깊은 인상을 받았다.

이 컬렉션은 아주 오래 전에 있었던 일을 회상하게 한다.

표지의 다른 그림들과 마찬가지로 오스만 컬렉션에서 인용한 이 그림은 2백년 전 부

유하고 다채로웠던 의상을 보여준다. 이 그림들은 우리의 너무나 바쁜 일상과 동떨어

진 시간의 거리를 느끼게 해준다. 그토록 풍요로웠던 시대가 지난 후, 의상 코드는 지

역마다 다르게 변하고 사라졌다. 이제는 한 대륙의 사람을 다른 대륙의 사람들과 구분

하기 어렵다. 좀 더 긍정적으로 생각해 본다면, 우리는 좀 더 다양한 개인의 삶을 위해

혹은 다양하고 흥미로운 지적, 기술적 생활을 위해 문화와 시각적인 다양성을 교류하

고 있는 것이다.

우리는 이 컬렉션의 그림을 가져와 생기를 불어 넣었다-2세기 전 특정 지역의 풍요로

운 다양성을 보여주는 책의 표지를 통해 창의성, 통찰 그리고 컴퓨터 비즈니스의 재미

를 세상에 알리고자 한다.

Page 34: Prototype & Scriptaculous 인 액션

01부

이 책에서는 Prototype과 Scriptaculous 라이브러리에 대해 상세하게 소개할

것이다. 라이브러리를 문서화 할 때 상세한 내용에 대해서 특징별로 설명하

는 것이 중요하지만 라이브러리에 대한 문맥을 짚어내어 라이브러리들이 보다 큰

그림에 어떻게 들어맞는지를 보여주는 것도 중요하다. 1부에서는 보다 큰 그림에

대해서 다루도록 한다.

1장에서는 두 라이브러리에 대해 소개하며, 라이브러리들을 어떻게 사용할 수 있

는지 보여주는 간단한 예제로 마친다. Prototype과 Scriptaculous는 Ajax 기반

웹 애플리케이션 개발을 좀 더 쉽고 간단하게 만들어 주며 많은 양의 반복적이고

단조로운 작업을 제거할 수 있도록 설계되었다. 따라서 우리는 동일한 애플리케

이션을 두 번 제시해서 비교해 볼 것인데, 첫 번째는 이 강력한 라이브러리들을

사용한 경우이고 두 번째는 사용하지 않은 경우이다.

1부의 나머지 부분은 QuickGallery라는 이름의 보다 상세한 예제를 탐구하는 데

Page 35: Prototype & Scriptaculous 인 액션

시작하기

할애했다. 평범하고 Ajax를 사용하지 않은 버전의 애플리케이션을 2장에서 소개

하여 전통적인 웹 애플리케이션의 여러 가지 한계에 대해서 토론한다. 3장과 4장

에서는 QuickGallery 애플리케이션을 Ajax 형태로 바꿀 수 있는 다양한 기술을

소개하여 이러한 이슈들을 해결할 것이다.

3장과 4장의 실질적인 목적은 여러분에게 보다 나은 이미지 브라우저를 개발할

수 있는 방법을 보여주는 것이 아니다. 이 장들을 통해서 Prototype이 지원하는

Ajax 헬퍼 클래스들을 탐구하고 그것들이 어떻게 동작하는지, 그리고 그것들이

웹 애플리케이션의 흐름을 향상시키는 데 어떤 일들을 할 수 있는지를 고찰하는

것이다. Prototype이 지원하는 여러 가지 스타일의 Ajax 기능을 평가해보는 것으

로 마무리한다

Page 36: Prototype & Scriptaculous 인 액션

2

Page 37: Prototype & Scriptaculous 인 액션

3

Prototype과 Scriptaculous 소개

01장

이번 장에서 다루는 내용 : Ajax의 역사

: Prototype과 Scriptaculous에 대한 소개

: Prototype과 Scriptaculous의 적용

Page 38: Prototype & Scriptaculous 인 액션

시작하기1부

Ajax는 빠르게 성장하고 있다. 이러한 성장의 징후들 중 하나는 Ajax를 다루기 쉽게 해

주는 써드파티 라이브러리들이 많이 출현하고 폭넓게 수용되고 있으며 웹 기술들인

DOM, CSS 그리고 무엇보다도 자바스크립트가 Ajax를 지원하고 있다는 점이다. 이 책

은 서로 관련이 있는 두 개의 자바스크립트 라이브러리인 Prototype과 Scriptaculous

를 아주 상세하게 다룬다. Prototype은 Ajax 애플리케이션을 쉽게 다룰 수 있도록 해주

는 많은 작은 특징들을 제공한다. Scriptaculous는 이러한 특징들을 이용하여 많은 고

수준의 사용자 인터페이스 컴포넌트들을 생성한다. 두 가지 라이브러리 모두 Ajax 개

발을 편리하게 할 수 있도록 해주며 여러분의 아이디어를 자바스크립트로 표현하기 쉽

게 해주어 놀랄 만큼 쉽게 세련된 인터페이스를 만들 수 있게 해준다.

이번 장은 Prototype과 Scriptaculous에 대한 준비 과정으로 이 라이브러리들이 어떻

게 Ajax 개발이라는 커다란 그림에 관련이 있는지, 왜 이 라이브러리에 대한 책을 쓰는

것이 유용한 일이라고 생각했는지를 설명한다. 우리는 독자들이 대체로 실용적인 것을

원한다는 것을 알고 있으므로 이번 장에서는 평범하고 오래된 Ajax 애플리케이션의 불

필요한 저수준 코드를 제거하고 유연하고 기분 좋은 사용자 인터페이스를 쉽게 생성할

수 있도록 이 라이브러리들을 사용해 볼 것이다. 이어지는 장들에서는 라이브러리들의

세부적인 내용까지 자세히 알아보고, 이번 장에서 진행한 것과 같은 방법으로 여러분

의 애플리케이션을 강력하게 만드는 데에 필요한 상세한 내용을 제공할 것이다.

이 책의 1부에서는 Ajax에 대한 내용, 즉 전체 페이지를 다시 로딩하지 않고 브라우

저와 서버 간의 통신을 수행하는 방법에 초점을 맞출 것이다. 1부의 마지막 부분을 읽

을 때쯤이면 Prototype이 지원하는 Ajax 관련 기능을 여러 가지 형태로 마음대로 사용

할 수 있게 될 것이다. 여기서 주제를 옮겨 2부에서는 Scriptaculous에 대해 자세히 알

아보고, 3부에서는 자바스크립트와 DOM에 대한 Prototype의 지원기능에 대해서 알

아본다. 1부에서는 예제 애플리케이션도 소개할 것인데, 이 애플리케이션은 우리가

배운 내용을 적용해 보기 위해 4부에서 다시 살펴보게 될 것이다. 그럼 Prototype과

Scriptaculous에 대한 문맥을 정립하기 위한 간단한 리뷰로 시작하도록 하자

1.1 간단하게 살펴보는 Ajax의 역사

Ajax는 HTML, CSS 그리고 적당한 양의 자바스크립트만을 사용하여 고도로 상호적인

(interactive) 웹 기반 인터페이스를 개발하는 방식을 기술하기 위해 최근에 생겨난 용어이

Page 39: Prototype & Scriptaculous 인 액션

Prototype과 Scriptaculous 소개 1장

다. 사람들이 이러한 종류의 애플리케이션을 몇 년 동안 개발해 왔지만 제스 제임스 가

렛 Jesse James Garrett이 처음으로 2005년 2월에 전파한 이후 가장 관심을 끄는 기술주제

가운데 하나가 되었다.

웹 커뮤니티가 Ajax를 받아들이는 속도는 엄청났고 웹 개발에 대한 양상은 현저하게

달라졌다. Prototype과 Scriptaculous는 이러한 변화의 중심에 자리잡고 있으며 이들

라이브러리가 어떻게 탄생되었는지를 알아보는 것은 매우 유용하다. 그러니 고고학 탐

사용 모자를 눌러 쓰고 Ajax의 역사를 발굴하러 떠나보자.

1.1.1 Ajax 등장 이전의 시대

Ajax의 역사가 2005년에 쓰여진 가렛의 기사에서 비롯되었지만 그 이전에도 Ajax의 기

반 기술들은 이름도 붙여지지 않은 채로 많은 실천가들을 자극하고 그들에 의해 탐구

되어왔다. Ajax는 XMLHttpRequest라는 ActiveX 컴포넌트가 개발됨으로써 처음으로

사용 가능하게 되었다. 이 컴포넌트는 웹 애플리케이션이 전체 페이지를 재로딩하지

않고 웹서버와 통신하고 서버의 응답결과를 스크립트 형태로 수신할 수 있게 해주었다.

이렇게 백그라운드로 데이터를 요청하는 방식을 일반적으로 비동기(asynchrosous)라고 부

르며 Ajax라는 용어의 첫 글자인 ‘A’는 여기서 유래한 것이다. 브라우저들은 오랫동안

Document Object Model(DOM)과 CSS를 프로그램상에서 사용하여 사용자 인터페이스

를 조작할 수 있었지만 서버에서 새로운 어떤 데이터도 가져올 방법이 없었다. 즉 전체

페이지를 재로딩하는 일은 아주 흔하게 일어났다. 이러한 조합 1 에 XMLHttpRequest

를 추가함으로써 전체 애플리케이션의 업무흐름이 단일 웹 페이지 내에 캡슐화될 수

있도록 해주었고 사용자의 작업을 방해하지 않으면서 비동기 방식으로 요청된 데이터

에 대한 응답을 가지고 간단하게 페이지를 재구성할 수 있게 되었다.

기술적으로 Ajax는 가지고 놀기에 아주 훌륭하고 새로운 장난감과 같은 것이다. 사

용성의 관점에서 보면, 브라우저가 서버에 요청을 보내고 서버의 응답을 기다리는 동

안 사용자로 하여금 계속 업무를 처리할 수 있도록 해줌으로써 중요한 전기를 마련하

였다. Ajax가 없다면 웹 애플리케이션은 새로운 페이지를 요청하는 동안 빈번하게 비

활성화되는 특징을 갖게 될 것이며 이러한 중지-시작 2 의 패턴은 어떤 중요한 애플리

1  Document Object Model과 CSS를 말한다.

2  HTTP의 특성상 요청을 보내고 응답을 받기 전까지는 브라우저가 대기하게 되는 현상을 말한다.

Page 40: Prototype & Scriptaculous 인 액션

6

시작하기1부

케이션에 있어서라도 적합하지 않다. 그럼에도 불구하고 웹 애플리케이션은 사용자의

PC에 설치될 필요가 없고 또한 즉각적으로 업그레이드가 가능했기 때문에 기술 지원

부서의 사랑을 받아왔다. 이러한 두 가지 상충되는 요소들 사이에서의 문제는 Ajax에

의해 해결되었는데, 다양한 분야에서 Ajax 기반의 웹 애플리케이션들을 데스크탑 애플

리케이션과 무거운 클라이언트 프로그램에 대한 대안으로 받아들인 결과였다.

XMLHttpRequest는 2000년에 인터넷 익스플로러 5에서 사용 가능하게 되었다. 그러

나 그 당시에는 Ajax를 수용하는 현상은 발생하지 않았다. 마이크로소프트사의 익스

체인지 웹 메일을 보았던 사람은 누구나 그것이 아주 깔끔하다고 생각을 했지만 대부

분의 사람들은 그것을 흉내 내려 들지 않았다. 아마도 그것이 ActiveX에 의존적이었기

때문에 결국 마이크로소프트 사의 운영체제에 국한될 것이고 그것이 큰 단점으로 인식

되었기 때문일 것이다. 아마도 서버로의 항시적인 연결이 필요한 애플리케이션 제공을

고려할 만큼 광대역 통신의 시장보급이 충분하지 않았기 때문일 수도 있다. 또 그것이

너무 복잡하고 어렵게 보였기 때문일 수도 있다. 어떤 이유였든 간에 이러한 기능은 많

은 사람들에 의해 사용되지 않았고 몇 년이 더 지나서야 기술분야의 폭넓은 관심이 생

기고 중지-시작과 같은 업무흐름에 대한 장벽이 마침내 사라지게 되었다.

1.1.2 개척자의 단계

Ajax가 등장하기 전인 이 단계에는 에릭 코스텔로Eric Costello, 에릭 해처Erik Hatcher, 그리

고 짐 레이Jim Ley(더 꼽으려 해도 이들 셋뿐이다)와 같은 몇몇 인내심 강한 사람들이 비

동기 방식으로 서버와 통신하는 것에 대한 가능성을 연구했고 비동기 통신을 위해 때

로는 XMLHttpRequest를 이용하거나 IFrame과 같은 브라우저의 기능들을 이용하는

기술들에 대한 내용을 발표하기도 했다. 이렇게 공개적으로 드러난 가시적인 노력들뿐

아니라 몇몇 회사나 우리 자신들을 포함한 개인 개발자들 또한 기술들을 발견해내고

내부적으로 사용하였다.

또 다른 그룹의 개척자들에 대해서 언급하지 않을 수 없다. 이들은 자바스크립트 언

어를 연구하고 자바스크립트가 실행되는 브라우저의 환경을 연구한 사람들이다. 더그

크록포드Doug Crockford는 일반적으로 자바스크립트가 스크립트 언어를 좋아하는 사람

들만의 장난감이라고 여겨지던 때에 자바스크립트 기술에 객체지향 개념을 도입하는

선구적인 일을 해냈다. 피어스-폴 콕스Piers-Paul Koch는 브라우저들 간의 호환성에 대한

복잡한 문제를 연구하였고 댄 스타인버그Dan Steinberg와 마이크 포스터Mike Foster는 브라

Page 41: Prototype & Scriptaculous 인 액션

7

Prototype과 Scriptaculous 소개 1장

우저들 간의 호환성을 보장하면서 DOM을 조작할 수 있도록 해주는 프레임워크를 개

발하였는데 이들 중 일부는 XMLHttpRequest의 첫 출현시기보다도 시대적으로 빠른

것이다. 자바스크립트는 Ajax 애플리케이션을 함께 묶어주는 역할을 하고 이들 네 사

람의 업적은 현재의 Ajax 기반 웹 개발방식에 많은 영향을 미쳤다.

Ajax가 일반에게 널리 알려졌을 때, 이미 크록포드, 콕스 그리고 많은 다른 이들이 개

발한 알려지지 않은 결과물들이 있었다. 그러나 2005년에는 이 주제에 대한 인지가 희

박했기 때문에 이러한 노력들 사이의 커뮤니케이션이 제한되어 있었고 초기의 Ajax 관

련 시장은 대부분 개인들이 직접 만든 임시방편적인 솔루션이나 프레임워크로 이루어

지게 되었다. 하지만 크고 견고한 자바스크립트 애플리케이션을 개발한다는 주제에 보

다 많은 사람들이 관심을 갖게 되면서 이 분야에 대한 노력들이 증가하게 되었다.

1.1.3 이주자들의 도착

2005년에는 폭발적인 숫자의 Ajax, 자바스크립트 프레임워크, 헬퍼 라이브러리 그리고

Ajax 애플리케이션의 개발을 보조하도록 설계된 프로젝트들을 보게 되었다. 『Ajax 인

액션』에는 40개가 넘는 프레임워크의 리스트가 포함되어 있고 그 중 몇은 사라졌다. 개

척자들의 뒤로 이주자의 물결이 따랐고 자신들의 영역을 지키고 바쁘게 작은 부락들을

이루기 시작했다. 불가피하게 이들 부락 중 일부는 쇠퇴하고 일부는 좀 더 큰 도시로

성장하였다. 다음해나 그 다음 1년이나 2년 정도 지나면, 베스트 프렉티스와 다른 사람

들의 실수로부터 학습된 결과들이 프레임워크와 유틸리티로 결실을 맺음에 따라 프레

임워크를 사용하지 않고 개발된 Ajax 애플리케이션이 감소하는 것을 볼 수 있을 것으

로 기대된다.

Prototype과 Scriptaculous는 이들 자바스크립트 프레임워크 중에서 가장 성공한 프

레임워크들이고 이들은 단기간에 커뮤니티로 성장했다. 사실 Ajaxian.com에서 실시한

2006년도 프레임워크와 라이브러리 부문 표본조사에서 Prototype과 Scriptaculous는 각

각 43퍼센트와 33퍼센트의 시장을 장악하고 있다. 이들 프레임워크의 설계는 대부분

Ajax의 개발을 보다 빠르고 쉽게 할 수 있도록 하는 것에 초점이 맞춰줘 있다. 이러한 프

레임워크들이 Ajax 개발의 본질에 미치는 영향은 무시 못할 수준이다.

Page 42: Prototype & Scriptaculous 인 액션

8

시작하기1부

1.1.4 문명화

위에서 얘기한 내용들이 Ajax 개발의 역사를 현재까지 이끌고 온 것이다. 우리가 ‘문명

화’ 단계라고 생각할 수 있는 단계는 아직은 도래하지 않았다. 여전히 Ajax를 사용하여

업무를 처리할 수 있는 많은 방법들이 존재하고 있고 이러한 방법들 중 일부만이 서로

호환된다. 이 책에서 여러분은 한 가지 특별한 방법에 대해서 상세하게 배우게 될 것이

지만 또한 Prototype과 Scriptaculous가 다른 대중적인 프레임워크들과 연동될 수 있

는지도 살펴볼 것이다.

자, 그럼 더 이상 야단법석 떨지 말고 Prototype과 Scriptaculous가 어떤 일들을 해낼

수 있는지 함께 알아보도록 하자.

1.2 Prototype이란?

두 라이브러리 중에 Prototype이 보다 근간이 되기 때문에 우리는 Prototype에 대해

서 먼저 알아본다. Prototype은 자바스크립트, 브라우저 환경 그리고 XMLHttpRequest

객체에 대한 언어적인 차원의 확장성을 제공한다. Scriptaculous(그리고 Rico와 같은

다른 라이브러리)는 위젯과 사용자들이 사용할 수 있는 컴포넌트들을 생성하기 위해

Prototype을 기반으로 작성되었다.

자바스크립트가 그것이 쓰여진 언어를 확장한다고 말하는 것이 좀 이상하게 보

일지도 모르겠지만 그것이 정확하게 Prototype이 하는 일이다. 자바스크립트는

prototype 3 기반 상속(여기에서 이 라이브러리의 이름을 따왔다)이라 알려진 메커니

즘을 제공한다. 사실 몇몇 스크립팅 언어들도 기본 객체를 확장할 수 있는 특성들을 제

공한다. 루비가 그렇고 Prototype에 의해 제공되는 많은 확장들이 루비에서 빌려온 것

들이다. 한때 Prototype의 목표가 자바스크립트를 보다 루비처럼 보이도록 하는 것이

었다, 라고 할 수도 있다.

우리들 대부분에게 솔깃할 만한 좋은 소식은 Prototype을 사용하는 데 따른 혜택을

얻기 위해서 라이브러리의 내부에서 벌어지는 모든 것을 이해할 필요는 없다는 것이다.

이 책의 3부에서 Prototype의 내부적인 내용을 살펴보겠지만 만약 여러분이 확장모듈

3  prototype 속성을 의미한다.

Page 43: Prototype & Scriptaculous 인 액션

9

Prototype과 Scriptaculous 소개 1장

을 만드는 것을 고민할 필요 없이 단지 자신만의 작업을 처리하고 싶다면 1부와 2부를

읽어보는 것으로 충분할 것이다.

하지만 지금은 Prototype이 제공하는 특성들의 범위와 Prototype이 해결하도록 설계

된 이슈들을 보다 명확하게 이해하도록 하기 위해 Prototype이 제공하는 특징들에 대

해서 알아볼 것이다.

1.2.1 자바스크립트 언어의 특징

자바스크립트는 범용적인 용도로 설계된 프로그래밍 언어이다. Ajax 개발자로서 여러

분은 보통 웹 브라우저 내에서 Prototype을 사용하게 될 것이다. 그러나 객체, 특징, 배

열, 문자열 그리고 숫자와 같은 부분들은 자바스크립트 언어 자체를 강화할 수 있도록

설계되었다.

자바스크립트 객체 클래스

자바스크립트 프로그래밍의 가장 중심에는 기반 클래스인 Object 클래스가 있다. 자바

스크립트에서 Object는 문자 두 개 정도로 생성된다.

varmyObject={};

myObject는 prototype 속성에 기반한 상속 메커니즘, 그리고 실행 중에 새로운 프로퍼

티와 메소드들을 받을 수 있는 몇 가지 유용한 특징들과 toString()과 같은 메소드들

을 부여받게 된다. 자바스크립트의 Object에 대한 보다 자세한 내용은 8장에서 보게 될

것이다.

Object의 prototype 프로퍼티를 사용하면 자바나 C# 프로그래머들이 익숙한 형태

와 유사하게 객체의 형에 따른 적절한 객체지향 계층구조를 생성하는 것이 가능해진

다. 즉 객체지향적인 계층구조를 가지는 것이 가능하다는 것이다. 하지만 다소 귀찮다.

Prototype은 객체의 형에 따라 계층구조를 개발하는 것이 보다 쉽고 자연스럽게 이루

어지도록 Object에 유용한 특징들을 추가해 놓았다. Prototype과 Scriptaculous에 대한

이러한 기능들을 비중 있게 다루고 있는 다른 부들을 살펴보면 이 기능들이 실제로 어

떻게 동작하는지 알게 될 것이다.

Page 44: Prototype & Scriptaculous 인 액션

�0

시작하기1부

자바스크립트의 함수

자바스크립트의 Function 객체는 호출 시에 파라미터를 넘겨줄 수 있는 코드들을 의미

한다. 이러한 점에서 Function은 객체지향 프로그래머들이 객체 내에 정의하게 되는

메소드들과 아주 유사하다.

자바스크립트의 함수는 자바나 C#의 메소드와는 다르게 자바스크립트 언어에 있어

최상위 객체(first-class citizen) 4 에 해당된다. 자바스크립트의 함수는 직접 참조될 수도 있

고 다른 함수에 파라미터로 넘겨질 수도 있고 심지어 임의의 객체에 프로퍼티로 설정

될 수도 있다. 이러한 자유로움 덕분에 자바스크립트 프로그래머들은 많은 종류의 희

한하고 교묘한 기법들을 사용할 수 있게 된다. 자바스크립트의 Function 객체를 이해

하는 것은 브라우저의 이벤트 모델이 이 객체들에 의존하고 있기 때문에 어느 정도 경

험이 있는 사람들에게 있어 아주 중요하다. Prototype은 이벤트 모델이 일반적으로 요

구하는 형태로 Function 객체를 자바스크립트의 객체에 쉽게 연결해줌으로 우리에게

도움이 된다. 함수에 대해서는 9장에서 자세히 알아볼 것이다.

자바스크립트의 배열

자바스크립트에서 배열은 확장이 가능하고, 숫자로 순서가 부여된 변수의 리스트이며

다음과 같이 사각형 괄호 표기를 사용하여 배열의 멤버에 접근할 수 있도록 지원하고

있다.

varelement=myArray[3];

배열의 멤버에 반복적으로 접근하기 위해서는 다음과 같이 일반적으로 for() 루프를

수행한다.

for(vari=0;i<myArray.length;i++){

alert(myArray[i]);

}

프로그래밍 언어인 루비는 배열을 다루는 데 있어 Enumeration 타입에 기반한 보다

풍부한 방법을 제공한다. Prototype은 이런 개념을 자바스크립트로 차용해와서 루비

의 Enumeration과 배열의 상관개념을 도입하여 자바스크립트의 고유한 배열의 기

4  http://en.wikipedia.org/wiki/First-class_object 참조

Page 45: Prototype & Scriptaculous 인 액션

��

Prototype과 Scriptaculous 소개 1장

능을 향상시켰다. 여러분이 루비의 Enumeration 타입을 다루어 보았다면 Prototype

은 집에 온 것 같은 편안함을 줄 것이다. 그리고 만약 여러분이 루비를 모른다고 해도

Prototype의 배열을 확장하는 개념은 익히기가 매우 쉬워서 곧 여러분이 자주 사용하

는 막강한 기능이 될 것이다. 10장에서는 이것에 대한 자세한 내용을 다룬다.

자바스크립트의 문자열과 숫자

자바스크립트의 String과 Number 클래스들은 언어에서 제공하는 기본형에 직접 메소

드를 추가하는 것을 허용한다. 문자열에 추가된 Function들은 문자열 상태에서 직접

호출할 수 있다.

“abcdefghijklm”.substring(4,10)

예를 들어 위의 라인은 문자열 “efghij” 값이 구해진다. 숫자를 다루는 경우에는 숫자들

을 먼저 변수에 할당해야만 한다.

varx=123456789;x.toExponential()

이것의 결과는 문자열 “1.23456789e+8”이다.

자바스크립트에서 기본형에 대한 표준 메소드들은 대부분 HTML 컨텐트를 생성하는

것을 도와주는 메소드이거나 포맷팅하는 데 관련이 있다. Prototype은 HTML의 색상

을 다루기 쉽게 하고, 국제화된 문자열을 지원하고 다른 유용한 특징들을 제공하는 몇

가지 유용한 유틸리티를 가지도록 String과 Number 클래스를 확장한다.

이상으로 자바스크립트 언어의 핵심부분에 영향을 미치는 Prototype의 특징들에 대

한 내용을 매듭짓기로 한다. 이제부터 Prototype이 웹 브라우저 내에서 정확히 무엇을

할 수 있는지 알아보자.

1.2.2 웹 브라우저의 특징들

웹 브라우저 내에서 자바스크립트 코드를 사용하기 위해서는 다른 어떤 개발환경의 경

우보다 더 많은 양의 코드를 작성해야 한다. 이런 환경에서 코딩을 할 때는 웹 브라우

저의 다양한 부분이 자바스크립트 인터프리터에 노출되며 Prototype은 웹 코더를 많은

방법으로 지원한다. 여기서 브라우저를 영역에 따라 구분할 것이며 이러한 주제들은

11장에서 상세하게 다루게 될 것이다.

Page 46: Prototype & Scriptaculous 인 액션

�2

시작하기1부

Document Object Model

DOM이라고 줄여서 부르는 Document Object Model은 웹 페이지를 구성하는 시각적

인 엘리먼트들이 자바스크립트 인터프리터에 노출되는 메커니즘을 의미한다. 우리가

마우스의 클릭이나 키보드가 눌려짐에 대한 응답으로 화면에 표시된 엘리먼트들을 숨

기거나 보이게 할 때, DHTML로 네비게이션 메뉴를 빌드할 때 또는 브라우저 기반의

애니메이션을 생성할 때 우리는 DOM을 사용한다. DOM을 제어하는 프로그래밍은 브

라우저 간 호환성 문제에 대한 회피나 편법에 있어서 주요한 과제였다. 그러나 최근

에 주요 브라우저 벤더들이 W3C 표준을 따르기로 하였고 브라우저 간 호환성에 대한

DOM 프로그래밍은 더 이상 이전과 같은 골칫거리가 되지 않는다. 그러나 W3C 모델

은 다소 장황하고 다루기 힘들며 W3C 모델에 반하는 방법으로 코딩을 하는 것은 체력

을 낭비하는 일이 될 수 있다.

Prototype은 DOM 프로그래밍의 이러한 어려움을 완화시켜주는 메소드를 제공하며

이러한 메소드들에 대해서는 11장에서 알아볼 것이다. 지금은 계속해서 Prototype의

특징에 대해 간략하게 알아보자.

HTML 폼

HTML 폼은 웹 애플리케이션 개발에 있어 가장 중요한 것이고 Ajax가 등장하기 이전에

는 사용자로부터 정보를 입력받을 수 있는 유일한 방법을 제공하였다. Ajax와 함께 드

래그 앤 드롭과 같은 다른 형태의 입력 메커니즘이 브라우저와 서버 간의 대화의 한 부

분으로 사용되고 있지만 여전히 폼은 매우 중요한 역할을 수행하고 있다. Prototype은

HTML 폼을 다루는 유틸리티 세트를 제공하며 이것들에 대해 11장에서 알아본다.

자바스크립트의 이벤트

이벤트 핸들링은 Ajax로 사용자 인터페이스를 구성하는 데 있어 중요하다. 비록 주요

브라우저들이 DOM을 조작하는 API를 표준화해왔지만 인터넷 익스플로러와 모질라

브라우저의 이벤트 모델은 호출구조와 상세 구현에 있어서 여전히 상당부분 다르다.

Prototype은 이벤트 코딩에 있어서 브라우저 간 호환성을 훌륭하게 지원하며 이미 앞

에서 언급한 것과 같이 Function 객체를 확장하여 이벤트 핸들링을 쉽게 처리할 수 있

도록 지원한다.

Page 47: Prototype & Scriptaculous 인 액션

�3

Prototype과 Scriptaculous 소개 1장

Ajax 유틸리티

Prototype의 기능들 중 마지막은 Ajax에 대한 지원이다. 모든 주요 브라우저들은

Ajax가 가능하도록 ActiveX 컴포넌트나 고유한 자바스크립트 객체 중 하나의 형태로

XMLHttpRequest 객체를 지원한다. 그러나 XMLHttpRequest는 HTTP 프로토콜을 아

주 저수준으로 노출하고 있기 때문에 개발자들에게 강력한 기능을 제공해 주지만 또한

간단한 일을 처리하기 위해서도 많은 양의 코드를 작성해야만 한다.

Prototype은 일반적인 기반 클래스와 단 한 줄의 코딩만으로 대부분의 일반적인 형

태의 Ajax 요청을 구현할 수 있도록 하는 것에 초점이 맞추어진 헬퍼들로 구성되는

Ajax 헬퍼 객체들의 계층구조를 제공하기 위해 자체적인 객체 상속 시스템을 사용한다.

Ajax를 이렇게 쉽게 구현할 수 있도록 도와줌으로써 Prototype은 웹 개발자들에게 보

다 나은 가치를 부여한다.

1.3 Scriptaculous란?

Prototype은 복잡하고 잘 구조화된 코드를 개발하는 데 극도로 견고한 기반을 제공하

지만 Prototype 자체만으로는 그 이상의 일을 해내기는 어렵다. 최종 사용자가 보게 되

는 기능을 개발하는 책임은 여전히 개발자에게 있다.

Scriptaculous는 개발자가 세련되고 상호적인(interactive) 사용자 인터페이스를 생성할

때 바로 적용할 수 있는 많은 고수준의 기능을 제공하기 위해 Prototype을 이용하는 라

이브러리이다. Prototype 자체만으로도 Ajax 개발에서 나타나는 많은 어려움들을 쉽게

풀 수 있지만 Scriptaculous와 함께 사용되면 간단히 몇 라인만의 코드로 애니메이션이

나 드래그 앤 드롭과 같은 효과들을 생성할 수 있기 때문에, 웹의 사용자 인터페이스에

접근하는 방법을 변화시킨다.

Prototype과 마찬가지로 Scriptaculous 역시 몇몇 독특한 분야를 다루고 있다. 그럼

간략하게 각각을 차례로 살펴보자.

1.3.1 시각적인 효과

어떤 컴퓨터 애플리케이션을 작성할 때 시각적인 피드백을 제공하기 위해서 특정 부분

의 인터페이스에 사용자가 관심을 갖도록 유도하는 것이 일반적이다. 버튼은 마우스

Page 48: Prototype & Scriptaculous 인 액션

��

시작하기1부

가 위치했을 때 자신이 클릭이 가능한 상태라는 것을 보여주길 원할지도 모른다. 리스

트 아이템은 새로운 아이템이 추가되거나 오래된 아이템이 제거되었을 때-특히 그것

이 백그라운드 프로세스에 의한 결과라면-사용자에게 통지하고 싶을지도 모른다. 이

런 형태의 기능을 남용하면 사용자의 주의를 흩트리거나 방해하는 사용자 인터페이스

가 되기 쉽다. 그러나 이러한 효과들은 적절하게 사용되면 애플리케이션을 보다 사용

하기 쾌적하게 만들어 준다. 사용자가 몇 번의 키를 누르는 것만으로 다른 곳으로 이

동할 수 있는 웹 애플리케이션의 세상에서 애플리케이션을 사용하기 쉽게 만드는 것은

필수적이다.

Scriptaculous는 Effect 라이브러리를 통해 이러한 유형의 비주얼한 피드백을 쉽게

생성할 수 있도록 해준다. 이 라이브러리는 사용 가능한 효과들의 품질과 종류에서 뛰

어날 뿐만 아니라 코드의 설계 면에서도 품질이 높아서 다수의 효과를 조합할 수 있고,

효과가 시작되기 전과 중간 그리고 끝난 후에 임의의 코드를 실행하거나, 효과들을 다

른 효과들과 동기화 하는 것이 아주 쉽다. 더 이상 언급할 필요는 없겠지만 이러한 좋

은 설계는 Prototype이 제공하는 언어적인 특징에 의해 가능해진 것이다.

코더가 직접 효과들을 사용할 수 있을 뿐 아니라, Effect 패키지는 Scriptaculous 내

에서 다른 주요 패키지에 시각적인 피드백을 추가하기 위해 사용된다. 이제 주요 패키

지에 대해 살펴보도록 하자.

1.3.2 드래그 앤 드롭

Ajax 이전에는, 하이퍼링크를 클릭하거나 HTML 폼을 전송(submit)하는 것만이 서버 측

으로 요청을 보낼 수 있는 방법이었지만 이러한 요청을 이제 프로그램에 의한 방법으

로 전송할 수 있으므로 다른 형태의 사용자 상호작용(interaction)을 사용하여 요청이 서

버로 전송되도록 할 수도 있다. 따라서 보다 폭넓은 사용자 상호작용 기술이 웹 애플리

케이션에서 자리를 잡아가고 있다.

드래그 앤 드롭은 데스크탑 애플리케이션에서는 일반적인 사용자 인터페이스이며

많은 경우에 있어 컴퓨터를 사용하는 데 가장 편리하고 직관적인 방법을 제공한다.

DOM은 직접적으로 드래그 앤 드롭 이벤트를 지원하지 않고 있으며 자바스크립트로

드래그 앤 드롭을 구현하는 것은 마우스 클릭과 이동 이벤트만을 가지고 구현해야 한

다는 것을 의미한다.

Page 49: Prototype & Scriptaculous 인 액션

��

Prototype과 Scriptaculous 소개 1장

좋은 소식은 Scriptaculous가 상대적으로 적은 양의 코딩만으로 대부분의 DOM 엘리

먼트 유형에 적용이 가능한 드래그 앤 드롭 시스템을 구현해 놓았다는 것이다. 룩 앤 필

은 Effect 라이브러리를 사용하여 커스터마이징이 가능하고 사용자지정 이벤트 핸들러

를 콜백함수로 추가하여 드래그 앤 드롭 이벤트의 모든 단계에서 콜백을 받을 수도 있다.

1.3.3 컴포넌트

우리가 지금까지 논의한 특징들은 코더가 애플리케이션을 향상시키는 데 사용할 수 있

는 프레임워크이다. Scriptaculous는 또한 Component 라이브러리 내에 다수의 완전

한 위젯을 제공한다. 이 책이 집필되는 시점에는 Component 라이브러리에 두 개의 컴

포넌트가 포함되어 있는데, AutoCompleter는 어떤 텍스트 필드에라도 예측 가능한 드

롭-다운 엘리먼트를 추가할 수 있어서 일반적인 HTML 폼 엘러먼트에 구글의 Suggest

와 같은 기능을 줄 수 있다. 또 InPlaceEditor는 어떤 DOM 엘리먼트라도 해당 엘리먼

트를 텍스트 입력 필드로 변경했다가 다시 원상복구 되도록 할 수 있다.

이런 고수준의 컴포넌트들 외에도 Scriptaculous는 다수의 헬퍼와 유틸리티들을 제

공한다. 이러한 헬퍼와 유틸리티들을 훑어보는 것으로 Scriptaculous 라이브러리에 대

한 1차 리뷰를 결론짓도록 한다.

1.3.4 유틸리티와 테스팅 프레임워크

Scriptaculous는 핵심 자바스크립트 객체들과 DOM 객체들에게 주로 사용자 인터페이

스에 대한 쉬운 조작에 관계된 확장기능을 제공한다. 이러한 기능들은 Prototype에 의

해 정의된 확장기능의 기반 위에 작성되었다.

추가적으로 Scriptaculous는 브라우저 내에서 실행 가능한 완전한 유닛테스팅

프레임워크를 제공한다. 이것은 원래 전체 라이브러리를 잘 테스트할 수 있도록

Scriptaculous 개발팀이 내부적으로 사용할 목적으로 설계된 것이지만 독립형 테스팅

라이브러리로 사용도 가능하다.

이것으로 Prototype과 Scriptaculous 라이브러리에 대한 기초적인 리뷰를 마치도록

하겠다. 각각의 이어지는 장에서 세세한 특징들에 대해서 살펴보기 전에 Prototype과

Scriptaculous가 일반적인 Ajax 애플리케이션의 개발을 돕기 위해 어떤 것을 할 수 있

는지 간단한 데모를 보도록 하자.

Page 50: Prototype & Scriptaculous 인 액션

�6

시작하기1부

1.4 Prototype과 Scriptaculous의 적용

Ajax 애플리케이션을 라이브러리의 도움 없이 작성하는 것은 자바스크립트의 언어적

특성에 대한 깊이 있는 지식을 요구하는데, 이런 자바스크립트의 언어적 특성들 대부

분은 자바, PHP, 그리고 C#과 같은 언어에 친숙하고 주로 서버 측 웹 코딩을 하던 사

람들이 Ajax를 접하는 경우 많은 부분이 생소하다. 더 나쁜 것은 브라우저 간의 미묘한

비호환성에 대해서 완전히 파악해야 한다는 점이다. Prototype과 Scriptaculous는 브

라우저 간 호환성 문제와 자바스크립트의 언어적 특성에 관련된 문제에 대한 기능을

내장하고 있다. 이러한 기능들이 많은 문제를 해결할 수 있도록 도와준다.

이번 절에서는 사용자가 기사(또는 노래, 음악, 그밖에 어떤 것이든)에 대해서 평점

을 줄 수 있는 간단한 Ajax 애플리케이션을 볼 것이다. 여러분에게 라이브러리를 사용

하지 않고 어떻게 애플리케이션을 작성하는지 보여주고, 그러고 나서 그 애플리케이션

내에 복잡하게 꼬여있는 자바스크립트를 단순화시키고 빠르게 원하는 기능을 추가할

수 있도록 Prototype과 Scriptaculous를 사용하여 리팩토링 해보도록 하겠다.

1.4.1 평점 예제 소개

평점 예제는 Ajax와 DHTML 기술을 사용하는 간단한 위젯으로, 사용자가 아이템에 할

당한 평점을 인터렉티브하게 보여주기 위해 쉽게 웹 페이지에 삽입이 가능하다. 그림

1.1은 위젯이 화면에서 어떤 형태로 나타나는지 보여주고 있다.

그림 1.1 웹 페이지에 삽입된 평점 위젯. 작은 화살표 아이콘을 사용하여 아이템(이 경우에는 기

사)에 할당된 별의 개수를 사용자가 증가시키거나 감소시킬 수 있다(아이콘은 David

Vignoni, http://www.icon-king.com 이 만든 “Nuvola” 아이콘 세트를 차용했다).

Page 51: Prototype & Scriptaculous 인 액션

�7

Prototype과 Scriptaculous 소개 1장

위젯의 동작은 아주 간단하다. 사용자는 마우스로 파란색 화살표 버튼을 클릭해서 평

점을 높이거나 낮출 수 있고 이에 따라 별의 개수가 0부터 5개 범위 내에서 증가하거나

감소된다. 사용자가 평점을 변경할 때 위젯은 서버 측으로 비동기 방식으로 호출을 전

송하여 저장된 평점 정보를 변경한다. 서버가 저장된 정보를 가지고 무슨 일을 하는지,

서버의 응답이 어떤 형태인지에 대해서 지금 당장 염려하지 않아도 된다.

간략하게 평점 위젯에 대해서 설명하였다. 코더로서 우리는 내부가 어떻게 구성되고

구현되는지를 보는 것에 더 흥미가 있다. 자 코드의 몇몇 주요부분을 살펴보자. 애플리케

이션에 대한 전체 코드는 http://www.manning.com/crane3 에서 다운로드 할 수 있다.

컴포넌트 사용하기

우리는 애플리케이션 작성에 있어 베스트 프랙티스를 따르려고 애써왔고 디자이너들

이 그들 스스로 많은 양의 자바스크립트나 복잡한 HTML 템플릿을 준비하지 않고도 간

단하게 애플리케이션을 사용할 수 있도록 노력해왔다. 그 결과로 평점 애플리케이션은

모든 사용자 인터페이스를 프로그램으로 생성하고 디자이너는 단지 평점 애플리케이

션이 위치하게 될 빈 HTML을 명시해주기만 하면 된다. 두말할 필요도 없이 우리는 코

드를 포함하는 .js 파일, CSS 스타일시트, 그리고 이미지들로 다양한 리소스들을 깔끔

하게 분리해냈다.

그러고 나서 위젯을 페이지와 통합시키기 위해서 디자이너는 페이지의 헤더 부분에

몇 줄의 코드를 추가할 필요가 있다.

<linkrel=stylesheet

type=”text/css”href=”css/ratings.css”>CSS 스타일시트 임포트

<scripttype=’text/javascript’

src=’scripts/ratings.js’></script>자바스크립트 라이브러리 임포트

<scripttype=’text/javascript’>

window.onload=function(){

newRating( Rating 객체 생성

“myRating”,”ratethisarticle”

);

}

</script>

Rating 객체는 우리가 곧 보게 될 자바스크립트 라이브러리 내에 정의되어 있다. 객체

의 생성자는 두 개의 파라미터를 받는다: 자신이 렌더링될 대상인 HTML 엘리먼트의

Page 52: Prototype & Scriptaculous 인 액션

�8

시작하기1부

ID와 이때 표시될 이름이다. 우리는 대상 엘리먼트의 이름을 myRating이라고 명시했

기 때문에 HTML에 다음과 같이 정의할 것이다.

<divid=’myRating’>

이상이 우리의 디자인팀이 위젯을 사용하기 위해 해야 하는 일들이다. 그럼 위젯이 동

작할 때 어떤 일들이 뒷단에서 벌어지는지 알아보자.

사용자 인터페이스의 초기화

Rating 객체의 생성자 함수는 메인 파라미터들을 받아서 프로퍼티로 셋팅한 후 두 번

째 함수인 updateUI()에게 위임을 하는 정도로 상대적으로 아주 간단하다. 예제 1.1

은 이들 함수의 코드를 보여준다.

예 제 1.1 | Rating 객체의 사용자 인터페이스

functionRating(divId,data){

b 생성자 정의this.body=document.getElementById(divId);this.title=data;this.rating=1;this.updateUI();}

Rating.prototype={updateUI:function(delta){if(!delta){delta=0;}if(delta>0){this.rating++;}elseif(delta<0){this.rating--;}varinner="<tableborder='0'><tr><tdwidth='42'>"+"<spanclass='title'>"+this.title+"</span></td>"+"<td>";for(vari=0;i<this.rating;i++){inner+="<imgsrc='images/star.png'/>"}inner+="</td></tr><td>"+"<imgsrc='images/up.png'id='plus_"+this.title+"'/>"+"<imgsrc='images/down.png'id='minus_"+this.title+"'/>"+"</td><td>"+"<divid='message_"+this.name+"'class='message'></div>"

Page 53: Prototype & Scriptaculous 인 액션

�9

Prototype과 Scriptaculous 소개 1장

+"</td></tr></table>";this.body.innerHTML=inner; c 타겟에 HTML 할당

varrating=this; d 클로저를 위한 레퍼런스 생성

this.plusButton=document.getElementById("plus_"+this.title);this.minusButton=document.getElementById("minus_"+this.title);

e 버튼 위젯 레퍼런스

this.body.onclick=function(event){ f 이벤트 핸들러 할당

vare=(event)?event:window.event;vartarget=(e.target)?e.target:e.srcElement;if(target.id==rating.plusButton.id&&rating.rating<5){rating.updateUI(1);}elseif(target.id==rating.minusButton.id&&rating.rating>0){rating.updateUI(-1);}}this.tellServer();

g 서버에 정보 전송

},

상당히 많은 일들이 벌어지고 있다. 하나하나 훑어보도록 하자. updateUI() 메소드는

선택적인 파라미터인 delta를 받으며, 초기에 생성자에서 updateUI()를 호출할 때는

이 파라미터를 무시할 것이다❶. 그 후에는 그림 1.1에서 HTML 테이블로 보았던 UI를

정의하는 일련의 HTML 마크업을 문자열로 생성하는 과정을 수행한다. 이 문자열은 그

후에 innerHTML 프로퍼티를 사용하여 대상 엘리먼트에 할당된다❷.

계속해서 버튼들에 이벤트 핸들러를 할당한다. 그 다음 라인은 상당히 이상해 보이

는데this에 대한 직접적인 레퍼런스인 rating이라는 변수를 선언한다❸. 이 이유는

다소 난해하다. 우리가 이벤트 핸들러를 정의할 때 클로저를 생성할 것인데 특별한 변

수인 this는 클로저에 파라미터로 넘겨질 수 없다. 그래서 클로저에 파라미터로 넘겨

주기 위해서 복사본으로 rating을 생성하는 것이다.

그 다음의 몇 라인은 아주 쉽다. 우리는 우리가 방금 작성한 긴 innerHTML 문자열

내에서 유일한 ID들을 버튼들에 추가하였으므로 이제 프로그램으로 버튼 엘리먼트들

을 참조할 수 있게 되었다❹.

Page 54: Prototype & Scriptaculous 인 액션

20

시작하기1부

이벤트 핸들러 추가

계속해서 전체 위젯을 위한 이벤트 핸들러를 정의한다(예제 1.1의 ❺). 이것은 이름이

명시되지 않는 익명 함수이며 인라인으로 정의된다. 이벤트 모델이 작동하는 방식 때

문에 함수가 호출될 때 변수 this는 더 이상 Rating 객체를 참조할 수 없게 되고 해당

이벤트를 발생시킨 HTML 엘리먼트를 참조하게 된다. 우리는 이벤트 핸들링 코드 내의

Rating 객체를 보기 위해 클로저의 일부로 함수에 바인딩되어 있는 rating을 참조한다.

흔히 이벤트 핸들러 내에서 this를 참조하는 실수를 하게 되는데 이러한 코드 내에

존재하는 모든 rating 변수와 this 참조들을 바로 잡는 데는 오랜 시간이 소요되지만

우리는 이 문제를 해결했다. 버튼들이 눌러지면 updateUI()를 다시 호출하여 전체 UI

를 다시 그린다. 이번에는 delta 파라미터가 평점이 증가되는지 감소되는지를 의미하

는 구분자로 동작한다.

최종적으로 서버 측에 해당 아이템의 평점이 변경되었다고 알려준다❻. 이 작업을

수행하기 위해서 핵심 Ajax 기술을 사용하므로 잠시만 이 기술들에 대해서 알아보도록

하자. 먼저 두 개의 버튼들을 동작하게 만들기 위해 수행한 일을 알아보자. 임의적인

컨텍스트(즉, 함수 내에서 this 참조자로 사용될 수 있는 변수)로 Function 객체를 호

출하는 기능, 그리고 암시적으로 클로저를 생성하는 Function 객체의 기능과 같은 자

바스트립트의 몇몇 별난 언어적인 특징을 살펴보았다. 이 두 가지 기능은 모두 언어에

대한 상당히 깊은 수준의 이해도를 요구한다. 우리가 별난 프로그래밍 언어를 수집하

기를 좋아한다면 다행이지만 우리가 자바나 PHP 코더이고, 부차적으로 약간의 Ajax

업무를 하고 있다면 언어 자체를 이해하는 것은 상당한 무리가 따른다.

우리는 곧 어떻게 Prototype과 Scriptaculous가 자바스크립트를 복잡하지 않게 유지

하는 데 도움을 주는지 보게 될 것이다. 먼저 Ajax 코드를 보도록 하자.

비동기 방식으로 HTTP 호출하기

사용자가 버튼 중 하나를 클릭할 때마다 XMLHttpRequest 객체를 사용하여 서버에 접

속할 것이다. 이전에 언급한 대로 XMLHttpRequest는 아주 저수준으로 HTTP 프로토

콜을 사용하여 작업을 할 수 있도록 해주므로 결과적으로는 극도로 간단한 작업에 사

용하기에는 직관적이지 않다. 현재 XMLHttpRequest을 위한 몇몇의 래퍼들이 존재하

는데 잠시후에는 Prototype이 제공하는 래퍼를 볼 것이다. 하지만 차이점을 강조하

Page 55: Prototype & Scriptaculous 인 액션

2�

Prototype과 Scriptaculous 소개 1장

기 위해서 이번 예제에서는 저수준의 XMLHttpRequest를 사용할 것이다. 예제 1.2는

XMLHttpRequest를 저수준으로 사용하는 데 필요한 코드를 보여준다.

예 제 1.2 | Rating 객체에 사용되는 Ajax 호출 코드

tellServer:function(){if(window.XMLHttpRequest){this.request=newXMLHttpRequest();}elseif(window.ActiveXObject){this.request=newActiveXObject(“Microsoft.XMLHTTP”);}

bXMLHttpRequest 객체 획득

if(!this.request){this.showMessage(“noAjaxsupport”);}try{varrating=this;

C 클로저를 위한 레퍼런스 생성

varparams=”name=” d 인코딩된 쿼리스트링 생성

+encodeURI(this.name)+”&rating=”+encodeURI(this.rating);this.request.onreadystatechange=function(){rating.onReadyState(); e 묵시적으로 클로저 생성

};this.request.open(“POST”,“updateRating.php”,true);this.request.setRequestHeader(‘Content-Type’,‘application/x-www-form-urlencoded’);this.request.setRequestHeader(“Content-Length”,params.length);this.request.send(params); f 요청 전송

}catch(err){This.onAjaxError(err.msg);},onReadyState:function(){varreq=this.request;varready=req.readyState; g 요청의 readystate 검사

if(ready==4){varhttpStatus=req.status;

Page 56: Prototype & Scriptaculous 인 액션

22

시작하기1부

if(httpStatus==200||httpStatus==0){this.onAjaxLoad.call(this); h 성공처리를 위한 핸들러 호출

}else{this.onAjaxError.call( i 에러처리를 위한 핸들러 호출

this,“HTTPcode”+httpStatus);}}},onAjaxLoad:function(){this.showMessage(“servererror”+((msg)?“–“+msg:“”));},onAjaxError:function(msg){this.showMessage("serverOK"+this.request.responseText);),showMessage:function(str){document.getElementById(“message_”+this.name).innerHTML=str;}};

다시 말하지만 비동기 통신을 저수준으로 처리하는 데 필요한 코드는 그렇게 짧지 않

다. 주요한 부분들을 훑어보자. 먼저 XMLHttpRequest 객체를 생성해야 한다. 어떤 브

라우저에서는 이 객체가 내장객체이지만 또 다른 브라우저에서는 ActiveX 컴포넌트이

다. 그래서 우리는 모든 경우의 수를 고려해야만 한다❶. 운좋게도 우리가 내장 객체

를 먼저 체크하므로 효과적으로 해당 객체를 가져올 수 있었다. 인터넷 익스플로러 7

이 출시되었는데 이 버전은 하위 호환성을 위해 ActiveX를 제공할 뿐만 아니라 내장

XMLHttpRequest 객체 역시 지원한다. 만약 우리가 ActiveX를 먼저 체크했다면 인터

넷 익스플로러 7에서도 결국엔 불필요하게 ActiveX를 사용하게 되었을 것이고 어쩌면

ActiveX 컨트롤들을 사용하지 않도록 설정된 브라우저들을 차단하게 되었을 것이다.

그러나 우리의 Ajax 코드는 다른 방법으로 작동한다. 우리는 선택적으로 ActiveX 타입

을 체크함으로써 오래된 버전의 인터넷 익스플로러를 지원할 수도 있다. 그러나 이러

한 경우는 간단한 평점 위젯 하나를 구현하는데도 많은 배경지식이 요구된다. 따라서

Page 57: Prototype & Scriptaculous 인 액션

23

Prototype과 Scriptaculous 소개 1장

인터넷 익스플로러 5.5의 사용자들은 아마도 우리의 애플리케이션을 사용할 수 없을지

도 모른다.

주의할 두 번째 포인트는 생소한 클로저 트릭이다. 우리는 rating이란 변수를 선언

하였고❷ 이 변수를 이벤트 핸들러 내에서 참조한다❹. 이 경우에 이벤트 핸들러는 단

순하게 한 라인으로 또 다른 함수를 호출하고 있는데, 만약 우리가 자바스크립트 에서

암시적으로 사용되는 클로저의 복잡함을 이해하지 못했다면 왜 onReadyState() 함

수를 직접 할당하지 않았을까 하고 궁금해했을 것이다.

우리는 표준 쿼리스트링인 키-값 형태로 서버 측 프로세스를 호출한다. 거의 모

든 서버 측 개발 언어들은 자동으로 쿼리스트링을 파싱하는 기능을 제공하지만

XMLHttpRequest을 사용하는 경우에는 각각의 값에 대해서 encodeURI() 함수를 호

출하여 문자열을 직접 만들어줘야 한다❸. 그 후 요청을 전송하기 전에 몇 개의 중

요한 HTTP 헤더 정보를 설정해줘야 한다❺. 자바 서블릿(Java Servlet)의 request.

getParameter()와 PHP의 $_GET 배열과 같이 서버 측에서 우리가 사용할 편리한 메

소드들은 요청의 형태가 application/x-www-form-urlencoded의 형태일 때만 원하

는 값을 생성한다는 것은 잘 알려진 사실이다. HTML 폼들은 이 값을 자동으로 채워주

지만 XMLHttpRequest를 사용할 때는 우리가 직접 채워줘야 한다.

일단 요청이 전송되고 나면 우리의 콜백 핸들러들이 바빠진다. 요청이 완료되었을

때 한 번만 호출되는 것이 아니라 요청의 생명주기에 존재하는 여러 단계에서 호출되

는데 이것은 진행 프로그레스 바를 구현하는 데는 아주 유용하지만 우리에겐 부담이

된다. readystate의 값인 4는 요청완료에 해당되며 우리는 간단하게 이 값을 체크한 뒤

에❻ 응답의 HTTP 코드에 따라 성공을 처리하는 핸들러❼나 에러를 처리하는 핸들러

❽를 호출한다.

이쯤에서 우리가 본 것을 리뷰해보자. 다시 말하지만 모든 것이 완료되었고 동작도

한다. 하지만 우리는 상당히 많은 노력을 기울여야 했다. 그리고 요청에서 쿼리스트링

이 어떻게 인코딩되어야 하는지와 HTTP 헤더가 올바르게 설정이 되어야 서버 측에서

디코딩되는 것과 같은 HTTP 프로토콜에 대한 다소 높은 이해가 필요했다. 더구나 클

로저에 대한 개념을 이해해야 한다.

이 애플리케이션을 작성하고 난 후에 Prototype과 Scriptaculos을 사용하기 쉽게 하고 몇

몇 부분에서 Prototype과 Scriptaculous의 특징을 사용하기 위해 코드를 리팩토링하였다.

Prototype과 Scriptaculous가 어떻게 작업을 단순화시켜주는지 살펴보자.

Page 58: Prototype & Scriptaculous 인 액션

2�

시작하기1부

1.4.2 Prototype과 Scriptaculous 추가하기

우리는 파일들을 직접 열어보지 않고도 Prototype과 Scriptaculous를 사용하는 것이

가져다 주는 첫 번째 이점을 볼 수 있다. 메인 코드 파일인 ratings.js(예제 1.3을 보라)

는 Prototype과 Scriptaculous를 적용한 결과로 약 20퍼센트 사이즈가 작아졌고 이것

은 확실히 이 두 라이브러리가 우리의 생산성을 높여준다는 것을 의미한다. 그러나 파

일 사이즈가 감소했다는 사실만 가지고는 많은 것을 설명할 수가 없다. 자, 리팩토링을

하면서 자세한 사항에 대해서 알아보도록 하자.

DOM 헬퍼 메소드

Prototype은 DOM을 사용하기 편리하게 해주는 여러 가지 헬퍼 메소드들을 제공한다.

그 중에서 가장 간단한 것으로는 $()라는 함수가 있다(그렇다 이 것은 자바스크립트에

서는 변수로 유효한 형태이다). 우리의 원래 코드에서는 DOM 엘리먼트를 찾기 위해

엘리먼트들의 ID를 다음과 같이 사용했다.

this.body=document.getElementById(divId);

Prototype을 사용하므로 위의 코드를 다음과 같이 간단하게 다시 쓸 수 있다.

this.body=$(divId);

현재로서는 우리가 단순반복적인 타이핑을 하지 않게 되었다는 점을 알게 된 것만으로

충분하다. 사실 $()는 11장에서 보게 되겠지만, document.getElementById() 메소

드보다 훨씬 강력하다. 하지만 지금은 그쯤 해두기로 하고 다음 아이템을 살펴보자.

이벤트 핸들러

오리지널 버전의 코드에서 우리는 버튼들을 위한 이벤트 핸들러를 작성할 때 클로저

와 함수 컨텍스트를 이해해야 했다(예제 1.1의 ❺를 보라). 이것은 두 가지의 실질적

인 결과를 갖는다. 첫째로, 클로저가 동작하도록 하기 위해 익명 함수를 사용하여 이벤

트 핸들러 코드를 인라인으로 선언해야만 한다. 때때로 익명 인라인 함수를 사용하는

것이 좋을 때도 있지만 이 경우에 우리는 선택할 수 있는 다른 방법이 없기 때문에 사

용한 것이다. 둘째로, 이벤트 핸들러 코드 내에서 Rating 객체를 this 참조자가 아닌

rating 변수를 통해서 참조해야만 하며 이것은 아주 이상하게 보인다.

Page 59: Prototype & Scriptaculous 인 액션

2�

Prototype과 Scriptaculous 소개 1장

또한 이벤트 핸들러를 작성할 때 브라우저마다 이벤트 객체와 대상 엘리먼트를 획득

하는 방법이 다르기 때문에 이것을 처리할 수 있도록 브라우저 호환성을 보장하는 코

드를 작성해야 한다.

Prototype은 이런 허드렛일을 단 한 번의 호출로 처리하여 우리의 업무를 덜어준다.

Function.bindAsEventListener() 함수는 일반 함수를 이벤트 핸들러로 만들어주며

우리를 대신해 클로저를 생성하고, 함수 컨텍스트와 관련된 이슈들을 정리하고, 대상 엘리

먼트에 즉시 접근할 수 있는 견고하고 브라우저 간 호환이 보장되는 이벤트 객체를 제공한

다. 예제 1.3은 수정된 코드를 보여주며 변경된 부분이 볼드체로 표기하고 있다.

예 제 1.3 | 수정된 이벤트 핸들러 코드

updateUI:function(delta){if(!delta){delta=0;}if(delta>0){this.rating++;}varinner="<tableborder='0'><tr><tdwidth='42'>"+"<spanclass='title'>"+this.title+"</span></td>"+"<td>";for(vari=0;i<this.rating;i++){inner+="<imgsrc='images/star.png'id='ratingstar_"+i+"'/>"}inner+="</td></tr><td>"+"<imgsrc='images/up.png'id='plus_"+this.title+"'/>"+"<imgsrc='images/down.png'id='minus_"+this.title+"'/>"+"</td><td>"+"<divid='message_"+this.name+"'class='message'></div>"+"</td></tr></table>";this.body.innerHTML=inner;varrating=this;this.plusButton=$("plus_"+this.title);this.minusButton=$("minus_"+this.title); Event.observe( b 이벤트를 DOM 노드에 바인딩

this.body, "click", this.clickHandler .bindAsEventListener(this) c 이벤트 핸들러 생성

);this.tellServer();},clickHandler: function(event) { d 핸들러 코드 정의

Page 60: Prototype & Scriptaculous 인 액션

26

시작하기1부

var target = Event.element(event); e 이벤트 타겟을 가져온다

if(target == this.plusButton && this.rating<5) { this.updateUI(1); } else if (target == this.minusButton && this.rating>0) { this.updateUI(-1); } },

우리는 브라우저 간의 상이한 이벤트 모델에 관련한 문제를 피하기 위해 두 가지

의 이벤트 핸들러 특징을 사용하고 있다. Event.observe()❶ 메소드는 안전하

게 HTML 엘리먼트에 복수의 핸들러 함수를 등록할 수 있도록 해준다. Function.

bindAsEventListener()❷는 일반적인 함수를 이벤트 핸들러로 변경해주며 이벤트

핸들러에게 브라우저 간 호환이 되는 이벤트 객체를 제공하고 첫 번째 파라미터로 이

벤트 컨텍스트를 넘겨준다. 여기서 우리는 Rating 객체를 넘겨주었고 이것은 우리가

이벤트 핸들링 코드를 Rating 프로토타입❸의 일반적인 멤버 함수로 정의할 수 있다는

의미이다.

우리가 정의한 clickHandler() 함수는 원본 코드의 익명함수와 동일한 로직을 가

지고 있지만 확실히 읽기가 쉽다. 우리는 이벤트를 발생시킨 HTML 엘리먼트에 단 한

라인의 코드❹로 접근할 수 있고 자연스러운 방법인 this 참조자를 사용하여 객체의

멤버 변수를 참조할 수 있다.

하지만 서버 측 정보를 갱신하기 위해 Ajax 요청을 전송할 때에 더 많은 이득이 있다.

다음을 보도록 하자.

더 쉬워진 Ajax 요청

Ajax 요청을 코딩하는 것은 자바스크립트의 본질에 대한 해박한 지식뿐만 아니라

HTTP 프로토콜에 대한 지식 또한 요구된다. 지식은 좋은 것이지만 바쁜 우리가 이런

세부적인 것을 파악하는 것은 개발속도를 아주 더디게 만든다.

Prototype는 이러한 복잡함을 캡슐화하고 있는 Ajax.Request라는 유틸리티 객체를

제공하므로 다음과 같이 간단하게 코딩할 수 있다(하지만 여전히 HTTP를 직접 이용하

여 코딩을 할 수도 있다!). 예제 1.4는 수정된 Ajax 코드를 보여준다.

Page 61: Prototype & Scriptaculous 인 액션

27

Prototype과 Scriptaculous 소개 1장

예 제 1.4 | 수정된 Ajax 요청 코드

tellServer:function(){ var params = $H( {name: this.name, rating: this.rating} ).toQueryString();

b 쿼리스트링 생성

new Ajax.Request(

cAjax.Request 객체 생성 "updateRatings.php",

{ method: "post", parameters: params, onSuccess: this.onAjaxLoad .bind(this), onFailure: this.onAjaxError .bind(this)

d 콜백 핸들러 선언

} );},onAjaxLoad:function(transport){this.showMessage("serverOK"+transport.responseText);},onAjaxError:function(transport){this.showMessage("servererror["+transport.httpStatus+"]");},

직접 Ajax 호출을 코딩할 때는 우리 손으로 직접 쿼리스트링을 생성하고(예제 1.2의

❸을 보라) 인코딩해줘야 했었다. 여기서는 일반적인 자바스크립트 객체로부터 해시

(Hash) 객체를 생성하기 위해 Prototype의 $H() 함수(그렇다. 이 친구들은 짧은 이름

을 좋아한다!)를 사용할 것이다❶. 10장에서 해시에 대해서 보다 자세하게 알아볼 것

이다. 그러니 지금은 해시 객체가 우리를 위해서 파라미터를 생성해주는 미리 정의

된 toQueryString() 메소드를 가지고 있다고 알아두자. 문법이 처음에는 이상하

게 보일지도 모른다. 특히 $H()가 단지 자바스크립트 함수라는 것을 이해하지 못했

을 때는 더 그렇다. 하지만 일단 이해하게 되면 여러분이 쿼리스트링을 생성할 때마다

encodeURI() 함수를 매번 호출해야 한다는 것을 기억해야 하는 문제로부터 자유로워

진다.

Page 62: Prototype & Scriptaculous 인 액션

28

시작하기1부

자 이젠 코딩에 있어서 가장 큰 향상을 가져오게 되는 부분인 ‘요청생성’ 부분을 보도

록 하자. Ajax.Request 객체는 생성자에서 두 개의 파라미터를 받는다❷. 첫 번째는 서

버 측 리소스의 URL이고 두 번째는 옵션파라미터로 채워진 JavaScript 객체이다(이 책

을 읽는 동안 사전 정의된 객체와 우리의 코드에서 이러한 형태로 사용되는 것을 자주

보게 될 것이다). 우리는 HTTP 메소드를 POST 방식으로 명시하고 쿼리스트링을 파라

미터로 넘겨준다. MIME 타입과 같은 상세한 내용들은 자동으로 설정된다.

우리는 또한 두 개의 콜백 핸들러를 추가한다. Ajax.Request는 요청이 성공했을 경

우와 실패했을 경우에 호출되는 적절한 고수준의 콜백 함수를 정의할 수 있도록 하고

있다❸. 여기서 우리가 Function.bind() 메소드를 사용하고 있음에 주목하라. 이 함

수는 bindAsEventListener() 메소드와 마찬가지로 콜백 함수가 호출되었을 때 우리

가 필요한 컨텍스트 객체를 가지고 있도록 보장한다.

우리는 더 이상 요청이 수행되는 동안 여러 번에 걸쳐 호출되는 콜백함수를 작성할

필요가 없다. 왜냐하면 Prototype이 HTTP 응답코드에 대한 처리를 대신 해주므로 이

렇게 간단한 경우에는 우리가 작성할 필요가 없기 때문이다. 예제 1.2와 비교해 볼 때

tellServer() 메소드는 적어도 50% 가량 코드량이 감소했고 onReadyState() 메소

드도 제거하였다.

여기서 만족할 수도 있지만 이번 장을 마치기 전에 마지막으로 애플리케이션에

Scriptaculous가 제공하는 유용한 기능들 중 하나를 추가해 보도록 하자.

사용자 인터페이스에 세련미를 추가하기

우리가 리팩토링한 애플리케이션은 적은 노력을 기울였음에도 기능면에서는 오리지널

버전과 동일하다. 오리지널 애플리케이션을 코딩할 때 몇 가지 ‘있었으면’ 하는 기능에

대해서 고민했었지만 구현할 만큼 충분한 시간이 없었다. 자 이제 꽤 많은 시간을 아낄

수 있었으니 그 기능들 중 하나를 검토해보자.

사용자가 평점을 수정했을 때 별 모양의 아이콘이 사라지는 것 외에는 별다른 시각

적인 피드백이 없다. 약간의 애니메이션은 애플리케이션이 보다 사용하기에 만족스럽

도록 만들어주며 궁극적으로는 프로젝트에 대한 이해도를 증가시킨다. 하지만 이런 종

류의 이익은 평가하기 어렵기 때문에 이러한 일에 많은 노력을 기울여 우리가 보다 중

요한 문제들을 놓치는 일이 발생하는 것을 원하지는 않는다.

Page 63: Prototype & Scriptaculous 인 액션

29

Prototype과 Scriptaculous 소개 1장

Scriptaculous의 Effect 라이브러리를 사용하면 예제 1.5에서 보는 것과 같이 단 몇

라인의 코드만을 사용하여 별 모양의 아이콘이 추가되거나 제거되는 것에 애니메이션

효과를 줄 수가 있다(우리는 전체 함수를 다시 작성하였고 추가된 코드들은 볼드체로

표기하였다).

예 제 1.5 | Rating 애플리케이션에 효과 추가하기

updateUI:function(delta){if(!delta){delta=0;} if(delta>0) { this.rating++; b 평점을 증가시킨다

} varinner="<tableborder='0'><tr><tdwidth='42'>"+"<spanclass='title'>"+this.title+"</span></td>"+"<td>";for(vari=0;i<this.rating;i++){inner+="<imgsrc='images/star.png'" +"id='ratingstar_"+i+"'/>" c 이미지 ID를 부여한다

}inner+="</td></tr><td>"+"<imgsrc='images/up.png'id='plus_"+this.title+"'/>"+"<imgsrc='images/down.png'id='minus_"+this.title+"'/>"+"</td><td>"+"<divid='message_"+this.name+"'class='message'></div>"+"</td></tr></table>";this.body.innerHTML=inner;varrating=this;this.plusButton=$("plus_"+this.title);this.minusButton=$("minus_"+this.title);Event.observe(this.body,"click",this.clickHandler.bindAsEventListener(this));this.tellServer(); if(delta<0) { new Effect.DropOut("ratingstar_0"); this.rating--;

d 애니메이션을 적용하고 평점을 감소시킴

} else if(delta>0) { new Effect.Pulsate ("ratingstar_"+(this.rating-1));

평점이 증가되는 경우에 애니메이션 적용

}},

Page 64: Prototype & Scriptaculous 인 액션

30

시작하기1부

이전 버전의 애플리케이션에서, 우리는 항상 화면을 렌더링하기 전에 평점을 수정하였

다. 이번 경우에는 우리가 평점을 감소시킬 때 처음에 하나의 여분의 별모양 아이콘을

그리고 그 후에 그것을 제거하기를 원한다. 그래서 평점이 증가되는 경우에만 미리 점

수를 수정한다❶. 모든 것이 렌더링된 후에 효과를 적용시키고 필요하다면 평점을 감

소시킨다❸.

효과를 적용하는 것은 우스울 만큼 쉽게 사용할 수 있으며 우리가 필요한 것은 효과

를 적용할 엘리먼트의 ID뿐이다. 따라서 이미지들에 대한 ID 속성(attribute)을 부여해야

하지만❷ 이것은 아주 쉬운 일이다. Ajax.Request의 경우에서와 같이 생성자는 옵션으

로 채워진 객체를 파라미터로 받을 수 있지만 5장에서 보다 자세히 알아볼 것이기에 이

번 예제에서는 옵션을 적용하지 않았다.

이렇게 몇 라인의 새로운 코드를 추가하여 새로이 개선된 평점 애플리케이션은 사용

자가 인지할 수 있도록 때때로 잠시 동안 반짝거리고 평점이 감소될 때는 가장 왼쪽의

별 모양 아이콘이 페이지의 바닥으로 떨어져 내린다. 불행하게도 이런 내용을 정지된

그림으로 이 책에 담는 것은 어려우므로 여러분 스스로 코드를 다운로드 받아서 직접

실행시켜 보기를 바란다.

이것으로 Prototype과 Scriptaculous 라이브러리가 우리에게 어떤 도움을 줄 수 있는

지를 알아보는 첫 번째 장을 마치도록 하겠다. 이어지는 장들에서 이들 라이브러리에

대해서 보다 체계적으로 알아볼 것이다.

Page 65: Prototype & Scriptaculous 인 액션

3�

Prototype과 Scriptaculous 소개 1장

1.5 요약

이번 장에서는 Ajax 관련 기술들의 발전에 대해서 알아보았다. 1990년대 후반에는 브

라우저와 서버 간의 비동기 통신에 대한 초기적인 연구가 시작되었고 이 연구들의 대

부분은 격리된 채로 진행되었다. 2005년의 초기에 와서 Ajax라는 용어의 탄생이 이러

한 연구들을 주목받게 하였다. 그 이후로부터 Ajax 개발을 보다 쉽게 하려는 많은 노력

들이 이루어졌고 이런 노력 중에 프레임워크와 라이브러리들이 많은 중요한 역할을 수

행하였다. 이제 더 이상 Ajax 애플리케이션을 동작할 수 있게 만드는 것만으로는 충분

치가 않다. 우리는 Ajax 애플리케이션이 보다 부드럽고 견고하며 개발과 유지보수가

쉽기를 원한다.

우리는 Prototype과 Scriptaculous라는 가장 뛰어난 자바스크립트, Ajax 두 라이브러

리를 소개하였고 이 라이브러리들의 주요한 목적과 구성 요소들에 대해서 알아보았다.

Prototype은 추가적으로 언어적인 특징과 편의기능을 제공하는 상대적으로 저수준의

라이브러리이다. Scriptaculous는 Prototype을 이용하며 대부분 사용자 인터페이스를

생성하는 데 초점이 맞추어진 고수준의 위젯과 컴포넌트들을 제공한다.

두 가지 라이브러리 모두 내부적으로는 많은 고급 자바스크립트 기술을 사용하며,

심지어는 그들만의 새로운 진보적인 기술도 소개하고 있다. 그럼에도 불구하고 이들

라이브러리를 사용하는 것은 매우 쉬우며, 깊은 이해도를 요구하지도 않는다. 우리는

간단한 Ajax 예제를 소개하였고 이 예제를 Prototype과 Scriptaculous를 이용하여 리

팩토링하였다. 내부적으로 이들 라이브러리는 복잡해서 소스를 읽고 이해하기 위해서

는 로켓 과학에 대한 학위가 필요할 정도라고 느껴질 정도이다. 그러나 우리의 리팩토

링 예제에서 알 수 있듯이 우리는 보통 수준의 코더들이 이들 라이브러리를 사용하여

빠르게 원하는 것을 얻을 수 있을 것이라 확신한다. 계속해서 이 책을 읽어나가는 동안

이들 라이브러리에 대해서 보다 상세하게 알아볼 것이고 이 라이브러리를 이용하여 어

떤 이득을 얻을 수 있는지 쉽게 설명할 것이다.

Page 66: Prototype & Scriptaculous 인 액션

32

시작하기1부

Page 67: Prototype & Scriptaculous 인 액션

33

QuickGallery 소개

02장

이번 장에서 다루는 내용 : QuickGallery 웹 애플리케이션 소개

: 전통적인 웹 애플리케이션 모델에 대한 평가

Page 68: Prototype & Scriptaculous 인 액션

3�

시작하기1부

Prototype과 Scriptaculous는 Ajax 애플리케이션을 빠르고 쉽게 개발할 수 있도록 설

계되었다. Ajax의 핵심 기능은 비동기 방식의 요청을 서버로 전송하는 것이고 이전 장

에서 어떻게 Prototype의 Ajax.Request 클래스가 비동기 요청의 전송을 단순화시켜줄

수 있는지 알아보았다(예제 1.4를 보라). 이어지는 3개의 장에서 우리는 Prototype의

Ajax 지원기능에 대해서 보다 면밀하게 알아볼 것이고 Prototype이 보다 복잡한 애플

리케이션의 요구사항을 어떻게 지원하는지 볼 것이다. 3장에서는 Ajax.Request의 세

부적인 내용을 알아볼 것이며 이 책의 전반에 걸쳐 우리가 사용하게 될 여타 기능들과

Ajax에 대한 검토를 위한 준비를 할 것이다.

우리가 Prototype과 Scriptaculous의 다양한 부분들로 진행해 감에 따라 이 두 개

의 라이브러리가 적당히 복잡하고 현실적인 상황에서 어떻게 사용될 수 있는지 보고

싶을 것이다. 이번 장에서는 1부의 나머지 부분에 걸쳐 우리가 개발해 나갈 예제 애

플리케이션을 소개할 것이다. 그리고 이 예제는 12장에서 다시 다루게 된다. 그것은

QuickGallery라고 부르는 웹 기반 이미지 갤러리 애플리케이션이다(모든 애플리케이

션은 이름이 필요하고 대부분의 웹 애플리케이션들은 다소 바보스런 이름들을 가지고

있다!). 이번 장에서 우리가 다룰 버전은 단순하고 평범하다. 이 예제 애플리케이션은

Ajax를 사용하지 않으며 단지 3장과 4장에서 이 애플리케이션에 적용하게 될 Ajax의

이점에 대해서 알아보기 위한 시작점으로 설계되었다. QuickGallery의 마지막 버전은

12장에서 소개하며 실제 업무 환경에서 Prototype과 Scriptaculous의 전체적인 능력을

설명하기 위해 많은 새로운 기능을 추가해서 보여줄 것이다.

그러니 이번 장에서는 불꽃놀이와 같은 화려함을 기대하지는 말자! 만약 여러분이

급한 상황이라면 3장으로 바로 넘어가도 좋다. 그리고 여러분이 QuickGallery의 세세

한 구현에 대해서 알아야 할 필요가 있을 때 다시 이번 장을 읽어도 좋다.

2.1 설계와 구현

우리가 다뤄야 할 항목은 두 가지이다. 첫째로 QuickGallery가 사용성과 기술적인 관

점에서 어떻게 동작하는지 설명할 필요가 있다. 둘째로는 전통적인 웹 애플리케이션

모델의 단점들에 대해서 살펴볼 필요가 있다. 특히 이러한 단점이 QuickGallery에 어

떤 영향을 미치는지 눈여겨 보아야 한다. 그래야 3장과 4장에서 Ajax를 소개할 때 어떤

부분들에서 향상이 가능한지를 구별해낼 수 있다.

Page 69: Prototype & Scriptaculous 인 액션

3�

QuickGallery 소개 2장

이번 절에서는 QuickGallery를 마음 편하게 둘러 볼 것이다. 그럼 이 애플리케이션

에 대한 요구사항과 이 애플리케이션이 수행했으면 하는 일들에 대해서 알아보는 것으

로부터 시작하자.

2.1.1 애플리케이션에 대한 요구사항

우리가 이 책에서 다루려고 하는 애플리케이션은 서버 파일시스템의 트리구조 내에 존

재하는 이미지들의 썸네일 화면과 클로즈업 화면을 제공하는 이미지 겔러리 뷰어이다.

원래 우리의 요구사항은 상당히 간단하다. 우선 폴더 내의 이미지들을 썸네일로 보여

주고 해당 썸네일을 클릭하면 전체 크기의 이미지로 보여줄 수 있기를 원한다. 또한 하

위폴더로 내려가거나 상위폴더로 올라갈 수 있기를 원한다. 그래서 그림 2.1에서 보는

것과 같이 스크린을 세 개의 영역으로 나누었다.

상단에 위치한 ‘현재 위치 메뉴(breadcrumb trail)’ 1 을 따라서 트리구조 상위로 이동할

수 있고 왼쪽에 위치한 리스트를 통해서 하위폴더로 이동할 수 있다. 나머지 영역은 썸

네일이나 선택된 이미지의 클로즈업 이미지를 표시하는 데 할당된다.

썸네일 이미지들은 사용자가 미리보기를 할 수 있도록 빠르게 다운로드할 수 있고

렌더링도 빨리 할 수 있는 작은 크기의 이미지 복사본으로 구성된다. 현대 디지털 카

메라가 생성하는 이미지는 크기가 너무 커서 대량으로 다운로드하기에는 어렵고, 많은

수의 이미지를 화면상의 크기만 줄여서 표시하는 것은 사용자 브라우저가 감당하기 힘

들다. 대신에 갤러리 애플리케이션은 필요할 때마다 썸네일 이미지를 생성할 것이다.

갤러리 애플리케이션은 PHP를 이용하여 백엔드를 구현하였다. 간단하고 어디서든

사용될 수 있는 언어이기 때문에 PHP를 선택하였다. 서버 측의 기능은 상대적으로 간

단하여 이 애플리케이션을 다른 서버 측 언어들로 바꾸는 것은 매우 쉽다. Ajax 애플리

케이션을 위한 서버 측 코드들은 대부분 Ajax 기반이 아닌 애플리케이션에서 사용되는

기술들과 동일한 기술을 사용한다. 하지만 몇 가지 차이점들이 있으며 우리는 이러한

기술들을 대중적으로 사용되는 서버 측 언어들(PHP, 자바, .NET 루비온레일스)을 사

용하여 어떻게 구현하는지에 대해서 부록 E에 다루어 놓았다.

1 웹 사이트의 계층구조를 기준으로 현재위치를 나타내는 메뉴. 원문에는 breadcrumb trail로 표기되어 있으며 헨델과 그레텔의 이야기로부터 생

성된 용어이다. 이 책에서는 현재 위치 메뉴로 의역하였다.

Page 70: Prototype & Scriptaculous 인 액션

36

시작하기1부

그림 2.1 좌측에 위치한 메뉴를 통해 하위폴더의 컨텐트를 보여주고 상단에 위치한 ‘현재 위치

메뉴’를 통해서 상위폴더로 네비게이션 할 수 있는 QuickGallery 애플리케이션.

현업에서는 두 종류의 Ajax 프로젝트가 존재한다. 하나는 새로 개발하는 경우이고 나

머지는 기존의 애플리케이션을 Ajax 기반으로 변경하는 경우이다. 비록 QuickGallery

애플리케이션을 특별히 이 책을 위해서 작성하긴 했지만 전통적인 웹 애플리케이션을

Ajax 기반으로 변경하는 경험을 시뮬레이션 하기 위해서 이 애플리케이션을 전통적인

방식으로 개발된 웹 애플리케이션이라고 가정하도록 하였다.

QuickGallery 애플리케이션은 어떤 사용자의 요청에 대해서도 전체 페이지 갱신이

필요한 전통적인 웹 애플리케이션으로 개발되었다. 백엔드 측의 구현은 뷰를 생성하는

하나의 PHP 파일과 애플리케이션 뒤에 숨겨진 로직을 포함하고 있는 PHP include 파

일로 구성되어 있다. 그럼 비즈니스 로직을 먼저 살펴보도록 하자.

2.1.2 파일시스템 네비게이션

가장 먼저 정의해야 하는 것은 우리의 애플리케이션이 파일시스템의 어느 부분을 접근

할 수 있는지 정하는 것이다. 문제를 단순하게 다루기 위해 우리는 모든 이미지들이 하

나의 폴더에 저장된다고 가정할 것이며 이 폴더의 경로를 환경설정 정보에 명시할 것

이다. 이미지의 URL을 작성할 때 이미지의 URL이 웹서버가 설치된 디렉토리(문서루트)

에서 상대적인 경로를 나타내도록 부분적인 URL 경로를 사용하도록 할 것이다.

Page 71: Prototype & Scriptaculous 인 액션

37

QuickGallery 소개 2장

데모 서버는 우분투 리눅스에서 실행 중이고 환경설정을 수정하지 않은 아파치 2.0

서버이며 문서루트는 /var/www/로 설정되어 있다. 우리는 /var/www/dave/album 폴

더를 생성하여 이곳에 QuickGallery 파일들을 저장토록 하였고 홈디렉터리 내의 “sites”

라는 폴더가 /var/www/dave 폴더를 가리키도록 심볼릭 링크를 추가하였다. 따라서

갤러리 애플리케이션을 위한 설정은 다음과 같다.

$basedir=’/home/dave/sites/album/images’;

$img_pre_path=’/dave/album/images’;

우리는 이 정보를 여러 가지 방법으로 사용할 것이다. 성공적으로 파일시스템을 네비

게이션하기 위해서, 우리가 첫 번째로 알아야 할 것은 우리가 트리구조에서 어디에 위

치해 있느냐 하는 것이다. 우리는 베이스 디렉터리에 상대적 경로를 명시하여 요청변

수를 애플리케이션으로 전달할 것이다. 만약 경로가 지정되지 않으면 우리는 최상위

디렉터리에서 시작할 것이다. 이러한 코드는 직관적이다.

if(isset($_GET[‘path’])){

$path=$_GET[‘path’];

$fulldir=implode(‘/’,array($basedir,$path));

}else{

$path=””;

$fulldir=$basedir;

}

PHP의 implode() 함수는 단순히 배열의 요소들을 명시된 구분자로 연결하는 기능

을 수행한다. $path 변수는 이미지 디렉터리 내에서 사용자의 현재 위치를 나타내고

$fulldir은 이것을 실제 파일시스템의 위치와 매핑한다.

자 이제 우리는 우리가 어디에 위치하는지 알 수 있게 되었다. 그럼 네비게이션 정보

를 생성해보도록 하자.

폴더 내의 컨텐트 검사

우리의 첫 번째 임무는 현재 디렉터리의 이미지들과 하위폴더들을 검사하는 것이다.

이 임수는 list_dir() 함수에 의해서 처리되며 코드는 다음과 같다.

functionlist_dir($dir,$path){

$dirs=array();

$imgs=array();

Page 72: Prototype & Scriptaculous 인 액션

38

시작하기1부

$others=array();

$d=dir($dir);

while(false!=($entry=$d->read())){ b 폴더에 반복연산을 수행

if(is_dir(implode('/',array($dir,$entry)))){

if(($entry!='.')&&($entry!='..')){

$dirs[]=$entry; c 하위폴더를 기록

}

}elseif(is_image_file($entry,$path)){

$bits=explode('.',$entry);

$imgs[]=$bits[0];

d 이미지 파일을 기록}else{

$others[]=$entry;

}

}

$results=array(

'dirs'=>$dirs,

'imgs'=>$imgs,

'others'=>$others

);

return$results;

} e 결과를 조합

함수는 디렉터리에 대한 절대경로와 사용자 관점의 논리적인 경로 등 두 개의 파라미

터를 받는다. 이 함수에서는 단지 절대경로만이 필요하지만 후에 썸네일 이미지를 생

성할 때 논리적인 경로를 사용하게 될 것이다.

list_dir() 메소드는 기본적으로 PHP의 파일시스템 관련 함수를 사용하여 현재 폴

더에 반복연산을 수행하며❶ 하위폴더❷, 이미지❸ 그리고 그 밖의 것들로 세 가지 분

류에 해당하는 아이템들을 기록한다. 그 후에 결과값들은 배열로 조합되어 리턴된다❹.

우리는 PHP의 내장함수인 is_dir() 메소드를 사용하여 하위폴더 여부를 검사할 수

있다. 우리가 명시적으로 특별한 폴더들인 . 과 ..을 제외시킨 것에 주목하라 이 폴더들

은 각각 현재 폴더와 바로 상위의 폴더를 나타낸다. ‘현재 위치 메뉴’는 트리구조 상위

로의 네비게이션을 관리하며 우리는 이미 현재 위치에 위치에 있다.

우리는 이름만을 검사하여 간단하게 해당 파일이 이미지인지를 결정할 수 있

다. 일을 단순하게 만들기 위해 지금은 JPEG 이미지만을 가지고 작업할 것이다.

is_image_file() 함수는 다음과 같이 동작한다.

Page 73: Prototype & Scriptaculous 인 액션

39

QuickGallery 소개 2장

functionis_image_file($entry,$path){

$is_image=false;

$bits=explode(‘.’,$entry);

$last=count($bits)-1;

if($bits[$last]==‘jpg’){

$is_image=($bits[$last-1]!=‘thumb’);

if($is_image){

ensure_thumbnail($bits[0],$path);

}

}

return$is_image;}

PHP의 explode() 함수는 implode() 함수와는 정반대로 동작하며 명시된 구분자를

기준으로 문자열을 배열로 분리한다. 우리는 이 함수를 사용하여 파일의 확장자를 추

출해낸다. 즉 파일명이 ‘.jpg’로 끝나면 이 파일을 이미지로 인식한다. 예외가 있다. 만

약 파일명이 ‘.thumb.jpg’로 끝나면 그것이 이미 생성한 썸네일 이미지라고 가정하기

때문에 이 파일을 이미지로 인정하지 않는다. 올바른 이미지파일을 가졌다고 생각하면

true를 리턴하지만 그렇게 하기 전에 썸네일이 준비되어 있는지 확인한다.

어떻게 썸네일을 생성하는지에 대해서는 곧 알아볼 것이다. 하지만 먼저 ‘현재 위치

메뉴’를 생성하여 네비게이션 기능에 대해 결론짓도록 하자.

현재 위치 메뉴 생성

현재 위치 메뉴는 애플리케이션을 사용하는 사용자들로 하여금 빠르게 상위 디렉터리

로 이동할 수 있도록 해주며 그들이 지금 어디에 위치하고 있는지에 대한 정보를 제공

한다. 현재 위치 메뉴를 생성하는 것은 단순히 사용자의 경로를 그 경로를 구성하는 폴

더들로 분리해내는 정도의 문제이다.

fuctionget_breadcrumbs($path){

$bits=split(‘/’,$path);

$crumbs=array();

$tmp_path=‘/’;

$crumbs[]=array(b 최상위 위치

정보를 추가

‘name’=>‘home’,

‘path’=>$tmp_path

);

Page 74: Prototype & Scriptaculous 인 액션

�0

시작하기1부

foreach($bitsas$i=>$value){

if(strlen($value)>0){

$tmp_path.=$value.’/’;

$crumbs[]=array(c 폴더에 대한 위치

정보 추가

‘name’=>$value,

‘path’=>$tmp_path

);

}

}

return$crumbs;

}

먼저, 최상위 폴더를 나타내는 현재 위치 메뉴를 추가하였다❶. 그 후에 해당 경로

에 존재하는 엘리먼트들에 반복연산을 하면서 각 아이템들에 해당하는 위치메뉴를 생

성하였다❷. 우리가 생성한 각각의 위치메뉴에 대해서 해당 위치메뉴가 표시될 이름과

해당 위치 메뉴의 상위에 있는 엘리먼트들의 누적정보인 경로 정보를 기록하기를 원한

다. 최종적으로 데이터를 이차원 배열로 리턴한다.

자 이것으로 모든 네비게이션 관련 데이터를 생성하였다. 이제 썸네일 생성에 대해

서 간단히 알아보도록 하자.

2.1.3 썸네일 이미지 생성

파일이 이미지라는 것을 확인하였을 때 해당 이미지에 대한 썸네일이 존재하는지를 확

인하기 위해 함수를 호출하게 된다. 썸네일을 생성할 데는 큰 이미지일 수도 있는 이미

지를 로딩하고 그 이미지에 스케일링 알고리즘을 적용해야 하는 비용이 소요된다. 일

반적인 HTML의 생성과 비교해 볼 때 이것은 상대적으로 비싼 작업이며 따라서 필요한

경우에만 썸네일 생성기능을 수행하도록 체크하는 메소드가 필요하다. 이것을 어떻게

수행하는지 보도록 하자.

functionensure_thumbnail($base_name,$path){

global$basedir,$thumb_max;

$thumb_name=join('/',

array($basedir,$path,

$base_name.'.thumb.jpg')

);

if(!file_exists($thumb_name)){b 썸네일이 있는지

확인

Page 75: Prototype & Scriptaculous 인 액션

��

QuickGallery 소개 2장

$source_name=join('/',

array($basedir,$path,$base_name.'.jpg')

);

$source_img=imagecreatefromjpeg

($source_name);C 이미지 파일을

읽는다

$source_x=imageSX($source_img);

$source_y=imageSY($source_img);

$thumb_x=($source_x>$source_y)?

$thumb_max:

$thumb_max*($source_x/$source_y);

$thumb_y=($source_x<$source_y)?

$thumb_max:

$thumb_max*($source_y/$source_x);

$thumb_img=ImageCreateTrueColor($thumb_x,$thumb_y);

d썸네일 생성imagecopyresampled(

$thumb_img,$source_img,

0,0,0,0,

$thumb_x,$thumb_y,

$source_x,$source_y

);e 썸네일 데이터

복사

imagejpeg($thumb_img,$thumb_name);

f썸네일 저장imagedestroy($source_img);

imagedestroy($thumb_img);

}

}

이 함수에서 수행한 첫 번째 작업은 썸네일 이미지가 이미 존재하는지를 체크하는 것

이다 ❶. 만약 존재한다면 썸네일을 만드는 것과 같은 어려운 일을 할 필요 없이 그냥

건너 뛰면 되고 만약 썸네일을 찾을 수 없다면 썸네일을 하나 생성해야 한다.

이제 애플리케이션과 관련된 마지막 설정이 남아있다. 썸네일이 얼마 만한 크기로

생성될지를 명시해야 한다. 모든 이미지들이 동일한 비율을 가지고 있지는 않으므로

하나의 축을 지정하여 수행해야 하는데 썸네일의 가장 큰 축을 기준으로 축소작업을

하게 된다. 이렇게 해서 모든 썸네일들은 보여질 때 CSS에 의해 정의한 사각형 모양의

타일들 안에 깔끔하게 정렬되게 될 것이다(그림 2.1을 보라).

썸네일들은 PHP에서 이미지를 다룰 때 가장 많이 사용되는 시장표준인 GD 라이브

러리가 제공하는 함수에 의해 생성된다. GD 라이브러리는 PHP 5.2 이전 버전에서는

선택 모듈이었으나 5.2 버전부터 코어 모듈로 함께 배포되기 시작했다. 우리의 테스트

Page 76: Prototype & Scriptaculous 인 액션

�2

시작하기1부

리눅스 서버에서는 아파치와 PHP를 설치한 이후에 php-gd 모듈을 별도로 설치해야 했

다. 여러분의 환경은 여러분이 사용하는 배포판이나 ISP에 따라 다양할 것이다. 부록 D

에서는 윈도우, 맥 그리고 리눅스 시스템에서 PHP와 GD를 어떻게 동작하게 하는지를

보여줄 것이다. 만약 애플리케이션을 다른 서버 측 언어로 포팅할 것이라면 해당 언어

에 맞는 이미지 처리 라이브러리를 찾을 필요가 있다. 그러나 원리는 유사할 것이다.

일단 GD가 설치되어 동작한다면 다음과 같은 단계들을 거쳐 썸네일을 생성할 수 있

다. 첫째로 소스이미지를 읽어 들인다❷. 그 다음 최대 썸네일 축의 크기를 기준으로

축소된, 비어 있는 이미지를 생성한다❸. 그 후에 소스 이미지를 썸네일 크기에 맞게

축소시킨다❹. 최종적으로 앞서 이야기한 것처럼 “.jpg” 확장자를 “.thumb.jpg”로 바꾸

는 간단한 네이밍 규칙을 적용하여 썸네일 이미지를 저장한다❺.

자 이제 갤러리 애플리케이션 제작에서 요구되는 모든 요소들에 대해서 언급하였다.

애플리케이션의 비즈니스 로직에 있어 마지막 단계는 이러한 기능들을 조율하는 것뿐

이다. 그럼 이제 그 부분을 보도록 하자.

2.1.4 조각들을 합치기

우리는 우리가 어디에 위치하는지 알고 있고 네비게이션을 하기 위해 필요한 모든 데

이터들을 어떻게 생성해 내는지도 알고 있다. 필요할 때 이미지 파일들에 대해서 썸네

일을 생성할 수 있고 그것들을 나중에 사용하기 위해 저장할 수 있다. 이러한 일들을

하나로 묶어내는 것은 이제 아주 수월하다. 애플리케이션의 마지막 코드는 다음에서

보는 것과 같은 함수들의 호출로 동작한다.

$crumbs=get_breadcrumbs($path);

$cc=count($crumbs);

if($cc>0){

$closeup=is_close_up($crumbs[$cc-1]['name']);

}else{

$closeup=false;

}

if($closeup==false){

$listings=list_dir($fulldir,$path);

$subdirs=$listings['dirs'];

$imgs=$listings['imgs'];

$others=$listings['others'];

}

Page 77: Prototype & Scriptaculous 인 액션

�3

QuickGallery 소개 2장

첫째로, ‘현재 위치 메뉴’에 필요한 데이터를 가져온다. 만약 현재 위치 메뉴를 생성

하였다면 우리가 검사하고 있는 것이 폴더인지 하나의 클로즈업 이미지인지를 체크한

다. 만약 폴더를 검사하고 있는 것이라면 폴더 내에 포함된 컨텐트들을 목록으로 생성

한다.

현재 위치 메뉴의 마지막 부분이 ‘.jpg’로 끝나는지를 검사하여 간단하게 하나의 이미

지 파일을 보고 있는지를 결정한다. 만약 그렇다면 경로가 가리키는 것이 바로 이미지

라고 가정할 수 있다. 아래 코드는 이러한 기능을 구현한 것이다.

functionis_close_up($name){

$result=false;

$bits=explode('.',$name);

$last=$bits[count($bits)-1];

if($last=='jpg'){$result=true;}

return$result;

}

다시 한 번 간단하게 PHP의 explode() 메소드를 사용하여 파일명에 대한 정보를 분리

해 내었다. 이러한 시스템은 오류에 대한 방지기능이 없다. 예를 들어 폴더명이 ‘.jpg’

로 끝나는 폴더를 생성하는 것으로 쉽게 오류가 발생할 수 있다. 그러나 수동으로 이미

지 디렉터리를 다루도록 하지 않을 것이기 때문에 이 시스템은 그럭저럭 잘 동작할 것

이다.

이것으로 애플리케이션의 비즈니스 로직에 대한 결론을 맺도록 한다. 요약의 차원에

서 include 파일의 전체 내용이 예제 2.1에 실려 있다. 첫 부분의 코드 두 라인에 정의

된 경로정보는 여러분의 시스템에 따라 다를 수 있음에 주의하라. 부록 D의 3절에서는

QuickGallery 애플리케이션을 어떻게 설정하는지 다루고 있다.

예 제 2.1 | QuickGallery의 비즈니스 로직(images.inc.php)

<?php$basedir='/home/dave/sites/album/images';$img_pre_path='/dave/album/images';$thumb_max=120;

functionlist_dir($dir,$path){$dirs=array();$imgs=array();$others=array();

Page 78: Prototype & Scriptaculous 인 액션

��

시작하기1부

$d=dir($dir);while(false!=($entry=$d->read())){if(is_dir(implode('/',array($dir,$entry)))){if(($entry!='.')&&($entry!='..')){$dirs[]=$entry;}}elseif(is_image_file($entry,$path)){$bits=explode('.',$entry);$imgs[]=$bits[0];}else{$others[]=$entry;}}$results=array('dirs'=>$dirs,'imgs'=>$imgs,'others'=>$others);return$results;}

functionis_image_file($entry,$path){$is_image=false;$bits=explode('.',$entry);$last=count($bits)-1;if($bits[$last]=='jpg'){//우리가 이미 가지고 있는 썸네일의 경우는 무시한다!

$is_image=($bits[$last-1]!='thumb');if($is_image){ensure_thumbnail($bits[0],$path);}}return$is_image;}

functionensure_thumbnail($base_name,$path){global$basedir,$thumb_max;$thumb_name=join('/',array($basedir,$path,$base_name.'.thumb.jpg'));if(!file_exists($thumb_name)){$source_name=join('/',array($basedir,$path,$base_name.'.jpg'));$source_img=imagecreatefromjpeg($source_name);$source_x=imageSX($source_img);$source_y=imageSY($source_img);$thumb_x=($source_x>$source_y)?$thumb_max:

Page 79: Prototype & Scriptaculous 인 액션

��

QuickGallery 소개 2장

$thumb_max*($source_x/$source_y);$thumb_y=($source_x<$source_y)?$thumb_max:$thumb_max*($source_y/$source_x);$thumb_img=ImageCreateTrueColor($thumb_x,$thumb_y);imagecopyresampled($thumb_img,$source_img,0,0,0,0,$thumb_x,$thumb_y,$source_x,$source_y);imagejpeg($thumb_img,$thumb_name);imagedestroy($source_img);imagedestroy($thumb_img);}}

functionget_breadcrumbs($path){$bits=split('/',$path);$crumbs=array();$tmp_path='/';$crumbs[]=array('name'=>'home','path'=>$tmp_path);foreach($bitsas$i=>$value){if(strlen($value)>0){$tmp_path.=$value.'/';$crumbs[]=array('name'=>$value,'path'=>$tmp_path);}}return$crumbs;}

functionis_close_up($name){$result=false;$bits=explode('.',$name);$last=$bits[count($bits)-1];if($last=='jpg'){$result=true;}return$result;}

Page 80: Prototype & Scriptaculous 인 액션

�6

시작하기1부

if(isset($_GET['path'])){$path=$_GET['path'];$fulldir=implode('/',array($basedir,$path));}else{$path="";$fulldir=$basedir;}$crumbs=get_breadcrumbs($path);$cc=count($crumbs);if($cc>0){$closeup=is_close_up($crumbs[$cc-1]['name']);}else{$closeup=false;}if($closeup==false){$listings=list_dir($fulldir,$path);$subdirs=$listings['dirs'];$imgs=$listings['imgs'];$others=$listings['others'];}?>

일단 이 include 파일이 실행되었다면 HTML을 생성하는 데 필요한 모든 데이터는 수

집한 것이다. 사실 이런 방식으로 백엔드에서 동작하는 내용을 분리하는 것은 많은 이

점이 있다. 이 파일은 웹 브라우저에게 데이터를 어떤 형태로 보여줄지에 대해서 가정

을 하지 않는다. 따라서 이 코드는 완전한 HTML 페이지가 아닌 텍스트, HTML, XML

또는 다른 어떠한 타입으로 브라우저에 데이터를 전송하는 Ajax 애플리케이션에서 재

사용하기에 아주 쉽다. 3장과 4장에서 이 코드를 다시 살펴보게 될 것인데 이 코드를

아주 많이 수정할 필요는 없을 것이다.

하지만 애플리케이션의 프리젠테이션 레이어와 연관된 부분에 있어서 반 가량 수

정이 필요할 것이다. 다음 절에서 비즈니스 로직에 의해 생성된 데이터로부터 어떻게

HTML 페이지를 생성하는지 알아볼 것이다.

2.1.5 HTML 생성

애플리케이션을 위한 작업 중 대부분은 우리가 필요한 모든 데이터를 포함하고 있는

include 파일에 처리되어 있다. HTML을 작성하는 것은 상대적으로 매우 쉬운 일이며

Page 81: Prototype & Scriptaculous 인 액션

�7

QuickGallery 소개 2장

사용자 인터페이스 관련 엘리먼트를 감싸는 여러 <DIV> 태그를 정의하고 CSS 스타일

시트를 사용하여 엘리먼트들의 위치를 고정시키고 우리가 생성한 배열 데이터에 반복

연산을 수행하는 정도의 간단한 문제들만 처리하면 된다. 예제 2.2는 애플리케이션을

위한 메인 PHP 파일을 보여준다.

예 제 2.2 | QuickGallery 애플리케이션을 위한 HTML 생성(index.php)

<?phprequire('images.inc.php');

b비즈니스 로직을 포함시킨다?>

<html><head><linkrel='stylesheet'type="text/css"href="images.css"></head><body>

<divid='title'class='box'><?phpforeach($crumbsas$i=>$value){?>

C 현재 위치 메뉴에 반복연산 수행

&nbsp;&gt;&nbsp;<ahref="images.php?path=<?phpecho$value['path']?>"><?phpecho$value['name']?></a><?php}?></div>

<?phpif($closeup){?>d 클로즈업 뷰 화면

렌더링

<divid='closeup'class='box'><imgsrc='<?phpecho$img_pre_path.$path?>'></div><?php}else{?> e 폴더 뷰를 렌더링

<?phpif(count($subdirs)>0){?><divid='folders'class='box'><?phpforeach($subdirsas$i=>$value){?>

f 하위폴더에 반복연산 수행

<div><ahref="images.php?path=<?phpechoimplode('/',array($path,$value))?>"><?phpecho$value?></a></div><?php}?></div>

Page 82: Prototype & Scriptaculous 인 액션

�8

시작하기1부

<?php}?>

<?phpif(count($imgs)>0){?>g 이미지들에 반복

연산 수행

<divid='images'class='box'><?phpforeach($imgsas$i=>$value){$full_img=implode('/',array($path,$value));?><divclass='img_tile'> h 이미지 타일 생성

<ahref="images.php?path=<?phpecho$full_img?>.jpg"><imgborder='0'src="<?phpecho$img_pre_path.$full_img?>.thumb.jpg"/></a><br/><?phpecho$value?></a></div><?php}?></div><?php}?>

<?php}?>

</body></html>

비즈니스 로직 부분은 단 하나의 견고한 PHP 코드의 블록으로 구성되어 있으며 여기

서 JSP나 ASP 프로그래머들에게 익숙한 방법으로 PHP 부분 코드들을 HTML과 섞어

넣었다.

첫 번째로 한 일은 비즈니스 로직 부분을 포함한 것이다❶. 그 다음은 렌더링하기를

원하는 현재 위치 메뉴 관련 변수에 반복연산을 수행한다❷. 그 후에 이미지를 클로즈

업 형태❸로 렌더링할 것인지 또는 폴더의 내용을❹ 렌더링할 것인지를 선택해야 한다.

만약 후자라면 하위폴더❺들과 이미지들❻에 반복연산을 수행하여 각 이미지들을 타

일형태로 렌더링한다❼.

이것은 본질적으로 문서의 구조를 정의한 것이다. 즉, 페이지 내의 엘리먼트들 간의

부모-자식 관계들을 정의한 것이다. 예를 들어 images라는 ID를 가진 엘리먼트 내에

썸네일 이미지들을 위치시키는 경우이다. 우리는 HTML 내에 엘리먼트들이 정확하게

얼마만한 크기인지 또는 어떻게 페이지 내의 공간을 차지하는지에 대해 명시하는 등의

Page 83: Prototype & Scriptaculous 인 액션

�9

QuickGallery 소개 2장

스타일을 정의하지 않았으며 이 일을 CSS 스타일 시트에서 처리하도록 하였다. CSS 파

일의 내용은 예제 2.3과 같다.

예 제 2.3 | QuickGallery에서 사용하는 CSS (images.css)

*{font-family:Arial,Helvetica;}.box{ b 공통적인 스타일 규칙

position:absolute;border:solid#adf1px;background-color:white;padding:4px;}#title{

C 명시적인 위치관련 규칙

top:5px;left:5px;height:18px;font-size:14px;color:#8af;}#folders{

C 명시적인 위치관련 규칙

top:35px;left:5px;width:150px;}#images{

C 명시적인 위치관련 규칙

top:35px;left:180px;}#closeup{

C 명시적인 위치관련 규칙

top:35px;left:180px;}.img_tile{ d 썸네일 이미지 타일

float:left;width:160px;height:160px;}

스타일 시트는 주로 레이아웃에 관련이 있다. 페이지에 존재하는 각각의 주요 엘리먼

트들은 box라는 CSS 클래스를 가지게 되며 이 클래스는 간단한 경계선의 스타일과 보

Page 84: Prototype & Scriptaculous 인 액션

�0

시작하기1부

다 중요한 절대경로의 위치에 관하여 정의하고 있다❶. 다양한 엘리먼트들은 또한 그

들의 ID에 매칭되는 페이지 내의 위치에 관련된 각각의 CSS 규칙을 가진다❷. 마지막

으로 우리는 썸네일을 포함하는 이미지 타일에 대한 규칙을 정의하며 브라우저 윈도의

크기에 관계 없이 폴더보기 화면에서 깔끔하게 펼쳐놓기 위해서 CSS float 프로퍼티

를 사용한다❸.

HTML을 생성하는 PHP 페이지(예제 2.2)와 스타일 시트(예제 2.3)는 함께 동작하여

하나의 단일한 페이지로 애플리케이션의 외양을 정의한다. 우리가 페이지에 있는 어떤

것을 바꾸고 싶을 때면 언제나 전체 페이지를 재생성하고 페이지 내의 모든 엘리먼트

들을 다시 렌더링한다. 이것이 웹 애플리케이션의 특성이다. 적어도 Ajax가 등장하기

전까지는 말이다. 다음 절에서는 이 이슈에 대해서 보다 자세히 알아보도록 하자.

이것으로 Ajax 도입이전 형태의 전통적인 QuickGallery 애플리케이션에 대해서 알

아보았으며 아직까지는 어떤 놀랍거나 독창적인 것도 보여주지 않았다. 그러나 Ajax라

는 마법을 가지고 어디부터 손대야 할지에 대한 견고한 토대를 마련해 주었다. 또한 모

든 비즈니스 로직을 하나의 파일에 담고, 뷰를 HTML이란 구조와 CSS라는 프리젠테이

션으로 분리하는 등 애플리케이션의 서로 다른 관심들을 분리해내려는 노력을 기울였

다는 것도 주목할 만하다. 앞으로 보게 될 것이지만 이러한 구현방법들은 우리가 Ajax

의 도입을 검토할 때 도움이 된다. 이어지는 절에서는 Ajax가 애플리케이션의 설계에

어떤 영향을 미치는지 그리고 우리에게 어떤 가치가 있는지 알아보도록 하자.

2.2 전통적인 웹 애플리케이션 모델에 대한 평가

이번 장의 도입부에서 언급했듯이 우리는 Ajax를 사용하지 않은 간단한 웹 애플리케이

션을 개발하는 것으로 Ajax에 대한 논의를 시작할 것이며 이러한 접근방법의 한계들에

대해서 평가할 수 있게 될 것이다. 이것은 단순히 Ajax를 소개하기 위한 목적이 아니

라 Ajax가 어떤 경우에 진정으로 도움이 될 수 있는지를 식별하는 데 도움이 될 것이다.

자 이제 QuickGallery가 어떻게 동작하는지에 대한 설명을 모두 마쳤으니 전통적인 웹

애플리케이션의 접근방법에서 QuickGallery 애플리케이션이 어떤 형태로 구현되는지

알아보자.

Page 85: Prototype & Scriptaculous 인 액션

��

QuickGallery 소개 2장

2.2.1 링크, 폼 그리고 전체 페이지 갱신

이전 절에서 언급했듯이 전통적인 웹 애플리케이션의 사용자 인터페이스는 하나의

HTML 페이지로 정의된다. 이 페이지는 CSS 스타일 시트와 이미지와 같은 여러 가지의

부가적인 엘리먼트를 포함할 수 있지만 서버는 하나의 단일한 페이지만 생성한다.

사용자는 두 가지 방법, 즉 하이퍼링크를 클릭하거나 HTML 폼을 입력하는 방법으로

페이지를 사용할 수 있다. 이 두 가지 경우 모두 서버 측으로 요청을 보내게 되고 이 요

청에 대한 응답으로 완전히 새로운 페이지가 전달된다. 1장에서 언급한 것처럼 이것은

사용자 흐름이 중지-시작되는 패턴이 되도록 유도하게 되고, 이러한 패턴은 서버에 어

떤 요청을 보내더라도 사용자가 서버로부터 응답이 오기를 기다리는 동안 비활성화의

시간을 요구한다. 이러한 상황이 그림 2.2에 요약되어 있다.

시간은 다이어그램의 왼쪽에서 오른쪽으로 이동한다. 상단의 밴드는 웹 브라우저를

나타낸다-사용자는 서버가 유휴상태이며 요청을 처리하지 않을 때에만 애플리케이션

을 사용할 수 있다. 요청을 기다리는 동안 웹 브라우저는 사용자 상호작용의 결과로 이

미 낡은 데이터가 되어버린 이전 페이지 이외에는 화면에 표시할 내용이 없다. 양방향

의 애플리케이션일수록 이러한 비활성화 기간은 자주 발생되며 더 불만스럽다.

자 이제 포괄적인 문제에 대해서 이해했을 것이다. 그럼 이러한 문제가 QuickGallery

에 어떻게 나타나는지 보도록 하자.

그림 2.2 전통적인 웹 애플리케이션에서의 중지-시작형태의 사용자 상호작용(interaction)

중지 중지시작 시작

브라우저

서버

Page 86: Prototype & Scriptaculous 인 액션

�2

시작하기1부

2.2.2 전통적인 웹 애플리케이션과 QuickGallery

QuickGallery에서 우리는 오로지 하이퍼링크만을 가지고 사용자와 상호작용한다. 우

리는 디렉터리 변경을 위해서(하위폴더 목록이나 현재 위치 메뉴를 통해서) 그리고 썸

네일로부터 전체 사이즈의 이미지를 요청하기 위해서 서버와 두 가지 방식으로 상호작

용한다. 그럼 차례로 이 두 가지의 상호작용에 관해 보도록 하자.

디렉터리 변경

QuickGallery에서 표시되는 이미지들은 서버 파일시스템 내의 이미지들의 위치를 기

준으로 트리구조로 배열된다. 우리는 이미지가 표시되는 영역의 상단에 위치한 현재

위치 메뉴와 하단의 좌측에 위치한 하위목록을 통해서 이 트리구조에 대한 네비게이션

을 제공한다. 따라서 애플리케이션은 화면상에 세 부분의 영역이 존재하고 우리가 이

세 가지 영역 중 어떤 부분과 상호작용할 때마다 세 부분 모두 그림 2.3에 나타난 것처

럼 갱신된다.

엘리먼트 내의 컨텐트들이 변경되는지 아닌지를 표시하기 위해서 (회색은 변경된 것

을 의미하고 흰색은 변경이 되지 않았음을 의미한다) 우측 편의 다양한 엘리먼트들을

어둡게 표시하였다. 이 경우에는 거의 모든 엘리먼트들이 변경되었다 따라서 전체 페

이지를 갱신하는 것이 그다지 비효율적이지는 않다. 하나의 예외 경우는 현재 위치 메

뉴이다. 트리구조를 얼마나 상위로 또는 하위로 이동할 수 있느냐에 따라 어떤 컨텐트

들은 반복될 것이다. 우리는 서버의 응답에 의해 다시 렌더링되는 영역들을 표시하였

다. 그러나 비스듬하게 교차된 무늬 패턴으로 표시된 반복적인 컨텐트를 포함하고 있

다. 이들이 전체 스크린 갱신 모델이 가진 문제이며 이 부분들은 추가적인 네트워크 트

래픽을 생성하고 스크린이 갱신될 때 화면의 갑작스런 움직임을 유발하게 된다.

그림 2.3 QuickGallery의 화면 레이아웃에 있어서 디렉터리 변경의 영향

폴더변경

Page 87: Prototype & Scriptaculous 인 액션

�3

QuickGallery 소개 2장

자, 그럼 썸네일을 클릭하여 클로즈업 이미지를 가져올 때 어떤 일이 발생하는지 보도

록 하자.

클로즈업 모드로 이미지 보기

이미지를 클로즈업 모드로 볼 때 우리는 썸네일 영역을 클로즈업 이미지로 대체한다.

하위폴더 리스트는 그대로이고 현재 위치 메뉴 역시 이미지의 이름이 추가된 것을 제

외하면 그대로이다. 이것은 하위폴더나 현재 위치 메뉴 링크를 클릭함으로써 썸네일

보기 모드로 되돌아 갈 수 있도록 해준다. 그림 2.4는 클로즈업 모드로 들어가고 나오

는 것에 연관된 변화를 묘사하고 있다.

클로즈업 모드로 들어갈 때 우리는 현재 위치 메뉴와 하위폴더 목록에 불필요한 갱신

을 수행한다(사실 이번에 현재 폴더를 변경하지 않았고 단지 폴더에 포함된 컨텐트를

자세히 보기 위해 하위로 이동했을 뿐이다). 그래서 다시 말해 이번에 사용한 전체 페

이지를 갱신하는 접근방법은 최적의 방법이 아니다. 보다 흥미로운 것은 우리가 썸네일

뷰로 되돌아갈 때, 사용자가 이미 보았던(폴더 내의 컨텐트들이 사용자의 마지막 방문

이후에 변경되지 않았다면) 전체 컨텐트 페이지를 그려낸다. 이것에 대한 단 하나의 예

외 경우는 사용자가 클로즈업 뷰로부터 이전에 방문한 적이 없는 하위폴더로 직접 이동

하는 경우이다. 클라이언트에 애플리케이션의 이전 상태에 대한 어떠한 정보도 유지할

수 없기 때문에, 이러한 경우 네트워크 부하와 애플리케이션의 응답속도 면에서 비싼

비용을 지불하게 한다.

그림 2.4 클로즈업 모드에 들어갈 때와 나갈 때 화면 레이아웃에 미치는 영향

클로즈업이미지

썸네일로되돌아가기

Page 88: Prototype & Scriptaculous 인 액션

��

시작하기1부

자, 전통적인 웹 애플리케이션이 우리가 양방향의 응답성이 뛰어난 애플리케이션을

개발하는 데 문제점을 지니고 있음을 볼 수 있었다. 나아가서 QuickGallery는 전통적

인 웹 애플리케이션이 가진 문제를 가지고 있다. 우리는 이 문제에 대해서 3장과 4장을

할애할 것이고 QuickGallery에 Ajax를 도입하고 몇몇 해결책에 대해 논의할 것이다.

2.3 요약

이번 장에서는 Ajax가 적용되지 않은 갤러리 애플리케이션의 주요한 특징에 대해

서 소개하였고 이것을 토대로 이어지는 장들에서 Ajax를 적용하여 변경할 것이다.

QuickGallery는 맡은 업무를 수월한 방법으로 수행하는 단순한 애플리케이션이다. 전

통적인 웹 애플리케이션의 상호작용 모델에 대한 논의로부터 이 애플리케이션이 문제

점을 가지고 있음을 볼 수 있었으며, 이러한 문제점들을 대부분의 전통적인 웹 애플리

케이션들이 겪고 있음을 알 수 있었다.

이러한 문제에 대한 해결책으로 Ajax를 도입하는 것은 어쩌면 어려워 보일 수도 있다.

하지만 Prototype과 Scriptaculous의 도움으로 원하는 것을 얼마나 쉽게 얻을 수 있는

지 보여줄 수 있기를 희망한다. 다음 장에서 이러한 작업을 시작할 것이며 전체 페이지

갱신을 사용하지 않고 Ajax 기반으로 서버와 통신하는 방법을 사용할 것이다.

Page 89: Prototype & Scriptaculous 인 액션

��

Prototype으로 Ajax를 단순화하기

03장

이번 장에서 다루는 내용 : QuickGallery에 Ajax를 사용하기 위해 재설계하기

: XML과 Ajax 함께 사용하기

: JSON과 Ajax 함께 사용하기

Page 90: Prototype & Scriptaculous 인 액션

�6

시작하기1부

비동기 방식의 요청을 서버로 전송함으로써 사용자 인터페이스로부터 통신구조를 분

리하는 것이 Ajax의 핵심기능이다. 비동기 통신이 사용자 편의에 미치는 영향은 아무

리 언급해도 지나치지 않다. 비동기 통신은 웹 애플리케이션이 자신이 처리해야 할 일

들을 처리하는 동안 사용자의 작업과 웹 애플리케이션의 작업이 충돌하지 않고 원활하

게 처리될 수 있도록 지원한다. 사용자 편의를 제고하는 것은 현재의 웹 애플리케이션

을 보다 사용하게 쉽게 만들 뿐만 아니라 많은 노력을 요하는 사용자 시나리오와 매일

매일 집중적으로 사용되는 미션-크리티컬한 애플리케이션의 범위까지 웹 애플리케이

션의 사용범위를 확장시킬 수 있게 만든다.

1장에서 XMLHttpRequest 객체를 다루는 것이 얼마나 복잡할 수 있는지, 그리고

Prototype의 Ajax 관련 헬퍼 클래스들을 사용하여 XMLHttpRequest 객체를 얼마나 쉽

게 다룰 수 있는지에 대해 간단하게 알아보았다. 이번 장에서는 Prototype의 Ajax 지

원 내용에 대해서 보다 포괄적으로 알아볼 것이며 Prototype이 제공하는 옵션들의

전체적인 범위에 대해서도 검토할 것이다(이번 장과 다음 장은 Prototype을 다루고

Scriptaculous는 5장부터 다룬다). 여러분이 이번 장의 내용을 숙지하게 되면 중요도

순에 따라 여러분이 개발하는 애플리케이션의 사용자 편의를 향상시킬 수 있을 뿐만

아니라 안정적으로 제시간에 일을 마칠 수 있게 될 것이다.

2장에서 Prototype의 Ajax 지원 기능을 테스트하기 위한 용도로 사용할 QuickGallery

애플리케이션을 소개했다. 2장의 말미에 언급했듯이 QuickGallery는 Ajax 없이 동작

이 가능하지만 서버 측으로 요청을 보낼 때마다 전체 페이지를 갱신해줘야 하기 때문

에 응답성이 떨어지는 불편함이 있었다. 이번 장에서는 이 문제점에서 시작하여 어떻

게 프리젠테이션 레이어에서 통신구조를 분리하고 사용자를 귀찮게 하는 전체 페이지

갱신을 제거할 것인지를 설명할 것이다.

3.1 Ajax 적용을 위한 재설계

QuickGallery 애플리케이션은 아주 기본적인 기능만을 가지고 있으며 우리가 수행시

킨 작업만을 수행한다. 현재의 형태에서는 그다지 훌륭해 보이지 않는 외형을 가지고

있지만 프리젠테이션 레이어를 스타일시트로 분리해낸 뒤에 전문적인 디자인 팀이 처

리하거나 또는 금요일 오후에 우리가 직접 처리하면 애플리케이션의 외형에 대한 작업

을 처리해줄 수 있을 것이다.

Page 91: Prototype & Scriptaculous 인 액션

�7

Prototype으로 Ajax를 단순화하기 3장

애플리케이션을 사용해보면서 많은 수의 썸네일을 최초로 생성하는 시점과 같은 특

정한 경우에 수행속도가 느려지는 것을 느꼈을 것이다. 또 옆 부분에 다른 컨텐트를 배

치하여 보다 큰 페이지를 구성하는 등의 여러 실험을 통해 지속적으로 전체 페이지를

갱신하는 것이, 심지어는 집중력까지 떨어뜨린다는 사실도 알아냈다. 나아가 애플리케

이션을 사용해 보면서 우리가 추가하고 싶은 많은 기능들도 목록으로 정리하였다. 이

렇게 정리한 기능들에는 하나 이상의 폴더를 동시에 브라우징하는 기능, 서버 측의 컨

텐트가 변경되었을 때 썸네일 리스트를 자동으로 업데이트하는 기능, 우리가 보고 있

는 이미지들을 일자순, 이름순, 그리고 이미지들에 붙여 놓은 태그와 같은 정보 순서로

필터링하는 기능들이 있다. 또 우리는 이미지들을 폴더들 사이로 이동하고 삭제하고

웹으로 새로운 이미지들을 업로드하는 경우에 이미지들이 재정렬되기를 원한다.

이러한 기능들의 구현에 많은 노력이 필요하다는 것을 알고 있고 Ajax가 이러한 귀

찮은 문제를 해결해 줄 수 있다고 들었다. 또한 사용자들이 중지-시작을 반복해야 하기

때문에 사용하기 어려워지는 전통적인 애플리케이션과 사용자 간의 대화특성 1 을 보

다 양방향의 특징들로 변화시킬 것임을 알고 있다. 전통적인 웹 애플리케이션 모델은

우리가 2장에서 개발한 기본적인 기능들만을 처리하고 있는데, 애플리케이션을 가지고

수행할 수 있기를 바라는 모든 기능을 지원할 것처럼 보이지는 않는다. 따라서 다음 버

전의 QuickGallery 애플리케이션을 Ajax 기반 애플리케이션으로 개발할 것이다. 대부

분의 프로젝트와 마찬가지로 웹 애플리케이션을 Ajax가 지원되는 형태로 바꾸기 위한

첫 번째 단계는 이미 존재하는 기능을 Ajax를 사용하여 다시 구현하는 것이다. 이번 장

과 다음 장에서 QuickGallery의 기능을 다시 구현할 것이고 Prototype과 Scriptaculous

의 모든 세부적인 내용까지 이해를 하게 되면 12장에서 다시 QuickGallery로 돌아가

새로운 기능 몇 가지를 추가해볼 것이다.

이런 작업들 중에 우리는 몇 가지 선택을 하게 된다. Ajax는 다른 방식으로 조합될

수 있는 여러 가지 기술들과 함께 사용될 수 있다. 어떤 방식을 채택할지를 선택해야

하므로 우리가 선택할 수 있는 몇 가지 선택사항들에 대해 살펴보도록 하겠다.

3.1.1 비동기적인 요청의 설계

지금까지 언급해 왔듯이 Ajax의 핵심기능은 비동기적인 요청을 생성하는 것이다. 즉

1  HTTP 프로토콜의 비연결 지향적 특성 때문에 발생하며 요청, 응답 간에 연결상태가 없음을 의미한다.

Page 92: Prototype & Scriptaculous 인 액션

�8

시작하기1부

전체 페이지가 갱신됨으로 해서 사용자가 수행하던 작업을 멈추지 않아도 되도록 서버

와 백그라운드로 통신을 하는 것이다. 우리의 중요한 선택사항은 서버가 요청에 대해

어떠한 형태로 응답을 하게 할 것이냐, 하는 것이다. 폭 넓게 보면 세 가지의 선택사항

이 있다.

첫째, HTML 형태의 컨텐츠로 응답할 수 있다. 이 경우에는 전체 웹 페이지를 리턴하

지 않고 현재 존재하는 웹 페이지에 끼워 넣어질 수 있는 컨텐츠의 일부만을 리턴한다.

이런 경우를 컨텐츠 중심적인 Ajax 활용이라고 부른다. 두 번째는 웹 브라우저가 실행

시킬 약간의 자바스크립트를 생성해서 리턴하는 경우이다. 이런 경우 스크립트 중심적

인 방법이라고 부른다. 세 번째는 클라이언트 측의 커스텀 코드가 파싱한 후에 실행시

킬 수 있도록 데이터 자체를 리턴하는 방법이다. 이런 경우를 데이터 중심적인 방법이

라고 부른다.

또한 우리가 언급해야 할 방법들 중에는 비동기적인 요청을 생성하기 위해서

XMLHttpRequest 객체를 전혀 사용하지 않는 방법들도 존재한다. 숨겨져 있는 iframe

을 사용하여 데이터를 로딩하는 것과 같은 이러한 방법들은 컨텐트, 스크립트 그리고

데이터 중심적인 패턴으로 분류될 수 있다. 그러나 동적으로 이미지의 src 속성 값을

변경하는 것과 같은 방법은 전혀 다른 방법이다.

각 접근방법에 대해서는 찬반양론이 존재한다. 컨텐트 중심에서 스크립트 중심, 데

이터 중심적인 솔루션으로 이동함에 있어 우리는 보다 많은 책임을 클라이언트 측 코

드에 지우게 된다. 그러므로 클라이언트 측 코드의 복잡도를 증가시키는 대가로 서버

측 코드를 단순화시키게 된다. 자 그럼 각 옵션들에 대해서 간략하게 알아보자.

컨텐트 중심적인 Ajax 활용

컨텐트 중심적인 방법에서는 HTML을 생성하고 생성된 HTML을 자바스크립트를 사

용하여 동적으로 페이지에 끼워 넣는다. 이것은 전통적인 웹 애플리케이션을 Ajax로

변경할 때 아주 큰 이점이 있다. 왜냐하면 전통적인 애플리케이션(2장에서 소개했던

QuickGallery의 버전) 또한 HTML을 생성해내기 때문이다. 우리는 공식적인 DOM 메

소드를 사용할 수도 있고 또는 innerHTML 프로퍼티를 사용할 수도 있다. DOM 메소드

는 공식적인 표준이라는 이점을 가지고 있지만 사용하기가 다소 어렵다. innerHTML

프로퍼티는 어떤 표준의 일부도 아니지만 그것은 사용하기가 쉽고 모든 주요 브라우저

Page 93: Prototype & Scriptaculous 인 액션

�9

Prototype으로 Ajax를 단순화하기 3장

에서 동작한다. 우리는 대다수의 Ajax 개발자를 따라 innerHTML을 사용할 것이다.

가장 간단하게 처리하기 위해 HTML의 한 부분을 리턴할 것이며 하나의 DOM 엘리

먼트에 innerHTML로 할당할 것이다. 불행하게도 QuickGallery 애플리케이션의 설계

는 우리가 폴더를 표시할 때 현재 위치 메뉴, 하위폴더 목록, 썸네일 이미지 등 한 번에

스크린의 세 개 영역을 업데이트를 하도록 한다. 서버로 세 개의 개별적인 호출을 할

수도 있지만 이것은 여러 가지 새로운 문제를 만들어 낸다. 첫째, 네트워크 오버헤드를

유발할 수도 있다. 둘째, 현재 하위폴더와 이미지들의 목록을 동일한 반복연산을 통해

서 생성해내기 때문에 비즈니스 로직을 한 번 이상 실행해야 할 수도 있다. 셋째, 스크

린의 세 부분이 서로 동기화가 되지 않을 가능성을 유발할 수도 있다. 그러므로 컨텐트

중심적인 접근방법을 채택하려면 세 가지 세트의 컨텐트에 대한 요청을 한 번에 처리

하는 방법과 이들에 대한 응답을 클라이언트에 배포하는 방법을 찾을 필요가 있다.

곧 컨텐트 중심적인 접근방법으로 돌아갈 것이지만 우선 다음 옵션으로 넘어가 보자.

스크립트 중심적인 Ajax

스크립트 중심적인 접근에서는, 자바스크립트를 생성하여 클라이언트에게 전송한 뒤

자바스크립트는 언어에 내장된 eval() 함수를 이용하여 실행된다.

스크립트 중심적인 접근방법은 스크린에서 다수의 영역이 업데이트되는 경우에 보

다 유연하게 사용될 수 있다. 부정적인 면으로는, HTML이 아닌 자바스크립트를 생성

하기 위해 서버 측 코드를 보다 많이 변경해야만 한다는 것이다. 만약 이 방법을 따라

갈 것이라면, 코드 생성에 대한 베스트 프랙티스에 대해서 많이 공부해 두는 것이 좋고

직접 저수준의 코드를 생성하는 것보다는 고수준 API를 사용하여 코드를 생성하는 것

이 좋다. 이것은 생성되어야 할 코드를 단순화시켜주고 또한 클라이언트와 서버 측 코

드의 결합도(coupling)를 감소시켜줄 것이다.

코드 간의 단단한 결합도는 어떠한 소프트웨어 개발에 있어서도 일반적인 문제이다.

두 부분의 코드들에 있어 한 쪽이 다른 쪽의 상세한 구현에 대해서 호출을 할 때 단단

하게 결합되어 있다고 표현된다. 느슨하게 결합된 코드에서는, 각 부분의 코드에 있어

단지 몇 개의 메소드 또는 함수들 만이 public으로 선언되어 있어서 이 두 부분의 코드

간의 통신은 이렇게 public인 메소드들을 통해서만 가능하다. 느슨한 결합의 이점은

각 부분의 코드들이 다른 코드들과의 상호작용이 깨지는 것을 두려워할 필요 없이 다

Page 94: Prototype & Scriptaculous 인 액션

60

시작하기1부

른 부분의 코드들과는 무관하게 수정되거나 향상될 수 있다는 것이다. 많은 부분들로

구성되는 복잡한 소프트웨어에서, 단단한 결합은 정체와 침체로 이어질 수 있다.

따라서 스크립트 중심적인 접근방법을 따를 계획이라면, 고정적인(즉, .js 파일들에

작성된 자바스크립트) 클라이언트 측 코드에 자바스크립트 API를 정의해야만 하고 그

API들을 호출해야 한다. 이 옵션에 대해서 더 고민하기 전에 우리가 사용할 수 있는 마

지막 옵션에 대해서 알아보도록 하자.

데이터 중심적인 Ajax

데이터 중심적인 Ajax 애플리케이션은 가공되지 않은 데이터를 서버로부터 수신한다.

데이터의 포맷은 그것이 텍스트로 표현될 수 있는 한 우리가 좋아하는 어떤 것이라도

될 수 있다. 가장 보편적인 두 가지는 XML과 JSON이다.

XML은 산업표준의 포맷으로 서버 측 언어와 프레임워크들로부터 폭넓게 지원되고

있으며 게다가 최근에는 거의 모든 프로그래밍 환경이 지원하고 있다. 나아가서 Ajax

에서 비동기적인 요청을 수행하는 XMLHttpRequest 객체는 수신되는 응답 데이터를

자동적으로 파싱하고 이 데이터들을 단순한 텍스트가 아닌 객체들의 집합으로 다룰 수

있도록 XML을 특별히 지원한다. 이러한 기능의 단점은 DOM 메소드를 사용해서 파싱

된 XML 데이터를 다룬다는 것인데 이미 언급한 바대로 이것은 다소 귀찮다.

이런 부분에서 Prototype이 추가적인 DOM 헬퍼(11장에서 보게 된다)들을 제공하

고 DOM 유사 배열(10장에서 보게 된다)에 대한 지원을 함으로써 우리의 불편함을 덜

어줄 수 있다. 그렇다 하더라도, JSON이 XML보다 가벼운 대안으로 보인다. JSON은

JavaScript Object Notation을 의미하는 것으로 복잡한 객체를 자바스크립트 인터프리

터가 쉽게 파싱할 수 있는 포맷으로 나타낼 수 있도록 해준다. 일단 파싱되면 이들 객

체들은 XML을 다루는 것보다는 훨씬 적은 오버헤드로 일반적인 자바스크립트 객체와

같이 다룰 수 있게 된다. JSON을 사용할 때의 단점은 이것이 오로지 자바스크립트 인

터프리터에 의해서만 이해되기 때문에 아주 적은 수의 서버 시스템만이 쉽게 이해할

수 있다는 것이다. 그러므로 서버 측에서 데이터를 생성하는 것은 대체로 보다 많은 오

버헤드를 유발한다.

우리가 데이터의 포맷으로 어떤 형태를 선택하든 간에, 데이터 중심적인 접근 방법

은 응답을 파싱하기 위해서 추가적인 코드를 작성하고 그것을 가지고 무엇을 할지를

결정해야 한다.

Page 95: Prototype & Scriptaculous 인 액션

6�

Prototype으로 Ajax를 단순화하기 3장

이렇게 우리가 가진 세 가지 옵션에 대해서 알아보았다. 하지만 QuickGallery 애플

리케이션을 Ajax 기반으로 다시 만들기로 하는 동안, Prototype 라이브러리가 Ajax를

작업하기 쉽게 도와준다고 들었다. 그러니 선택을 하기 전에, Prototype이 우리를 위해

서 무엇을 해줄 수 있는지 보도록 하자.

3.1.2 Prototype의 Ajax 관련 클래스

앞에서 Ajax의 서로 다른 세 가지 유형에 대해서 고려해보았다. 이들 중에 어떤 것을

Prototype이 지원하는가? 짧게 대답하면 “모두” 이다. 그러나 모든 것을 동일한 방법으

로 지원하지는 않는다. 자 그럼 Prototype이 지원하는 Ajax 관련 클래스들을 살펴보고

우리가 어떤 결론에 도달할지 보도록 하자.

Prototype은 하나가 아니라 네 개의 Ajax 헬퍼 객체를 제공한다. 이것들은 클래스 계

층구조로 구성되어 있으며 Prototype의 자체적인 클래스 정의방법을 사용한다. 8장에

서 Prototype의 내부를 들여다 볼 것이기 때문에 이런 부분에 대한 상세한 구현에 대해

서 아직 걱정할 필요는 없다. 지금은 단지 Prototype이 자동차 제조사가 몇몇 모델을

제공하는 것과 같이 몇 개의 Ajax 헬퍼 객체를 제공한다는 것만 이해하고 있으면 된다.

Prototype이 제공하는 Ajax 헬퍼들 중 가장 기본적인 헬퍼는 우리가 가고자 하는 곳에

부드럽고 소동 없이 도착하게 해줄 것이다. 그보다 좀 더 고급 버전의 헬퍼들은 추가적

인 편의성과 특징들을 제공한다. 이번 장에서 가장 기본적인 Ajax 객체로 시작하고, 4

장에서는 특별한 객체들에 대해서 다뤄볼 것이다.

Ajax.Base

모든 Ajax 헬퍼 클래스들의 공통적인 부모 클래스는 Ajax.Base 클래스이다. 객체지향

이란 용어 관점에서 보면, 이것은 추상 클래스이거나 가상클래스이다. 즉, 이 클래스들

은 직접 사용되도록 설계되지 않고 오히려 이것을 상속받는 클래스들의 공통적인 기반

으로 사용되도록 설계된 것이다.

Ajax.Base는 Prototype에 의해 통신용 모듈로 참조되고 이 모듈을 통한 요청이 성공

적이었는지 아닌지를 결정하는 XMLHttpRequest 객체를 인스턴스화하는 기능을 제공

한다. 또한 HTTP관련 옵션, CGI 파라미터 그리고 요청이 비동기 방식인지 아닌지를

지정하는 것과 같은 일반적인 파라미터를 전달하는 기능을 제공한다(만약 이 용어들이

친숙하지 않다면 HTTP 프로토콜에 대한 입문내용을 다룬 부록 A를 참고하라).

Page 96: Prototype & Scriptaculous 인 액션

62

시작하기1부

이 모든 것들이 베이스 클래스에 포함된 것들이다. 자 그럼 실제로 사용 가능한 첫

번째 Ajax 클래스를 보도록 하자.

Ajax.Request

Ajax.Request 클래스는 URL로 표현되는 서버 측 리소스에 요청을 보내는 메커니즘을

제공함으로써 Ajax.Base 클래스를 확장한다. 또한 서버로부터 수신한 응답을 처리하

고 고수준 콜백 기능을 정의하는 데 필요한 모든 구현을 제공한다. 예제 1.4에서 Ajax.

Request를 어떻게 사용하는지를 보았으며 이것은 Ajax.Request를 사용하지 않고 작성

한 예제 1.2에 비해 상당히 코드가 짧다.

Ajax.Request 객체는 생성시에 두 개의 파라미터를 받는다. 첫째는 요청이 수행될

서버 측 리소스의 URL이다. 둘째는 옵션들을 포함하는 자바스크립트 객체(자바스크립

트 객체들은 연관 배열처럼 처리될 수 있다-우리는 이 특징들에 대해서 8장과 10장에

서 자세히 논의할 것이다)로 몇 개의 옵션이라도 설정할 수 있다. Ajax.Request 객체가

생성될 때, 옵션으로 전달되는 파라미터들은 모두 생략될 수 있으며 정의된 것들 중 일

부만 전달될 수도 있다. 명시적으로 정의되지 않은 옵션들은 모두 적절한 기본값으로

설정된다. 따라서 우리는 Ajax.Request 객체를 다음과 같이 아주 간단하게 생성할 수

있다.

varrequest=newAjax.Request(“ajax/myData.jsp”);

일반적으로, 몇몇 옵션을 파라미터로 전달할 수 있으며 옵션들을 인라인으로 정의할

것이다. 어떤 CGI 파라미터를 요청이나 요청이 완료되었을 때 호출되는 함수에 전달하

려고 한다면, 호출하는 코드는 다음과 같을 것이다.

Varrequest=newAjax.Request(

“ajax/myData.jsp”,

{

parameters:“id=1234”,

onComplete:parseData

}

);

두 번째 파라미터(그렇다, 전달되는 파라미터는 단지 두 개 뿐이다!)는 우리가 인라인

으로 정의한 객체이다. JSON이라고 알려진 이러한 표기법은 객체의 인스턴스를 생성

Page 97: Prototype & Scriptaculous 인 액션

63

Prototype으로 Ajax를 단순화하기 3장

하고 해당 인스턴스의 프로퍼티를 명시하는 약식 표기법이다. 이런 형태의 파라미터는

Prototype과 Scriptaculous 코딩 스타일의 표준적인 부분이다. 이 책에서 이러한 코딩

스타일을 본 것이 처음이므로 조금 상세한 부분을 보고 넘어가도록 하자.

Prototype.js의 코딩 스타일

루비, 파이썬 그리고 Visual Basic과 같은 많은 스크립팅 언어에 있어, 함수에 이름이

있는 파라미터들을 전달하는 것은 가능한 일이다. 이것은 만약 함수가 넓은 범위의 파

라미터를 받을 수 있다면 아주 도움이 되는 일이지만 보통은 한 개 또는 두 개 정도를

받아 호출된다. 파라미터에 이름이 붙여진 덕에 일반적인 사용자들에게는 합리적인 기

본값을 제공해주고 또한 파워 유저에게는 세세한 수준의 컨트롤을 가능케 한다.

자바스크립트는 이름이 붙여진 파라미터를 지원하지 않는다. 하지만 Prototype.js는

가장 간단한 코딩 방식을 도입하였다. Ajax.Request의 생성자 함수는 이러한 방식을

사용하는데 그럼 이것이 어떻게 동작하는지 예제를 통해 살펴보자.

Ajax.Request 객체를 생성하는 과정에서, 우리는 생성자 함수를 단지 두 개의 파라미

터만을 가지고 호출했으며 두 번째의 것은 다소 복잡하다. 우리는 이 파라미터를 JSON

을 사용하여 인라인으로 정의했다. 이전에 우리가 사용한 표기법은 다음과 같이 쓸 수

도 있다.

varxyz=newObject();

xyz.parameters=“id=1234”;

xyz.onComplete=parseData;

varrequest=newAjax.Request(“ajax/myData.jsp”,xyz);

JSON을 사용하면 확실히 더 간결해지고 일단 여러분이 익숙해지기만 한다면 빨리

훑어보기에 훨씬 쉽다.

여러분은 Prototype과 Scriptaculous가 왜 이러한 형태로 옵션을 전달하는지 궁금할

것이다. 결국 자바스크립트는 선택적인 파라미터를 전달할 수 있도록 하고 있다. 왜 모

든 옵션들을 파라미터로 갖는 함수를 정의하지 않는 것일까?

설명을 위해서, 함수가 7개의 파라미터를 받는다고 가정해보자, 이 중에서 첫 번째 파

라미터만이 필수이다. 이것은 두 번째 파라미터부터 7번째 파라미터까지는 옵션사항이

고 이들이 파라미터 목록의 끝부분에 온다면 전혀 명시될 필요가 없다는 것을 의미한다.

Page 98: Prototype & Scriptaculous 인 액션

6�

시작하기1부

단 하나의 필수 파라미터를 명시하여 이 함수를 호출하는 것은 놀라울 만큼 간단하다.

someFunction(‘something’);

간단한 null 체크만으로 파라미터가 존재하는지를 알 수 있기 때문에 함수의 내부에 있

는 코드가 파라미터들이 존재하는지를 체크하는 것은 간단하다. 만약 함수의 시그너쳐

가 다음과 같이 정의되었다면,

functionsomeFunction(required,opt1,opt2,opt3,

opt4,opt5,opt6){

다음과 같은 테스트를 통해서,

If(opt1)alert(‘opt1exists!’);

파라미터가 존재하는지 여부를 체크할 수 있다.

이 모든 것은 함수 작성자에게 아주 좋은 일이다. 그러나 이 함수를 호출해야 하는

바보 같은 사용자들에게는 어떤가? 사용자가 이 함수의 옵션 중 4번째와 마지막 파라

미터를 명시하여 호출하고 싶다라고 가정해보자. 그러면 이런 형태로 호출할 것이다.

someFunction(‘something’,null,null,null,‘avalue’,

null,‘anothervalue’);

앗! 파라미터들의 순서를 지킬 필요가 있기 때문에, 값을 설정하고 싶지 않은 옵션 파

라미터 항목들에 대해서 null 값들이 명시되어야 한다. 이것은 코드를 아주 지저분하게

만들 뿐 아니라 읽기도 어렵게 만들고, 사용자로 하여금 함수 호출에 대한 이해가 필요

할 때마다 문서나 함수의 소스코드에 심하게 의존하게 만든다. 함수에 대한 이러한 호

출코드를 보는 것만으로는 파라미터들의 특성이나 의미에 대해 많은 것을 알려주지 않

는다. 우리는 이름이 붙여진 파라미터를 사용할 것이므로 의미에 대해 많은 것을 알려

줄 수 있다.

자, Ajax.Request 객체를 호출해보자. 익명 객체를 사용하지 않기 때문에 호출코드

는 다음과 같을 것이다.

newAjax.Request(‘ajax/myData.jsp’,“id=123”,parseData);

어떤 파라미터가 post 방식으로 전송되는 값 중 body에 해당하는지 쉽게 구분할 수 있

는가? 콜백 함수는 어느 것인가? 함수의 소스코드나 문서를 보지 않는 한 아무것도 확

Page 99: Prototype & Scriptaculous 인 액션

6�

Prototype으로 Ajax를 단순화하기 3장

실히 알 수 있는 방법이 없다.

더 나쁜 것은, 이것들 외에도 이 객체에 많은 옵션들이 더 있다는 것이다. 따라서 익명

객체를 사용하는 방식을 사용하지 않는다면 객체에 대한 호출은 보다 끔찍하다.

newAjax.Request(‘ajax/myData.jsp’,null,null,“id=123”,null,parseData);

익명 객체를 사용하는 기술이 가져오는 이점은 다음의 두 가지이다.

명시적으로 지정된 옵션들만이 포함되며 null 값들이 차례를 지키기 위해 위치

를 차지 하도록 요구될 필요가 없다.

각 옵션들이 명시적으로 이름이 부여되므로 어떤 옵션에 값들이 할당되어 있는

지 알아내기가 쉽다.

일단 여러분이 이런 이상한 표기법에 대해 익숙해졌다면 이 표기법을 어떻게 잘 활용

할지 궁금해할 것이다. 그리고 멀지 않아, 복잡한 파라미터를 받는 여러분의 함수에서

이런 표기법을 사용하고 있을 것이다.

우리는 8장에서 JSON 문법에 대해서 보다 깊게 논의할 것이다. 지금은 우리가 다루

지 않았던 옵션들에 대해서 알아보도록 하자.

Ajax.Request의 선택사항 옵션들

예로 든 Ajax.Request 객체에 넘겨준 첫 번째 옵션은 서버 측에 POST 변수로 전달될

간단한 쿼리스트링이다. 두 번째는 데이터를 파싱해 낼 수 있도록 서버가 응답을 리턴

할 때 호출되는 콜백함수이다. 여기서 우리는 미리 정의한 함수 객체에 대한 레퍼런스

를 넘겨준다. 그러나 일반적으로 이러한 배열들 내에 인라인으로 정의되어 생성자 함

수 호출을 상당히 길어지게 만드는 함수들을 보게 될 것이다. 들여쓰기는 일반적으로

가독성을 유지하는 데 중요한 요소이다.

옵션을 객체 형태로 넘겨주는 방법은 파워풀하고 간결하지만 역시 약점을 가지

고 있다. 소스코드가 사용가능 할지라도, 객체가 지원하는 전체 범위의 옵션들을 모

두 파악하기란 정말 어렵다. 이 때문에 우리가 이런 옵션들을 볼 때마다 Prototype

과 Scriptaculous 객체에 사용 가능한 옵션들을 표로 정리할 것이다. 표 3.1은 Ajax.

Request 객체를 생성할 때 설정할 수 있는 옵션들을 디폴트 값과 함께 정리하였다.

Page 100: Prototype & Scriptaculous 인 액션

66

시작하기1부

테이블 3.1 Ajax.Request 객체의 옵션 프로퍼티

이름 디폴트 값 설명

method ‘post’ 요청을 보낼 때 사용할 HTTP 메소드. 일반적으로 ‘get’이나 ‘post’

(Prototype에서는 이들을 소문자로 사용함을 주목하라). 좀 더 자세한

내용은 부록 A를 참조하라. Ajax.Base에 사용된다.

asynchronous True 요청을 보낼 때 응답이 올 때까지 스레드의 실행을 블로킹시킬지 (만약

false로 설정되면) 또는 스레드의 실행이 즉시 리턴되고 응답의 수신

이 콜백함수를 실행시킬지를 나타내는 값(만약 true 설정되면)이다.

자바스크립의 인터프리터가 싱글-스레드 기반이기 때문에, 동기방식

의 요청들은 브라우저를 중지시켜 사용자 인터페이스 전체를 블로킹하

는 경향이 있다. 따라서 동기방식의 요청들은 권장되지 않는다. 이 옵

션은 Ajax.Base에 사용된다.

parameters ‘’ GET방식 요청의 URL 쿼리스트링이나 POST방식 요청의 요청 body

부분으로 서버로 전송되는 문자열 파라미터. GET방식 요청은 쿼리스

트링 포맷을 지켜야 하지만 POST방식 요청은 XML, JSON, 또는 어

떤 다른 형태의 텍스트 body로도 요청을 보낼 수 있다. 다른 방법으로

쿼리스트링을 생성할 수 있는 배열이 될 수도 있다. 이 옵션은 Ajax.

Base에 사용된다.

postBody null parameters와 동일한 옵션이지만 POST방식의 요청에만 사용된다.

requestHeaders null 부가적인 HTTP 헤더정보로 요청에 적용될 수 있는 배열 데이터.

HTTP 헤더에 대해서는 부록 A에서 자세히 다룬다. 일반적인 사용으로

는 요청의 MIME 타입을 설정하는 것이 있다.

onLoading null XMLHttpRequest 객체가 로딩 상태(readyState=1)에 도달했

을 때 호출되는 콜백함수. 비록 Ajax.Request 객체가 기반 객체인

XMLHttpRequest 객체의 readyState 전이에 대한 콜백함수를 제공

하지만, 이 옵션을 사용할 만한 경우는 거의 없다.

onLoaded null XMLHttpRequest 객체가 로딩을 완료한 상태(readyState=2)에 도달

했을 때 호출되는 콜백함수. 비록 Ajax.Request 객체가 기반 객체인

XMLHttpRequest 객체의 readyState 전이에 대한 콜백함수를 제공

하지만, 이 옵션을 사용할 만한 경우는 거의 없다.

onInteractive null XMLHttpRequest 객체가 인터렉티브 상태(readyState=3)에 도달

했을 때 호출되는 콜백함수. 이 콜백함수는 모질라 브라우저에서 큰 리

소스를 로딩할 때 예를 들어 간단한 진행바와 같은 것을 구현할 수 있

도록 여러 번에 걸쳐 호출된다. 그러나 인터넷 익스플로러에서는 로딩

되는 리소스가 아무리 커도 이 콜백함수는 단 한 번 호출된다.

onComplete null XMLHttpRequest 객체가 완료상태(readyState=4)에 도달했을 때

호출되는 콜백함수. 이 시점이 되면 응답은 완전히 로딩이 되었고 적절

하다면 XML로 파싱될 수 있다.

onSuccess null HTTP 응답코드의 값이 200-299 사이에 있을 때만 호출되는 보다 구

체적인 버전의 onComplete 핸들러. Ajax.Request 객체를 사용할 때

가장 자주 사용하는 콜백함수이다.

Page 101: Prototype & Scriptaculous 인 액션

67

Prototype으로 Ajax를 단순화하기 3장

이름 디폴트 값 설명

onException null 응답이 자바스크립트 exception을 만났을 때 처리를 위해 호출되는 콜

백함수.

onFailure null HTTP 응답코드의 값이 200-299 밖에 있을 때만 호출되는 보다 구체

적인 버전의 onComplete 핸들러로 응답이 성공적이지 않다는 것을

나타낸다. HTTP 응답의 상태들은 부록 A에 정리되어 있다. 많은 서버

측 프레임워크들이 HTML로 표현된 에러 메시지가 포함된 ‘success’

HTTP 응답(200코드)를 전송함으로써 내부적인 서버 에러들을 리

포팅함에 주목하라. 이 응답들은 onFailure 핸들러 함수가 아닌

onSuccess 핸들러에 의해 처리된다.

우리는 곧 QuickGallery 애플리케이션에서 Ajax.Request가 사용되는 것을 보게 될 것

이다. Prototype은 또한 Ajax.Updater와 Ajax.PeriodicalUpdater 같은 몇몇 보다 구체

적인 Ajax 헬퍼 클래스들을 제공하는데, 이 클래스들을 다음 장까지는 사용하지 않을

것이며 추후에 이들에 대한 주제로 돌아갈 것이다.

우리는 세 가지의 기본적인 Ajax의 사용형태와 Prototype이 제공하는 네 가지의

Ajax 헬퍼 객체에 대해서 개략적으로 언급하였다. 자, 이제 이들을 사용하여 2장에서

제시하였던 QuickGallery 애플리케이션에 새로운 생명을 불어넣을 차례다. 이 애플리

케이션은 다른 폴더로 이동할 때나 또는 클로즈업 이미지를 볼 때 전체 페이지를 갱신

한다. 이제 Ajax를 사용하여 이러한 전체 페이지 갱신 문제들을 제거할 것이다. 여기서

첫 번째 문제는 데이터, 스크립트 그리고 컨텐트 중심적인 방법이라는 세 가지 카테고

리 중 어떤 형태의 Ajax를 사용할 것이냐 하는 것이다.

우리는 이미 각각의 접근방법에 대한 장 ∙ 단점에 대해 알고 있다. 더 이상의 논의를

진행하는 것보다, 세 가지 접근방법 중 데이터와 컨텐트 중심적인 방법을 이용하여 먼

저 구현을 시작할 것이며 아직 스크립트 중심적인 구현에 대해서는 논의하지 않을 것

이다. 하지만 솔루션 중에 하나로서 이 접근방법을 채택하게 될 것이다.

두 가지 중 어느 접근방법에 대해서도 아주 자세하게 구현하지는 않을 것이다. 그러

나 각 접근방법에 대해서 여기서 다뤄본 경험은 어느 쪽으로 가야 할지를 결정하는 의

사결정을 할 때 도움이 될 것이다. 자, 얘기는 이 정도로 충분하다. 애플리케이션을 데

이터 중심적인 방법으로 구현하기 위해 재설계하는 것으로 시작하자.

Page 102: Prototype & Scriptaculous 인 액션

68

시작하기1부

3.2 XML과 Ajax 함께 사용하기

Ajax의 x가 XML를 의미한다는 것과 많은 Ajax 프로젝트가 요청에 대한 응답으로 서

버상에서 XML데이터를 생성하고 그것을 파싱한다는 것을 알고 있다. XML을 파싱하는

것은 XMLHttpRequest가 XML 파싱 기능을 내장하고 있기 때문에 XMLHttpRequest 객

체에 꼭 들어맞는 것처럼 보인다. 이번 절에서, XML을 통신수단으로 사용하는 Ajax 기

반의 QuickGallery를 개발할 것이다. 가장 중요한(그리고 빈번한) 애플리케이션의 페

이지 이동은 사용자가 새로운 폴더로 이동하거나 애플리케이션이 클로즈업 이미지를

보여줄 때 발생한다. 폴더의 경우가 보다 복잡하므로 먼저 이 경우에 집중하도록 하자.

새로운 폴더를 보여줄 때, 사용자 인터페이스의 세 가지 엘리먼트-현재 위치 메뉴,

하위폴더 목록, 썸네일 이미지-모두를 갱신해야 한다(그림 2.1을 보라). 만약 응답을

XML로 전송한다면 이런 모든 정보를 포함시켜야 한다.

3.2.1 XML 응답 설계하기

서버가 응답하고 클라이언트가 파싱할 XML 데이터를 어떻게 생성해내는지를 보기 전

에, 데이터 포맷을 정의할 필요가 있다. 결국 XML은 구조화된 데이터를 전송하는 범용

적인 포맷이므로, 우리는 어떤 태그들을 사용할지 그리고 이 태그들이 어떻게 연관될

지 결정할 필요가 있다. 그리고 이런 결정은 우리가 어떤 정보를 전송하려고 하는가에

따라 달라질 수 있다.

우리는 이미지 디렉터리 내의 경로, 인접한 하위폴더들, 그리고 현재 폴더의 컨텐트

들과 같은 세 부분의 정보를 전송해야 한다. 경로는 클라이언트에 하나의 값으로 전송

될 수 있지만 하위폴더 목록과 이미지 목록은 엘리먼트들의 컬렉션으로 다루는 게 최

상이다. 예제 3.1은 프로세스가 생성할 XML에 대한 예를 보여준다.

예 제 3.1 | Ajax QuickGallery에 의해 생성된 예제 XML 데이터

<gallerypath=’/plants/trees’> b Path 속성

<folders>c

하위폴더들의 목록 <folder>forest</forest>

<folder>barkclose-ups</folder> </folders> <images>

d이미지들의 목록<image>dscn0034</image>

Page 103: Prototype & Scriptaculous 인 액션

69

Prototype으로 Ajax를 단순화하기 3장

<image>dscn0037</image><image>dscn0187</image></images></gallery>

현재 이미지 폴더어디에 있는지를 구성하는데 사용할 수 있는 path 속성❶을 가진 최

상위 엘리먼트인 <gallery>를 정의하였다. 이 안에 하위폴더 목록❷과 이미지 목록

❸이 각각 포함되어 있다. 비록 두 가지 모두 옵션사항이지만 폴더가 적어도 하나나 둘

정도는 포함할 것이라 기대한다. 이미지 이름들이 파일의 형식을 나타내는 확장자 없

이 리턴된다는 것에 주목하라. 이전의 예에서와 같이, 모든 이미지들이 JPEG 포맷이며

이름들은 ‘.jpg’로 끝난다고 가정할 것이다. 파일 확장자를 생략함으로써 썸네일 이미

지 이름을 생성하는 것 또한 간단해진다.

XML이 클라이언트 측 코드와 서버 측 코드를 이어주는 역할을 하기 때문에 XML 포

맷부터 정의하는 것이 좋겠다. 그럼 XML이 어떻게 서버와 클라이언트 코드를 구현하

는 데에 영향을 미치는지 보도록 하자.

3.2.2 서버 측 코드의 수정

Ajax가 적용되지 않은 버전의 QuickGallery 애플리케이션에 있어, 서버 측에서 리턴

되는 응답은 HTML 문서 형태를 띤다. 여기 예제 3.1에 설명된 것처럼, 우리는 응답이

순수한 XML로 리턴되기를 원한다. 다행하게도 Ajax를 적용하지 않았던 애플리케이션

은 로직(예제 2.1을 보라)과 프리젠테이션(예제 2.2를 보라)을 명확히 분리하여 깔끔하

고 모듈화된 방식으로 개발되었다. 이제 우리는 동일한 기본적인 정보-현재 위치메뉴,

하위목록, 이미지 목록-를 다른 형태로 보여주기를 원한다. 그러므로 프리젠테이션 템

플릿이 HTML 대신 XML을 생성하도록 바꿔주기만 하면 된다. XML 생성 템플릿 파일

은 예제 3.2에 표기되어 있다.

예 제 3.2 | XML을 생성하는 dataXML/images.php

<?phpheader( "Content-type:text/xml;charset=utf-8"

b MIME 타입 설정

);require('../config.php');

Page 104: Prototype & Scriptaculous 인 액션

70

시작하기1부

require('images.inc.php');C 비즈니스 로직을

포함

?><gallery path="<?phpecho$path?>"

d Path 속성

pre="<?phpecho$img_pre_path?>"><?phpif(count($subdirs)>0){?>

e하위폴더의 목록<folders>

<?phpforeach($subdirsas$i=>$value){?><folder><?phpecho$value?></folder><?php}?></folders><?php}?>

<?phpif(count($imgs)>0){?>f 이미지들의

목록

<images><?phpforeach($imgsas$i=>$value){?><image><?phpecho$value?></image><?php}?></images><?php}?></gallery>

XML을 생성하기 전에, 몇 가지 중요한 일을 처리해야 한다. 첫째, 브라우저가 응

답이 XML이라는 것을 이해할 수 있도록 응답의 MIME 타입을 셋팅 해줘야 한다❶.

XMLHttpRequest 객체는 응답을 XML 문서로 생성하는 내장 XML 파서를 가지고 있으

므로 클라이언트 측 코드에서 데이터를 파싱하기 위해 이 기능을 사용할 것이다. 그러

나 이 기능은 응답 body 부분이 XML이라는 것을 응답의 MIME 타입이 가리키고 있을

때만 사용할 수 있다. PHP에서는 MIME 타입을 설정하기 위해 내장 함수인 header()

함수를 사용한다. 다른 서버 측 언어들도 유사한 메커니즘을 가지고 있다―JSP는 페이

지 지시어(Directive)를 사용하거나 또는 직접 ServletResponse.setContentType()을

사용한다. ASP/.NET 프로그래머들은 Response.ContentType를 직접 세팅할 것이다.

루비온레일스 사용자들은 컨트롤러 클래스 코드 내의 headers[] 배열을 수정할 것이

다. 자세한 내용은 부록 E를 보라.

사전에 처리해야 할 두 번째 일은 HTML 템플릿에서 했듯이 비즈니스 로직 파일을

인클루드하는 것이다❷. 이것은 템플릿이 XML에 있는 블랭크를 채우는 데 필요한 변

수들을 생성할 것이다.

Page 105: Prototype & Scriptaculous 인 액션

7�

Prototype으로 Ajax를 단순화하기 3장

이것이 완료되면, 템플릿의 나머지 부분들은 단지 Path 속성과❸ 하위폴더 목록과❹

이미지들의❺ 컬렉션을 정의한 예제 3.1에 정의된 XML 스펙을 따른다.

여기서 우리가 한 것처럼 JSP를 템플릿으로 사용하여 XML을 직접 수동으로 작성하

는 것이 상당히 단순화된 것이라는 점을 명확히 해야겠다. 이번과 같은 작은 문서에 있

어서는 아주 잘 동작하겠지만 보다 큰 문서라면 수동으로 시작과 종료 태그들과 이스

케이프 변수 값들을 매핑하는 것은 부담이 된다. 실 서비스 환경에서는 객체 모델로부

터 자동으로 XML을 구성할 수 있도록 해주는 라이브러리를 사용할 것을 강력히 추천

한다. 하지만 이 책에서는, 강조하는 것이 클라이언트 관련 내용이고 이러한 라이브러

리들은 특정한 서버 측 기술에서만 의미가 있는 경향이 있으므로, 문제를 명확하게 하

기 위해 요점에만 집중하도록 하자

여러분이 보다시피, 서버 측 코드가 Ajax를 사용하도록 포팅하는 것은 상대적으로 간

단하다. 모든 Ajax 관련 작업이 누워서 떡 먹기처럼 쉽다고 단정하기 전에, 지금껏 우리

가 단지 문제의 한 단면만을 다뤄왔다는 것을 기억하도록 하자. 서버는 브라우저에게

XML을 어떻게 보내는지를 알고 있지만, 여전히 이 응답을 처리하기 위한 자바스크립트

코드를 작성해야 한다. 다음 절에서, 클라이언트 측에서 수정해야 할 내용들에 대해 살

펴볼 것이다.

3.2.3 클라이언트 측 코드의 작성

Ajax가 적용되지 않은 버전의 QuickGallery는 클라이언트 측 코드라고 할 만한 것이

없었다. 사용자가 상호작용할 수 있는 유일한 형태인 하이퍼링크를 포함한 HTML 인터

페이스는 서버에서 생성되었다. 전체적인 업무흐름(이미지 갤러리를 브라우징하는 데

이것이 너무 과한 용어가 아니라면 말이다)이 서버에 정의되어 있었다. 그러나 이제 서

버에서 가공되지 않은 데이터 스트림을 보낼 것이고 따라서 클라이언트 측에서 이것을

파싱할 코드가 필요하다. 우리는 더 이상 사용자가 어떤 일을 할 때마다 페이지를 갱신

하지 않을 것이기 때문에, 또한 클라이언트 측 코드가 작동할 페이지에 대한 간략한 레

이아웃도 정의할 필요가 있다.

좋은 소식은 페이지 윤곽을 정의하는 것이 아주 간단하다는 것이다. 심지어 페이지를

생성하기 위해 PHP(또는 어떤 다른 동적인 서버 측 시스템)를 사용할 필요도 없다. 초기

상태에는 컨텐트를 포함하고 있지 않기 때문에, 평범한 HTML이면 충분하다. 예제 3.3은

XML을 사용한 Ajax 기반 QuickGallery를 위한 페이지 레이아웃에 대한 코드를 보여준다.

Page 106: Prototype & Scriptaculous 인 액션

72

시작하기1부

예 제 3.3 | Ajax 기반 QuickGallery를 위한 페이지 레이아웃(dataXML/index.html)

<html><head><linkrel='stylesheet' type="text/css"href="images.css"/><scripttype='text/javascript' src='lib/prototype/prototype.js'></script>

b prototype 포함

<scripttype='text/javascript' src='lib/images.js'></script>

c클라이언트 측 코드 포함</head>

<body>

<divid='title'class='box'> d 타이틀바

정의

</div>

<divclass='box'id='closeup'>e 클로즈업 이미지

정의

<imgid='closeup_img'></img></div>

<divid='folders'class='box'>f 하위폴더

목록 정의

</div>

<divid='images'class='box'>g 이미지 목록

정의

</div>

</body></html>

HTML 파일 자체는 문서의 구조를 표현하는 것일 뿐이다. 실제 레이아웃 설정이나

위치를 맞추는 작업은 CSS 스타일 시트에, 그리고 동작들은 클라이언트 측 자바스크

립트에 위임한다. 먼저 Prototype 라이브러리를 포함시킨다❶. 그러고 나서 곧 자세한

내용을 보게 될 우리가 작성한 클라이언트 코드❷를 포함시킨다. 다양한 시각적인 엘

리먼트들-타이블바❸, 클로즈업 이미지❹, 폴더 목록❺, 썸네일 이미지 목록❻-은 처음

에는 컨텐트가 없고 할당된 클래스 속성을 가짐으로써 CSS 파일에 의해 스타일이 적용

된다. 또한 시각적인 엘리먼트들을 이 페이지 내에 동시에 포함시킨다는 것에 주목하

라. 클로즈업 이미지와 썸네일 목록은 동시에 보여지는 일이 결코 없다. 그러나 필요하

다면 엘리먼트들을 프로그램적으로 숨기거나 보이게 할 것이다.

클라이언트 측 로직을 구현하는 것은 그렇게 간단하지가 않다. 자바스크립트로 Ajax

Page 107: Prototype & Scriptaculous 인 액션

73

Prototype으로 Ajax를 단순화하기 3장

요청을 생성, XML 응답 파싱, 그리고 사용자 인터페이스의 다양한 부분을 렌더링하는

것을 처리해야 한다. 우리는 이러한 각 단계를 처리하는 코드를 제공해야 한다.

첫 번째 단계는 서버로 요청을 전송하는 것이다. 자, 그럼 보도록 하자.

서버에 데이터를 요청하기

우리가 3.1.2 항에서 다룬 Prototype의 Ajax.Request 클래스를 사용하여 아주 쉽게 서

버에 요청을 보낼 수가 있다. 다음과 같이 요청의 생성을 함수 내에 래핑할 것이다.

functionload(path){

newAjax.Request(

"images.php?path="+path,

{

method:"get",

onSuccess:parseAjaxResponse

}

);

}

서버 측 프로세스는 현재 폴더에 대한 경로 정보 하나만을 파라미터로 받아서 우리

의 함수에 경로정보를 파라미터로 넘겨줄 것이다. Ajax.Request 객체는 생성될 때 파

라미터로 받을 수 있는 여러 옵션을 가지고 있다. 그러나 지금은 간단하게 HTTP 관련

옵션과 응답이 도착했을 때 그것을 처리할 콜백 함수에 대한 레퍼런스만을 명시할 것

이다.

여기서 우리는 기반객체인 XMLHttpRequest를 비동기 방식으로 사용한다. 콜백 핸

들러를 사용하는 것은 단순히 응답이 돌아올 때까지 기다리는 것보다는 약간 더 복잡

하지만 훨씬 유연하고 사용자 친화적이다. 어떤 브라우저에서는 동기방식의 요청이 완

료될 때까지 기다리는 동안 전체 사용자 인터페이스를 사용할 수 없게 된다. 대부분의

실제 시스템의 Ajax 코드들은 비동기 요청을 사용하며, Ajax.Request 객체는 비동기

방식을 디폴트로 하고 있다.

응답을 풀어놓기

이것은 데이터 중심적인 Ajax 구현방법이다. 따라서 응답은 가공되지 않은 데이터로

이루어져 있다. 일단 응답이 도착하면 응답이 포함하고 있는 데이터를 파싱해야 한다.

Page 108: Prototype & Scriptaculous 인 액션

7�

시작하기1부

따라서 이 내용은 다음에 다룰 것이다. 이번 예제는 간단한 것이기 때문에, 여러 가지

데이터를 담기 위한 용도로 전역 변수를 선언할 것이다. 이것은 단순히 비어 있는 자바

스크립트 객체로, 여기에 조금 후에 데이터를 추가할 것이다.

vardata={};

Ajax.Request 객체를 생성할 때, 응답이 도착하면 콜백 핸들러로 동작할 parseData 함

수에 대한 레퍼런스를 전달하였다는 것을 기억하라. Ajax에서는 응답이 돌아왔을 때

그것을 처리하는 코드를 제공해야 할 필요가 있다. 그 함수 내에서 다음에서 보여주는

것처럼 데이터 객체를 채울 것이다.

functionparseAjaxResponse(transport){

varresponse=transport.responseXML;

vardocRoot=response.getElementsByTagName('gallery')[0];

data.path=docRoot.attributes.getNamedItem("path").value;

data.pre=docRoot.attributes.getNamedItem("pre").value;

data.folders=parseChildNodes(docRoot,"folders","folder");

data.images=parseChildNodes(docRoot,"images","image");

showDir();

}

functionparseChildNodes(node,parentTag,childTag){

varresults=[];

try{

varchildren=$A(

node.getElementsByTagName(parentTag)[0].

getElementsByTagName(childTag)

);

results=children.collect(

function(value,index){

returnvalue.firstChild.data;

}

)

}catch(e){

returnresults;

}}

응답 내의 데이터를 파싱해내기 위해 두 개의 함수를 정의하였다. 첫째는, 요청

을 생성할 때 레퍼런스를 넘겨주었던 콜백함수인 parseAjaxResponse()이다.

Page 109: Prototype & Scriptaculous 인 액션

7�

Prototype으로 Ajax를 단순화하기 3장

XMLHttpRequest 객체는 Prototype의 Ajax 클래스들에 의해 기반 통신 모듈로 참조되

며 콜백함수에 transport라는 변수로 전달된다. 응답을 구조화된 XML 문서로 가져오

는 것은 쉽지만 DOM 메소드를 이용하여 문서를 읽어내는 것은 힘들고 지루한 작업이

며 데이터로부터 속성과 자식노드를 가져오기 위해 상당한 양의 코드를 작성해야 한다.

몇몇 DOM 메소드들은 강조할 만한 가치가 있다. 첫째는 getElementsByTagName()

메소드이다. 이것은 현재 엘리먼트의 하위 엘리먼트들 중에 태그의 이름이 파라미터와

매칭되는 자식노드들의 컬렉션을 리턴한다. 여기서는 문서의 첫 번째 자식노드를 찾기

위해 사용하였다. node.firstChild라고 작성하는 것이 node.getElementsByTagNa

me(tag)[0]라고 작성하는 것보다는 쉬울지 모르지만 훨씬 가독성이 떨어진다. DOM

노드들은 몇몇 텍스트 노드와 엘리먼트 형태의 노드를 포함한 형태로 제공된다. 모질

라 브라우저들은 XML 마크업에 포함된 공백문자를 텍스트 노드로 해석하고, 깔끔하게

포맷팅된 XML 문서 내의 firstChild는 종종 캐리지 리턴과 몇 개의 탭 또는 들여쓰

기로 인한 스페이스를 나타내는 텍스트 노드이다.

두 번째 메소드는 DOM 엘리먼트로부터 속성 값을 가져오는 데 사용하는 메소드이

다. DOM 엘리먼트의 attribute 속성은 모든 속성의 컬렉션을 리턴하는데, 이것은 그

자체로 getNamedItem() 메소드를 사용하는 Attribube 객체를 리턴한다. Attribute

객체는 속성의 값을 참조하는 프로퍼티 값을 가지고 있다. 이쯤 되었으면 DOM 메소

드를 직접 작업하는 것이 다소 지루한 작업임을 여러분에게 확신시켜주었을 것이라

생각한다.

XML에서 하위폴더 목록과 이미지 목록을 파싱하는 것은 본질적으로 동일한 방식으

로 이루어지기 때문에 두 가지 문제를 모두 처리하는 parseChildNodes() 헬퍼 메소

드를 정의한다. 이 메소드에서 우리는 Prototype의 배열에 관한 확장기능을 두 번 사용

할 것이다. $A() 함수는 DOM 컬렉션 클래스들(getElementsByTagName()에 의해 리

턴되는 것들과 같은)을 자바스크립트 Array 객체로 변환해주고 역시 Prototype에 의해

제공되는 Array.collect() 메소드는 배열의 모든 엘리먼트에 간결한 방법으로 작업

을 수행하여 두 번째 배열로 결과값을 수집하게 해준다.

10장에서 Prototype의 Array 관련 메소드들에 대해 자세히 알아볼 것이므로 지금은,

파싱한 데이터를 어떻게 사용하는지 보도록 하자.

Page 110: Prototype & Scriptaculous 인 액션

76

시작하기1부

새로운 데이터를 디스플레이 하기

새로운 디렉터리의 컨텐트를 보여줄 때, 우리는 세 가지 일을 수행하게 된다: 현재 위

치메뉴를 렌더링하고, 하위목록을 보여주고, 그리고 현재 폴더의 썸네일 컨텐트를 디

스플레이한다. 우리는 세 가지 작업으로 구성된 최상위 메소드를 제공할 것이다.

functionshowDir(){

showBreadcrumbs();

showFolders();

showThumbnails();

}

또한 모든 사용자 인터페이스 컴포넌트에 대한 레퍼런스를 담는 전역 변수를 정의할

것이며, 이것은 백엔드에서 발생하는 모든 상황에 대한 상태를 저장하는 데이터 변수

와 아주 비슷하다. 다시 한 번, 여기서 전역 변수 사용함으로써 초기작업을 단순하게

유지시켜주지만 후에 이것을 리펙토링할 것이다. 우리는 사용자 인터페이스 변수인

ui를 window.onload() 이벤트 내에서 초기화시켜야 한다. 왜냐하면 그 시점이면 페

이지 내의 모든 DOM 노드들이 충분히 로딩되었다고 보장되기 때문이다.

varui={};

window.onload=function(){

ui.title=$('title');

ui.closeup=$('closeup');

ui.closeupImg=$('closeup_img');

ui.folders=$('folders');

ui.images=$('images');

Element.hide(ui.closeup,ui.folders);

load('/');

}

우리는 Prototype의 $() 함수를 사용하여 ID 속성으로 모든 DOM 엘리먼트를 가져

온다. 또한 DOM 엘리먼트를 다루는 데 사용되는 다양한 헬퍼 클래스를 제공하는

Prototype의 Element 객체를 사용한다. hide() 메소드와 이에 대응되는 show() 메소

드는 화면에 보이거나 사라지는 HTML 엘리먼트를 CSS로 스타일링하는 데 사용되는

프로그램적인 인터페이스를 래핑하고 있다. 시작 시에, 클로즈업 이미지와 하위폴더

뷰를 화면에서 감춘다. 그 후에 최초의 Ajax 요청을 생성하여 갤러리에 필요한 데이터

를 가져오기 위해 load() 메소드를 루트 경로에 호출한다.

Page 111: Prototype & Scriptaculous 인 액션

77

Prototype으로 Ajax를 단순화하기 3장

현재 위치 메뉴 렌더링

지금까지는 아주 간단했다. 우리는 요청을 생성하고 그것을 브라우저에서 우리의 데

이터 구조로 파싱했다. 프로세스를 완료하기 위해서, 이제 새로운 데이터를 가지고

사용자 인터페이스를 업데이트하는 코드를 작성해야 한다. 이미 언급한 바와 같이,

QuickGallery의 사용자 인터페이스는 현재 위치 메뉴, 하위폴더 리스트, 그리고 메인

뷰 영역으로 나눠지는 몇 가지 컴포넌트로 구성되어 있다. 그럼 이들 중 첫 번째인 현

재 위치 메뉴의 렌더링부터 보도록 하자.

서버는 현재 폴더에 대한 경로를 단일 문자열로 제공한다. 따라서 우리는 클라이언

트에서 그것을 각각 폴더 별로 분해해야 한다. 경로에 있는 각각의 폴더에 있어, 해당

폴더의 이름과 그 폴더까지의 누적 경로 모두를 추출해야 한다(예를 들어, /here/are/

my/files와 같은 경로가 있다면 세 번째 위치는 my라는 이름을 가질 것이고 누적 경

로는 /here/are/my라고 표시될 것이다). 여기에 현재 위치 메뉴를 렌더링하는 코드가

있다.

functionshowBreadcrumbs(){

varcrumbHTML="&gt;<spanonclick='load(\"\")'>home</span>";

varcrumbs=data.path.split("/");

for(vari=0;i<crumbs.length;i++){

varcrumb=crumbs[i];

if(crumb.length>0){

varpath=subpath(data.path,"/",i);

crumbHTML+="&gt;<spanonclick='load(\""+path+"\")'>"+crumb+"</span>";

}

}

ui.title.innerHTML=crumbHTML;

}

이것을 데이터 집합으로 생성할 수 있지만, 여기에서 저항이 가장 최소화되는 방

법을 택하였고 사용자 인터페이스 엘리먼트에 할당할 긴 HTML 문자열을 조립하여

innerHTML 프로퍼티를 사용하여 할당한다. 가장 어려운 작업인 각각의 위치를 나타

내는 노드에 대한 누적 경로를 생성하는 일은 subpath() 메소드에 위임하였다. 그럼

subpath()의 구현을 보도록 하자.

functionsubpath(str,delim,ix){

varall=str.split(delim);

varsome=all.findAll(

Page 112: Prototype & Scriptaculous 인 액션

78

시작하기1부

function(v,i){

return(i<=ix);

}

);

returnsome.join(delim);

}

다시 한 번, Prototype의 array 헬퍼 메소드에 대한 좋은 사용 예를 보았다. findAll()

메소드는 배열 내의 모든 엘리먼트들에 테스트를 적용하여 테스트를 통과한 엘리먼트

들만을 배열로 리턴한다. 테스트 함수는 각 엘리먼트의 값과 숫자로 이루어진 인덱스

에 접근할 수 있어서, 여기서 하위 경로에 속한 엘리먼트들을 연산하기 위해 숫자 인덱

스를 사용하였다.

이렇게 하여 현재 위치 메뉴가 생성된다. 그럼 하위폴더 목록을 렌더링하는 것을 보자.

하위폴더 목록의 렌더링

하위폴더들을 렌더링하는 것은 아주 쉽다. 그것은 엘리먼트에 반복연산을 하여 각각의

엘리먼트에 load() 함수에 대한 링크를 생성하는 정도의 문제이다. 다음 코드를 보자.

functionshowFolders(){

if(data.folders.length==0){

Element.hide(ui.folders);

}else{

varlinks=data.folders.collect(

function(value,index){

return"<divonclick='load(\""+path+"\")'>"+value+"</div>";

}

);

Element.show(ui.folders);

ui.folders.innerHTML=links.join("");

}}

우리는 각각의 하위폴더들이 출력되는 이름을 알고 있으며 서버의 응답으로부터 수

집한 데이터에 의해 제공된 기초 경로를 추가함으로써 폴더에 대한 절대 경로를 계

산해 낸다. 다시, 간단한 이벤트 핸들러를 포함하는 HTML 생성을 단순화시키기 위

해 Prototype의 Array.collect() 메소드를 사용하며, 그러고 나서 이렇게 생성된

HTML을 innerHTML 프로퍼티를 사용하여 적용한다.

Page 113: Prototype & Scriptaculous 인 액션

79

Prototype으로 Ajax를 단순화하기 3장

썸네일 이미지의 렌더링

마지막으로, 썸네일을 생성하는 것은 하위폴더 목록을 렌더링하는 것과 아주 유사하다.

이에 대한 코드는 다음과 같다.

functionshowThumbnails(){

Element.hide(ui.closeup);

if(data.images.length==0){

Element.hide(ui.images);

}else{

varlinks=data.images.collect(

function(value,index){

varimgUrl=data.pre+data.path+"/"+value+".thumb.jpg";

return"<divclass='img_title'>"

+"<imgonclick='showCloseup(\""

+value

+"\")'src='"

+imgUrl

+"'/>"

+"<br/>"

+value

+"</div>"

}

);

Element.show(ui.images);

ui.images.innerHTML=links.join("");

}}

구조적으로, showThumbnails()와 showFolders()는 거의 동일하다. 따라서 세부적

인 내용을 다시 언급하지는 않는다. 한 가지 주의할 것은 showCloseup() 메소드를 썸

네일을 위한 onclick 이벤트 핸들러에서 참조하였다는 것이다. showCloseup() 메소

드에 대한 코드는 다음과 같다.

functionshowCloseup(imgSrc){

Element.hide(ui.images);

Element.show(ui.closeup);

ui.closeupImg.src=imgSrc;

}

클로즈업 이미지를 화면에 출력하는 것은 Prototype의 Element.hide()와 Element.

Page 114: Prototype & Scriptaculous 인 액션

80

시작하기1부

show() 메소드를 사용하여 단지 사용자 인터페이스 엘리먼트를 재배열하고 적절하게

이미지 객체의 소스를 세팅하는 정도의 문제이다. 페이지 갱신 없이 서버로부터 비동

기 방식으로 리소스를 가져온다는 것에 주목하라. 따라서 비록 XMLHttpRequest 객체

를 사용하지는 않았지만 기술적으로 Ajax를 사용하였다. 사실, 구글 맵스와 같은 권위

있는 Ajax 애플리케이션도 인터페이스를 업데이트하기 위해 같은 방법을 사용하고 있

으며 XMLHttpRequest 객체는 거의 사용하지 않는다.

모두를 조합하기

이것으로 데이터 중심적인 QuickGallery 애플리케이션의 구현은 완료되었다. 되돌아

생각해보면, 이것을 구현하기 위해서 가장 힘든 부분은 클라이언트 측이고 Prototype

은 몇 가지 방법으로 우리를 도와주었다.

Ajax 헬퍼 객체들은 그것을 사용하지 않았을 때보다 XML 데이터를 가져오

는 것을 보다 쉽게 해주었다. ready 상태와 HTTP 상태에 대해 걱정을 해야 하는

XMLHttpRequest 객체의 저수준 콜백과는 다르게 Ajax.Request에 고수준의 콜백함수

를 제공할 수 있었다. 설정 옵션으로 HTTP 관련 옵션을 제공할 수 있었다. $() 함수와

Element 객체와 같은 DOM 헬퍼 클래스들은 Array 객체의 확장들과 마찬가지로 한 번

이상 사용되었다. Prototype의 도움이 없었다면, 보다 많은 자바스크립트 코드를 직접

작성해야 했을 것이다. 그럼에도 불구하고, 이 모든 것을 조합함에 있어 상당한 양의

자바스크립트 코드를 작성해야 한다.

우리는 몇 가지 방법으로 클라이언트 측 코드를 구조화하기 위해서 최선을 다했다.

그럼 설계에 대해서 간략하게 리뷰 해보도록 하자. 한 쌍의 전역변수를 선언하여 애플

리케이션에 대한 모든 상태를 담도록 하였다. 하나는 사용자 인터페이스 엘리먼트들

이고 다른 하나는 백그라운드 데이터이며 우리는 이 전역변수 각각을 적절한 타이밍에

초기화한다. 즉, DOM 로딩이 완료되었을 때 사용자 인터페이스 관련 변수를 초기화하

고 Prototype의 헬퍼 클래스들을 이용하여 서버로 비동기 호출을 수행한 후에 데이터

관련 변수를 초기화한다. 서버에서 리턴된 XML 데이터를 래핑되지 않은 DOM 메소드

를 사용하여 파싱하고 사용자 인터페이스를 업데이트하는 작업을 몇 개의 하위작업으

로 쪼개어 화면상의 컴포넌트에 하나씩 할당한다. 나아가 새로운 기능을 추가할 때, 코

드는 쉽게 유지보수가 가능하고 리펙토링이 가능할 것이다.

Page 115: Prototype & Scriptaculous 인 액션

8�

Prototype으로 Ajax를 단순화하기 3장

그러나 약간 의심스러운 것이 있다. Prototype이 요청을 생성하는 작업을 처리해줌

에도 불구하고 일이 완료되기 위해서는 상당한 양의 코드를 작성해야만 하며 여전히

직접 응답을 파싱해야 한다는 것이다. 특히, parseAjax() 메소드는 라인수도 길고 모

양새도 좋지 않다.

우리는 저 밖에 JSON이라는 XML을 대체할 보다 가벼운 대안이 있음을 알고 있다.

XML을 사용한 방식에서 JSON을 사용하는 방식으로 변경하는 것은 아주 많은 변경을

요하지는 않으므로, 한번 시도해보고 이것이 일을 더 쉽게 만들어 주는지 보도록 하자.

3.3 JSON과 Ajax 함께 사용하기

3.2절에서, 우리는 통신수단으로 XML을 이용하여 QuickGallery의 Ajax 버전을 구현하

였다. 우리는 Ajax 프로그래머로서 여전히 우리가 사용할 수 있는 옵션들에 대해서 탐

구하고 있으며 JSON이 XML에 대한 흥미로운 대안처럼 보인다. JSON은 앞서 말한 것

처럼 JavaScript Object Notation을 나타내는 말이다. 그것은 XML과 같이 데이터 구조

에 대한 마크업이지만 자바스크립트 언어의 컨벤션을 준수한다. 자바스크립트의 객체

를 검토하는 8장에서 JSON의 구조에 대해서 자세히 알아볼 것이다.

JSON을 사용하여 통신을 할 때, 계속 동일한 Ajax 메커니즘을 사용할 것이므로

Prototype의 Ajax.Request를 사용하여 여전히 해당 부분을 쉽게 구현할 수 있다. 차이

점은 어떻게 응답을 파싱하는가에 달려 있다. JSON을 사용할 때 얻게 되는 커다란 이

점은 응답이 도착하면 자바스크립트 인터프리터가 우리를 대신하여 파싱해준다는 것

이다.

JSON을 사용하면, 데이터 중심적인 접근방법을 따를 수 있으므로 XML 기반 해법을

아주 쉽게 수용할 수 있다. 단지 우리가 수정해야 할 것은 서버 측에서의 데이터 생성

과 응답의 파싱부분이다. 그럼 각각에 대해서 차례로 보도록 하자.

3.3.1 서버 측 코드의 수정

우리는 여전히 경로 정보를 목록화한 데이터 구조와 하위폴더, 이미지의 리스트를 생성

하기를 원한다. 예제 3.4는 서버가 생성하는 전형적인 형태의 JSON 데이터를 보여준다.

Page 116: Prototype & Scriptaculous 인 액션

82

시작하기1부

예 제 3.4 | Ajax기반 QuickGallery에 의해 생성된 예제 JSON 데이터

{path:'/plants/trees',

Path 속성

folders:[ 하위폴더 목록"forest",

"barkclose-ups"],images:[ 이미지

목록"dscn0034","dscn0037","dscn0187"]}

이것을 예제 3.1에서 제시한 예제 XML과 비교해 보면, 차이점은 순수하게 언어적인 것

이라는 것을 알수 있다. 그러면 JSON 데이터를 생성하는 것은 단지 PHP 템플릿을 수

정하는 단순한 문제이다. 예제 3.5는 수정한 내용을 보여준다.

예 제 3.5 | JSON을 생성하는 dataJSON/images.php

<?phpheader("Content-type:text/javascript");require('../config.php');require('images.inc.php');?>{path:"<?phpecho$path?>",pre:"<?phpecho$img_pre_path?>"<?phpif(count($subdirs)>0){?>,folders:["<?phpechojoin($subdirs,'","');?>"]<?php}?><?phpif(count($imgs)>0){?>,images:["<?phpechojoin($imgs,'","');?>"]<?php}?>}

JSON 결과 데이터가 XML보다는 덜 복잡하기 때문에 폴더와 이미지 목록을 조합하기

위해서 PHP의 join() 메소드를 사용할 수 있다. 이것을 제외하고라도, 코드는 아주

직관적이다. 이 코드에 의해 생성되는 전형적인 JSON은 다음과 같다.

Page 117: Prototype & Scriptaculous 인 액션

83

Prototype으로 Ajax를 단순화하기 3장

{

path:"",

pre:"/album/images"

,folders:["animals","buildings","landscape","plants","things"]

}

단순하고 논쟁의 여지가 있지만 직접 JSON을 작성하고 마크업 내에 변수를 추가하고

루프를 직접 제어하는 거친 템플릿 생성 방법을 사용하고 있다. 여러분이 JSON을 사용

하는 것에 대해 고민 중이라면 대부분의 프로그래밍 언어에서 사용 가능하고 데이터를

내부에 포함된 배열과 객체로 조합할 수 있도록 해주고, 이것으로부터 JSON 마크업을

자동 생성할 수 있는 라이브러리가 존재한다. 이전 절에서 XML을 생성하였지만, 우리

는 가능한 한 서버 측 코드를 단순하게 유지하기를 원하기 때문에 이전 절에서와 같이

XML을 생성하는 유혹에 빠지지를 않았고 클라이언트 측 코드에만 전념할 수 있다. 여

기서 흥미로운 것은 결국 JSON이 클라이언트 티어에 어떤 영향을 주느냐이다. 그럼 다

음을 보도록 하자.

3.3.2 클라이언트 코드의 수정

이제 서버는 보기 좋은 모양의 JSON을 생성하며 우리는 XML을 사용할 때 했던 것과

같이 그것을 파싱할 콜백함수를 작성해야 한다. 어떻게 JSON을 사용하는지 보도록 하

자. 클라이언트 코드에 있어 진입점은 Prototype의 Ajax.Request 객체에 전달한 콜백

함수가 될 것이다. 이 메소드에 대한 코드는 다음과 같다.

functionparseAjaxResponse(transport){

varresponse=transport.responseText;

varjsonObj=eval("("+response+")");

data.path=jsonObj.path;

data.pre=jsonObj.pre;

data.folders=jsonObj.folders||[];

data.images=jsonObj.images||[];

showDir();

}

여기서 주목해야 할 것은 XMLHt tpReques t 객체의 responseXML이 아닌

responseText 프로퍼티를 읽는다는 것이다. 그 결과로 모든 JSON 데이터를 포함

한 문자열이 리턴된다. 다음 라인에서, 우리는 단순히 JSON 표현식의 값을 구하고 다

Page 118: Prototype & Scriptaculous 인 액션

8�

시작하기1부

시 자바스크립트 객체로 되돌아 간다. 함수의 나머지 부분은 컨텐트를 보여주기 위해

showDir() 메소드를 호출하기 전에 전역 데이터 객체를 파싱된 데이터로 채우는 것에

관계가 있다. XML의 파싱에 비교해 보면 JSON을 사용하는 것이 확실히 더 작성하기

쉽고 읽기에도 쉽다.

이 정도로 이번 장을 마무리하도록 하자. 우리의 갤러리는 이제 통신수단으로 JSON

을 사용하여 동작한다. 이것으로 XML에 대한 대안으로 JSON에 대해 알아보는 것을 마

친다. 데이터를 파싱하기 위해 DOM을 사용하지 않아도 되니 클라이언트 코드가 쉬워

졌다. 물론 대부분의 서버 측 기술들이 XML을 많이 사용하기 때문에 XML은 상황에 따

라 큰 이점을 준다. 우리의 경우에는 생성되는 데이터가 충분히 작아서 쉽게 JSON으로

변경할 수 있었다.

Page 119: Prototype & Scriptaculous 인 액션

8�

Prototype으로 Ajax를 단순화하기 3장

3.4 요약

이번 장에서는 Ajax.Request 객체를 통한 Prototype의 Ajax 지원에 대해서 알아보았고

Ajax.Request를 사용해 보았다. 이 장의 마지막까지, 갤러리 애플리케이션의 두 가지

Ajax 버전을 개발하였다: 하나는 XML을 사용하고 다른 하나는 JSON을 통신매체로 사

용한다.

경험을 되살려 보면, 성공적으로 갤러리 애플리케이션에 Ajax 기술을 도입하였지만

여전히 우리가 사용자 인터페이스를 지원하기 위해서 작성해야만 하는 코드의 양에 대

한 의심이 있었다. 더 나아가서, 이전에 Prototype의 Ajax 지원 클래스들을 살펴보았을

때, Ajax를 보다 쉽게 만들어 주는 매력적인 하위 클래스들을 보았다. 여기서 우리는

단지 Ajax.Request 클래스를 사용했을 뿐이다. 설마 더 나은 방법이 있다는 말인가?

현재 QuickGallery 애플리케이션에 Ajax 기능을 추가하는 초기 프로토타이핑 단계

(말 장난이 아니다!)에 있고 따라서 그러한 의구심에 귀 기울일 좋은 시점이다. 우리

는 일찍이 Ajax 통신에 폭넓게 세 종류-데이터 중심, 스크립트 중심, 컨텐트 중심-가 있

음을 알아봤고, 지금까지 데이터 중심적인 방법을 시도했고 다양한 결과들을 얻었다.

Prototype의 Ajax.Updater 클래스는 우리가 컨텐트 중심적인 방법이라고 부르는 것에

더 많은 지원을 제공하므로, 다음 장에서 그러한 스타일을 사용하여 갤러리를 다시 구

현 할 것이고 차이점을 알아볼 것이다.

Page 120: Prototype & Scriptaculous 인 액션

86

시작하기1부