프로 리액트 : react.js를 이용한 모던 프런트엔드 구축

36

Post on 30-Jul-2016

265 views

Category:

Documents


16 download

DESCRIPTION

카시우 지 소자 안토니우 지음 | 최민석 옮김 | 오픈소스 & 웹 시리즈_079 | ISBN: 9791158390426 | 28,000원 | 2016년 05월 31일 발행 | 456쪽 | React, React.js, 가상DOM, 리액트, 반응형, 사용자 인터페이스, 페이스북, 프런트엔드

TRANSCRIPT

Page 1: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축
Page 2: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차|VIII

시작하기 201 장

시작하기 전에 3

Node.js와 npm 3

자바스크립트 ES6 4

리액트의 정의 4

리액트의 장점 5

편리한 반응형 렌더링 5

순수 자바스크립트를 이용한 컴포넌트 기반 개발 6

문서 모델의 유연한 추상화 6

첫 번째 리액트 앱 작성 7

리액트 개발 워크플로 8

첫 번째 컴포넌트 만들기 12

타이핑 수고를 약간 줄이는 방법 13

동적 값 14

컴포넌트 조합하기 14

속성 14

칸반 보드 앱 소개 16

컴포넌트 계층 정의 18

속성의 중요성 19

컴포넌트 만들기 19

앱 모듈(App.js) 20

상태 소개 29

칸반 앱: 토글되는 카드 29

정리 32

책2.indb 8 2016-05-24 오후 10:30:59

Page 3: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차 | IX

DOM추상화의내부 3302 장

리액트의 이벤트 34

DOM 이벤트 리스너 34

칸반 앱: DOM 이벤트 관리 35

JSX 자세히 살펴보기 37

JSX와 HTML 비교 38

JSX와 HTML의 차이 38

JSX의 특이점 39

칸반 앱: 카드가 열려있는지 여부 확인 43

공백 44

JSX의 주석 45

동적 HTML 렌더링 46

칸반 앱: 마크다운 렌더링 46

JSX를 배제하고 리액트 이용 49

일반 자바스크립트로 리액트 요소 만들기 49

요소 팩토리 49

커스텀 팩토리 51

인라인 스타일링 51

인라인 스타일 정의 51

칸반 앱: 인라인 스타일링을 이용한 카드 색상 지정 52

폼 처리 55

제어 컴포넌트 55

특수 사례 58

책2.indb 9 2016-05-24 오후 10:31:00

Page 4: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차|X

비제어 컴포넌트 58

칸반 앱: 태스크 폼 만들기 60

가상 DOM의 작동 방식 61

키 62

칸반 앱: 키 62

ref 64

정리 65

컴포넌트를이용한애플리케이션구축 6603 장

속성 유효성 검사 67

속성 기본값 69

기본 제공되는 propTypes 유효성 검사기 70

칸반 앱: 속성 형식 정의 71

커스텀 propTypes 유효성 검사기 73

컴포넌트 조합 전략과 모범 사례 75

상태 저장 컴포넌트와 순수 컴포넌트 75

어떤 컴포넌트가 상태 저장이어야 할까? 76

데이터 흐름과 컴포넌트 통신 80

컴포넌트 수명주기 85

수명주기 단계와 메서드 85

수명주기 함수의 실제 활용: 데이터 가져오기 87

책2.indb 10 2016-05-24 오후 10:31:00

Page 5: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차 | XI

불변성에 대한 개요 90

일반 자바스크립트에서의 불변성 91

중첩된 객체 93

리액트 불변성 도우미 95

칸반 앱: 약간의 복잡성 추가 99

정리 117

정교한상호작용 11804 장

리액트의 애니메이션 119

CSS 트랜지션과 애니메이션의 기초 119

ReactCSSTransitionGroup 127

드래그 앤드 드롭 135

리액트 DnD 구현 개요 136

리액트 DnD 예제 구현 136

칸반 앱: 애니메이션과 드래그 앤드 드롭 지원 152

카드 토글 애니메이션 152

카드 드래그 155

정리 173

책2.indb 11 2016-05-24 오후 10:31:00

Page 6: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차|XII

라우팅 17405 장

라우팅을 구현하는 단순한 방식 175

리액트 라우터 180

인덱스 라우트 184

매개변수를 이용하는 라우트 185

활성 링크 설정 191

속성 전달하기 192

UI와 URL의 연결 분리 196

프로그래밍 방식으로 라우트 변경 198

히스토리 201

칸반 앱: 라우팅 203

정리 221

플럭스를이용한리액트애플리케이션설계 22206 장

플럭스란? 224

스토어 224

액션 225

디스패처 226

실용성이 없는 최소 플럭스 앱 226

은행계좌 애플리케이션 227

책2.indb 12 2016-05-24 오후 10:31:01

Page 7: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차 | XIII

플럭스 유틸 237

플럭스 유틸 스토어 237

컨테이너 컴포넌트 고차 함수 240

비동기 플럭스 242

waitFor: 스토어 업데이트 순서 242

비동기 데이터 가져오기 246

에어치프 애플리케이션 246

설정: 프로젝트 구성과 기본 파일 247

공항을 가져오는 액션 생성자와 API 도우미 작성 248

AirportStore 252

App 컴포넌트 253

에어치프 애플리케이션 완성: 항공권 로딩 260

비동기 데이터를 가져오는 구현 개선하기 273

AppDispatcher의 dispatchAsync 메서드 274

칸반 앱: 플럭스 아키텍처로 전환 277

리팩터: 플럭스 기본 구조 제작 및 파일 이동 277

플럭스 아키텍처로 데이터 가져오기 전환 283

FetchCards 액션, API 메서드 호출,

스토어 콜백 구현 285

모든 카드와 태스크 조작을

플럭스 아키텍처로 이식하기 288

기능 이식을 위한 준비 289

컴포넌트 300

모든 컴포넌트 상태 제거 308

정리 322

책2.indb 13 2016-05-24 오후 10:31:01

Page 8: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차|XIV

성능튜닝 32307 장

조정 프로세스 작동 방식 324

일괄 처리 324

하위 트리 렌더링 325

리액트 퍼프 326

성능 테스트 애플리케이션 326

리액트 퍼프 설치와 이용 330

shouldComponentUpdate 336

shallowCompare 애드온 338

정리 339

동형리액트애플리케이션 34008 장

Node.js와 익스프레스 341

Node.js와 익스프레스를 이용한

“Hello World” 애플리케이션 제작 342

동형 리액트의 기본 348

프로젝트 구조 만들기 348

서버 상의 리액트 컴포넌트 렌더링 353

클라이언트에 리액트 마운팅 357

라우팅 361

내부 라우트 설정 361

동적 데이터 가져오기 363

라우트 렌더링 366

정리 372

책2.indb 14 2016-05-24 오후 10:31:01

Page 9: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차 | XV

리액트컴포넌트의테스트 37309 장

제스트 374

리액트 테스트 유틸리티 376

테스트용 컴포넌트 렌더링 377

자식 순회 및 찾기 380

이벤트 시뮬레이션 382

얕은 렌더링 383

정리 388

웹팩 389부록 A웹팩이란? 390

그런트나 걸프와 같은 빌드 도구와의 차이점 390

시작하기 392

예제 프로젝트 392

첫 번째 빌드 실행 394

구성 파일 정의 395

태스크 바로가기 추가 396

소스맵 생성 397

웹팩 개발 서버 399

로더 401

바벨 403

설치와 구성 403

바벨 구성 파일 406

책2.indb 15 2016-05-24 오후 10:31:01

Page 10: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

목차|XVI

자바스크립트 외의 애셋 407

스타일시트 407

CSS 모듈 410

CSS 프로세서 412

플러그인 413

플러그인 이용하기 414

html-webpack-plugin 415

HMR 417

실무용 빌드 420

최적화 플러그인 422

캐싱 424

정리 425

자바스크립트2015 426부록 B클래스 427

모듈 428

let과 const 430

프로미스 431

화살표 함수 431

템플릿 문자열 433

구조분해 할당 434

책2.indb 16 2016-05-24 오후 10:31:02

Page 11: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

들어가며

리액트React는 조합형 인터페이스를 제작하기 위한 오픈소스 라이브러리로서 현재는 페이스북이

관리하고 있다. 이 라이브러리는 처음 공개된 이후로 빠른 속도로 보급되고 있으며, 관련 커뮤니티의

사용자도 꾸준히 증가하고 있다.

이 책에서는 리액트 라이브러리를 자세히 소개하고 인터페이스를 조합형으로 제작하는 최상의 방법을

설명한다. 리액트 라이브러리 자체는 아직 작기 때문에 완전한 애플리케이션을 만들 수 있는 충분한

지식을 독자에게 전달하기 위해 리액트 라우터나 플럭스 아키텍처 같은 리액트 생태계의 부가적인

도구와 라이브러리를 함께 다룬다.

각 주제는 특정 문제를 효과적으로 해결할 수 있는 정보를 전달하기 위해 간결하고 명확하게 구성했다.

가장 중요한 기능에 대해서는 현실적이고 구체적인 활용 방안을 제시하며, 모든 단원에서 흔히

발생하는 문제와 이러한 문제를 예방하는 방법을 자세히 다룬다.

이 책의 구성

1장에는 기본 리액트 환경을 준비하는 과정과 리액트에서 사용자 인터페이스를 구성하는 방법을

비롯해 아주 많은 내용을 담았다.

2장에서는 자바스크립트에서 컴포넌트 마크업을 선언하는 데 이용하는 리액트의 자바스크립트 언어

확장인 JSX를 자세히 다룬다. 또한 리액트의 이벤트 시스템과 가상 DOM 구현을 이용하는 방법도

알아본다.

서문 | XVII

책2.indb 17 2016-05-24 오후 10:31:02

Page 12: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

서문|XVIII

3장에서는 컴포넌트를 이용해 완전한 애플리케이션을 제작하는 방법을 설명한다. 리액트

애플리케이션 내부의 데이터 흐름에 대해 배우고 컴포넌트에 대한 자세한 내용(컴포넌트 중첩, 속성,

상태, API 노출)을 살펴본다.

4장에서는 최종 사용자를 위한 풍부한 경험을 만드는 방법을 다룬다. 리액트의 CSSTransitionGroup

애드온을 이용해 애니메이션을 구현하는 방법과 리액트 DnD라는 외부 라이브러리를 이용해 드래그

앤드 드롭을 구현하는 법을 배운다.

5장은 완전히 라우팅에 대한 단원이다. 리액트 커뮤니티에서 가장 인기가 많은 라이브러리 중 하나인

리액트 라우터React Router를 이용해 애플리케이션 엔드포인트를 설정하고 URI를 관리하는 방법을

배운다.

6장에서는 플럭스Flux 아키텍처를 소개한다. 이 아키텍처와 이를 이용해 해결할 수 있는 문제를

확인하고 이를 리액트 애플리케이션에 통합하는 법을 배운다.

7장에서는 성능 튜닝에 대해 다룬다. 애플리케이션의 성능을 측정하는 방법을 배우고 코드 최적화를

통해 애플리케이션의 성능을 개선하는 방법을 이해한다.

8장에서는 동형(또는 유니버셜) 리액트 애플리케이션에 대해 알아보고 리액트를 서버에서

렌더링하는 방법을 배운다. 이 기법을 이용해 체감 성능을 개선하고 검색 엔진을 최적화하며 로컬에서

자바스크립트가 비활성화된 경우에도 앱을 실행하는 단계적 기능 축소graceful degradation를 지원할 수 있다.

마지막으로 9장에서는 테스트에 대해 다룬다. 리액트의 테스트 유틸리티를 이용해 컴포넌트를

테스트하는 법을 배우고 리액트 프로젝트의 테스트를 위해 페이스북에서 개발한 권장 테스트

프레임워크인 제스트Jest를 소개한다.

책2.indb 18 2016-05-24 오후 10:31:02

Page 13: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

서문 | XIX

대상 독자

이 책은 jQuery 또는 백본/앵귤러Backbone/Angular 등으로 프런트엔드 앱을 개발해본 경험이 있지만 날로

복잡해지는 프런트엔드 애플리케이션을 효율적으로 제작할 수 있는 향상된 도구와 지식을 필요로 하는

중급 자바스크립트 개발자를 위해 구성됐다.

소스코드

이 책에 나오는 코드는 에이프레스 웹 사이트의 Source Code 섹션에서 내려받을 수 있다.

www.apress.com을 방문하고 Source Code를 클릭한 후 이 책의 제목Pro React을 찾아본다. 이 책의

홈페이지에서도 소스코드를 내려받을 수 있으며, 깃허브(pro-react.github.io)에서도 모든 예제 코드와

몇 가지 유용한 추가 코드를 내려받을 수 있다1.

저자 연락처

이 책을 구매해 주셔서 감사드리며, 모쪼록 이 책에서 도움이 되는 유용한 정보를 얻을 수 있기를

바란다. 이 책의 내용이나 소스코드에 대한 개인적 의견이나 질문이 있으면 이메일(proreactbook

@gmail.com)로 보내주길 바란다.

행운이 따르기를 바라며, 여러분의 리액트 애플리케이션을 만날 수 있기를 기대한다!

1 위키북스 출판사 홈페이지에서도 소스코드를 내려받을 수 있다: http://wikibook.co.kr/pro-react

책2.indb 19 2016-05-24 오후 10:31:03

Page 14: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

2 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

시작하기

01

시작하기 전에

리액트의 정의

리액트의 장점

첫 번째 리액트 앱 작성

컴포넌트 조합하기

상태 소개

정리

책2.indb 2 2016-05-24 오후 10:31:03

Page 15: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 3

리액트React는 페이스북에서 만든 오픈소스 프로젝트로서 자바스크립트로 사용자 인터페이스를

구축하는 창의적인 접근법을 제공한다. 리액트는 처음 공개된 이후로 빠른 속도로 보급되고 있으며,

관련 커뮤니티의 활동도 꾸준히 증가하고 있다.

이 책에서는 프로젝트에 리액트를 활용하기 위해 알아야 할 모든 내용을 다룬다. 리액트는 UI를

렌더링하는 데만 관여하고 나머지 기술 스택에 대해서는 아무것도 전제하지 않으므로 이 책에서는 이

라이브러리의 패턴에 맞는 라우팅과 애플리케이션 아키텍처를 다룬다.

1장에서는 최대한 빨리 애플리케이션을 직접 만들어볼 수 있게 몇 가지 주제를 개략적으로 다룬다.

여기서 다룰 주제는 다음과 같다.

■ 리액트의 정의와 리액트의 장점

■ 리액트에서 UI를 나타내기 위한 자바스크립트 확장인 JSX 사용법

■ 속성과 상태를 포함하는 리액트 컴포넌트를 만드는 법

시작하기 전에

리액트는 최신 자바스크립트 개발 생태계의 일부분이다. 이 책에 나오는 예제를 직접 작성하고

실행하려면 Node.js와 npm을 설치해야 한다. 또한 함수형 자바스크립트 패러다임에 익숙해야 하며,

화살표 함수arrow function 및 클래스와 같은 자바스크립트의 몇 가지 새로운 기능에 대해 알고 있어야

한다.

Node.js와 npm

자바스크립트는 원래 브라우저에서 실행하도록 만들어졌지만 Node.js는 오픈소스 명령줄 도구를

통해 자바스크립트 프로그램을 로컬 컴퓨터와 서버에서 실행할 수 있게 해준다. Node.js를 이용하면

작업(예: 파일 복사와 이동 또는 로컬 개발 서버 시작)을 실행하는 스크립트를 작성할 수 있으며

의존성을 자동으로 내려받는 기능을 통해 npm(노드 패키지 매니저)과 함께 자바스크립트 중심

애플리케이션을 로컬에서 개발하기 위한 필수 도구로 자리 잡았다.

아직 Node.js를 설치하지 않았다면 잠시 시간을 내서 운영체제(윈도우, 맥, 리눅스)에 맞는 설치

관리자를 https://nodejs.org/에서 내려받고 설치하자.

책2.indb 3 2016-05-24 오후 10:31:03

Page 16: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

4 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

자바스크립트 ES6

자바스크립트는 끊임없이 진화하는 살아있는 언어다. 최근에는 자바스크립트 언어의 새로운

기능들에 대한 합의가 이뤄졌다. 일부 최신 브라우저는 이미 이러한 최신 기능을 지원하며, 리액트

커뮤니티에서도 이러한 기능(화살표 함수, 클래스, 스프레드 연산자 등)을 집중적으로 이용하고

있다. 리액트에서는 자바스크립트에서 함수형 패턴을 이용하도록 권장하므로 자바스크립트의 함수와

컨텍스트가 작동하는 방법과 함께 map, reduce, assign 같은 메서드에도 익숙해야 한다. 이러한 세부

사항에 익숙하지 않다면 에이프레스 부록 B를 참고한다.

리액트의 정의

리액트가 무엇인지 명확하게 설명하기 위해 필자는 다음과 같이 리액트를 정의한다.

리액트는 자바스크립트와 (필요에 따라) XML을 이용해 조합형 사용자 인터페이스를 구축하는

엔진이다.

이 정의를 각 부분으로 분리해서 알아보자.

리액트는 엔진이다: 리액트 사이트에서는 리액트를 라이브러리라고 정의하고 있지만 필자는 리액트의 핵심 장점 중 하나인

반응형 UI 렌더링을 잘 나타내는 “엔진”이라는 용어를 선호한다. 이 방식은 사용자에게 제공되는 UI로부터 상태(특정 시점

에 애플리케이션을 정의하는 모든 내부 데이터)를 분리한다. 리액트를 이용해 상태가 DOM의 시각 요소로 표현되는 방법을

선언하면 이후에는 DOM이 상태 변경을 반영해 자동으로 업데이트된다.

저스턴 딜Justin Deal은 반응형 렌더링과 게임 엔진이 작동하는 방식의 유사성에 주목하고 리액트를 설명하는 데 “엔진”이라는

용어를 처음 사용했다(https://zapier.com/engineering/react-js-tutorial-guide gotchas/).

조합형 사용자 인터페이스를 구축한다: 리액트의 핵심 개념은 사용자 인터페이스의 생성과 유지 관리의 복잡성을 줄이는

것이다. 이를 위해 UI를 컴포넌트(재사용, 확장, 유지 관리하기 쉽고 특정 목적을 가진 독립형 구성요소)로 분리하는 개념을

받아들였다.

자바스크립트와 (필요에 따라) XML을 이용한다: 리액트는 브라우저, 서버, 모바일 장치에서 이용할 수 있는 순수 자바스크

립트 라이브러리다. 그런데 1장에서 살펴보겠지만 리액트에는 XML을 이용해 UI를 기술하는 선택적인 구문이 포함돼 있다.

처음에는 이상하게 보일 수 있지만 XML은 사용자 인터페이스를 설명하는 데 아주 적합하다. XML은 선언적이며 손쉽게 요

소 간의 관계를 파악하고 UI의 전체 구조를 시각화할 수 있다.

책2.indb 4 2016-05-24 오후 10:31:04

Page 17: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 5

리액트의 장점

자바스크립트 MVC 프레임워크는 이미 많이 나와 있다. 그렇다면 페이스북이 리액트를 개발한 이유,

그리고 여러분이 이를 이용하려고 하는 이유는 무엇일까? 다음의 세 절에서는 리액트의 장점을

살펴보면서 이 질문의 답을 찾아본다.

편리한 반응형 렌더링

단일 페이지 애플리케이션single page application의 개념이 등장하기 한참 전의 초기 웹 개발 시대에는

사용자가 페이지에서 수행하는 모든 상호작용(예: 버튼 클릭)을 처리하기 위해 사용자가 현재 보고

있는 것과 사소한 차이점이 있는 경우에도 완전히 새로운 페이지를 서버로부터 전송해야 했다. 이

방식은 사용자 관점에서는 형편없는 경험을 제공했지만 개발자는 특정 상호작용이나 특정 시점에

사용자에게 보여줄 내용을 아주 쉽게 계획할 수 있다.

단일 페이지 애플리케이션은 사용자가 상호작용하는 동안 끊임없이 새로운 데이터를 가져오고

DOM의 일부를 변환한다. 그런데 인터페이스가 복잡해지면 애플리케이션의 현재 상태를 조사하고

시기적절하게 DOM에 변경사항을 반영하고 업데이트하는 작업이 더욱 복잡해진다.

여러 자바스크립트 프레임워크가 (특히 리액트가 등장하기 전에) 증가하는 복잡성을 해결하고

인터페이스와 상태를 동기화하기 위해 데이터 바인딩data binding을 이용하기도 했지만 이 기법은 유지

관리성, 확장성, 성능 면에서 단점에 있었다.

반응형 렌더링reactive rendering은 기존 데이터 바인딩보다 사용하기 쉽다. 개발자가 컴포넌트의 모양과

동작을 선언식으로 정의하면 리액트가 데이터 변경을 감지하고 개념상으로 전체 인터페이스를 다시

렌더링한다.

그런데 상태 데이터가 변경될 때마다 실제로 전체 인터페이스를 다시 렌더링하는 것은 성능 저하를

감안할 때 불가능하므로 리액트는 “가상 DOM”이라고 하는 DOM의 인-메모리 경량 표현을 이용해

작업한다.

실제 DOM을 조작하는 것보다는 DOM의 인-메모리 표현을 조작하는 것이 훨씬 효율적이고 빠르다.

예를 들어, 사용자 상호작용이나 데이터 가져오기 등을 통해 애플리케이션의 상태가 달라지면

리액트는 신속하게 UI의 현재 상태와 원하는 상태를 비교하고 실제 DOM의 최소 집합으로 계산을

책2.indb 5 2016-05-24 오후 10:31:04

Page 18: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

6 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

수행한다. 덕분에 리액트는 아주 빠르고 효율적으로 작업할 수 있다. 리액트 앱은 모바일 장치에서도

손쉽게 60fps 속도를 달성할 수 있다.

순수 자바스크립트를 이용한 컴포넌트 기반 개발

리액트 애플리케이션의 모든 부분은 특정 목적을 가진 독립형 구성요소인 컴포넌트로 구성된다.

컴포넌트를 이용해 애플리케이션을 개발하면 특별히 복잡한 부분이 없는 경우 “분할 정복” 방식을

적용할 수 있다. 컴포넌트는 작게 유지되며 서로 조합할 수 있으므로 여러 작은 컴포넌트를 조합해

복잡하고 기능이 많은 컴포넌트를 손쉽게 만들 수 있다.

리액트 컴포넌트는 기존 웹 애플리케이션 UI에 많이 이용되던 HTML 지시문이나 템플릿 언어가 아닌

일반 자바스크립트로 작성한다. 이렇게 하는 데는 합당한 이유가 있다. 템플릿은 UI를 구축하는 데

이용할 수 있는 전체 추상화 집합을 좌우하므로 한계로 작용하는 단점이 있기 때문이다. 리액트는

완전한 기능을 갖춘 프로그래밍 언어를 이용하므로 추상화를 구축하는 데 큰 장점이 있다.

또한 컴포넌트는 독립적이며 해당하는 뷰 논리에 통합 마크업을 이용하므로 관심사의 분리를 돕는다.

웹 초창기에는 관심사를 강제로 분리하기 위해 각기 다른 언어(콘텐츠 구조를 위한 HTML, 스타일링을

위한 CSS, 동작을 위한 자바스크립트)를 이용했는데, 당시의 주류 웹 페이지는 정적 프레젠테이션

스타일을 이용했기 때문에 이러한 분리 방법이 효과적이었다. 그러나 현재의 인터페이스는 이보다

몇 배는 더 복잡하며, 어쩔 수 없이 표시 논리와 마크업이 서로 연결돼 있다. 즉, 마크업, 스타일링,

자바스크립트 간의 분리는 더 이상 관심사의 분리가 아닌 단순한 기술의 분리가 됐다.

리액트는 표시 논리와 마크업이 서로 밀접하게 연관된다고 가정한다. 이 둘은 모두 UI를 표시하는

역할을 하며, 각 관심사에 대해 독립적이고, 잘 캡슐화되며, 재사용 가능한 컴포넌트를 만드는

방식으로 관심사를 분리하도록 권장한다.

문서 모델의 유연한 추상화

리액트는 기반 문서 모델을 추상화하는 UI의 경량 표현을 자체적으로 갖추고 있다. 이 방식의 가장

주요한 장점은 웹용 HTML을 렌더링할 때는 물론 네이티브 iOS와 안드로이드 뷰를 렌더링할 때도

동일한 원칙을 적용할 수 있다는 것이다. 또한 이 추상화는 다른 두 가지 흥미로운 요점과 연관돼 있다.

책2.indb 6 2016-05-24 오후 10:31:05

Page 19: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 7

■ 이벤트가 모든 브라우저와 장치에서 자동으로 위임을 이용해 일관되고 표준을 준수하는 방식으로 작동한다.

■ 리액트 컴포넌트를 서버에서 렌더링해 SEO와 체감 성능을 개선할 수 있다.

첫 번째 리액트 앱 작성

앞에서 컴포넌트는 리액트 UI의 기본 구성요소라고 했는데, 컴포넌트는 어떻게 생겼을까? 또 어떻게

만들 수 있을까? 기본적으로 리액트 컴포넌트는 다음과 같이 컴포넌트의 UI에 대한 설명을 반환하는

render 메서드가 포함된 자바스크립트 클래스다.

class Hello extends React.Component {

render() {

return (

<h1>Hello World</h1>

)

}

}

자바스크립트 코드 안에 HTML 태그가 있는 것을 볼 수 있다. 앞에서 언급한 것처럼 리액트에는 코드

안에 인라인으로 XML(결과적으로 HTML까지)을 작성할 수 있게 해주는 JSX라는 자바스크립트 구문

확장이 있다.

JSX는 필수는 아니지만 선언식 구문을 이용할 수 있고 표현성이 좋으며 일반 자바스크립트 함수

호출로 변환되므로 언어의 의미를 바꾸지 않는다는 장점 때문에 리액트 컴포넌트에서 UI를 정의하는

표준적인 방법으로 널리 이용되고 있다.

JSX에 대해서는 2장에서 더 자세히 다루겠지만, 일단은 JSX를 자바스크립트로 “변환”(또는

트랜스파일)하는 단계가 필요하다는 것만 알아두자.

최신 자바스크립트 개발 생태계에는 이 단계를 처리할 수 있는 도구가 많이 있다. 다음은 리액트

프로젝트를 위한 개발 워크플로를 설정하는 방법을 알아보자.

책2.indb 7 2016-05-24 오후 10:31:06

Page 20: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

8 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

리액트 개발 워크플로

예전에는 모든 자바스크립트를 한 파일에 작성하고, 자바스크립트 라이브러리 한두 개를 직접

내려받은 다음, 모든 것을 한 페이지에 집어넣던 시절이 있었다. 물론 지금도 리액트 라이브러리를

축소된 자바스크립트 파일로 내려받거나 심지어 복사하고 붙여넣은 다음, 런타임에 JSX를 변환하면서

곧바로 컴포넌트를 실행하는 것도 가능하지만 아주 작은 데모나 프로토타입이 아니면 아무도 이렇게

하지 않는다.

가장 기본적인 시나리오에서도 다음과 같은 작업이 가능한 개발 워크플로가 필요하다.

■ JSX를 작성하고 즉석에서 일반 자바스크립트로 변환

■ 코드를 모듈 패턴으로 작성

■ 의존성 관리

■ 자바스크립트 파일을 번들로 만들고 디버깅을 위해 소스 맵을 이용

이를 위해 리액트 프로젝트의 기본 프로젝트 구조에는 다음과 같은 항목이 포함된다.

1. 모든 자바스크립트 모듈을 포함하는 소스 폴더.

2. index.html 파일. 리액트 애플리케이션에서 HTML 페이지는 거의 비어 있는 경우가 많다. 이 페이지는 애플리케이션의

자바스크립트를 로드하고 리액트에서 애플리케이션의 컴포넌트를 렌더링하는 데 이용하는 div(또는 다른 요소)를 제공하

는 역할을 한다.

3. package.json 파일. package.json은 표준 npm 매니페스트 파일이며, 프로젝트 이름, 설명, 개발자 등과 같이 프로젝트

에 대한 다양한 정보를 포함한다. 이 파일은 의존성(자동으로 내려받고 설치)을 지정하고 스크립트 작업을 정의하는 데 이

용된다.

4. 모듈 패키저 또는 빌드 도구. JSX 변환과 모듈/의존성 번들 작업에 이용된다. 모듈은 코드를 각기 다른 의존성을 선언하는

여러 파일로 분할함으로써 자바스크립트 코드를 정리하는 데 도움을 준다. 모듈 번들러는 올바른 로드 순서에 따라 모든 항

목을 하나로 패키징한다. 이 중단 단계를 처리할 수 있는 도구로는 그런트Grunt, 걸프Gulp, 브런치Brunch 등이 있다. 이러한 도구

의 리액트용 레시피를 찾기는 어렵지 않지만 리액트 커뮤니티에서는 이 작업을 위한 도구로 웹팩webpack을 선호한다. 웹팩은

기본적으로 모듈 번들러지만 로더를 통해 소스코드를 변환 및 컴파일할 수도 있다.

그림 1-1에는 방금 언급한 파일과 폴더 구조가 나온다.

책2.indb 8 2016-05-24 오후 10:31:06

Page 21: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 9

그림 1-1. 최소한의 리액트 프로젝트 파일과 폴더 구조

팁 이 책의 부록 A에서는 웹팩을 이용해 리액프 프로젝트를 설정하는 과정을 설명한다. 이 부록에서는 웹팩을 자세히 소

개하고 리액트 컴포넌트의 핫 리로딩hot reloading과 같은 고급 옵션을 설정하는 방법을 설명한다.

빠르게 시작하기

이 책에서는 리액트 라이브러리를 배우는 데 집중할 수 있게 리액트 앱 보일러플레이트 팩을 제공한다.

apress.com 또는 깃허브 페이지(https://github.com/pro-react/react-app-boilerplate)에서 보일러플레이트

팩을 다운로드한다. 보일러플레이트 프로젝트에는 즉시 개발을 시작하는 데 필요한 모든 기본적인

파일과 구성이 포함돼 있다. 보일러플레이트 팩을 내려받은 다음에는 의존성을 설치하고 개발 서버를

실행하면 브라우저에서 프로젝트를 테스트할 수 있다. 모든 의존성을 자동으로 설치하려면 터미널이나

명령 프롬프트를 열고 npm install을 실행한다. 개발 서버를 실행하려면 npm start를 실행한다

이제 준비가 끝났다. 다음 주제는 건너뛰고 첫 번째 리액트 컴포넌트를 만드는 단계를 진행해도 된다.

또는 직접 해보기

직접 해보는 것을 선호한다면 5단계로 기본 프로젝트 구조를 직접 만들 수 있다. 이 책의 초점은

리액트 라이브러리이므로 여기서 세부 사항이나 선택적인 구성을 자세하게 설명하지는 않지만,

부록에서 자세한 내용을 볼 수 있으며 리액트 앱 보일러플레이트 프로젝트의 소스 파일을 살펴봐도

된다. 프로젝트 소스 파일은 에이프레스 웹 사이트(www.apress.com/)나 이 책의 깃허브 페이지(http://

pro-react.github.io/)에서 내려받을 수 있다.

책2.indb 9 2016-05-24 오후 10:31:07

Page 22: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

10 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

1. 가장 먼저 소스 폴더(일반적인 이름은 source 또는 app )를 만든다. 이 폴더는 자바스크립트 모듈만 포함하며, 모듈 번들

러로 처리되지 않는 정적 애셋(예: index.html, 이미지 파일, CSS 파일 등)은 루트 폴더에 저장된다.

2. 프로젝트의 루트 폴더에 예제 1-1과 같은 내용의 index.html 파일을 만든다.

예제 1-1. 번들된 자바스크립트를 로드하고 리액트 컴포넌트를 렌더링할 루트 div를 제공하는 간단한 HTML 페이지

<!DOCTYPE html>

<html>

<head>

<title>First React Component</title>

</head>

<body>

<div id="root"></div>

<script type="text/javascript" src="bundle.js"></script>

</body>

</html>

3. 터미널이나 명령 프롬프트에서 npm init 명령을 실행한 후 지시에 따라 package.json 파일을 만든다. npm은 의존성을

관리(필요한 모든 라이브러리를 내려받고 설치)하는 데 사용된다. 이 프로젝트의 의존성에는 리액트, JSX 변환(로더와

코어)을 위한 바벨Babel 컴파일러, 웹팩webpack (웹팩 개발 서버 포함)이 있다. 예제 1-2와 같이 package.json 파일을 편집

한 후 npm install을 실행한다.

예제 1-2. package.json에 포함된 의존성

{

"name": "your-app-name",

"version": "X.X.X",

"description": "Your app description",

"author": "You",

"devDependencies": {

"babel-core": "^5.8.*",

"babel-loader": "^5.3.*",

"webpack": "^1.12.*",

"webpack-dev-server": "^1.10.*"

},

"dependencies": {

"react": "^0.13.*"

}

}

책2.indb 10 2016-05-24 오후 10:31:07

Page 23: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 11

4. 다음은 우리가 선택한 모듈 번들러인 웹팩을 구성해야 한다. 예제 1-3은 구성 파일이다. 첫 번째로 주 애플리케이션 모듈

에 대한 entry 키 포인트가 나온다.

예제 1-3. webpack.config.js 파일

module.exports = {

entry: [

'./source/App.js'

],

output: {

path: __dirname,

filename: "bundle.js"

},

module: {

loaders: [{

test: /\.jsx?$/,

loader: 'babel'

}]

}

};

두 번째 키인 output은 모든 모듈을 올바른 순서로 포함하는 단일 자바스크립트 파일을 저장할 위치를 웹팩에 알려준다.

마지막으로 module의 loaders 섹션에서는 모든 JSX를 일반 자바스크립트 코드로 변환하는 자바스크립트 컴파일러인

바벨을 통해 모든 .js 파일을 처리한다. 바벨은 여기서 그치지 않고 화살표 함수 및 클래스와 같은 최신 자바스크립트 구

문을 이용할 수 있게 해준다.

5. 이제 프로젝트 구조가 완성됐고 마무리를 할 차례다. 프로젝트를 브라우저에서 테스트하려면 로컬 서버를 시작해야 한다.

이를 위해 node_modules/.bin/webpack-dev-server 명령을 실행해야 하지만 3단계에서 만든 package.json을 예제

1-4와 같이 편집해 명령을 작업으로 바꾸면 매번 명령을 길게 입력할 필요가 없다.

예제 1-4. package.json에 start 스크립트 추가

{

"name": "your-app-name",

"version": "X.X.X",

"description": "Your app description",

"author": "You",

"scripts": {

책2.indb 11 2016-05-24 오후 10:31:07

Page 24: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

12 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

"start": "node_modules/.bin/webpack-dev-server --progress"

},

"devDependencies": {

"babel-core": "^5.8.*",

"babel-loader": "^5.3.*",

"webpack": "^1.12.*",

"webpack-dev-server": "^1.10.*"

},

"dependencies": {

"react": "^0.13.*"

}

}

이제부터는 간단히 npm start를 입력하면 로컬 개발 서버를 실행할 수 있다.

첫 번째 컴포넌트 만들기

의존성을 관리하고, 모듈 시스템을 제공하며, JSX를 변환하는 기본 프로젝트 구조를 준비한 다음에는

Hello World 컴포넌트를 만들고 이를 페이지에 렌더링할 수 있다. 컴포넌트의 코드는 처음에 본

예제와 동일하지만 import 문을 추가해 번들되는 자바스크립트에 리액트 라이브러리가 포함되게 했다.

import React from 'react';

class Hello extends React.Component {

render() {

return (

<h1>Hello World</h1>

);

}

}

책2.indb 12 2016-05-24 오후 10:31:08

Page 25: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 13

다음은 React.render를 이용해 그림 1-2에 나오는 것처럼 컴포넌트를 페이지에 표시한다.

React.render(<Hello />, document.getElementById('root'));

그림 1-2. 브라우저에 렌더링한 첫 번째 컴포넌트

팁 문서 본문으로 직접 렌더링하는 것도 가능하지만 그보다는 자식 요소(일반적으로 div)로 렌더링하는 것이 일반적이다.

노드를 문서 본문에 연결하는 브라우저 확장과 라이브러리가 많고 리액트도 자체적으로 제어하는 DOM 트리를 완전하

게 관리해야 하므로 컴포넌트를 문서 본문에 직접 렌더링하면 예기치 않은 문제가 발생할 수 있다.

타이핑 수고를 약간 줄이는 방법

모듈 임포트에 구조분해 할당destructuring assignemt을 적용하면 모듈 내부 함수와 클래스에 직접

접근할 수 있어 코드를 입력할 때 타이핑을 조금이라도 줄일 수 있다. 이전 예제에 이를 적용하면

“React.Component”를 생략할 수 있게 된다.

import React, { Component } from 'react';

class Hello extends Component {

render() {

return (

<h1>Hello World</h1>

);

}

}

책2.indb 13 2016-05-24 오후 10:31:08

Page 26: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

14 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

이 예제의 경우 효과가 그리 크지 않았지만 대규모 프로젝트에서는 사용할 가치가 충분하다.

참고 구조분해 할당은 다음 버전의 자바스크립트 사양에 포함돼 있다. 이를 비롯해 리액트에서 이용 가능한 향후 버전의 기

능에 대해서는 부록 B에서 다룬다.

동적 값

JSX에서 중괄호({}) 안에 있는 값은 자바스크립트 식으로 계산되고 마크업 안에 렌더링된다. 로컬

변수의 값을 렌더링하려면 다음 예제와 같이 할 수 있다.

import React, { Component } from 'react';

class Hello extends Component {

render() {

var place = "World";

return (

<h1>Hello {place}</h1>

);

}

}

React.render(<Hello />, document.getElementById("root"));

컴포넌트 조합하기

리액트는 재사용 가능한 간단한 컴포넌트를 중첩하고 조합해 복잡한 UI를 만드는 방식을 권장한다.

지금까지 리액트 컴포넌트의 기본 구조를 살펴봤으므로 다음은 컴포넌트를 조합하는 방법을 알아보자.

속성

컴포넌트를 재사용하고 조합하는 것이 가능한 가장 중요한 이유는 컴포넌트를 구성할 수 있기

때문이며, 이와 같이 컴포넌트를 구성하기 위해 리액트는 속성property을 제공한다. 속성은 리액트의

책2.indb 14 2016-05-24 오후 10:31:09

Page 27: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 15

부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 메커니즘이다. 속성은 자식 컴포넌트 안에서

변경할 수 없으며 부모 컴포넌트가 전달하고 “소유”한다.

JSX에서 속성은 HTML의 태그 특성과 비슷하게 제공된다. 여기서는 부모 GroceryList 컴포넌트와 자식

GroceryItem 컴포넌트로 구성되는 간단한 식료품 리스트를 만들어보자.

import React, { Component } from 'react';

// 부모 컴포넌트

class GroceryList extends Component {

render() {

return (

<ul>

<ListItem quantity="1" name="Bread" />

<ListItem quantity="6" name="Eggs" />

<ListItem quantity="2" name="Milk" />

</ul>

);

}

}

// 자식 컴포넌트

class ListItem extends Component {

render() {

return (

<li>

{this.props.quantity}× {this.props.name}

</li>

);

}

}

React.render(<GroceryList />,document.getElementById("root"));

이름을 지정한 속성 외에도 props.children을 이용해 열기 태그와 닫기 태그 사이에 내용을 참조할 수

있다.

책2.indb 15 2016-05-24 오후 10:31:09

Page 28: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

16 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

import React, { Component } from 'react';

// 부모 컴포넌트

class GroceryList extends Component {

render() {

return (

<ul>

<ListItem quantity="1">Bread</ListItem>

<ListItem quantity="6">Eggs</ListItem>

<ListItem quantity="2">Milk</ListItem>

</ul>

);

}

}

// 자식 컴포넌트

class ListItem extends Component {

render() {

return (

<li>

{this.props.quantity}× {this.props.children}

</li>

);

}

}

React.render(<GroceryList />, document.getElementById('root'));

칸반 보드 앱 소개

이 책 전체에서는 각 주제마다 예제 코드와 함께 여러 작은 컴포넌트를 작성한다. 또한 완전한

애플리케이션인 칸반Kanban 스타일의 프로젝트 관리 툴을 개발하는 과정도 다룬다.

칸반 보드에서는 각 프로젝트 활동이 각기 다른 카드와 대응된다(그림 1-3). 카드는 상태를 기준으로

목록에 포함되며, 개념부터 구현까지 기능의 흐름과 비슷하게 한 목록에서 다음 목록으로 진행된다.

책2.indb 16 2016-05-24 오후 10:31:09

Page 29: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 17

그림 1-3. 칸반 보드 예제

온라인으로 이용 가능한 칸반 스타일의 프로젝트 관리 앱이 많이 있다. 잘 알려진 예로 Trello.com이

있지만 예제 프로젝트는 당연히 이보다는 단순하다. 완성된 프로젝트는 그림 1-4와 같으며, 예제

1-5는 이 칸반 앱이 사용하는 데이터 모델이다.

그림 1-4. 이후 장에서 개발할 칸반 앱

책2.indb 17 2016-05-24 오후 10:31:10

Page 30: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

18 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

예제 1-5. 칸반 앱 데이터 모델

[

{ id:1,

title: "Card one title",

description: "Card detailed description.",

status: "todo",

tasks: [

{id: 1, name:"Task one", done:true},

{id: 2, name:"Task two", done:false},

{id: 3, name:"Task three", done:false}

]

},

{ id:2,

title: "Card Two title",

description: "Card detailed description",

status: "in-progress",

tasks: []

},

{ id:3,

title: "Card Three title",

description: "Card detailed description",

status: "done",

tasks: []

},

];

컴포넌트 계층 정의

가장 먼저 인터페이스를 중첩된 컴포넌트로 분할하는 방법을 이해해야 한다. 여기에는 세 가지 고려할

사항이 있다.

1. 컴포넌트는 단일 관심사를 가져야 하며 작아야 한다. 즉, 컴포넌트는 한 가지 일만 해야 한다. 컴포넌트가 더 성장하는 경우

작은 하위 컴포넌트로 분할해야 한다.

2. 프로젝트의 와이어프레임과 레이아웃을 분석하면 컴포넌트 계층에 대한 많은 힌트를 얻을 수 있다.

책2.indb 18 2016-05-24 오후 10:31:10

Page 31: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 19

3. 데이터 모델에 주목한다. 인터페이스와 데이터 모델은 동일한 정보 아키텍처를 따르는 예가 많기 때문에 UI를 컴포넌트로

분리하는 작업도 아주 쉽게 해결되는 경우가 많다. 즉, 데이터 모델의 한 조각을 나타내는 컴포넌트로 분리할 수 있다.

이러한 개념을 칸반 앱에 적용하면 그림 1-5와 같은 결과를 얻는다.

그림 1-5. 칸반 앱의 컴포넌트 계층

속성의 중요성

속성property은 컴포넌트 조합에서 가장 중요한 역할을 한다. 속성은 리액트의 부모 컴포넌트에서 자식

컴포넌트로 데이터를 전달하는 메커니즘이다. 속성은 자식 컴포넌트 안에서 변경할 수 없으며 부모

컴포넌트가 전달하고 “소유”한다.

컴포넌트 만들기

인터페이스 계층을 이해하고 나면 컴포넌트 만들기를 시작할 차례다. 컴포넌트를 만드는 데는

하향식top-down과 상향식bottom-up의 두 가지 기본적인 접근법이 있다. 즉, 계층 위쪽에 있는 컴포넌트(예:

App 컴포넌트)를 먼저 만들거나 아래쪽에 있는 컴포넌트(예: CheckList 컴포넌트)를 먼저 만들

수 있다. 여기서는 속성이 하위 컴포넌트로 전달되는 방법과 자식 컴포넌트에서 이용되는 방법을

이해하는 데 도움이 되도록 하향식으로 칸반 컴포넌트를 만든다.

책2.indb 19 2016-05-24 오후 10:31:11

Page 32: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

20 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

또한 프로젝트의 체계를 유지하고 새로운 기능을 추가하거나 유지 관리하는 데 도움이 되도록 각

컴포넌트를 별도의 자바스크립트 파일로 만든다.

앱 모듈(App.js)

우선 app.js 파일은 데이터만 포함하고 KanbanBoard 컴포넌트를 렌더링하는 일만 하도록 아주

간단하게 유지한다. 첫 번째 칸반 앱에서는 데이터를 로컬 변수로 하드코딩했지만 이후에는 API에서

가져오는 방법을 이용한다. 예제 1-6을 보자.

예제 1-6. 간단한 app.js 파일

import React from 'react';

import KanbanBoard from './KanbanBoard';

let cardsList = [

{

id: 1,

title: "Read the Book",

description: "I should read the whole book",

status: "in-progress",

tasks: []

},

{

id: 2,

title: "Write some code",

description: "Code along with the samples in the book",

status: "todo",

tasks: [

{

id: 1,

name: "ContactList Example",

done: true

},

{

id: 2,

name: "Kanban Example",

done: false

책2.indb 20 2016-05-24 오후 10:31:11

Page 33: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 21

},

{

id: 3,

name: "My own experiments",

done: false

}

]

},

];

React.render(<KanbanBoard cards={cardsList} />, document.getElementById('root'));

KanbanBoard 컴포넌트(KanbanBoard.js)

KanbanBoard 컴포넌트는 데이터를 속성을 통해 받고 상태를 필터링해 List 컴포넌트 세 개(“To

Do”, “In Progress,” “Done”)를 만드는 역할을 한다. 예제 1-7을 확인하자.

참고 1장의 첫 부분에서 언급했듯이, 리액트 컴포넌트는 일반 자바스크립트로 작성한다. 일반 자바스크립트에는 템플릿 라이

브러리(예: 머스태시Mustache)에서 볼 수 있는 분기 및 루프 도우미가 없지만 얼마든지 완전한 기능의 프로그래밍 언어를

사용할 수 있으므로 걱정하지 않아도 된다. 예를 들어, 다음에 나올 컴포넌트는 필터와 맵 함수를 이용해 cards 배열의

데이터를 처리한다.

예제 1-7. KanbanBoard 컴포넌트

import React, { Component } from 'react';

import List from './List';

class KanbanBoard extends Component {

render(){

return (

<div className="app">

<List id='todo' title="To Do" cards={

this.props.cards.filter((card) => card.status === "todo")

} />

책2.indb 21 2016-05-24 오후 10:31:12

Page 34: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

22 프로 리액트: React.js를 이용한 모던 프런트엔드 구축

<List id='in-progress' title="In Progress" cards={

this.props.cards.filter((card) => card.status === "in-progress")

} />

<List id='done' title='Done' cards={

this.props.cards.filter((card) => card.status === "done")

} />

</div>

);

}

}

export default KanbanBoard;

List 컴포넌트(List.js)

List 컴포넌트는 목록의 이름을 표시하고 그 안에 들어 있는 모든 Card 컴포넌트를 렌더링한다. List

컴포넌트는 속성을 통해 cards 배열을 받은 다음 제목이나 설명과 같은 개별 정보를 다시 속성을 통해

Card 컴포넌트로 전달한다. 예제 1-8을 확인하자.

예제 1-8. List 컴포넌트

import React, { Component } from 'react';

import Card from './Card';

class List extends Component {

render() {

var cards = this.props.cards.map((card) => {

return <Card id={card.id}

title={card.title}

description={card.description}

tasks={card.tasks} />

});

return (

<div className="list">

<h1>{this.props.title}</h1>

책2.indb 22 2016-05-24 오후 10:31:12

Page 35: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축

01 _ 시작하기 23

{cards}

</div>

);

}

}

export default List;

Card 컴포넌트(Card.js)

Card는 사용자 상호작용이 주로 수행되는 컴포넌트다. 그림 1-6과 예제 1-9에 나오는 것처럼 각

카드에는 제목, 설명, 체크리스트가 포함돼 있다.

그림 1-6. 칸반 앱 카드

예제 1-9. Card 컴포넌트

import React, { Component } from 'react';

import CheckList from './CheckList';

class Card extends Component {

render() {

return (

<div className="card">

<div className="card__title">{this.props.title}</div>

<div className="card__details">

{this.props.description}

<CheckList cardId={this.props.id} tasks={this.props.tasks} />

</div>

</div>

책2.indb 23 2016-05-24 오후 10:31:12

Page 36: 프로 리액트 : React.js를 이용한 모던 프런트엔드 구축