node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

72

Post on 22-Jul-2016

249 views

Category:

Documents


1 download

DESCRIPTION

마이크 캔텔론, 마크 하터, T.J. 할로웨이척, 나단 라즈리치 지음 | 정승희, 민창현, 이준 옮김 | 오픈소스 & 웹 시리즈_064 | ISBN: 9788998139636 | 35,000원 | 2014년 08월 29일 발행 | 516쪽

TRANSCRIPT

Page 1: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법
Page 2: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

Node.js 인 액션

Page 3: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

지은이 마이크 캔텔론, 마크 하터, T.J. 할로웨이 척, 나단 라즈리치

옮긴이 정승희, 민창현, 이준

펴낸이 박찬규 엮은이 윤가희 디자인 북누리 표지디자인 아로와 & 아로와나

펴낸곳 위키북스 전화 031-955-3658, 3659 팩스 031-955-3660

주소 경기도 파주시 문발로 115 세종출판벤처타운 311호

가격 35,000 페이지 516 책규격 188 x 240mm

초판 발행 2014년 08월 29일

ISBN 978-89-98139-63-6 (13000)

등록번호 제406-2006-000036호 등록일자 2006년 05월 19일

홈페이지 wikibook.co.kr 전자우편 [email protected]

Node.js in Action by MIKE CANTELON, MARC HARTER, T.J. HOLOWAYCHUK, NATHAN RAJLICH

Original English language edition published by Manning Publishions, Co USA.

Copyright © 2014 by Manning Publications Co.

Korean edition copyright © 2014 by WIKIBOOKS.

All rights reserved.

이 책의 한국어판 저작권은 대니홍 에이전시를 통한 저작권사와의 독점 계약으로 위키북스가 소유합니다.

신 저작권법에 의해 한국 내에서 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다.

이 책의 내용에 대한 추가 지원과 문의는 위키북스 출판사 홈페이지 wikibook.co.kr이나

이메일 [email protected]을 이용해 주세요.

이 도서의 국립중앙도서관 출판시도서목록 CIP는

서지정보유통지원시스템 홈페이지(http://seoji.nl.go.kr)와

국가자료공동목록시스템(http://www.nl.go.kr/kolisnet)에서 이용하실 수 있습니다.

CIP제어번호 CIP2014024306

Node.js 인 액션

Page 4: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법
Page 5: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

IV

목 차

1부 노드의 기반 기술

01_ 노드에 오신 것을 환영합니다 ............................................................................................................28

1.1 자바스크립트 기반 .......................................................................................................................................29

1.2 비동기와 이벤트: 브라우저 ..........................................................................................................................30

1.3 비동기와 이벤트: 서버 .................................................................................................................................32

1.4 DIRTy 애플리케이션 .....................................................................................................................................34

1.5 DIRTy의 기본 요소 ........................................................................................................................................36

1.5.1 간단한 비동기 예제 .................................................................................................37

1.5.2 Hello World HTTP 서버 ..........................................................................................39

1.5.3 스트리밍 데이터 ......................................................................................................39

1.6 요약 ............................................................................................................................................................41

02_ 다중 채팅방 애플리케이션 만들기 ......................................................................................................42

2.1 애플리케이션 개요 .......................................................................................................................................43

2.2 애플리케이션 요구사항과 초기 설정 ............................................................................................................45

2.2.1 HTTP와 웹소켓 서비스 .............................................................................................46

2.2.2 애플리케이션의 파일 구조 생성 .................................................................................47

2.2.3 의존성 모듈 명시 .....................................................................................................48

2.2.4 의존성 모듈 설치 ....................................................................................................49

2.3 HTML, CSS, 클라이언트 측 자바스크립트 서비스 .........................................................................................49

2.3.1 기본적인 정적 파일 서버 생성 ...................................................................................50

2.3.2 HTML과 CSS 파일 추가 ...........................................................................................53

Page 6: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

V

목 차

2.4 Socket.IO를 이용한 채팅 관련 메시지 처리 ................................................................................................. 56

2.4.1 Socket.IO 서버 구성 ...............................................................................................57

2.4.2 애플리케이션 시나리오와 이벤트 처리 ........................................................................59

2.5 애플리케이션의 사용자 인터페이스를 위한 클라이언트 측 자바스크립트 .................................................... 64

2.5.1 메시지와 닉네임/채팅방 변경 요청을 서버로 전달 ........................................................65

2.5.2 메시지 및 입장할 수 있는 채팅방 목록을 사용자 인터페이스에 보여주기 ..........................66

2.6 요약 ............................................................................................................................................................ 71

03_ 노드 프로그래밍의 기본 ....................................................................................................................72

3.1 노드의 기능 관리와 재사용 .......................................................................................................................... 73

3.1.1 모듈 생성 ...............................................................................................................76

3.1.2 module.exports를 이용해 잘 정비된 모듈 생성하기 .....................................................78

3.1.3 node_modules 디렉터리로 모듈 재사용하기 ..............................................................80

3.1.4 알아둘 점 ...............................................................................................................81

3.2 비동기 프로그래밍 기법 .............................................................................................................................. 82

3.2.1 일회성 이벤트를 콜백으로 처리하기 ...........................................................................83

3.2.2 반복적인 이벤트를 이벤트 발생자로 처리하기 ..............................................................88

3.2.3 비동기 개발의 어려운 점 ..........................................................................................97

3.3 비동기 로직의 순서 배열하기 ...................................................................................................................... 99

3.3.1 직렬 흐름 제어를 사용하는 경우 ...............................................................................101

3.3.2 직렬 흐름 제어 구현하기 ........................................................................................102

3.3.3 병렬 흐름 제어 구현 ...............................................................................................105

3.3.4 커뮤니티 도구 활용하기 ..........................................................................................108

3.4 요약 ..........................................................................................................................................................110

Page 7: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

VI

목 차

2부 노드를 이용한 웹 애플리케이션 개발

04_ 노드 웹 애플리케이션 만들기 ...........................................................................................................114

4.1 HTTP 서버의 기본 ..................................................................................................................................... 116

4.1.1 노드가 HTTP 요청을 개발자에게 전달하는 방법 ..........................................................116

4.1.2 “Hello World”로 응답하는 기본적인 HTTP 서버 .........................................................118

4.1.3 요청 헤더 읽기와 응답 헤더 설정하기 .......................................................................119

4.1.4 HTTP 응답 상태 코드 설정하기 ...............................................................................119

4.2 RESTful 웹 서비스 만들기 ......................................................................................................................... 120

4.2.1 POST 요청으로 자원 생성하기 ................................................................................121

4.2.2 GET 요청으로 자원 가져오기 ..................................................................................124

4.2.3 DELETE 요청으로 자원 삭제하기..............................................................................125

4.3. 정적 파일 서비스하기 ............................................................................................................................... 127

4.3.1 정적 파일 서버 만들기 ............................................................................................128

4.3.2 서버 오류 처리하기 ................................................................................................132

4.3.3 fs.stat을 이용한 선제 오류 처리 ...............................................................................133

4.4 폼에서 사용자 입력받기 ............................................................................................................................ 134

4.4.1 제출된 폼 항목 처리하기 ........................................................................................135

4.4.2 formidable을 이용한 파일 업로드 처리하기 ..............................................................139

4.4.3 업로드 진행 상황 계산하기 ......................................................................................144

4.5 HTTPS를 이용한 애플리케이션 보안 ......................................................................................................... 145

4.6 요약 .......................................................................................................................................................... 147

Page 8: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

VII

목 차

05_ 노드 애플리케이션 데이터 저장하기 ................................................................................................148

5.1 서버가 없는 데이터 저장소 .......................................................................................................................149

5.1.1 인메모리 저장소 ...................................................................................................150

5.1.2 파일 기반 저장소 ..................................................................................................150

5.2 관계형 데이터베이스 관리 시스템 ............................................................................................................154

5.2.1 MySQL ................................................................................................................154

5.2.2 PostgreSQL .........................................................................................................164

5.3 NoSQL 데이터베이스 ................................................................................................................................167

5.3.1 레디스 .................................................................................................................168

5.3.2 몽고디비 ..............................................................................................................174

5.3.3 몽구스..................................................................................................................178

5.4 요약 ..........................................................................................................................................................181

06_ 커넥트 ..............................................................................................................................................182

6.1 커넥트 애플리케이션 준비 .........................................................................................................................183

6.2 커넥트 미들웨어의 동작방식 .....................................................................................................................184

6.2.1 로그를 남기는 커넥트 미들웨어 ................................................................................185

6.2.2. “hello world”로 응답하는 미들웨어 .........................................................................186

6.3 미들웨어 순서의 중요성 ............................................................................................................................187

6.3.1 미들웨어가 next ( )를 호출하지 않을 때 .....................................................................188

6.3.2 미들웨어 순서를 사용해 인증하기 .............................................................................189

6.4 미들웨어와 서버 마운팅 ............................................................................................................................189

6.4.1 인증 미들웨어 .......................................................................................................191

6.4.2 관리영역을 보여주는 미들웨어 컴포넌트 ...................................................................192

Page 9: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

VIII

목 차

6.5 설정 가능한 미들웨어 만들기 .................................................................................................................... 194

6.5.1 설정 가능한 logger 미들웨어 컴포넌트 만들기 ...........................................................195

6.5.2 router 미들웨어 컴포넌트 만들기.............................................................................196

6.5.3 URL을 다시 만드는 미들웨어 컴포넌트 ......................................................................200

6.6 에러 핸들링 미들웨어 사용 ........................................................................................................................ 201

6.6.1 커넥트의 기본 에러 핸들러 ......................................................................................202

6.6.2 애플리케이션 에러 직접 다루기 ................................................................................202

6.6.3 다수의 에러 핸들링 미들웨어 컴포넌트 사용 ..............................................................204

6.7 요약 .......................................................................................................................................................... 209

07_ 커넥트의 내장 미들웨어 ...................................................................................................................210

7.1 쿠키와 요청 본문, 쿼리 스트링을 해석하는 미들웨어 ................................................................................. 212

7.1.1 cookieParser ( ): HTTP 쿠키 해석 ............................................................................212

7.1.2 bodyParser ( ): 요청 본문 해석 ................................................................................216

7.1.3 limit ( ): 요청 본문의 크기 제한 ................................................................................219

7.1.4 query ( ): 쿼리 스트링 파서 .....................................................................................222

7.2 핵심 웹 애플리케이션 기능을 실행하는 미들웨어 ...................................................................................... 223

7.2.1 logger ( ): 요청 로그 남기기 ....................................................................................223

7.2.2 favicon( ): 파비콘 서비스 .......................................................................................227

7.2.3 methodOverride( ): 위조 HTTP 메서드 ...................................................................227

7.2.4 vhost ( ): 가상 호스트 .............................................................................................231

7.2.5 session( ): 세션 관리 .............................................................................................232

7.3 웹 애플리케이션의 보안을 다루는 미들웨어 .............................................................................................. 237

7.3.1 basicAuth( ): HTTP 기본 인증 ................................................................................238

7.3.2 csrf ( ): 사이트 간 요청 위조 방어 .............................................................................241

7.3.3 errorHandler ( ): 개발 에러 핸들링...........................................................................241

Page 10: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

IX

목 차

7.4 정적 파일 서비스 미들웨어 ........................................................................................................................244

7.4.1 static ( ): 정적 파일 서비스 ......................................................................................244

7.4.2 compress ( ): 정적 파일 압축 ...................................................................................246

7.4.3 directory ( ): 디렉터리 목록 .....................................................................................249

7.5 요약 ..........................................................................................................................................................251

08_ 익스프레스 .......................................................................................................................................252

8.1 애플리케이션의 뼈대 만들기 .....................................................................................................................254

8.1.1 익스프레스가 실행되게 설치하기 ..............................................................................256

8.1.2 애플리케이션 생성하기 ...........................................................................................257

8.1.3 애플리케이션 둘러보기 ...........................................................................................257

8.2 익스프레스 및 애플리케이션 설정하기 ......................................................................................................260

8.2.1 환경 기반 설정 ......................................................................................................261

8.3 뷰 렌더링 ..................................................................................................................................................262

8.3.1 뷰 시스템 설정 ......................................................................................................263

8.3.2 뷰 찾기 .................................................................................................................266

8.3.3 뷰에 데이터 노출하기 .............................................................................................268

8.4 폼과 파일 업로드를 다루는 방법 ................................................................................................................274

8.4.1 사진의 데이터 모델 구현하기 ...................................................................................274

8.4.2 사진 업로드 폼 생성하기 .........................................................................................275

8.4.3 업로드 한 사진 목록 보여주기 ..................................................................................278

8.5 자원 내려받기 다루기 ................................................................................................................................280

8.5.1 사진 내려받을 경로 생성하기 ...................................................................................280

8.5.2 사진 내려받을 경로 구현하기 ...................................................................................281

8.6 요약 .........................................................................................................................................................283

Page 11: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

X

목 차

09_ 고급 익스프레스 ...............................................................................................................................284

9.1 사용자 인증하기 ........................................................................................................................................ 285

9.1.1 사용자를 저장하고 불러오기 ....................................................................................286

9.1.2 새로운 사용자 등록하기 ..........................................................................................293

9.1.3 등록된 사용자 로그인 .............................................................................................300

9.1.4 사용자 정보를 불러오는 미들웨어 .............................................................................304

9.2 고급 라우팅 기술 ....................................................................................................................................... 306

9.2.1 사용자가 제출한 데이터 검증 ...................................................................................307

9.2.2 경로에 특화된 미들웨어 ..........................................................................................312

9.2.3 페이징 구현 ..........................................................................................................316

9.3 공개 REST API 생성하기 ............................................................................................................................ 321

9.3.1 API 설계하기 ........................................................................................................321

9.3.2 기본 인증 추가하기 ................................................................................................322

9.3.3 라우팅 구현하기 ....................................................................................................322

9.3.4 내용 협상 기능 ......................................................................................................328

9.4 에러 다루기 ............................................................................................................................................... 331

9.4.1 404 에러 다루기 ...................................................................................................331

9.4.2 에러 다루기 ..........................................................................................................334

9.5 요약 .......................................................................................................................................................... 338

10_ 노드 애플리케이션 테스트................................................................................................................339

10.1 단위 테스트 ............................................................................................................................................. 341

10.1.1 assert 모듈 .........................................................................................................341

10.1.2 노드 유닛 ...........................................................................................................346

10.1.3 모카 ...................................................................................................................348

Page 12: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XI

목 차

10.1.4 보우즈................................................................................................................355

10.1.5 should.js ...........................................................................................................358

10.2 인수 테스트 .............................................................................................................................................360

10.2.1 토비 ...................................................................................................................361

10.2.2 소다 ...................................................................................................................363

10.3 요약 ........................................................................................................................................................366

11_ 웹 애플리케이션 템플릿 ...................................................................................................................367

11.1 템플릿으로 코드 깔끔하게 유지하기 ........................................................................................................368

11.1.1 템플릿 사용하기 ..................................................................................................369

11.2 임베디드 자바스크립트 템플릿 ................................................................................................................373

11.2.1 템플릿 생성하기 ..................................................................................................374

11.2.2 EJS 필터로 템플릿 데이터 변경하기 ........................................................................376

11.2.3 애플리케이션에 EJS 통합하기 ................................................................................380

11.2.4 클라이언트 측 애플리케이션에서 EJS 사용하기 ........................................................382

11.3 호간으로 머스태쉬 템플릿 언어 사용하기 ................................................................................................383

11.3.1 템플릿 생성하기 ..................................................................................................383

11.3.2 머스태쉬 태그 .....................................................................................................384

11.3.3 호간 세부 조정하기 ..............................................................................................387

11.4 제이드 템플릿 .........................................................................................................................................388

11.4.1 제이드 기초 ........................................................................................................390

11.4.2 제이드 템플릿의 로직 ...........................................................................................393

11.4.3 제이드 템플릿 구성하기 ........................................................................................397

11.5 요약 ........................................................................................................................................................403

Page 13: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XII

목 차

3부 노드로 할 수 있는 더 많은 것들

12_ 노드 애플리케이션의 배포와 가동시간 관리 ....................................................................................406

12.1 노드 애플리케이션 호스팅 ....................................................................................................................... 407

12.1.1 전용 서버와 가상 사설 서버 ...................................................................................408

12.1.2 클라우드 호스팅 ..................................................................................................409

12.2 간단한 배포 ............................................................................................................................................. 411

12.2.1 깃 저장소에서 배포 ..............................................................................................411

12.2.2 노드 실행 유지 ....................................................................................................412

12.3 서버 가동 시간과 성능의 최대화 .............................................................................................................. 414

12.3.1 Upstart로 가동 시간 관리 .....................................................................................415

12.3.2 클러스터 API: 다중 코어의 장점 활용 ......................................................................417

12.3.3 정적 파일 서비스와 프록시 ....................................................................................419

12.4 요약 ........................................................................................................................................................ 421

13_ 웹 서버 이외의 것들 .........................................................................................................................422

13.1 Socket.IO ................................................................................................................................................ 423

13.1.1 간단한 Socket.IO 애플리케이션 만들기 ..................................................................424

13.1.2 Socket.IO를 사용한 페이지 동작과 CSS 리로드 ........................................................426

13.1.3 Socket.IO의 또 다른 사용법 ..................................................................................430

13.2 TCP/IP 네트워크 ..................................................................................................................................... 431

13.2.1 버퍼와 바이너리 데이터 사용 .................................................................................432

13.2.2 TCP 서버 생성 .....................................................................................................434

13.2.3 TCP 클라이언트 생성 ...........................................................................................438

Page 14: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XIII

목 차

13.3 운영체제와 상호작용하는데 필요한 도구 .................................................................................................440

13.3.1 process 전역 싱글톤 ............................................................................................441

13.3.2 파일 시스템 모듈 사용 ..........................................................................................445

13.3.3 외부 프로세스 생성 ..............................................................................................450

13.4 개발 명령행 도구 .....................................................................................................................................456

13.4.1 명령행 인자 해석 .................................................................................................457

13.4.2 표준 입력과 표준 출력 처리 ...................................................................................459

13.4.3 색상이 들어간 결과 추가 .......................................................................................461

13.5 요약 ........................................................................................................................................................465

14_ 노드 생태계 ......................................................................................................................................466

14.1 노드 개발자를 위한 온라인 자원 ..............................................................................................................467

14.1.1 노드와 모듈 레퍼런스 ...........................................................................................467

14.1.2 구글 그룹스 ........................................................................................................469

14.1.3 IRC ....................................................................................................................469

14.1.4 깃허브 이슈 ........................................................................................................470

14.2 깃허브 .....................................................................................................................................................471

14.2.1 깃허브 시작하기 ..................................................................................................471

14.2.2 깃허브에 프로젝트 추가하기 ..................................................................................472

14.2.3 깃허브에서 함께 개발하기 .....................................................................................477

14.3 npm 저장소에 기여하기 .........................................................................................................................479

14.3.1 패키지 준비 ........................................................................................................480

14.3.2 패키지 명세 작성하기 ...........................................................................................481

14.3.3 패키지 테스트 및 배포 ..........................................................................................482

14.4 요약 ........................................................................................................................................................485

Page 15: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XIV

목 차

부록 A노드 및 커뮤니티 부가 프로그램 설치하기

A.1 맥 OS X에서 설치하기 .............................................................................................................................. 486

A.1.1 Homebrew로 설치하기 ........................................................................................488

A.2 윈도우에서 설치하기 ............................................................................................................................... 488

A.3 리눅스에서 설치하기 ............................................................................................................................... 490

A.3.1 우분투에 설치할 때 필요한 패키지 ...........................................................................490

A.3.2 CentOS에 설치 시 필요한 패키지 ............................................................................490

A.4 노드 컴파일하기 ...................................................................................................................................... 491

A.5 노드 패키지 매니저 사용하기 ................................................................................................................... 493

A.5.1 패키지 검색하기 ....................................................................................................494

A.5.2 패키지 설치하기 ....................................................................................................495

A.5.3 문서와 패키지 코드 찾아보기 ..................................................................................496

부록 B노드 디버깅

B.1 JSHint로 코드 분석하기 ............................................................................................................................. 497

B.2 디버깅 정보 출력하기 ................................................................................................................................ 498

B.2.1 console 모듈로 디버깅하기 .....................................................................................499

B.2.2 디버깅 출력을 관리하는 디버그 모듈 사용하기 ...........................................................500

Page 16: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XV

목 차

B.3 노드의 내장 디버거 ...................................................................................................................................500

B.3.1 디버거 네비게이션 .................................................................................................501

B.3.2 디버거로 상태 확인 및 조작하기 ...............................................................................502

B.4 노드 인스펙터 ...........................................................................................................................................503

B.4.1 노드 인스펙터 시작하기 ..........................................................................................503

B.4.2 노드 인스펙터 네비게이션 .......................................................................................504

B.4.3 노드 인스펙터에서 상태 둘러보기 .............................................................................505

부록 C익스프레스확장 및 설정하기

C.1 익스프레스 확장하기 .................................................................................................................................506

C.1.1 템플릿 엔진 등록하기 .............................................................................................506

C.1.2 consolidate.js로 템플릿 작성하기 ...........................................................................508

C.1.3 익스프레스 확장 및 프레임워크................................................................................509

C.2 고급 설정 ..................................................................................................................................................510

C.2.1 JSON 응답 조작하기 ..............................................................................................511

C.2.2 JSON 응답 포맷 만들기 ..........................................................................................512

C.2.3 역방향 프록시 헤더 필드 신뢰하기 ...........................................................................512

Page 17: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XVI

추천사

노드에 관한 책을 쓰는 것은 매우 도전적인 과제다. 노드는 비교적 최신 플랫폼이며 이제서야 막 안정화

되기 시작했다. 노드의 핵심부는 나날이 발전하고 있으며 사용자 제작 모듈과 관련된 커뮤니티는 그 누

구도 따라잡을 수 없을 만큼의 속도로 폭발적인 증가세를 보이고 있다. 노드 커뮤니티는 여전히 그 정체

성을 찾아가고 있다. 이러한 역동적인 대상을 책에 담기 위한 유일한 방법은 노드의 본질은 무엇이며 어

떻게 성공의 길을 걸어왔는지 다루는 것이다. 여기 그 일을 해낸 노드의 베테랑들이 있다. 마이크 켄탤론

은 노드 커뮤니티에서 노드에 관한 실험과 이야기로 대단히 적극적으로 활동하는 사람이다. 그는 노드를

언제 사용하는 것이 적합하고 (아마도 더 중요할지 모르는) 언제 사용하기 적합하지 않은지에 대한 탁

월한 판단력을 가지고 있다. T.J. 할로웨이척은 엄청난 인기를 누리고 있는 웹 프레임워크인 익스프레스

(Express )를 포함해서 가장 많은 노드 모듈을 개발한 개발자 중 한 명이다. TooTallNate로 더 잘 알려

진 나단 라즈리치는 지금까지 꽤 오랫동안 노드의 핵심 커미터로 활동했으며 노드가 현재 모습으로 성숙

하기까지 플랫폼 개발에 적극적으로 참여하고 있다.

이 책은 그들의 상당한 경험을 토대로 컴퓨터에 노드를 설치하는 초기 작업부터 제품 애플리케이션을 생

성, 디버깅, 배포하는 방법까지 모든 단계에 걸친 내용을 담고 있다. 이 책을 통해 노드가 흥미로운 이유

를 알게 될 것이며 저자들의 종합적인 지식을 통해 노드 프로젝트가 뻗어 나갈 미래의 방향도 엿볼 수 있

을 것이다. 무엇보다 인상적인 것은 각 단계의 선행 학습을 기반으로 책의 내용이 기본에서부터 고급까

지 무리 없이 잘 진행된다는 것이다.

노드는 상승 중인 로켓과 같으며 저자들은 독자들이 이 로켓에 함께 탑승할 수 있게 멋진 일을 해냈다.

노드 인 액션이 여러분 자신의 지평선을 탐험할 수 있는 발사대가 되길 바란다.

아이작 Z. 슐레터

NPM 개발자

노드 프로젝트 리더

Page 18: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XVII

2011년 초 매닝이 우리에게 노드에 관한 책을 써보자는 제안을 해왔을 때 노드 커뮤니티의 상황은 지금

과는 많이 달랐다. 커뮤니티의 규모는 작았으며 노드가 상당한 흥미를 끌기 시작했지만, 여전히 주류 개

발 커뮤니티로부터 유혈의 날 기술1로 취급됐다. 관련 도서는 한 권도 없었고 책을 쓰자는 제안은 벅차게

느껴졌지만 우리는 한번 해보기로 했다.

각자의 개발 성향을 고려했을 때 우리는 노드를 사용한 웹 애플리케이션의 개발 방법뿐만 아니라 노드를

사용할 잠재성이 있는 다른 흥미로운 분야에 대한 내용 또한 담고 있는 책을 만들기 바랐다. 우리는 상투

적인 기술을 사용하는 웹 애플리케이션 개발자에게 노드가 서버 측에 도입한 비동기 방식의 개발에 대해

알려주고 싶었다.

우리가 2년 이상 책을 집필하는 동안 기술은 계속 발전해왔으며 그에 따라 책의 내용도 수정했다. 기술

의 변화와 더불어 커뮤니티 또한 발전해왔다. 현재는 그 규모가 훨씬 커졌으며 많은 큰 규모의 회사에서

도 기꺼이 노드를 도입하고 있다.

무언가 새로운 시도를 해보고 싶은 웹 애플리케이션 개발자에게는 지금이 노드를 배우기 위한 가장 좋은

시기이며, 우리의 책이 여러분이 빠르게 배우고 즐겁게 사용하는 데 도움이 되길 바란다.

1 역자주: 너무 신기술이라 도입하면서 위험을 감수할 필요가 있는 기술

서문

Page 19: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XVIII

이 책이 나오기까지 각자의 역할을 잘 수행 해준 매닝의 멋진 사람들에게 감사의 인사를 전한다. 리네 그

레고리는 우리가 풍부하고 명쾌하며 양질의 책을 만들 수 있도록 추진하는 중요한 역할을 맡아주었다.

버트 베이츠는 이 책에 담긴 많은 개념을 표현하기 위한 그래픽을 디자인하여 책의 시각적인 부분을 완

성하는 데 도움을 주었다. 마잔 베이스와 마이클 스티븐스는 우리에게 이 책을 만드는 일을 믿고 맡겨 주

었으며 프로젝트가 계속 진행될 수 있게 도와주었다. 또한, 매닝의 편집과 제작, 기술 스텝과 함께했던

날들은 정말로 놀라운 시간이었다.

많은 사람이 출판의 여러 과정에서 원고를 검토해 주었으며 그들의 피드백에 감사를 표하고 싶다. 그

들은 바로 이 책의 온라인 포럼에서 의견이나 수정 내용을 올려준 MEAP (Manning Early Access

Program ) 독자들과 원고를 여러 번 정독하며 그들의 통찰과 의견으로 이 책의 완성도를 높이는 데 도

움을 준 리뷰어들이다 : 알렉스 마드렐, 버트 토마스, 브래들리 멕, 브라즈 판다, 브라이언 L. 쿨레이, 브

라이언 델 베키호, 브라이언 딜러드, 브라이언 에먼, 브라이언 포크, 다니엘 브레토이, 개리 이완 박, 제

레미 마틴, 제론 노우스, 제론 트래퍼스, 카산드라 퍼치, 케빈 베이스터, 마이클 피스카텔로, 패트릭 스티

거, 폴 스택, 그리고 스캇 배나호스키.

또한, 출판 직전 최종 원고의 기술 교정을 세심하게 도와준 발렌틴 크레타즈와 마이클 레빈에게도 감사

한다. 마지막으로 이 책의 추천사를 작성해 준 노드 프로젝트 리더인 아이작 슐레터에게 감사의 인사를

전한다.

마이크 캔텔론

기술 업계에 발을 들여놓은 후 처음으로 휴식을 취할 수 있게 해주었으며 오픈 소스 세상을 소개해 주었

고 책을 쓸 수 있게 응원해 준 나의 친구 죠수어 폴에게 고마운 마음을 전한다. 또한, 내가 책을 쓰는 동

안 나를 격려해주며 계속 집에만 틀어박혀 책을 집필하던 시간 동안 인내를 보여줬던 나의 파트너 말콤

에게 감사의 인사를 하고 싶다. 또한, 나에게 창의성과 탐구에 대한 열정을 주셨고 8비트 머신에만 정신

이 팔려 있던 나의 불안한 어린 시절을 감내해준 부모님께 큰 감사의 인사를 드린다. 그리고 나의 일생을

프로그래밍으로 사로잡았던 ‘코모도 64’를 선물해 주신 조부모님께도 감사한다.

감사의 말

Page 20: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XIX

책을 써 가는 과정에서 T.J.와 나단의 전문성은 헤아릴 수 없을 만큼 귀중했으며 그들의 좋은 유머감각을

더욱 높이 평가한다. 그들의 강한 믿음과 협력에 대한 동의에 감사한다. 마크 하터 또한 편집, 증명, 내용

작성 등을 모두 하나로 묶는 매우 어려운 작업에 참여해 큰 도움을 주었다.

마크 하터

4년 전 즈음 내가 서버 측 자바스크립트 프로그래밍에 진지하게 눈을 뜰 수 있게 나에게 영감을 주었던

라이언 달에게 감사한다. 또한, 노드 내부 작업에 있어 빼놓을 수 없는 인물인 벤 눌드히즈에게도 감사한

다. 나를 믿어주고, 노력하게 하고 책을 쓰는 동안 항상 도와주려 했던 버트 베이츠에게도 고마움을 전한

다. 마지막 순간에 나를 환영해 준 마이크, 네이트 그리고 T.J.에게 감사한다. 그들과 함께 일할 수 있어

서 영광이었다. 특별히 내 아내이자 친구인 한나에게 그녀가 이 새로운 도전으로 보여준 용기와 친절에

감사의 인사를 표하고 싶다.

나단 라즈리치

먼저 노드 커뮤니티로 나를 이끌어주고 나의 자리를 찾아준 길레모 라치에게 감사의 마음을 전하고 싶

다. 또한, 이 책을 쓸 수 있게 응원해준 데이비드 블릭슈테인에게도 감사한다. 노드의 전진을 시작하게

해준 라이언 달과 지난 몇 년간 이 배의 승무원 역할을 탁월하게 해준 아이작 슐레터에게도 감사의 인사

를 전한다. 또한, 책을 쓰는 동안 밤을 지새우고 다양한 감정의 변화를 견뎌준 내 가족, 친구들과 여자친

구에게도 감사하고 싶다. 그리고 수년간 컴퓨터 분야에서 나의 성과를 위한 노력을 처음부터 끝까지 지

원해준 나의 부모님께 큰 감사의 인사를 드린다. 내 곁에 그들 없었다면 현재의 나는 없었을 것이다.

감사의 말

Page 21: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XX

이 책에 관하여

노드 인 액션의 주된 목표는 웹 애플리케이션에 주안점을 두고 노드 애플리케이션을 생성하고 배포하는

방법을 알려주는 것이다. 이 책의 많은 부분이 익스프레스 웹 프레임워크와 커넥트 미들웨어 프레임워크

에 초점을 맞추고 있는데 그 이유는 바로 유용성과 커뮤니티의 지원 때문이다. 또한, 자동화된 테스트를

생성하는 방법과 애플리케이션을 배포하는 방법도 배운다.

이 책은 웹 애플리케이션 개발에 경험이 있으며 노드를 이용해 빠르게 반응하며 확장성 있는 애플리케이

션을 만드는 데 관심이 있는 개발자를 주 독자 대상으로 한다.

노드 애플리케이션은 자바스크립트로 작성됐기 때문에 해당 언어에 대한 사전 지식이 필요하다. 또한 윈

도우, 맥 OS X 또는 리눅스 명령행 환경에 친숙한 것이 좋다.

로드맵

이 책은 총 3부로 구성돼 있다.

1부는 노드에 대한 소개와 이를 이용한 개발에 필요한 기반 기술을 가르친다. 1장에서는 노드의 특징에

대한 설명과 몇 가지 예제 코드를 이용한 따라 하기가 있다. 2장에서는 예제 애플리케이션 만들기를 소

개한다. 3장에서는 노드 개발에 있어 어려움이 있는 부분을 설명하고 이를 극복하기 위한 기술을 설명한

다. 또한, 애플리케이션 코드 구성 방식을 가르친다.

이 책의 가장 많은 부분을 차지하는 2부는 웹 애플리케이션 개발에 초점을 맞추고 있다. 4장에서는 노드

기반 웹 애플리케이션 만들기의 기본에 대해 설명하며 5장에서는 노드를 이용해 애플리케이션 데이터를

어떻게 저장할 수 있는지 이야기한다.

계속해서 2부에서는 웹과 관련된 프레임워크 세상으로 안내한다. 6장에서는 커넥트 프레임워크에 대한

소개와 동작 원리, 사용상의 이점 등을 설명한다. 7장에서는 커넥트 프레임워크 내부의 다양한 컴포넌

트를 이용해 웹 애플리케이션에 기능을 추가하는 방법을 가르친다. 8장에서는 익스프레스 프레임워크를

소개하고 9장에서는 익스프레스의 고급 사용법에 대한 내용으로 독자를 안내한다.

책 소개

Page 22: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XXI

웹 개발의 기본에 대한 내용을 배우고 나서 2부는 관련된 주제에 관한 두 개의 장으로 마무리한다. 10장

에서는 독자들에게 노드의 여러 테스팅 프레임워크에 대해 소개한다. 11장에서는 노드 웹 애플리케이션

에서 로직으로부터 데이터의 표현을 분리하기 위한 템플릿을 사용하는 방법을 알려준다.

3부는 웹 개발을 넘어 노드로 할 수 있는 것에 대해 알아본다. 12장에서는 제품 서버에 노드 애플리케이

션을 배포하는 방법, 업타임을 관리하는 방법, 성능을 최대화 하는 방법을 이야기한다. 13장에서는 Http

를 사용하지 않는 애플리케이션을 만드는 방법과 실시간 애플리케이션을 만들기 위해 Socket.io 프레임

워크를 이용하는 방법, 그리고 수많은 편리한 노드 내장 API의 사용에 대해 설명한다. 마지막 장인 14장

에서는 노드 커뮤니티가 어떤 역할을 하고 노드 패키지 관리자(Node Package Manager )를 이용해서

노드 저작물을 등록하는 방법을 논의한다.

코드 작성 규칙과 코드 내려받기

이 책에 담긴 코드는 일반적인 자바스크립트 작성 규칙을 따른다. 들여쓰기할 때는 탭보다는 띄어쓰기를

사용했다. 한 줄은 80자가 넘지 않게 했다. 많은 예제에서 주요 개념을 설명하기 위해 코드에 주석을 활

용했다.

한 줄에 하나의 문장을 사용했고 문장 끝에는 세미콜론을 붙였다. 한 줄 이상의 문장으로 된 코드 단락은

중괄호로 감쌌으며 왼쪽 괄호는 단락을 시작하는 줄의 가장 끝에 위치하게 했다. 오른쪽 괄호는 들여쓰

기를 이용해 단락의 시작 줄과 세로로 열을 맞추게 했다.

이 책에 나온 예제 코드는 출판사 웹사이트인 www.manning.com/Node.jsinAction에서 내려받을 수

있다. 또는 위키북스 홈페이지 www.wikibook.co.kr/node-js-in-action에서도 내려받을 수 있다.

책 소개

Page 23: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XXII

온라인 저자 활동

노드 인 액션을 구매하는 사람들은 매닝 출판사에서 운영하는 비공개 포럼에 참여할 수 있다. 포럼에서

는 책에 대한 의견이나 기술적인 질문을 남기거나 저자나 다른 사용자에게 도움을 받을 수 있다. 포럼에

참여하고 구독하려면 웹 브라우저에서 www.manning.com/Node.jsinAction을 방문하면 된다. 이

페이지에는 등록한 사용자가 포럼에 참여하는 방법과 어떠한 도움을 받을 수 있는지, 포럼의 규칙은 무

엇인지 설명해 놓았다.

매닝은 독자 개개인 또는 독자와 저자 사이에 의미 있는 대화가 오갈 수 있는 장을 만들고자 한다. 이는

저자에게 의무가 아닌 단지 저술 활동의 일부로써 봉사하는 마음으로 그리고 무보수로 포럼에 계속 기여

하기를 원하는 것이다. 우리는 저자들이 흥미를 잃지 않게 독자들이 도전적인 질문을 던지길 바란다.

온라인 저자 포럼과 기존 토론의 기록은 이 책이 출판되는 동안 출판사의 웹사이트에서 확인할 수 있다.

책 소개

Page 24: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XXIII

역자 서문

정승희

플랫폼에 대한 선택의 폭은 개발자의 의도와 상관없이 다양해졌다. 단순함을 무기로 뚜렷한 강점을 취한

플랫폼들도 있고 전통적으로 꾸준히 신뢰받는 플랫폼도 여전히 존재한다. 이런 와중에도 여전히 확실한

것은, 바라는 은총알은 어디에도 없다는 것이다. 개발하고자 하는 목적에 맞는 플랫폼을 제대로 고르는

눈이 필요하지, 플랫폼을 잘 골라서 성공적인 프로젝트가 되길 바라는 것은 요원하다.

이 책은 노드라는 플랫폼을 소개한다. 나는 노드가 처음 등장했을 때 프론트엔드 개발자였는데도, 서버

에다 V8을 띄워놓고 자바스크립트를 돌린다니 “참, 애 많이 쓴다”고 생각했던 적이 있다. 하지만 노드는

나름의 명확한 특징과 장점을 갖춘 엄연한 플랫폼이다. 웹 서버만 놓고 보더라도 전통적인 방식과 다른

처리가 필요하지만, 그것이 이 플랫폼의 특징이자 자바스크립트의 특징이기도 하다.

프론트엔드 개발자에게는 자바스크립트의 특징을 다시 한 번 새길 수 있을 테고 익숙한 언어로 서버 프

로그래밍을 시작할 좋은 기회가 될 것이다. 서버 개발자에게는 어떤 목적에 적절히 사용될만한 플랫폼인

지에 대한 궁금증을 풀어줄 수 있을 것이다.

이 책은 예제를 이해하는 데 필요한 모듈에서부터 실용적인 예제까지 자세히 다루고 있어 혼자 진행하기

에 좋다. 익숙한 방식으로 짜뒀던 코드를 노드로 옮겨본다면 플랫폼에 대한 이해의 폭을 한층 넓힐 수 있

을 거라 확신한다.

번역 제의를 순순히(?) 받아준 준님과 창현님, 그리고 아름다운 제주의 봄을 맘껏 누리지 못했던 식구들

에게 미안하고 또 고맙다고 전하고 싶다.

Page 25: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XXIV

민창현

노드에 대해 처음 가졌던 생각은 프론트엔드 개발자를 위한 연습용 백엔드 플랫폼이라는 것이었다. 당시

나는 강력하면서도 많은 수의 오픈소스와 상용 웹서버들이 이미 자리를 잡고 있는 서버 플랫폼 시장에서

노드의 필요성을 전혀 느낄 수 없었다. 더군다나 스크립트 언어가 제대로 된 서버의 역할을 할 수 있다고

는 생각지도 않았다.

역시나 세상은 생각보다 빠르게 변했고 기술의 진보는 더욱 빠르게 이뤄졌다. 커뮤니티에서 만든 모듈들

은 강력해졌고 실시간이나 고성능, 그리고 빠른 개발을 위한 플랫폼 후보군에 노드가 오르내리기 시작했

다. 또한 새로운 모바일 시장을 겨냥한 수많은 스타트업들이 프론트엔드와 백엔드를 같은 언어로 빠르게

개발하면서도 고성능으로 서비스할 수 있는 노드를 주 플랫폼으로 선택하고 있다.

이 책은 노드의 가장 기본부터 노드에 날개를 달아주는 웹 개발과 테스트 프레임워크, 그 외에도 놓쳐서

는 안 될 다양하면서도 세부적인 내용을 빠짐없이 다루고 있다. 저자들의 고민으로 만들어진 친숙하면서

도 이해하기 쉬운 예제는 노드에 대한 진입 장벽을 더욱 낮춰줄 것이다. 노드와 노드 인 액션이 여러분의

성공을 좀 더 앞당겨주길 바란다.

역자 서문

Page 26: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

XXV

역자 서문

이준

자바스크립트는 웹서비스가 등장한 초기에는 그 화려함을 뽐내며 브라우저를 마음껏 주무르며 웹을 이

끌어가는 원동력이었다. 그러던 것이 웹표준의 중요성이 대두되면서 웹표준을 망치는 천덕꾸러기가 됐

다. 하지만 그 시련을 딛고 몇 년 전부터 ajax를 이용한 비동기 서비스를 시작으로 자바스크립트는 이제

명실상부 웹에서 가장 중요한 언어가 됐다. 그리고 수많은 프레임워크를 장비하고 웹을 넘어서 애플리케

이션을 만드는데 사용되고 있다. 그리고 드디어 노드가 등장해 자바스크립트를 프론드엔드 영역에서 서

버 영역으로 한 발 내딛게 해주었다.

노드는 초기에 많은 우려를 안고 있었다. 성능에 대한 부분과 자바스크립트라는 언어의 태생적인 부분에

이르기까지 많은 부분에서 장벽이 있었기 때문에, 많은 사람들이 노드가 이렇게 발전할 것이라고는 생각

하지 못했던 것이 사실이다. 하지만 지금 노드는 명실상부 최고의 서버측 언어로 자리 잡았다. 성능 면에

서 확장성 면에서 그리고 진입장벽 면에서 굉장한 장점을 가지고 그 영역을 거침없이 넓혀가고 있으며,

상업적인 대형 서비스에도 훌륭한 성능을 보이며 사용되고 있다.

노드는 자바스크립트를 다루는 개발자라면 한 번쯤은 둘러봐야 한다. 그리고 자바스크립트를 많이 다루

지 않는 서버개발자라고 하더라도 한 번쯤은 둘러보는 것이 좋다.

이 책의 번역을 시작하기 전에 나도 이미 노드를 접해본 상태였다. 하지만 이 책을 접하고 나서 노드를

다시 열어보게 됐다. 노드는 빠른 속도로 발전하고 있고 빠른 속도로 적용되고 있다. 책을 한번 보고 흥

미를 갖게 된다면 온라인을 통해서 더 새롭고 성능이 좋아진 노드를 경험해보길 바란다.

Page 27: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

26 Node.js 인 액션

3부 SPA 서버3부 The SPA server1부 노드의 기반 기술

Page 28: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 27

프로그래밍 언어나 프레임워크를 배울 때 보통 기존과는 다른 방식으로 생각해야 하는 새로운 개념을 마주하게

된다. 노드도 예외 없이 애플리케이션 개발의 다양한 측면에서 새로운 접근방식을 취한다.

이 책의 1부에서는 노드가 다른 플랫폼과 정확히 어떤 부분에서 다른지 소개하고 기본적인 사용에 대해서 설명

한다. 노드로 개발한 애플리케이션이 어떤 모습인지, 어떻게 구성되는지 그리고 노드로 개발할 때 부딪히는 어

려움에 어떻게 대처해야 하는지 배울 것이다. 1부에서 배울 내용은 추후 2부에서 자세히 소개할 노드로 웹 애플

리케이션을 만드는 방법과 3부에서 다룰 웹 이외의 애플리케이션 만드는 방법을 배울 때 필요한 기반 지식이 될

것이다.

Page 29: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

28 Node.js 인 액션

이 장에서 다루는 내용

■ 노드란 무엇인가?

■ 서버에서의 자바스크립트

■ 노드의 비동기와 이벤트 속성

■ 노드를 사용하기 적합한 애플리케이션의 종류

■ 노드 프로그램 예제

노드는 무엇일까? 이 단어를 이미 들어봤거나, 노드를 사용하고 있을지도 모르겠다. 어쩌면 노드

에 대해서 궁금할 것이다. 이 책을 집필하는 시점에서 노드가 세상에 나온 지 오래되지는 않았지

만(2009년에 첫선을 보였다), 노드는 매우 인기 있는 플랫폼이다. 깃허브에서는 한 때 가장 주목

받는 프로젝트(https://github.com/joyent/node )였으며 아직도 그 인기는 여전하다. 구글 그

룹스(http://groups.google.com/group/nodejs )와 IRC 채널(http://webchat.freenode.

net/?channels=node.js )이 지원하고 있으며, 패키지 관리자인 NPM (http://npmjs.org )에는

15,000개가 넘는 커뮤니티 모듈이 등록돼 있다. 이 모든 것들이 노드라는 플랫폼의 견인차 구실을 톡톡

히 하고 있다.

노드에 오신 것을 환영합니다

01

Page 30: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 29

노드의 공식 웹사이트(http://www.nodejs.org )에서는 노드를 “크롬의 자바스크립트 실행 환경에 기

반을 둔 빠르고 확장성 있는 네트워크 애플리케이션을 만들기 위한 플랫폼”이라고 정의하고 있다. 노드

는 이벤트 주도 방식과 논블럭킹 I/O 방식을 사용하는데, 이는 가볍고 효율적이며 분산 환경에서 실행되

는 데이터 집약적인 실시간 애플리케이션에 매우 적합하다.

이 장에서는 다음과 같은 개념을 살펴보겠다.

■ 서버 측 개발에서 자바스크립트가 중요한 이유는 무엇인가?

■ 브라우저는 자바스크립트를 이용해 어떻게 I/O를 처리하는가?

■ 노드는 서버에서 어떻게 I/O를 처리하는가?

■ DIRTy 애플리케이션이 무엇이며, 노드에 적합한 이유는 무엇인가?

■ 기본적인 노드 프로그램 예제

우선, 자바스크립트에 주목해 보자.

1.1 자바스크립트 기반

좋든 싫든 자바스크립트는 세상에서 가장 인기 있는 프로그래밍 언어다.1 웹 프로그래밍을 해본 경험이

있다면 자바스크립트는 피할 수 없는 선택이다. 웹이 영향을 미치지 않는 곳이 없는 덕에 자바스크립트

는 90년대 자바가 꿈꾸던 “한번 작성하고 모든 곳에서 실행한다”는 원칙을 실현했다.

2005년에 Ajax 혁명이 일어날 즈음부터 사람들은 자바스크립트를 장난감 같은 언어에서 실질적이고 중

요한 프로그램을 작성하기 위한 언어로 사용했다. 구글 맵스와 지메일이 그 시작을 알렸고, 현재는 트위

터부터 페이스북, 깃허브까지 웹 애플리케이션의 주요 언어로 사용되고 있다.

2008년 말에 구글 크롬이 출시된 이후, 브라우저 업체(모질라, 마이크로소프트, 애플, 오페라, 구글) 사

이의 치열한 경쟁으로 자바스크립트의 성능은 계속 향상돼왔다.2 이러한 최신 자바스크립트 가상 머신의

성능이 웹에서 실행할 수 있는 애플리케이션의 형태를 완전히 바꿔놓고 있다.3 극단적인 예로 자바스크

립트로 수행되는 PC 에뮬레이터인 제이에스리눅스(jslinux )를 들 수 있는데 브라우저에 리눅스 커널을

불러오고 터미널 세션을 사용하며 C 프로그램 컴파일까지 가능하다.

1 유튜브에서 “JavaScript: Your New Overload” 영상을 참고하자. www.youtube.com/watch?v=Trurfqh_6fQ

2 “Chrome Experiments” 페이지에서 몇 개의 예제를 볼 수 있다. www.chromeexperiments.com/

3 자바스크립트 PC 에뮬레이터, 제이에스리눅스. http://bellard.org/jslinux/

Page 31: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

30 Node.js 인 액션

노드는 구글 크롬에 탑재된 V8 가상 머신을 서버 프로그래밍에 사용한다. V8은 바이트코드를 실행하거

나 인터프리터를 사용하는 중간 과정을 없애고 네이티브 기계어로 바로 컴파일하는 방식으로 노드에 상

당한 성능 향상을 가져왔다. 또한, 노드가 서버상에서 자바스크립트를 실행하므로 다음과 같은 이점도

얻을 수 있다.

■ 개발자는 하나의 언어로 웹 애플리케이션을 개발할 수 있기 때문에 서버와 클라이언트를 넘나드는 비용을 줄일 수 있

다. 또한, 폼의 유효성 검증, 게임 로직과 같은 코드를 서버와 클라이언트 사이에서 재사용할 수 있다.

■ JSON은 현재 매우 보편적인 데이터 교환 포맷으로 자바스크립트에 바탕을 두고 있다.

■ 자바스크립트는 카우치디비(CouchDB), 몽고디비(MongoDB)와 같은 다양한 NoSQL 데이터베이스에서 사용되는 언어

로 상호작용하기에 아주 적합하다. 예를 들어, 몽고디비의 셸과 질의언어가 자바스크립트이며 카우치디비의 맵리듀스

또한 자바스크립트다.

■ 자바스크립트는 컴파일 타겟으로 이미 많은 언어가 자바스크립트로 컴파일하고 있다. 4

■ 노드가 사용하는 V8 가상 머신은 ECMA스크립트 표준을 준수한다. 5 다시 말해, 노드가 사용하고 있는 자바스크립트의

새로운 기능을 모든 브라우저가 지원할 때까지 기다릴 필요가 없다.

자바스크립트가 서버 측 애플리케이션을 작성할 수 있는 강력한 언어가 될 것이라고 누가 생각이나 했을

까? 자바스크립트의 넓은 도달 범위와 성능, 그리고 앞서 언급했던 다른 특징들 덕분에 노드는 큰 힘을

받았다. 하지만 자바스크립트 자체는 퍼즐의 한 조각일 뿐이다. 노드가 자바스크립트를 사용하는 방식에

도 주목해야 한다. 노드의 환경을 이해하기 위해 먼저 가장 친숙한 자바스크립트 환경인 ‘브라우저’에 대

해 알아보자.

1.2 비동기와 이벤트: 브라우저

노드는 서버 측 자바스크립트에 이벤트 주도 방식과 비동기 플랫폼을 제공한다. 이는 브라우저가 클라이

언트에서 자바스크립트를 사용할 수 있게 한 것처럼 서버에서 자바스크립트를 사용할 수 있게 한다. 노

드가 동작하는 방식을 이해하려면 브라우저의 동작 방식을 이해하는 것이 중요하다. 브라우저와 노드 모

두 이벤트 주도 방식을 사용하며(이벤트 루프 사용) 논블럭킹 방식으로 I/O를 처리한다(비동기 I/O 사

용). 이것이 무엇을 의미하는지 예제를 통해 살펴보자.

4 “자바스크립트로 컴파일 할 수 있는 언어 목록”을 참고하자. https://github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-

to-JS

5 ECMA스크립트 표준에 관한 더 많은 정보는 위키피디아를 참고하자. http://ko.wikipedia.org/wiki/ECMAScript

Page 32: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 31

이벤트 루프와 비동기 I/O

이벤트 루프와 비동기 I/O에 대한 좀 더 자세한 내용은 위키피디아 문서를 참고하자. http://en.wikipedia.org/wiki/Event_

loop와 http://en.wikipedia.org/wiki/Asynchronous_I/O

XMLHttp-Request (XHR )로 Ajax 요청을 수행하는 일반적인 jQuery 코드를 살펴보자.

$.post('/resource.json', function (data) {

console.log(data);

});

// 스크립트 실행이 계속된다

이 프로그램은 resource.json에 대해 HTTP 요청을 수행한다. 응답이 돌아오면 해당 요청에서 수신한

데이터인 data를 인자로 받는 익명 함수(여기서는 “콜백”)가 호출된다.

다음과 같이 코드를 작성하지 않았다는 점에 주목하자.

var data = $.post('/resource.json');

console.log(data);

이벤트 루프 1. resource.json에

대한 Ajax 요청 생성

resource.json

…대기…

4. 최종적으로 resouce.json에 대한 Ajax

요청의 응답이 도착하여 콜백에서 처리됨

3. 다른 Ajax 요청이 들어옴

2. 사용자 클릭; onclick 이벤트에 대한 처리

그림 1.1 브라우저에서의 논블럭킹 I/O 예제

I/O가 완료될 때까지 코드의 실행을 멈추지 않는다

I/O가 완료될 때까지 코드의 실행이 멈춰있다

Page 33: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

32 Node.js 인 액션

앞선 예제에서 resource.json의 응답이 준비되면 data 변수에 저장되고 console.log 함수는 그전까지

실행되지 않는다고 가정한다. I/O 작업(Ajax 요청)은 준비될 때까지 계속해서 스크립트의 실행을 멈추

게 한다. 브라우저는 단일 스레드이므로 요청 응답에 400ms가 걸린다면 페이지의 다른 이벤트는 이전

의 실행이 완료될 때까지 대기해야 한다. 이 때문에 애니메이션이 멈추거나 사용자가 페이지와 상호작용

하려고 노력하는 등의 불편한 사용자 경험을 상상할 수 있을 것이다.

다행히 이런 일은 일어나지 않는다. 브라우저에서 I/O가 발생할 때 이벤트 루프 외부(주 스크립트 실행

의 외부)에서 발생하고 I/O가 완료될 때 이벤트가 발생하며,6 그림 1.1과 같이 주로 “콜백”이라 불리는

함수에 의해 처리된다.

I/O가 비동기로 처리되며 스크립트 실행이 “멈추지” 않기 때문에 이벤트 루프는 페이지에서 수행되는

다른 상호작용이나 요청에 대해서도 응답할 수 있다. 이런 점이 브라우저로 하여금 클라이언트에 빠르게

반응하고 페이지의 수많은 상호작용을 처리하게 한다.

이런 점을 기억하면서 서버로 바꿔 생각해보자.

1.3 비동기와 이벤트: 서버

1.2절에서 살펴본 jQuery의 ‘실행 멈춤’ 예제처럼 대부분 서버 측 프로그래밍의 일반적인 I/O 모델에

친숙할 것이다. PHP로 작성한 예제를 살펴보자.

$result = MySQL_query('SELECT * FROM myTable');

print_r($result);

위 코드에서는 I/O가 실행되고 모든 데이터가 도착할 때까지 프로세스가 멈춘다. 대부분 애플리케이션

에서 이런 방식은 잘 동작하며 따라 하기 쉽다. 프로세스의 상태나 메모리는 눈에 보이지 않는 것이고 이

들은 I/O가 종료될 때까지 아무것도 하지 않는다. I/O 실행이 지연되면 어느 부분에서든 10ms에서 수

분까지 소요될 수 있다. 지연은 다음과 같은 예상치 못한 원인에서 비롯될 수도 있다.

6 브라우저에서 실행을 멈추는 데에는 몇 가지 예외가 있지만, 일반적으로 얼럿, 프롬프트, 컨펌, 동기식 XHR 등의 사용은 지양해야 한다.

데이터베이스 질의가 완료될 때까지 실행을 멈춘다

Page 34: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 33

■ 디스크의 유지보수 작업 수행으로 읽기/쓰기가 정지될 때

■ 데이터베이스의 부하가 높아져 질의 수행이 느려질 때.

■ 알 수 없는 이유로 sitexyz.com에서 자원을 가져오는 것이 갑자기 느려졌을 때

만약 프로그램이 I/O 대기 중일 때, 서버가 더 많은 요청을 처리해야 한다면 어떻게 될까? 대체로 이런

상황에서 멀티스레드 접근법을 사용할 것이다. 일반적인 구현 방법은 하나의 연결당 하나의 스레드를 사

용하고 여러 연결을 위한 스레드 풀을 만드는 것이다. 스레드는 프로세서가 하나의 태스크를 처리하기

위한 계산 작업 공간이라고 볼 수 있다. 대부분의 경우 스레드는 프로세스 내부에 포함돼 있으며 자신의

작업 메모리를 유지한다. 각 스레드는 하나 이상의 서버 연결을 처리한다. 이는 적어도 오랫동안 이렇게

일해 온 개발자에게는 자연스러운 방법처럼 들리겠지만, 애플리케이션 내부에서 스레드를 관리하는 것

은 굉장히 복잡할 수 있다. 또한, 많은 수의 서버 연결을 동시에 처리해야 하는 경우라면 스레딩은 운영

체제의 자원에 부담을 주게 된다. 스레드는 추가적인 RAM을 사용할뿐만 아니라 CPU의 문맥 교환이 필

요하다.

이를 설명하기 위해 엔진엑스(NGINX )와 아파치(Apache )를 비교한 성능 측정 결과(그림 1.2 참고)

를 확인해 보자. 엔진엑스(http://nginx.com/)는 아파치와 같은 HTTP 서버지만, I/O 대기가 있는

멀티스레드 접근법 대신 브라우저나 노드처럼 비동기 I/O와 이벤트 루프를 사용한다. 이러한 방식을 선

택함으로써 엔진엑스는 더 많은 요청과 클라이언트 연결을 처리할 수 있게 됐고, 요청에 더욱 빠르게 반

응하는 솔루션으로 자리매김했다.7

노드에서 I/O는 대부분 주 이벤트 루프 외부에서 수행되어 엔진엑스처럼 서버가 효율적이고 요청에 잘

반응할 수 있는 상태가 되게 한다. 이런 방식에서 프로세스는 I/O 집약적이기 어려운데 수행이 멈춰진

상태에서도 I/O 지연 때문에 서버가 장애를 일으키거나 자원을 소비하지 않기 때문이다. 이런 이유로 서

버는 일반적으로 수행 성능을 가장 저해하는 부분에서 짐을 덜 수 있게 됐다. 8

7 이 문제에 대해서 좀 더 많은 내용을 알고 싶다면 “동시 접속자 1만 명 문제(The C10K problem)”를 참고하자(www.kegel.com/c10k.html).

8 노드 웹사이트의 ‘about’ 페이지에서 좀 더 자세한 내용을 볼 수 있다(http://nodejs.org/about/).

Page 35: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

34 Node.js 인 액션

초당 처리한 요청 개수 1

2

3

4

1

2

3 4

엔진엑스처럼 비동기와 이벤트 방식을 활용한 프로그램은 서버와 클라이언트 사이

에 좀 더 많은 양의 통신을 처리할 수 있다

이러한 프로그램은 요청에도 더 빠르게 반응한다 이 예제에서는 3,500개의 연결에

대해 각 엔진엑스 요청이 대략 3배 정도 더 빠르게 처리됐다

생성된 서버-클라이언트 연결 개수

그림 1.2 WebFaction의 아파치/엔진엑스 성능 측정 결과(출처: http ://mng.bz/eaZT)

이렇듯 이벤트 주도와 비동기 방식의 조합과 자바스크립트 언어의 넓은 접근성 덕분에 데이터 집약적인

실시간 애플리케이션의 흥미진진한 세상이 펼쳐지고 있다.

1.4 DIRTy 애플리케이션

DIRT는 노드를 적용하기에 적절한 형태의 애플리케이션인 데이터 집약적 실시간 애플리케이션(data-

intensive real-time )의 앞글자를 딴 단어다. 노드는 I/O 부분에서 매우 가벼워졌기 때문에 한 파이프

에서 다른 파이프로 데이터를 전송하는 프록싱(proxying )이나 셔플링(shuffling )에 적합하다. 이는

서버가 많은 요청을 처리하는 중에도 여러 개의 연결을 유지할 수 있으며 메모리 공간을 적게 사용하도

록 관리되기 때문이다. 이처럼 노드는 브라우저와 같이 요청에 빠르게 반응하도록 설계됐다.

실시간 애플리케이션은 웹을 사용하는 새로운 방식이다 최근 많은 웹 애플리케이션이 실시간에 가까운

정보를 제공하고 있고 온라인 화이트보드 협업, 버스 같은 대중교통의 이동 위치에 대한 실시간 핀 표시,

다중 사용자 게임과 같은 형태로 구현되고 있다. 이러한 흥미로운 애플리케이션이 실시간 컴포넌트의 발

Page 36: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 35

전으로 만들어졌든, 완전히 새로운 형태의 애플리케이션 인지와는 상관없이 웹은 더 잘 반응하고 협업에

편리해지는 방향으로 발전하고 있다. 하지만 새로운 분야의 웹 애플리케이션은 동시에 수많은 사용자에

게 거의 실시간으로 반응할 수 있는 플랫폼이 필요하다. 노드는 이 부분에서 강점이 있으며 이는 단지 웹

애플리케이션뿐만 아니라 I/O가 많이 발생하는 다른 애플리케이션에서도 적용된다.

노드로 작성된 DIRTy 애플리케이션의 좋은 예로 그림 1.3의 브라우저링(browserling.com )을 들 수

있다. 이 사이트는 브라우저에서 다른 브라우저를 사용해볼 수 있게 만들어졌다. 이는 테스트를 위해 수

많은 브라우저와 운영체제를 독립적으로 설치해야 하는 고통을 덜어주므로 프론트엔드 웹 개발자에게는

무척 유용하다. 브라우저링은 QEMU (Quick Emulator ) 에뮬레이터를 이용해 생성된 가상 머신을 관

리하는 StackVM이라는 노드 주도 프로젝트의 영향을 받았다. QEMU는 브라우저를 구동하는 데 필요

한 CPU와 기타 주변 장치를 에뮬레이트 한다.

그림 1.3 브라우저링: 노드를 활용한 대화형 크로스 브라우저 테스트

브라우저링은 테스트 브라우저를 구동한 가상 머신을 가지고 있으며 사용자의 브라우저에서 입력되는

키보드와 마우스 이벤트를 가상 브라우저로 전달한다. 그다음 가상 브라우저의 변경된 화면 정보를 전송

받아 사용자의 브라우저 화면에 다시 적용한다. 이 과정이 그림 1.4에 설명돼 있다.

Page 37: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

36 Node.js 인 액션

사용자의 마우스와 키보드 이벤트

Browserling.com

HTML5 캔버스

가상 브라우저

(QEMU)

데이터 URI 형태의 갱신된 이미지

웹소켓Node.js

2

1

웹 브라우저에서 발행한 사용자의 마우스 및 키보드 이벤트는 웹소켓을 통해

실시간으로 노드에 전달되며, 이는 다시 에뮬레이터에 전달된다

1

2 사용자와 상호 작용으로 변경된 브라우저 화면 정보는 노드와 웹소켓을 통해

다시 전송되고 브라우저의 캔버스에 다시 그려진다

그림 1.4 브라우저링의 동작 과정

브라우저링은 노드를 이용한 테스틀링(testling.com )이라는 유용한 프로젝트를 제공하는데, 이를 이용

해 명령행에서 여러 개의 브라우저에 대해 테스트를 병렬로 실행해 볼 수 있다.

브라우저링과 테스틀링은 DIRTy 애플리케이션의 좋은 예이며, 확장 가능한 네트워크 애플리케이션을

만들기 위한 기반 기술은 첫 번째 노드 애플리케이션 작성을 시작할 때 이미 준비돼 있을 것이다. 이제

노드 API가 어떻게 이러한 기능들을 제공하는지 좀 더 살펴보자.

1.5 DIRTy의 기본 요소

노드는 이벤트 주도와 비동기 방식을 기반으로 만들어졌다. 자바스크립트는 일반적인 서버 측 언어와 달

리 표준 I/O 라이브러리를 가지고 있지 않다. 자바스크립트의 기반 환경이 이를 제공한다. 가장 일반적

이며 가장 많은 개발자가 사용하는 자바스크립트 환경은 이벤트 주도와 비동기 방식을 사용하는 브라우

저다.

노드는 브라우저와 서버 사이에서 일관성을 유지하기 위해 다음과 같이 일반적으로 사용하는 주요 객체

를 다시 구현했다.

■ Timer API (예, setTimeout)

■ Console API (예, console.log)

Page 38: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 37

노드는 다양한 종류의 네트워크 및 파일 I/O에 사용되는 핵심 모듈도 포함하고 있다. 여기에는 HTTP,

TLS, HTTPS, 파일시스템(POSIX ), 데이터그램(UDP ), NET (TCP )에 대한 모듈이 포함돼있다. 핵심

모듈은 I/O 기반의 애플리케이션을 위한 기본적인 구성 요소만을 포함하여 일부러 작고 단순하며 하위

레벨로 만들어졌다. 이를 기반으로 만들어진 서드파티 모듈은 일반적인 문제에 대한 훌륭한 추상화를 제

공한다.

플랫폼 vs. 프레임워크

노드는 자바스크립트 애플리케이션을 위한 플랫폼이며 프레임워크와 혼동해서는 안 된다. 노드에 관한 일반적인 오해는

노드가 훨씬 낮은 계층임에도 불구하고 레일즈(Rails)나 장고(Django) 같은 자바스크립트의 프레임워크라고 생각하는 것

이다.

하지만 웹 애플리케이션을 위한 프레임워크에 관심이 있는 여러분을 위해 이 책의 후반부에서는 노드 기반의 대중적인

프레임워크인 익스프레스를 다룰 것이다.

위 내용을 학습했으니 이제 노드의 코드가 어떻게 생겼는지 궁금할 것이다. 몇 가지 간단한 예제를 살펴

보자.

■ 간단한 비동기 예제

■ Hello World 웹 서버

■ 스트림 예제

간단한 비동기 예제부터 살펴보자.

1.5.1 간단한 비동기 예제

1.2절에서 다뤘던 jQuery를 사용한 Ajax 예제를 다시 살펴보자.

$.post('/resource.json', function (data) {

console.log(data);

});

다음은 노드에서 위와 유사한 방식으로 파일시스템(fs ) 모듈을 이용해 디스크에서 resource.json을 가

져오는 예제다. jQuery 예제와 거의 비슷하다는 것에 주목하자.

Page 39: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

38 Node.js 인 액션

var fs = require('fs');

fs.readFile('./resource.json', function (er, data) {

console.log(data);

})

이 프로그램은 디스크로부터 resource.json 파일을 읽어 들인다. 모든 데이터의 읽기를 완료하면 그 과

정에서 발생한 모든 오류 정보를 담은 er과 파일 데이터를 담은 data를 인자로 받는 익명 함수(또는 콜

백 함수)가 호출된다.

데이터를 읽는 도중에 발생하는 다른 명령을 처리하기 위해 이 과정들은 프로그램 뒤편에서 눈에 띄지

않게 반복된다. 또한, 앞서 말했던 이벤트와 비동기로 인한 장점은 덤으로 얻게 된다. 브라우저에서는

jQuery로 Ajax 요청을 생성했지만, 노드는 파일시스템에 접근해 resource.json을 가져왔다는 것이 서

로 다른 점이다. 이 과정은 그림 1.5에 설명돼 있다.

이벤트 루프 1. resource.json

파일 요청 생성

resource.json

…대기…

4. resource.json 파일 데이터를 읽어와서

콜백 함수에서 처리

3. 또 다른 I/O 명령 실행 완료

2. 이벤트를 발생시킴

그림 1.5 노드의 논블럭킹 I/O 예제

Page 40: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 39

1.5.2 Hello World HTTP 서버

노드는 일반적으로 서버를 구성하는 데 많이 이용된다. 노드를 이용해 다양한 종류의 서버를 만드는 것

이 매우 간단하기 때문이다. 이는 아파치 HTTP 서버에서 PHP 애플리케이션을 올리는 것처럼 애플리

케이션을 위해서 서버를 따로 두어야 했던 환경에 익숙한 사람에게는 이상하게 들릴 수도 있다. 노드에

서는 서버와 애플리케이션이 같은 의미다.

모든 요청에 단순하게 ‘Hello World’라고 응답하는 HTTP 서버 예제를 보자.

var http = require('http');

http.createServer(function (req, res) {

res.writeHead(200, {'Content-Type': 'text/plain'});

res.end('Hello World\n');

}).listen(3000);

console.log('Server running at http://localhost:3000/');

요청이 들어오면 콜백 함수인 function (req, res )이 호출되어 “Hello World”라는 문장을 응답으로 보

낸다. 이러한 이벤트 처리 방식은 브라우저에서 onclick 이벤트를 처리하는 방법과 유사하다. 클릭은 어

떤 부분에서든 발생할 수 있으며 이벤트가 발생했을 때 이를 처리하기 위한 함수를 만들어야 한다. 이 예

제에서 노드는 언제 요청이 들어오든 간에 응답하는 함수를 제공하고 있다.

다음은 동일한 서버지만 요청에 대한 이벤트 처리를 좀 더 명확하게 표시해 작성한 예제다.

var http = require('http');

var server = http.createServer();

server.on('request', function (req, res) {

res.writeHead(200, {'Content-Type': 'text/plain'});

res.end('Hello World\n');

})

server.listen(3000);

console.log('Server running at http://localhost:3000/');

1.5.3 스트리밍 데이터

노드는 스트림과 스트리밍 데이터 처리에도 많이 사용된다. 스트림은 배열과 같은 개념으로 생각할 수

있다. 다만 데이터가 여러 공간에 걸쳐 분산된 것이 아니라 시간의 흐름에 따라 분산된 것이다. 쪼개진

요청에 대한 이벤트 리스너 등록

Page 41: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

40 Node.js 인 액션

데이터 조각이 하나씩 도착하므로 개발자는 데이터 전체가 준비될 때까지 기다렸다가 처리하는 대신 데

이터가 도착하는 즉시 처리할 수 있어야 한다. resource.json 스트림을 어떻게 처리하는지 살펴보자.

var stream = fs.createReadStream('./resource.json')

stream.on('data', function (chunk) {

console.log(chunk)

})

stream.on('end', function () {

console.log('finished')

})

data 이벤트는 새로운 데이터 조각이 만들어질 때마다 발생한다. 그리고 모든 데이터 조각을 다 읽었을

때 end 이벤트가 발생한다. 데이터 조각은 크기가 정해져 있지 않으며 데이터의 종류에 따라 다르다. 읽

기 스트림에 대한 하위레벨의 접근은 메모리 버퍼에 모든 데이터가 쌓일 때까지 기다리는 것보다 훨씬

효율적으로 데이터를 처리할 수 있다.

노드는 데이터 조각들을 쓸 수 있는 쓰기 스트림도 제공한다. 그중 하나가 바로 HTTP 서버에서 요청이

들어올 때 사용하는 응답(res ) 객체다.

읽기와 쓰기 스트림은 하나로 연결되어 데이터 파이프를 구성할 수 있는데, 마치 셸 스크립트에서 |(파

이프) 연산자를 사용하는 것과 비슷한 방식이다. 이런 방식은 데이터 전체를 완전히 읽을 때까지 기다렸

다가 쓰는 대신, 데이터를 읽어 들이는 즉시 쓸 수 있는 효율적인 방법을 제공한다.

이전의 HTTP 서버를 활용해서 클라이언트에 이미지를 스트리밍으로 전송하는 방법을 살펴보자.

var http = require('http');

var fs = require('fs');

http.createServer(function (req, res) {

res.writeHead(200, {'Content-Type': 'image/png'});

fs.createReadStream('./image.png').pipe(res);

}).listen(3000);

console.log('Server running at http://localhost:3000/');

이 짤막한 예제에서 파일(fs.createReadStream )로부터 데이터를 읽는 즉시 클라이언트(res )에게 내

보낸다(.pipe ). 이벤트 루프는 데이터가 스트림 되는 도중에도 다른 이벤트를 처리할 수 있다.

새로운 데이터 조각이 준비되면 data 이벤트 발생

읽기 스트림에서 쓰기 스트림으로 파이프 연결

Page 42: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 41

노드는 이러한 DIRTy의 기본적인 요소를 여러 유닉스와 윈도우를 포함한 다수의 플랫폼에 제공한다.

특히 기반을 이루고 있는 비동기 I/O 라이브러리(libuv )는 부모 운영체제와 상관없이 동일한 방식 제

공하므로 기기에 상관없이 프로그램을 이식하기 쉽고 필요할 경우 다양한 장비에서 실행할 수 있다.

1.6 요약

다른 기술과 마찬가지로 노드 역시 모든 것에 대한 해결책은 아니다. 노드는 그저 특정 문제를 해결하는

데 도움을 주고 새로운 가능성을 열어준다. 노드에 관해 한 가지 흥미로운 점은 시스템의 모든 분야 사람

들에게 관심을 받는다는 것이다. 대부분 자바스크립트로 개발하는 클라이언트 측 프로그래머이고 그 외

에 서버 측 프로그래머와 시스템 레벨 프로그래머도 있다. 여러분이 어디에 속해있든 해당 분야에서 노

드가 적합한 곳이 어딜지 이해하기 바란다.

다시 정리해보면 노드는 다음과 같다.

■ 자바스크립트 기반으로 만들어졌다.

■ 이벤트와 비동기를 사용한다.

■ 데이터 집약적 실시간 애플리케이션을 위해 설계됐다.

2장에서는 간단한 DIRTy 웹 애플리케이션을 만들어보면서 노드 애플리케이션이 어떻게 동작하는지 살

펴보겠다.

Page 43: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

42 Node.js 인 액션

이 장에서 다루는 내용

■ 다양한 노드 컴포넌트 살펴보기

■ 노드를 이용한 실시간 애플리케이션 예제

■ 서버와 클라이언트 간 상호 작용

1장에서 노드를 사용한 비동기 방식 개발과 기존의 동기식 개발의 차이를 살펴봤다. 이 장에서는 단순한

이벤트 주도 방식의 채팅 애플리케이션을 만들어 보면서 노드의 실용적인 측면을 살펴보겠다. 이번 장에

서 소개하는 상세한 내용 때문에 머리가 아프더라도 너무 걱정할 필요는 없다. 이번 장의 목적은 노드 개

발에 대한 궁금증을 풀어주고 이번 책을 다 읽었을 때 무엇을 할 수 있는지 미리 보여주는 것이다.

이 장은 독자들이 웹 애플리케이션을 개발해 본 경험이 있고 HTTP에 대한 기본적인 이해가 있으며

jQuery에 친숙하다는 전제하에 쓰였다. 이번 장에서 진행할 내용은 다음과 같다.

■ 애플리케이션의 동작 방식을 살펴본다.

■ 기술적인 요구 사항을 살펴보고 애플리케이션 초기 설정을 진행한다.

다중 채팅방 애플리케이션 만들기

02

Page 44: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 43

■ 애플리케이션에서 사용할 HTML, CSS, 클라이언트 측 자바스크립트를 서비스한다.

■ Socket.IO를 이용해 채팅과 관련된 메시지를 처리한다.

■ 애플리케이션 UI에 사용할 자바스크립트를 작성한다.

메시지는

여기에

작성한다

메시지는

여기에

출력된다

그림 2.1 채팅 애플리케이션에서 메시지 작성

우선 애플리케이션의 개요부터 살펴보자. 완성된 애플리케이션의 화면 구성과 동작 방식을 확인할 수

있다.

2.1 애플리케이션 개요

이번 장에서 만들 애플리케이션은 그림 2.1과 같이 여러 사용자가 대화창에 메시지를 입력해 온라인에

서 채팅할 수 있는 프로그램이다. 한 사용자가 메시지를 입력하면 같은 채팅방에 있는 다른 모든 사용자

에게 전송된다.

애플리케이션이 시작될 때 각 사용자에게 자동으로 닉네임이 주어지지만, 그림 2.2와 같이 명령어를 이

용해 닉네임을 변경할 수 있다. 닉네임을 변경하기 위한 채팅 명령어는 슬래시(/)로 시작한다.

Page 45: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

44 Node.js 인 액션

닉네임 변경을 위한 채팅 명령어

닉네임이 변경됐음을

알린다

그림 2.2. 사용자의 닉네임 변경

현재 채팅방

사용자가 만든

채팅방 목록

채팅방에 참여하거나 채팅방을 만들기 위한 채팅 명령어

그림 2.3 채팅방 변경

Page 46: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 45

비슷한 방식으로 그림 2.3처럼 새로운 채팅방을 만들거나 기존 방에 참여할 때 채팅 명령어를 사용할 수

있다. 채팅방을 만들거나 참여하면 애플리케이션 상단의 가로 막대 영역에 새롭게 참여한 채팅방의 이름

이 표시된다. 또한, 대화창 오른쪽에 있는 참여할 수 있는 모든 채팅방 목록에도 현재 채팅방의 정보가

표시된다.

사용자가 새로운 채팅방에 참여하면 시스템은 그림 2.4와 같이 변경 내용을 알려준다.

채팅방 참여/생성을 알림

그림 2.4 채팅방 변경 결과 확인

이 애플리케이션은 가장 단순한 기능만 있지만, 실시간 애플리케이션을 만드는 데 필요한 주요 컴포넌

트와 기반 기술을 소개하고 있다. 특히, 노드가 어떻게 정적 파일과 같은 일반적인 HTTP 데이터와 대화

내용과 같은 실시간성 데이터를 동시에 서비스 하는지 알 수 있다. 또한, 노드 애플리케이션의 구성 방식

과 의존성 모듈 관리 방식도 보여준다.

이제 애플리케이션 개발에 필요한 기술을 살펴보자.

2.2 애플리케이션 요구사항과 초기 설정

채팅 애플리케이션을 만들려면 다음과 같은 작업을 수행해야 한다.

■ 정적 파일 서비스(HTML, CSS와 클라이언트 측 자바스크립트 등)

■ 서버에서 채팅과 관련된 메시지 처리

■ 사용자 브라우저에서 채팅과 관련된 메시지 처리

Page 47: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

46 Node.js 인 액션

정적 파일을 서비스 하려면 노드에 포함된 HTTP 모듈을 사용해야 한다. 또한, HTTP를 이용해 파일을

서비스한다면 파일 내용뿐만 아니라 전송되는 파일의 종류도 포함하여 전송해야 한다. 이 정보는 HTTP

헤더의 Content-Type에 설정할 수 있으며 파일의 적절한 마임(MIME ) 형식을 헤더에 추가해준다.

마임 형식은 mime이라는 서드파티 모듈을 사용해서 둘러볼 수 있다.

마임 형식

마임 형식에 대한 좀 더 자세한 내용은 위키피디아 문서를 참고하자. http://ko.wikipedia.org/wiki/MIME

채팅과 관련된 메시지를 처리하기 위해 Ajax를 이용해 서버로부터 데이터를 가져올 수 있다. 하지만 애

플리케이션이 가능한 한 빨리 반응하게 하려면 기존의 Ajax 방식을 사용해 메시지를 전송하는 방법을

피해야 한다. Ajax가 전송 체계로 사용하는 HTTP는 실시간 통신을 위해 설계된 것이 아니다. HTTP를

이용해 메시지를 전송하면 매번 새로운 TCP/IP 연결을 사용해야 한다. 연결을 시작하고 종료하는데 시

간이 소요되며 모든 요청마다 HTTP 헤더 정보를 보내야 하므로 전송해야 할 데이터양도 더 많아지게

된다. 그러므로 HTTP보다는 실시간 통신을 지원하기 위해 설계된 양방향 경량 통신 프로토콜인 웹소켓

(http://en.wikipedia.org/wiki/WebSocket )을 이용하는 편이 더 낫다.

하지만 HTML5를 잘 지원하는 브라우저에서만 웹소켓을 지원하는 관계로 애플리케이션에서는 플래

시(Flash )를 비롯해 웹소켓을 사용할 수 없을 때 다양한 대체 기능을 제공하는 인기 라이브러리인

Socket.IO (http://socket.io/)를 활용하겠다. Socket.IO는 추가 코드나 설정 없이 대체 기능을 투명

하게 처리한다. Socket.IO는 13장에서 좀 더 자세히 다룰 예정이다.

이제 애플리케이션의 파일 구조나 의존 관계 설정 등 사전 작업을 본격적으로 시작하기에 앞서 노드가

HTTP와 웹소켓을 동시에 처리하는 방법을 조금 더 알아보자. 이는 노드가 실시간 애플리케이션에 적절

한 선택이 될 수 있는 이유이기도 하다.

2.2.1 HTTP와 웹소켓 서비스

애플리케이션에서 채팅 메시지를 주고받을 때 Ajax를 사용하지 않기로 했지만, 사용자의 브라우저에 그

릴 화면을 보여줄 때 필요한 HTML, CSS, 클라이언트 측의 자바스크립트를 전송하려면 여전히 HTTP

를 사용해야 한다. 그림 2.5에서 보듯이 노드는 하나의 TCP/IP 포트를 이용해 HTTP와 웹소켓을 동시

에 쉽게 서비스한다. 노드 내부에는 HTTP 서비스를 제공하는 모듈이 있다. 또한, 익스프레스와 같이 노

Page 48: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 47

드의 내장 기능을 이용해 웹 서비스를 조금 더 쉽게 할 수 있도록 도와주는 서드파티 모듈이 많이 있다.

8장에서는 웹 애플리케이션을 생성하기 위한 익스프레스의 사용 방법을 알아볼 것이다. 하지만 이번 장

에서 만들 애플리케이션은 기본 기능에만 충실할 것이다.

애플리케이션에서 사용할 핵심 기술을 대략 알아봤으니 좀 더 살을 붙여보자.

HTTP

요청

HTTP

요청

웹 브라우저 웹 브라우저

노드 서버 노드 서버

웹소켓

데이터 송신

웹소켓

데이터 수신

사용자가 채팅 애플리케이션에

방문했을 때만 발생

사용자가 대화를 주고받는 동안

계속해서 발생

그림 2.5 단일 애플리케이션으로 HTTP와 웹소켓 처리

노드를 설치해야 하나요?

노드를 설치하지 않았다면 지금 부록 A에 있는 설명에 따라 노드를 설치하세요.

2.2.2 애플리케이션의 파일 구조 생성

튜토리얼 애플리케이션을 제작하기에 앞서 프로젝트 디렉터리를 생성한다. 주요 애플리케이션 파일이

이 디렉터리에 바로 저장된다. 먼저, 서버 측 로직을 구현한 파일을 저장할 lib 디렉터리와 클라이언트

측과 관련된 파일을 저장할 public 디렉터리를 생성한다. public 디렉터리에는 javascripts와

stylesheets 디렉터리를 생성한다.

방금 생성한 디렉터리의 구조는 그림 2.6과 같다. 이 장에

서는 이와 같이 파일을 구조화했지만, 노드는 특정 디렉터

리 구조만을 고집하지는 않는다. 사용자가 생각하는 어떤

방식으로도 애플리케이션 파일을 관리할 수 있다.

디렉터리를 모두 생성했으면 애플리케이션의 의존성 모듈

을 명시하는 방법을 자세히 알아보자. 그림 2.6 채팅 애플리케이션 프로젝트의 디렉터리

골격

Page 49: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

48 Node.js 인 액션

애플리케이션 의존성 모듈이란 애플리케이션에 필요한 기능을 사용하기 위해 설치해야 하는 모듈을 말

한다. 예를 들어, MySQL 데이터베이스에 데이터를 저장하는 애플리케이션을 만들었다고 가정하자. 노

드 내부에는 MySQL에 접근할 수 있는 내장 모듈이 없으므로 이를 위한 서드파티 모듈을 따로 설치해야

하는데 이를 의존성 모듈로 볼 수 있다.

2.2.3 의존성 모듈 명시

물론 의존성 모듈을 형식에 맞게 명시하지 않더라도 노드 애플리케이션을 만들 수 있지만, 의존성 모듈

을 명시하는 것은 좋은 습관이다. 의존성 모듈을 명시함으로써 다른 사용자가 애플리케이션을 사용하거

나 여러 곳에서 프로그램을 실행해야 할 때 좀 더 수월하게 사용 환경을 설정할 수 있다.

애플리케이션 의존성 모듈은 package.json 파일에 명시한다. 이 파일은 항상 애플리케이션의 최상

위 디렉터리에 있어야 한다. package.json 파일은 CommonJS 패키지 기술어 표준(http://wiki.

commonjs.org/wiki/Packages/1.0 )을 따르는 JSON 표현식을 사용하며 애플리케이션에 대한 설명

을 담고 있다.

예제 2.1은 튜토리얼 애플리케이션의 기능과 의존 관계를 설명하는 패키지 기술 파일이다. 이 파일을 튜

토리얼 최상위 디렉터리에 package.json으로 저장한다.

예제 2.1 패키지 기술 파일

{

"name": "chatrooms",

"version": "0.0.1",

"description": "Minimalist multiroom chat server",

"dependencies": {

"socket.io": "~0.9.6",

"mime": "~1.2.7"

}

}

이 파일의 내용이 혼란스럽더라도 걱정할 필요는 없다. 다음 장에서 package.json 파일에 대해서 조금

더 살펴볼 것이며 14장에서 더욱 심도 있게 다룰 것이다.

패키지명

패키지 의존성 모듈

Page 50: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 49

2.2.4 의존성 모듈 설치

package.json 파일을 작성하면 애플리케이션의 의존성 모듈을 설치하는 일이 한결 쉬워진다. 노드 패

키지 매니저(Node Package Manager, npm, https://github.com/isaacs/npm )는 노드에 기본적

으로 포함된 유틸리티로 매우 많은 기능을 제공한다. 이를 이용하면 서드파티 모듈을 쉽게 설치할 수 있

고 직접 만든 노드 모듈을 누구나 사용할 수 있게 등록할 수도 있다. 더불어 명령어 하나로 package.

json 파일에 있는 의존성 모듈 목록을 읽어 각 모듈을 설치할 수 있다.

튜토리얼의 최상위 디렉터리에서 다음 명령을 실행해보자.

npm install

이제 튜토리얼 디렉터리를 확인해보면 그림 2.7처럼 node_

modules 디렉터리가 생성된 것을 확인할 수 있다. 이 디렉터리에

는 애플리케이션의 의존성 모듈이 설치돼 있다.

디렉터리 구조를 만들고 의존성 모듈을 설치했으니 이제 애플리케

이션 로직에 살을 붙일 준비가 됐다.

2.3 HTML, CSS, 클라이언트 측 자바스크립트 서비스

앞서 소개했듯이 채팅 애플리케이션에는 다음과 같은 세 가지 기능이 필요하다.

■ 사용자의 웹 브라우저에 정적 파일 서비스

■ 서버에서 채팅과 관련된 메시지 처리

■ 사용자의 웹 브라우저에서 채팅과 관련된 메시지 처리

애플리케이션 로직은 그림 2.8과 같이 서버에서 실행되는 파일과 클라이언트에서 실행되는 파일이 여러

개의 파일로 나뉘어 작성된다. 클라이언트에서 실행되는 자바스크립트 파일은 노드에서 실행되는 파일

과 달리 정적 파일로 서비스돼야 한다.

이 절에서는 위의 세 가지 중 첫 번째 요구사항인 정적 파일을 서비스하기 위한 로직을 만들어 본다. 그

리고 정적 HTML과 CSS 파일을 추가하겠다.

그림 2.7 npm을 이용해 의존성 모듈을 설치

하면 node_modules 디렉터리가 생성됨

Page 51: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

50 Node.js 인 액션

2.3.1 기본적인 정적 파일 서버 생성

정적 파일 서버를 생성하려면 노드에 내장된 몇 가지 기능과 함께 파일의 MIME 타입을 판단할 수 있는

서드파티 mime 모듈을 이용한다.

가장 먼저 할 일은 프로젝트의 최상위 디렉터리에 server.js 파일을 생성해 예제 2.2에 있는 변수 선언

문을 작성하는 것이다. 이 선언문은 노드의 HTTP 관련 기능과 파일시스템 연동, 파일 경로와 관련된 기

능, 그리고 MIME 타입 판단 기능을 사용할 수 있게끔 한다. cache 변수는 캐시 파일 데이터를 다루는

데 사용된다.

예제 2.2 변수 선언

var http = require('http');

var fs = require('fs');

var path = require('path');

var mime = require('mime');

var cache = {};

서버 측

(노드)

클라이언트 측

(웹 브라우저)

server.js

lib

public

stylesheets

javascripts

chat_server.js

index.html

server.js

chat.js

chat_ui.js

그림 2.8 채팅 애플리케이션에서는 클라이언트 측과 서버 측 자바스크립트 로직이 나뉘어 있다.

HTTP 서버와 클라이언트 기능을

제공하는 내장 http 모듈

파일시스템 관련 기능을

제공하는 내장 fs 모듈

파일명 확장자 기반의 MIME 타입 추론 기능을

제공하는 외부 mime 모듈 파일시스템 경로 관련 기능을

제공하는 내장 path 모듈 캐시 된 파일의 내용이 저장되는 캐시 객체

Page 52: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 51

파일 데이터 보내기와 오류 응답

다음으로 할 일은 정적 HTTP 파일 서비스에 필요한 세 개의 헬퍼 함수를 작성하는 것이다. 첫 번째는

요청한 파일이 존재하지 않을 때 404 오류를 전송하는 부분이다. server.js에 해당 함수를 추가해보자.

function send404(response) {

response.writeHead(404, {'Content-Type': 'text/plain'});

response.write('Error 404: resource not found.');

response.end();

}

두 번째는 파일 데이터를 서비스하는 함수다. 먼저 적절한 HTTP 헤더를 작성한 다음 파일의 내용을 전

송한다. server.js에 다음 코드를 추가하자.

function sendFile(response, filePath, fileContents) {

response.writeHead(

200,

{"content-type": mime.lookup(path.basename(filePath))}

);

response.end(fileContents);

}

파일시스템보다는 메모리 저장 장치(RAM )의 접근 속도가 더 빠르다. 이런 이유로 노드 애플리케이션

에서는 최근에 사용한 데이터를 일반적으로 메모리에 캐싱한다. 이번 채팅 애플리케이션에서는 정적 파

일을 처음 디스크에서 읽을 때를 제외하고는 메모리에 캐시해 사용할 것이다. 다음 함수는 캐시에 파일

이 존재하는지 판단하여 캐시에 있다면 바로 서비스하고 캐시에 없다면 디스크에서 읽어와서 서비스한

다. 만약 디스크에도 파일이 존재하지 않으면 응답으로 HTTP 404 오류를 반환한다. 이 함수를 server.

js에 추가하자.

예제 2.3 정적 파일 서비스

function serveStatic(response, cache, absPath) {

if (cache[absPath]) {

sendFile(response, absPath, cache[absPath]);

} else {

fs.exists(absPath, function(exists) {

if (exists) {

파일이 메모리에 캐시돼 있는지 확인

캐시에 존재하는 파일이면 바로 서비스

파일 존재 여부 검사

Page 53: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

52 Node.js 인 액션

fs.readFile(absPath, function(err, data) {

if (err) {

send404(response);

} else {

cache[absPath] = data;

sendFile(response, absPath, data);

}

});

} else {

send404(response);

}

});

}

}

HTTP 서버 생성

HTTP 서버를 생성할 때는 각 HTTP 요청을 어떻게 처리해야 하는지 정의한 콜백 역할을 하는 익명함

수가 createServer에 인자로 전달된다. 콜백 함수는 request와 response 두 개의 인자를 받는다. 콜백

이 실행될 때 HTTP 서버는 두 개의 인자로 사용될 객체를 생성해 전달하게 되는데 이를 이용해 세부적

인 요청사항에 대한 처리와 응답을 보내게 된다. 노드의 http 모듈에 대한 내용은 4장에서 더 자세하게

다루겠다.

HTTP 서버를 생성하기 위해 다음 예제에 있는 코드를 server.js에 추가한다.

예제 2.4 HTTP 서버를 생성하는 코드

var server = http.createServer(function(request, response) {

var filePath = false;

if (request.url == '/') {

filePath = 'public/index.html';

} else {

filePath = 'public' + request.url;

}

var absPath = './' + filePath;

serveStatic(response, cache, absPath);

});

디스크에서 파일 읽기

디스크에 저장된 파일 서비스

HTTP 404 오류 응답

요청에 대한 처리를 정의하고

있는 익명 함수를 이용한 HTTP

서버 생성

기본으로 서비스되는 HTML 파일 결정

URL을 파일의 상대 경로로 변환

정적 파일 서비스

Page 54: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 53

HTTP 서버 시작

지금까지 HTTP 서버를 생성하는 코드를 작성했지만, 아직 서버를 구동하는 데 필요한 로직을 추가하지

않았다. 이제 다음과 같이 TCP/IP 3000번 포트로 요청받는 서버를 구동할 수 있게 로직을 추가할 차례

다. 3000번 포트는 임의로 선택한 숫자이며 1024보다 큰 숫자 중에서 사용되지 않는 번호를 선택해 포

트로 사용할 수 있다(윈도우에서는 1024보다 작은 수의 포트 번호도 사용할 수 있으며, 리눅스나 맥 OS

X에서는 “root”와 같은 권한이 있는 계정으로 애플리케이션을 구동해야만 사용할 수 있다).

server.listen(3000, function() {

console.log("Server listening on port 3000.");

});

이제 애플리케이션이 어떻게 동작하는지 보기 위해 다음 명령을 명령행 프롬프트에 입력해 서버를 구동

한다.

node server.js

서버가 시작된 상태에서 웹 브라우저에서 http://127.0.0.1:3000에 방문하면 404 오류 함수가 실행돼

“Error 404: resource not found”라는 메시지가 출력될 것이다. 정적 파일을 처리하는 로직을 추가했

지만, 아직 정적 파일을 추가하지 않았기 때문이다. 실행 중인 서버는 명령행에서 Ctrl-C 키를 사용해

중단할 수 있다.

다음으로 채팅 애플리케이션의 추가 기능을 위해 정적 파일을 추가해 보자.

2.3.2 HTML과 CSS 파일 추가

가장 먼저 추가할 정적 파일은 기본 HTML 파일이다. public 디렉터리에 index.html 파일을 생성하고

예제 2.5에 있는 내용을 작성한다. HTML은 CSS 파일을 가져오고 애플리케이션 내용을 표시할 HTML

div 요소를 만들며, 여러 개의 클라이언트 측 자바스크립트 파일을 불러온다. 불러온 자바스크립트 파일

은 클라이언트 측의 Socket.IO 기능, 쉬운 DOM 조작을 위한 jQuery, 애플리케이션에 적합한 채팅 기

능을 제공하기 위한 파일이다.

Page 55: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

54 Node.js 인 액션

예제 2.5 채팅 애플리케이션을 위한 HTML

<!doctype html>

<html lang='en'>

<head>

<title>Chat</title>

<link rel='stylesheet' href='/stylesheets/style.css'></link>

</head>

<body>

<div id='content'>

<div id='room'></div>

<div id='room-list'></div>

<div id='messages'></div>

<form id='send-form'>

<input id='send-message' />

<input id='send-button' type='submit' value='Send'/>

<div id='help'>

Chat commands:

<ul>

<li>Change nickname: <code>/nick [username]</code></li>

<li>Join/create room: <code>/join [room name]</code></li>

</ul>

</div>

</form>

</div>

<script src='/socket.io/socket.io.js' type='text/javascript'></script>

<script src='http://code.jquery.com/jquery-1.8.0.min.js'

type='text/javascript'></script>

<script src='/javascripts/chat.js' type='text/javascript'></script>

<script src='/javascripts/chat_ui.js' type='text/javascript'></script>

</body>

</html>

현재 채팅방 이름을 표시할 div

참여할 수 있는 채팅방 목록을 표시할 div

채팅 메시지를 표시할 div

사용자가 명령어와 메시지를 입력할 Form 구성요소

Page 56: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 55

다음으로 추가할 파일은 애플리케이션의 CSS 스타일을 정의한 파일이다. public/stylesheets 디렉터리

에 style.css 파일을 만들고 다음 CSS 코드를 작성한다.

예제 2.6 애플리케이션 CSS

body {

padding: 50px;

font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;

}

a {

color: #00B7FF;

}

#content {

width: 800px;

margin-left: auto;

margin-right: auto;

}

#room {

background-color: #ddd;

margin-bottom: 1em;

}

#messages {

width: 690px;

height: 300px;

overflow: auto;

background-color: #eee;

margin-bottom: 1em;

margin-right: 10px;

}

애플리케이션은 800픽셀 너비에

가로로 중앙 정렬

현재 참여하고 있는 채팅방 이름을

표시하는 영역의 CSS

메시지 표시 영역은 가로 690픽셀, 세로

300픽셀 크기로 지정

Page 57: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

56 Node.js 인 액션

그림 2.9 개발 중인 애플리케이션

HTML과 CSS 작성이 적당히 완료되면 애플리케이션을 실행해 웹 브라우저에서 확인해보자. 애플리케

이션은 그림 2.9와 같은 모습일 것이다.

애플리케이션의 기능은 아직 구현되지 않았지만, 정적 파일이 서비스되고 기본적인 외형을 갖췄다. 이제

서버 측에서 채팅 메시지를 전달하는 부분으로 옮겨 개발을 계속 진행해보자.

2.4 Socket.IO를 이용한 채팅 관련 메시지 처리

앞서 언급한 애플리케이션의 필수 기능 세 가지 중 첫 번째 항목인 정적 파일 서비스를 완료했다. 이제

두 번째 항목인 브라우저와 서버 간 통신을 시작할 차례다. 최신 브라우저는 웹소켓을 사용해 브라우저

와 서버 사이의 통신을 처리한다. 지원 브라우저에 대한 자세한 내용은 Socket.IO 브라우저 지원 페이

지를 참고하자(http://socket.io/#browser-support ).

Page 58: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 57

Socket.IO는 노드와 클라이언트 측 자바스크립트 모두에서 사용하는 웹소켓과 그 외 다른 전송 방식을

위한 추상화된 계층을 제공한다. Socket.IO는 웹소켓이 브라우저에 구현돼 있지 않더라도 같은 API를

사용할 수 있도록 적절한 전송 방식으로 대체한다. 이 절에서는 다음 내용을 다룬다.

■ Socket.IO를 간단히 소개하고 서버 측에서 필요한 Socket.IO 기능을 정리

■ Socket.IO 서버를 사용하기 위한 코드를 추가

■ 다양한 채팅 애플리케이션 이벤트를 처리하기 위한 코드를 추가

Socket.IO가 제공하는 가상 채널을 이용하면 접속한 모든 사용자에게 메시지를 뿌리지 않고 특정 채널

을 구독하는 사용자에게만 메시지를 전송할 수 있다. 이 기능을 이용하면 앞으로 소개할 내용처럼 채팅

애플리케이션의 채팅방 기능을 매우 간단하게 구현할 수 있다.

또한, Socket.IO 는 이벤트 발생자(event emitter )의 유용함을 보여주는 좋은 예다. 이벤트 발생자는

원래 편리하게 비동기 로직을 관리하기 위한 디자인 패턴이다. 이번 장에서는 동작하는 이벤트 발생자

코드의 일부를 살펴볼 것이며, 다음 장에서 좀 더 자세한 내용을 다룬다.

이벤트 발생자

이벤트 발생자는 특정 자원으로부터 메시지를 받거나 보낼 수 있는 개념적인 자원과 연관이 있다. 이 자원은 원격 서버로의

연결일 수도 있지만, 게임 캐릭터처럼 보다 추상화된 것일 수도 있다. Johnny-Five 프로젝트(https://github.com/rwldrn/

johnny-five)는 노드의 영향을 받은 로봇 공학 애플리케이션 사례로 이벤트 발생자를 아두이노(Arduino)의 마이크로 컨트

롤러를 제어하는 데 이용했다.

먼저, 서버 기능을 시작하고 연결을 맺는 로직부터 시작해 보자. 그다음 서버 측에 필요한 기능을 정의해

나갈 것이다.

2.4.1 Socket.IO 서버 구성

다음 두 줄을 server.js에 추가하는 것으로 시작해보자. 첫 번째 줄은 서버 측에서 Socket.IO 기반으로

대화 기능에 대한 로직을 제공하는 커스텀 모듈을 가져온다. 이 모듈에 대한 내용은 잠시 후 정의하겠다.

그 다음줄은 Socket.IO 서버 기능을 시작한다. 이미 정의한 HTTP 서버를 이용하므로 같은 TCP/IP 포

트를 공유할 수 있다.

Page 59: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

58 Node.js 인 액션

var chatServer = require('./lib/chat_server');

chatServer.listen(server);

이제 lib 디렉터리에 chat_server.js 파일을 생성하고 다음 변수 선언문을 가장 앞부분에 추가한다. 이

선언문은 Socket.IO의 사용과 대화 상태를 정의하는 여러 변수의 초기화와 관련된 내용이다.

var socketio = require('socket.io');

var io;

var guestNumber = 1;

var nickNames = {};

var namesUsed = [];

var currentRoom = {};

연결 맺기 로직

다음으로 예제 2.7에 있는 로직을 추가해 서버 함수인 listen을 정의한다. 이 함수는 server.js에서 호출

하며 Socket.IO 서버를 시작하고 Socket.IO가 콘솔에 출력하는 로깅을 제한하며 유입되는 연결을 처

리하는 방법을 담고 있다.

연결 처리 로직은 수많은 헬퍼 함수를 호출하며 chat_server.js에 바로 추가할 수 있다.

예제 2.7 Socket.IO 서버 시작

exports.listen = function(server) {

io = socketio.listen(server);

io.set('log level', 1);

io.sockets.on('connection', function (socket) {

guestNumber = assignGuestName(socket, guestNumber,

nickNames, namesUsed);

joinRoom(socket, 'Lobby');

handleMessageBroadcasting(socket, nickNames);

handleNameChangeAttempts(socket, nickNames, namesUsed);

handleRoomJoining(socket);

socket.on('rooms', function() {

socket.emit('rooms', io.sockets.manager.rooms);

});

기존의 HTTP 서버에 피기백(piggyback)방식으로

SocketIO 서버를 시작

각 연결을 어떻게 처리해야

할지 정의

사용자가 접속하면 손님 닉네임을 부여 사용자가 접속하면 대기

실(Lobby)로 이동

사용자의 메시지, 닉네임

변경, 채팅방 생성이나

변경에 관한 처리를 수행

요청 시 이미 생성된 채팅방 목록

을 사용자에게 제공

Page 60: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 59

handleClientDisconnection(socket, nickNames, namesUsed);

});

};

연결 처리에 관한 내용을 완료했다면 이제 애플리케이션의 요구 사항을 처리할 수 있는 각 헬퍼 함수를

추가해야 한다.

2.4.2 애플리케이션 시나리오와 이벤트 처리

채팅 애플리케이션은 다음과 같은 종류의 시나리오와 이벤트에 대한 처리가 필요하다.

■ 손님 닉네임 부여

■ 채팅방 변경 요청

■ 닉네임 변경 요청

■ 채팅 메시지 전송

■ 채팅방 생성

■ 사용자 접속 해제

이러한 시나리오를 처리하려면 여러 개의 헬퍼 함수를 추가해야 한다.

손님 닉네임 부여

가장 먼저 추가해야 하는 헬퍼 함수는 새로운 사용자의 닉네임과 관련된 처리를 담당하는

assignGuestName 함수다. 새로운 사용자가 처음 채팅 서버에 접속하면 Lobby라는 채팅방에 입장하

게 되며 다른 사용자와 구분할 수 있는 이름을 부여하기 위해 assignGuestName 함수를 호출한다.

기본적으로 손님 닉네임은 Guest 뒤에 새로운 사용자가 접속할 때마다 증가하는 숫자를 붙여서 만든다.

생성된 닉네임은 nickNames 변수에 저장해 사용되며 내부적인 소켓 아이디와 연동된다. 또한, 손님 닉

네임은 현재 사용 중인 모든 닉네임을 저장하는 변수인 namesUsed에도 추가된다. 이 기능을 구현하려

면 예제 2.8의 코드를 lib/chat_server.js에 추가한다.

사용자가 접속을 끊었을

때 관련 데이터 정리를

위한 로직을 정의

Page 61: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

60 Node.js 인 액션

예제 2.8 손님 닉네임 부여

function assignGuestName(socket, guestNumber, nickNames, namesUsed) {

var name = 'Guest' + guestNumber;

nickNames[socket.id] = name;

socket.emit('nameResult', {

success: true,

name: name

});

namesUsed.push(name);

return guestNumber + 1;

}

채팅방 입장

chat_server.js에 두 번째로 추가할 헬퍼 함수는 joinRoom이다. 이 함수는 예제 2.9에서 볼 수 있듯이

사용자가 채팅방에 입장하는 로직과 관련된 처리를 한다.

사용자가 Socket.IO로 만든 방에 입장하는 방법은 간단하다. socket 객체의 join 함수만 호출하면 된

다. 그다음 애플리케이션은 입장한 사용자와 같은 방에 있는 다른 사용자와 관련된 세부 내용을 주고받

는다. 애플리케이션은 입장한 사용자에게 채팅방에 있는 다른 사용자들의 정보를 알려주고 다른 사용자

들에게는 새로운 사용자가 입장했다는 것을 알려준다.

예제 2.9 채팅방 입장과 관련된 로직

function joinRoom(socket, room) {

socket.join(room);

currentRoom[socket.id] = room;

socket.emit('joinResult', {room: room});

socket.broadcast.to(room).emit('message', {

text: nickNames[socket.id] + ' has joined ' + room + '.'

});

var usersInRoom = io.sockets.clients(room);

if (usersInRoom.length > 1) {

var usersInRoomSummary = 'Users currently in ' + room + ': ';

for (var index in usersInRoom) {

새로운 손님 닉네임 생성

닉네임을 클라이언트

연결 아이디와 연동 사용자에게 손님 닉네임을 알려줌

생성된 닉네임을 사용 중 닉네임에 추가

손님 닉네임 생성에 사용되는 카운터 숫자 증가

사용자가 채팅방에 입장

사용자가 이 방에 입장했음을 저장

사용자에게 새로운 채팅방에 입장한 사실을 알림

채팅방의 다른 사용자에게 새로운 사용자가 입장했음을 알림

사용자가 참여한 방에 다른 사용자가 있는지 판단

다른 사용자가 있다면 해당 사용자의 정보를 요약

Page 62: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 61

var userSocketId = usersInRoom[index].id;

if (userSocketId != socket.id) {

if (index > 0) {

usersInRoomSummary += ', ';

}

usersInRoomSummary += nickNames[userSocketId];

}

}

usersInRoomSummary += '.';

socket.emit('message', {text: usersInRoomSummary});

}

}

닉네임 변경 요청 처리

모든 사용자가 애플리케이션에서 할당된 손님 닉네임을 그대로 사용한다면 누가 누구인지 기억하기가

매우 어려울 것이다. 이런 이유로 채팅 애플리케이션에서는 사용자가 닉네임을 변경할 수 있다. 그림

2.10처럼 사용자의 닉네임 변경은 웹 브라우저에서 Socket.IO를 이용해 요청하게 되고 성공 여부를 응

답으로 받는다.

웹 브라우저 노드 서버

웹 브라우저 노드 서버

클라이언트에서 “Bob Bobbs”라는 문자열 데이터와 함께

nameAttempt 이벤트 전송

서버로부터 JSON 데이터와 함께 nameResult 이벤트 반환

그림 2.10 닉네임 변경 요청과 응답

다음 예제에 있는 코드를 lib/chat_server.js에 추가해 사용자의 닉네임 변경 요청을 처리하는 함수를

만들어보자. 애플리케이션 입장에서는 사용자가 이름을 변경하려 할 때 Guest로 시작하거나 이미 사용

중인 이름으로는 변경하지 못하게 해야 한다.

입장한 사용자에게 요약한 다른 사용자의

정보 전송

Page 63: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

62 Node.js 인 액션

예제 2.10 이름 변경 요청을 처리하기 위한 로직

function handleNameChangeAttempts(socket, nickNames, namesUsed) {

socket.on('nameAttempt', function(name) {

if (name.indexOf('Guest') == 0) {

socket.emit('nameResult', {

success: false,

message: 'Names cannot begin with "Guest".'

});

} else {

if (namesUsed.indexOf(name) == -1) {

var previousName = nickNames[socket.id];

var previousNameIndex = namesUsed.indexOf(previousName);

namesUsed.push(name);

nickNames[socket.id] = name;

delete namesUsed[previousNameIndex];

socket.emit('nameResult', {

success: true,

name: name

});

socket.broadcast.to(currentRoom[socket.id]).emit('message', {

text: previousName + ' is now known as ' + name + '.'

});

} else {

socket.emit('nameResult', {

success: false,

message: 'That name is already in use.'

});

}

}

});

}

채팅 메시지 보내기

닉네임과 관련된 부분은 완료했으니 이제 사용자가 전송한 채팅 메시지를 처리하는 함수를 추가할 차례

다. 그림 2.11은 기본적인 과정을 보여준다. 사용자는 메시지를 전송할 채팅방과 메시지를 명시해 이벤

트를 발생시키고, 서버는 채팅방에 있는 다른 사용자에게 채팅 메시지를 전달한다.

이벤트 리스너에 nameAttempt 이벤트 등록

Guest로 시작하는 닉네임은 허용하지 않음

등록되지 않은 닉네임이라면 등록

변경 전 닉네임은 다른 사용자가 사용할 수 있게 삭제

이미 등록된 닉네임인 경우 클라이언트에 오류 전송

Page 64: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 63

다음 코드를 lib/chat_server.js에 추가한다. 메시지를 전달하기 위해 Socket.IO의 broadcast 함수를

사용한다.

function handleMessageBroadcasting(socket) {

socket.on('message', function (message) {

socket.broadcast.to(message.room).emit('message', {

text: nickNames[socket.id] + ': ' + message.text

});

});

}

웹 브라우저 A

웹 브라우저 B

웹 브라우저 C

웹 브라우저 D

노드 서버

노드 서버 클라이언트에서 message 이벤트로 JSON 데이터 전송

서버에서 message 이벤트로 JSON 데이터 전송

그림 2.11 채팅 메시지 보내기

웹 브라우저

웹 브라우저 노드 서버

노드 서버 클라이언트에서 join 이벤트로 JSON 데이터 전송

서버에서 joinResult 이벤트로 JSON 데이터 전송

그림 2.12 다른 채팅방으로 변경

Page 65: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

64 Node.js 인 액션

채팅방 만들기

다음으로 사용자가 이미 만들어진 채팅방에 입장하거나 새로운 채팅방을 직접 만드는 기능을 추가해야

한다. 그림 2.12는 이에 관련된 사용자와 서버 사이의 상호작용을 보여준다.

다음 코드를 lib/chat_server.js에 추가해 채팅방을 변경할 수 있게 한다. Socket.IO의 leave 함수를

사용하는 것에 주목하자.

function handleRoomJoining(socket) {

socket.on('join', function(room) {

socket.leave(currentRoom[socket.id]);

joinRoom(socket, room.newRoom);

});

}

사용자의 접속 해제 처리

마지막으로 사용자가 채팅 애플리케이션을 나갔을 때 nickNames와 namesUsed 변수에서 사용자의

닉네임을 삭제하는 로직을 lib/chat_server.js에 추가하자.

function handleClientDisconnection(socket) {

socket.on('disconnect', function() {

var nameIndex = namesUsed.indexOf(nickNames[socket.id]);

delete namesUsed[nameIndex];

delete nickNames[socket.id];

});

}

이로써 서버 측의 구성 요소를 모두 갖췄다. 이제 한 걸음 더 나아가 클라이언트 측의 로직을 개발할 준

비가 됐다.

2.5 애플리케이션의 사용자 인터페이스를 위한 클라이언트 측 자바스크립트

지금까지 브라우저에서 전송한 채팅 메시지를 전달하기 위한 Socket.IO 로직을 서버 측에 추가하는 작

업을 했다. 이제 서버와의 통신에 필요한 클라이언트 측 자바스크립트를 추가해보자. 클라이언트 측 자

바스크립트는 다음과 같은 기능을 처리해야 한다.

Page 66: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 65

■ 사용자의 메시지와 닉네임/채팅방 변경 요청을 서버로 보내기

■ 다른 사용자의 메세지와 입장할 수 있는 채팅방 목록을 화면에 출력

첫 번째 기능부터 시작해보자.

2.5.1 메시지와 닉네임/채팅방 변경 요청을 서버로 전달

처음 추가할 클라이언트 측 자바스크립트는 채팅 명령과 메시지 전송 그리고 채팅방과 닉네임 변경에 대

한 처리를 수행할 자바스크립트 프로토타입 객체다.

public/javascript 디렉터리에 chat.js 파일을 만들고 다음 코드를 작성한다. 이 코드는 자바스크립트에

서 객체를 생성할 때 Socket.IO의 socket을 단일 인자로 받는 “클래스”와 같은 역할을 한다.

var Chat = function(socket) {

this.socket = socket;

};

다음으로 채팅 메시지를 전송하는 함수를 추가한다.

Chat.prototype.sendMessage = function(room, text) {

var message = {

room: room,

text: text

};

this.socket.emit('message', message);

};

채팅방을 변경하기 위한 함수도 추가한다.

Chat.prototype.changeRoom = function(room) {

this.socket.emit('join', {

newRoom: room

});

};

Page 67: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

66 Node.js 인 액션

마지막으로 채팅 명령을 처리하기 위해 다음 예제에 나오는 내용을 추가한다. 두 가지 명령을 수행할 수

있는데, join은 채팅방에 참여하거나 채팅방을 생성하기 위한 명령어이고 nick은 닉네임을 변경하는 데

사용하는 명령어다.

예제 2.11 채팅 명령 처리

Chat.prototype.processCommand = function(command) {

var words = command.split(' ');

var command = words[0]

.substring(1, words[0].length)

.toLowerCase();

var message = false;

switch(command) {

case 'join':

words.shift();

var room = words.join(' ');

this.changeRoom(room);

break;

case 'nick':

words.shift();

var name = words.join(' ');

this.socket.emit('nameAttempt', name);

break;

default:

message = 'Unrecognized command.';

break;

}

return message;

};

2.5.2 메시지 및 입장할 수 있는 채팅방 목록을 사용자 인터페이스에 보여주기

이제 jQuery를 이용해 브라우저 기반의 사용자 인터페이스와 직접 상호 작용하기 위한 로직을 추가할

차례다. 첫 번째 추가할 기능은 텍스트 데이터를 보여주는 기능이다.

첫 번째 단어에서 명령어 구문 분석

채팅방 변경/생성 처리

닉네임 변경 요청 처리

알 수 없는 명령일 때 오류 메시지 반환

Page 68: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 67

보안 관점에서 봤을 때 애플리케이션에는 두 종류의 텍스트 데이터가 있다. 하나는 애플리케이션이 생성

한 텍스트로 이뤄진 신뢰할 수 있는 텍스트 데이터이고, 다른 하나는 애플리케이션의 사용자가 생성했거

나 그것으로부터 파생된 신뢰할 수 없는 데이터다. 사용자의 텍스트 데이터를 신뢰할 수 없는 이유는 일

부 악의적인 사용자가 <script> 태그에 자바스크립트 로직이 들어간 텍스트 데이터를 고의로 입력할 수

있기 때문이다.

이러한 텍스트 데이터가 그대로 다른 사용자에게 보인다면 다른 웹페이지로 강제 이동되는 것과 같은

원치 않은 일이 발생 할 수 있다. 이처럼 웹 애플리케이션을 하이재킹 하는 방법을 사이트 간 스크립트

(XSS ) 공격이라고 한다.

애플리케이션에서는 텍스트 데이터를 화면에 출력하는 데 두 가지 헬퍼 함수를 사용할 것이다. 그중 하나

는 신뢰할 수 없는 데이터를 표시하는 함수이고 다른 하나는 신뢰할 수 있는 데이터를 표시하는 함수다.

divEscapedContentElement 함수는 신뢰할 수 없는 텍스트를 출력하는 함수다. 이 함수는 그림 2.13에서

볼 수 있듯이 특수문자를 HTML 요소로 정제함으로써 브라우저가 텍스트를 HTML 태그로 인식하지 않고

입력받은 대로 출력할 수 있게 해준다.

divSystemContentElement 함수는 사용자가 아닌 시스템이 생성한 신뢰할 수 있는 내용을 화면에 출력하

는 함수다.

메시지는 divEscapedContentElement 함수를 통해

정제된 뒤 <div> 태그에 들어간다

<script>alert('XSS attack!');</script>

<div>&lt;script&gt;alert('XSS attack!');&lt:/script&gt;<div>

그림 2.13 신뢰할 수 없는 컨텐츠 이스케이프

public/javascripts 디렉터리에 chat_ui.js 파일을 추가한 뒤 다음 두 개의 헬퍼 함수의 내용을 작성

한다.

function divEscapedContentElement(message) {

return $('<div></div>').text(message);

Page 69: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

68 Node.js 인 액션

}

function divSystemContentElement(message) {

return $('<div></div>').html('<i>' + message + '</i>');

}

다음으로 chat_ui.js에 사용자 입력을 위한 함수를 추가할 차례다. 다음 예제에 자세한 내용이 담겨 있

다. 사용자가 슬래시(/) 문자를 시작으로 작성한 글은 채팅 명령으로 처리된다. 그 이외의 메시지는 다

른 모든 사용자에게 전송되고 현재 참여한 채팅방의 대화글 목록에 추가된다.

예제 2.12 사용자 입력 처리

function processUserInput(chatApp, socket) {

var message = $('#send-message').val();

var systemMessage;

if (message.charAt(0) == '/') {

systemMessage = chatApp.processCommand(message);

if (systemMessage) {

$('#messages').append(divSystemContentElement(systemMessage));

}

} else {

chatApp.sendMessage($('#room').text(), message);

$('#messages').append(divEscapedContentElement(message));

$('#messages').scrollTop($('#messages').prop('scrollHeight'));

}

$('#send-message').val('');

}

지금까지 몇 가지 헬퍼 함수 작성을 완료했고 이제 웹 페이지가 사용자의 웹 브라우저에서 완전히 로딩

된 이후에 수행할 로직을 다음 예제와 같이 추가할 차례다. 이 코드는 Socket.IO 이벤트를 다루는 클라

이언트 측 초기화를 처리한다.

사용자 입력이 슬래시로 시작하면 채팅 명령으로 처리한다

다른 모든 사용자에게 입력한 내용을 전달한다

Page 70: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 69

예제 2.13 클라이언트 측 애플리케이션의 초기화 로직

var socket = io.connect();

$(document).ready(function() {

var chatApp = new Chat(socket);

socket.on('nameResult', function(result) {

var message;

if (result.success) {

message = 'You are now known as ' + result.name + '.';

} else {

message = result.message;

}

$('#messages').append(divSystemContentElement(message));

});

socket.on('joinResult', function(result) {

$('#room').text(result.room);

$('#messages').append(divSystemContentElement('Room changed.'));

});

socket.on('message', function (message) {

var newElement = $('<div></div>').text(message.text);

$('#messages').append(newElement);

});

socket.on('rooms', function(rooms) {

$('#room-list').empty();

for(var room in rooms) {

room = room.substring(1, room.length);

if (room != '') {

$('#room-list').append(divEscapedContentElement(room));

}

}

$('#room-list div').click(function() {

chatApp.processCommand('/join ' + $(this).text());

$('#send-message').focus();

});

});

닉네임 변경 요청 결과 출력

채팅방 변경 결과 출력

수신한 메시지 출력

입장할 수 있는 채팅방 목록 출력

채팅방 이름을 클릭해 채팅방을 변경할 수 있게 한다

Page 71: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

70 Node.js 인 액션

setInterval(function() {

socket.emit('rooms');

}, 1000);

$('#send-message').focus();

$('#send-form').submit(function() {

processUserInput(chatApp, socket);

return false;

});

});

마지막으로 애플리케이션을 마무리하기 위해 다음 CSS 스타일 코드를 public/stylesheets/style.css

파일에 추가한다.

예제 2.14 마지막으로 style.css에 추가할 내용

#room-list {

float: right;

width: 100px;

height: 300px;

overflow: auto;

}

#room-list div {

border-bottom: 1px solid #eee;

}

#room-list div:hover {

background-color: #ddd;

}

#send-message {

width: 700px;

margin-bottom: 1em;

margin-right: 1em;

}

#help {

font: 10px "Lucida Grande", Helvetica, Arial, sans-serif;

}

주기적으로 현재 채팅방 목록 요청

메시지를 전송하기 위해 폼을 제출할 수 있게 한다

Page 72: Node.js 인 액션 : 베테랑 개발자가 전하는 노드제이에스 완벽 활용법

1부. 노드의 기반 기술 71

마지막 코드를 추가했다면 node server.js를 이용해 애플리케이션을 실행해보자. 애플리케이션은 그림

2.14와 같은 모습을 갖췄을 것이다.

그림 2.14 완성된 채팅 애플리케이션

2.6 요약

지금까지 노드를 사용해 간단한 실시간 웹 애플리케이션을 완성했다!

이제 애플리케이션의 제작 방식과 코드 구성에 대해 어느 정도 감을 잡았을 것이다. 이 장의 예제를 정확

하게 이해하지 못했더라도 너무 걱정할 필요는 없다. 앞으로 나올 내용은 이번 예제에 사용된 기법과 기

술에 대한 좀 더 심도 있는 내용을 다룬다.

본격적으로 노드 개발에 대한 내용을 다루기 전에 비동기 개발 과정에서 겪을 수 있는 어려움을 먼저 알

아보는 것이 도움될 것이다. 이를 위해 다음 장에서는 개발 과정에서 좌절과 노력을 상당히 줄일 수 있는

꼭 필요한 기술과 기법을 알아보겠다.